xref: /openbsd-src/gnu/usr.sbin/mkhybrid/src/rock.c (revision 68cbdb5e9e7bb8699a5d08a6b912abb567da639e)
1f0d9efc0Sbeck /*
2f0d9efc0Sbeck  * File rock.c - generate RRIP  records for iso9660 filesystems.
3f0d9efc0Sbeck 
4f0d9efc0Sbeck    Written by Eric Youngdale (1993).
5f0d9efc0Sbeck 
6f0d9efc0Sbeck    Copyright 1993 Yggdrasil Computing, Incorporated
7f0d9efc0Sbeck 
8f0d9efc0Sbeck    This program is free software; you can redistribute it and/or modify
9f0d9efc0Sbeck    it under the terms of the GNU General Public License as published by
10f0d9efc0Sbeck    the Free Software Foundation; either version 2, or (at your option)
11f0d9efc0Sbeck    any later version.
12f0d9efc0Sbeck 
13f0d9efc0Sbeck    This program is distributed in the hope that it will be useful,
14f0d9efc0Sbeck    but WITHOUT ANY WARRANTY; without even the implied warranty of
15f0d9efc0Sbeck    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f0d9efc0Sbeck    GNU General Public License for more details.
17f0d9efc0Sbeck 
18f0d9efc0Sbeck    You should have received a copy of the GNU General Public License
19f0d9efc0Sbeck    along with this program; if not, write to the Free Software
20f0d9efc0Sbeck    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21f0d9efc0Sbeck 
22f0d9efc0Sbeck #include <stdlib.h>
23f0d9efc0Sbeck 
24f0d9efc0Sbeck #include "config.h"
25f0d9efc0Sbeck 
26f0d9efc0Sbeck #ifndef VMS
27f0d9efc0Sbeck #if defined(MAJOR_IN_SYSMACROS)
28f0d9efc0Sbeck #include <sys/sysmacros.h>
29f0d9efc0Sbeck #endif
30f0d9efc0Sbeck 
31f0d9efc0Sbeck #ifdef HAVE_UNISTD_H
32f0d9efc0Sbeck #include <unistd.h>
33f0d9efc0Sbeck #endif
34f0d9efc0Sbeck 
35f0d9efc0Sbeck #endif
36f0d9efc0Sbeck #if defined(MAJOR_IN_MKDEV)
37f0d9efc0Sbeck #include <sys/types.h>
38f0d9efc0Sbeck #include <sys/mkdev.h>
39f0d9efc0Sbeck #endif
40f0d9efc0Sbeck 
41f0d9efc0Sbeck #include "mkisofs.h"
42f0d9efc0Sbeck #include "iso9660.h"
43f0d9efc0Sbeck #include <string.h>
44f0d9efc0Sbeck 
45f0d9efc0Sbeck #ifdef	DOESNT_WORK
46f0d9efc0Sbeck 
47f0d9efc0Sbeck #ifdef NON_UNIXFS
48f0d9efc0Sbeck #define S_ISLNK(m)	(0)
49f0d9efc0Sbeck #else
50f0d9efc0Sbeck #ifndef S_ISLNK
51f0d9efc0Sbeck #define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
52f0d9efc0Sbeck #endif
53f0d9efc0Sbeck #endif
54f0d9efc0Sbeck 
55f0d9efc0Sbeck #else
56f0d9efc0Sbeck #include <statdefs.h>
57f0d9efc0Sbeck #endif
58f0d9efc0Sbeck 
59f0d9efc0Sbeck #define SU_VERSION 1
60f0d9efc0Sbeck 
61f0d9efc0Sbeck #define SL_ROOT    8
62f0d9efc0Sbeck #define SL_PARENT  4
63f0d9efc0Sbeck #define SL_CURRENT 2
64f0d9efc0Sbeck #define SL_CONTINUE 1
65f0d9efc0Sbeck 
66f0d9efc0Sbeck #define CE_SIZE 28
67f0d9efc0Sbeck #define CL_SIZE 12
68f0d9efc0Sbeck #define ER_SIZE 8
69f0d9efc0Sbeck #define NM_SIZE 5
70f0d9efc0Sbeck #define PL_SIZE 12
71f0d9efc0Sbeck #define PN_SIZE 20
72f0d9efc0Sbeck #define PX_SIZE 36
73f0d9efc0Sbeck #define RE_SIZE 4
74f0d9efc0Sbeck #define SL_SIZE 20
75f0d9efc0Sbeck #define ZZ_SIZE 15
76f0d9efc0Sbeck #ifdef APPLE_HYB
77f0d9efc0Sbeck #define AA_SIZE 14		/* size of Apple extension */
78f0d9efc0Sbeck #endif /* APPLE_HYB */
79f0d9efc0Sbeck #ifdef __QNX__
80f0d9efc0Sbeck #define TF_SIZE (5 + 4 * 7)
81f0d9efc0Sbeck #else
82f0d9efc0Sbeck #define TF_SIZE (5 + 3 * 7)
83f0d9efc0Sbeck #endif
84f0d9efc0Sbeck 
85f0d9efc0Sbeck /* If we need to store this number of bytes, make sure we
86f0d9efc0Sbeck    do not box ourselves in so that we do not have room for
87f0d9efc0Sbeck    a CE entry for the continuation record */
88f0d9efc0Sbeck 
89f0d9efc0Sbeck #define MAYBE_ADD_CE_ENTRY(BYTES) \
90f0d9efc0Sbeck     (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)
91f0d9efc0Sbeck 
92f0d9efc0Sbeck /*
93f0d9efc0Sbeck  * Buffer to build RR attributes
94f0d9efc0Sbeck  */
95f0d9efc0Sbeck 
96f0d9efc0Sbeck static unsigned char Rock[16384];
97f0d9efc0Sbeck static unsigned char symlink_buff[256];
98f0d9efc0Sbeck static int ipnt = 0;
99f0d9efc0Sbeck static int recstart = 0;
100f0d9efc0Sbeck static int currlen = 0;
101f0d9efc0Sbeck static int mainrec = 0;
102f0d9efc0Sbeck static int reclimit;
103f0d9efc0Sbeck 
104f0d9efc0Sbeck #ifdef APPLE_HYB
105f0d9efc0Sbeck /* if we are using the HFS name, we don't want the '/' character */
106f0d9efc0Sbeck static void
rstrncpy(char * t,char * f,int c)107f0d9efc0Sbeck rstrncpy(char *t, char *f, int c)
108f0d9efc0Sbeck {
109f0d9efc0Sbeck 	while (c-- && *f) {
110f0d9efc0Sbeck 	    switch (*f) {
111f0d9efc0Sbeck 		case '/':
112f0d9efc0Sbeck 		    *t = '_';
113f0d9efc0Sbeck 		    break;
114f0d9efc0Sbeck 		default:
115f0d9efc0Sbeck 		    *t = *f;
116f0d9efc0Sbeck 		    break;
117f0d9efc0Sbeck 	    }
118f0d9efc0Sbeck 	    t++; f++;
119f0d9efc0Sbeck 	}
120f0d9efc0Sbeck }
121f0d9efc0Sbeck #endif /* APPLE HYB */
122f0d9efc0Sbeck 
123f0d9efc0Sbeck static void add_CE_entry	__PR((void));
124f0d9efc0Sbeck 
add_CE_entry()125f0d9efc0Sbeck static void add_CE_entry(){
126f0d9efc0Sbeck           if(recstart)
127f0d9efc0Sbeck 	    set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart);
128f0d9efc0Sbeck 	  Rock[ipnt++] ='C';
129f0d9efc0Sbeck 	  Rock[ipnt++] ='E';
130f0d9efc0Sbeck 	  Rock[ipnt++] = CE_SIZE;
131f0d9efc0Sbeck 	  Rock[ipnt++] = SU_VERSION;
132f0d9efc0Sbeck 	  set_733((char*)Rock + ipnt, 0);
133f0d9efc0Sbeck 	  ipnt += 8;
134f0d9efc0Sbeck 	  set_733((char*)Rock + ipnt, 0);
135f0d9efc0Sbeck 	  ipnt += 8;
136f0d9efc0Sbeck 	  set_733((char*)Rock + ipnt, 0);
137f0d9efc0Sbeck 	  ipnt += 8;
138f0d9efc0Sbeck 	  recstart = ipnt;
139f0d9efc0Sbeck 	  currlen = 0;
140f0d9efc0Sbeck 	  if(!mainrec) mainrec = ipnt;
141f0d9efc0Sbeck 	  reclimit = SECTOR_SIZE - 8; /* Limit to one sector */
142f0d9efc0Sbeck }
143f0d9efc0Sbeck 
144f0d9efc0Sbeck #ifdef __STDC__
generate_rock_ridge_attributes(char * whole_name,char * name,struct directory_entry * s_entry,struct stat * statbuf,struct stat * lstatbuf,int deep_opt)145f0d9efc0Sbeck int generate_rock_ridge_attributes (char * whole_name, char * name,
146f0d9efc0Sbeck 				    struct directory_entry * s_entry,
147f0d9efc0Sbeck 				    struct stat * statbuf,
148f0d9efc0Sbeck 				    struct stat * lstatbuf,
149f0d9efc0Sbeck 				    int deep_opt)
150f0d9efc0Sbeck #else
151f0d9efc0Sbeck int generate_rock_ridge_attributes (whole_name, name,
152f0d9efc0Sbeck 				    s_entry,
153f0d9efc0Sbeck 				    statbuf,
154f0d9efc0Sbeck 				    lstatbuf,
155f0d9efc0Sbeck 				    deep_opt)
156f0d9efc0Sbeck char * whole_name; char * name; struct directory_entry * s_entry;
157f0d9efc0Sbeck struct stat * statbuf, *lstatbuf;
158f0d9efc0Sbeck int deep_opt;
159f0d9efc0Sbeck #endif
160f0d9efc0Sbeck {
161f0d9efc0Sbeck   int flagpos, flagval;
162f0d9efc0Sbeck   int need_ce;
163f0d9efc0Sbeck 
164f0d9efc0Sbeck   statbuf = statbuf;        /* this shuts up unreferenced compiler warnings */
165f0d9efc0Sbeck   mainrec = recstart = ipnt = 0;
166f0d9efc0Sbeck   reclimit = 0xf8;
167f0d9efc0Sbeck 
168f0d9efc0Sbeck   /* no need to fill in the RR stuff if we won't see the file */
169f0d9efc0Sbeck   if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
170f0d9efc0Sbeck     return 0;
171f0d9efc0Sbeck 
172f0d9efc0Sbeck   /* Obtain the amount of space that is currently used for the directory
173f0d9efc0Sbeck      record.  Assume max for name, since name conflicts may cause us
174f0d9efc0Sbeck      to rename the file later on */
175f0d9efc0Sbeck   currlen = sizeof(s_entry->isorec);
176f0d9efc0Sbeck 
177f0d9efc0Sbeck #ifdef APPLE_HYB
178f0d9efc0Sbeck   /* if we have regular file, then add Apple extensions */
179f0d9efc0Sbeck   if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) {
180f0d9efc0Sbeck     Rock[ipnt++] ='A';		/* AppleSignature */
181f0d9efc0Sbeck     Rock[ipnt++] ='A';
182f0d9efc0Sbeck     Rock[ipnt++] = AA_SIZE;	/* includes AppleSignature bytes */
183f0d9efc0Sbeck     Rock[ipnt++] = 0x02;	/* SystemUseID */
184f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->type[0];
185f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->type[1];
186f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->type[2];
187f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->type[3];
188f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->creator[0];
189f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->creator[1];
190f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->creator[2];
191f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->creator[3];
192f0d9efc0Sbeck     Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff;
193f0d9efc0Sbeck     Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff;
194f0d9efc0Sbeck   }
195f0d9efc0Sbeck #endif /* APPLE_HYB */
196f0d9efc0Sbeck 
197f0d9efc0Sbeck   /* Identify that we are using the SUSP protocol */
198f0d9efc0Sbeck   if(deep_opt & NEED_SP){
199f0d9efc0Sbeck 	  Rock[ipnt++] ='S';
200f0d9efc0Sbeck 	  Rock[ipnt++] ='P';
201f0d9efc0Sbeck 	  Rock[ipnt++] = 7;
202f0d9efc0Sbeck 	  Rock[ipnt++] = SU_VERSION;
203f0d9efc0Sbeck 	  Rock[ipnt++] = 0xbe;
204f0d9efc0Sbeck 	  Rock[ipnt++] = 0xef;
205f0d9efc0Sbeck 	  Rock[ipnt++] = 0;
206f0d9efc0Sbeck   };
207f0d9efc0Sbeck 
208f0d9efc0Sbeck   /* First build the posix name field */
209f0d9efc0Sbeck   Rock[ipnt++] ='R';
210f0d9efc0Sbeck   Rock[ipnt++] ='R';
211f0d9efc0Sbeck   Rock[ipnt++] = 5;
212f0d9efc0Sbeck   Rock[ipnt++] = SU_VERSION;
213f0d9efc0Sbeck   flagpos = ipnt;
214f0d9efc0Sbeck   flagval = 0;
215f0d9efc0Sbeck   Rock[ipnt++] = 0;   /* We go back and fix this later */
216f0d9efc0Sbeck 
217f0d9efc0Sbeck   if(strcmp(name,".")  && strcmp(name,"..")){
218f0d9efc0Sbeck     char * npnt;
219f0d9efc0Sbeck     int remain, use;
220f0d9efc0Sbeck 
221f0d9efc0Sbeck #ifdef APPLE_HYB
222f0d9efc0Sbeck     /* use the HFS name if it exists */
223f0d9efc0Sbeck     if (USE_MAC_NAME(mac_name, s_entry)) {
224f0d9efc0Sbeck 	remain = strlen(s_entry->hfs_ent->name);
225f0d9efc0Sbeck 	npnt = s_entry->hfs_ent->name;
226f0d9efc0Sbeck     }
227f0d9efc0Sbeck     else {
228f0d9efc0Sbeck #endif
229f0d9efc0Sbeck 
230f0d9efc0Sbeck 	remain = strlen(name);
231f0d9efc0Sbeck 	npnt = name;
232f0d9efc0Sbeck #ifdef APPLE_HYB
233f0d9efc0Sbeck     }
234f0d9efc0Sbeck #endif /* APPLE_HYB */
235f0d9efc0Sbeck 
236f0d9efc0Sbeck     while(remain){
237f0d9efc0Sbeck           use = remain;
238f0d9efc0Sbeck 	  need_ce = 0;
239f0d9efc0Sbeck 	  /* Can we fit this SUSP and a CE entry? */
240f0d9efc0Sbeck 	  if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
241f0d9efc0Sbeck 	    use = reclimit - currlen - CE_SIZE - (ipnt - recstart);
242f0d9efc0Sbeck 	    need_ce++;
243f0d9efc0Sbeck 	  }
244f0d9efc0Sbeck 
245f0d9efc0Sbeck 	  /* Only room for 256 per SUSP field */
246f0d9efc0Sbeck 	  if(use > 0xf8) use = 0xf8;
247f0d9efc0Sbeck 
248f0d9efc0Sbeck 	  /* First build the posix name field */
249f0d9efc0Sbeck 	  Rock[ipnt++] ='N';
250f0d9efc0Sbeck 	  Rock[ipnt++] ='M';
251f0d9efc0Sbeck 	  Rock[ipnt++] = NM_SIZE + use;
252f0d9efc0Sbeck 	  Rock[ipnt++] = SU_VERSION;
253f0d9efc0Sbeck 	  Rock[ipnt++] = (remain != use ? 1 : 0);
254f0d9efc0Sbeck 	  flagval |= (1<<3);
255f0d9efc0Sbeck #ifdef APPLE_HYB
256f0d9efc0Sbeck 	  /* filter out any '/' character in HFS filename */
257f0d9efc0Sbeck 	  if (USE_MAC_NAME(mac_name, s_entry))
258f0d9efc0Sbeck 	    rstrncpy((char *)&Rock[ipnt], npnt, use);
259f0d9efc0Sbeck 	  else
260f0d9efc0Sbeck #endif /* APPLE_HYB */
261f0d9efc0Sbeck 	    strncpy((char *)&Rock[ipnt], npnt, use);
262f0d9efc0Sbeck 	  npnt += use;
263f0d9efc0Sbeck 	  ipnt += use;
264f0d9efc0Sbeck 	  remain -= use;
265f0d9efc0Sbeck 	  if(remain && need_ce) add_CE_entry();
266f0d9efc0Sbeck 	};
267f0d9efc0Sbeck   };
268f0d9efc0Sbeck 
269f0d9efc0Sbeck   /*
270f0d9efc0Sbeck    * Add the posix modes
271f0d9efc0Sbeck    */
272f0d9efc0Sbeck   if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry();
273f0d9efc0Sbeck   Rock[ipnt++] ='P';
274f0d9efc0Sbeck   Rock[ipnt++] ='X';
275f0d9efc0Sbeck   Rock[ipnt++] = PX_SIZE;
276f0d9efc0Sbeck   Rock[ipnt++] = SU_VERSION;
277f0d9efc0Sbeck   flagval |= (1<<0);
278f0d9efc0Sbeck   set_733((char*)Rock + ipnt, lstatbuf->st_mode);
279f0d9efc0Sbeck   ipnt += 8;
280f0d9efc0Sbeck   set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
281f0d9efc0Sbeck   ipnt += 8;
282f0d9efc0Sbeck   set_733((char*)Rock + ipnt, lstatbuf->st_uid);
283f0d9efc0Sbeck   ipnt += 8;
284f0d9efc0Sbeck   set_733((char*)Rock + ipnt, lstatbuf->st_gid);
285f0d9efc0Sbeck   ipnt += 8;
286f0d9efc0Sbeck 
287f0d9efc0Sbeck   /*
288f0d9efc0Sbeck    * Check for special devices
289f0d9efc0Sbeck    */
290f0d9efc0Sbeck #ifndef NON_UNIXFS
291f0d9efc0Sbeck   if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
292f0d9efc0Sbeck     if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry();
293f0d9efc0Sbeck     Rock[ipnt++] ='P';
294f0d9efc0Sbeck     Rock[ipnt++] ='N';
295f0d9efc0Sbeck     Rock[ipnt++] = PN_SIZE;
296f0d9efc0Sbeck     Rock[ipnt++] = SU_VERSION;
297f0d9efc0Sbeck     flagval |= (1<<1);
298f0d9efc0Sbeck #if defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)
299f0d9efc0Sbeck     set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev ));
300f0d9efc0Sbeck     ipnt += 8;
301f0d9efc0Sbeck     set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
302f0d9efc0Sbeck     ipnt += 8;
303f0d9efc0Sbeck #else
304f0d9efc0Sbeck     /*
305f0d9efc0Sbeck      * If we don't have sysmacros.h, then we have to guess as to how
306f0d9efc0Sbeck      * best to pick apart the device number for major/minor.
307f0d9efc0Sbeck      * Note: this may very well be wrong for many systems, so
308f0d9efc0Sbeck      * it is always best to use the major/minor macros if the
309f0d9efc0Sbeck      * system supports it.
310f0d9efc0Sbeck      */
311f0d9efc0Sbeck     if(sizeof(dev_t) <= 2) {
312f0d9efc0Sbeck         set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8));
313f0d9efc0Sbeck         ipnt += 8;
314f0d9efc0Sbeck         set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff);
315f0d9efc0Sbeck         ipnt += 8;
316f0d9efc0Sbeck     }
317f0d9efc0Sbeck     else if(sizeof(dev_t) <= 4) {
318f0d9efc0Sbeck         set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8);
319f0d9efc0Sbeck         ipnt += 8;
320f0d9efc0Sbeck         set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff);
321f0d9efc0Sbeck         ipnt += 8;
322f0d9efc0Sbeck     }
323f0d9efc0Sbeck     else {
324f0d9efc0Sbeck         set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
325f0d9efc0Sbeck         ipnt += 8;
326f0d9efc0Sbeck         set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
327f0d9efc0Sbeck         ipnt += 8;
328f0d9efc0Sbeck     }
329f0d9efc0Sbeck #endif
330f0d9efc0Sbeck   };
331f0d9efc0Sbeck #endif
332f0d9efc0Sbeck   /*
333f0d9efc0Sbeck    * Check for and symbolic links.  VMS does not have these.
334f0d9efc0Sbeck    */
335f0d9efc0Sbeck   if (S_ISLNK(lstatbuf->st_mode)){
336f0d9efc0Sbeck     int lenpos, lenval, j0, j1;
337f0d9efc0Sbeck     int nchar;
338f0d9efc0Sbeck     unsigned char * cpnt, *cpnt1;
339*0a84d892Svincent     nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)-1);
340f0d9efc0Sbeck     symlink_buff[nchar < 0 ? 0 : nchar] = 0;
341f0d9efc0Sbeck     nchar = strlen((char *) symlink_buff);
342f0d9efc0Sbeck     set_733(s_entry->isorec.size, 0);
343f0d9efc0Sbeck     cpnt = &symlink_buff[0];
344f0d9efc0Sbeck     flagval |= (1<<2);
345f0d9efc0Sbeck 
346f0d9efc0Sbeck     if (! split_SL_field)
347f0d9efc0Sbeck       {
348f0d9efc0Sbeck 	int sl_bytes = 0;
349f0d9efc0Sbeck 	for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++)
350f0d9efc0Sbeck 	  {
351f0d9efc0Sbeck 	    if (*cpnt1 == '/')
352f0d9efc0Sbeck 	      {
353f0d9efc0Sbeck 		sl_bytes += 4;
354f0d9efc0Sbeck 	      }
355f0d9efc0Sbeck 	    else
356f0d9efc0Sbeck 	      {
357f0d9efc0Sbeck 		sl_bytes += 1;
358f0d9efc0Sbeck 	      }
359f0d9efc0Sbeck 	  }
360f0d9efc0Sbeck 	if (sl_bytes > 250)
361f0d9efc0Sbeck 	  {
362f0d9efc0Sbeck 	    /*
363f0d9efc0Sbeck 	     * the symbolic link won't fit into one SL System Use Field
364f0d9efc0Sbeck 	     * print an error message and continue with splited one
365f0d9efc0Sbeck 	     */
366f0d9efc0Sbeck 	    fprintf(stderr,"symbolic link ``%s'' to long for one SL System Use Field, splitting", cpnt);
367f0d9efc0Sbeck 	  }
368f0d9efc0Sbeck        if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry();
369f0d9efc0Sbeck      }
370f0d9efc0Sbeck 
371f0d9efc0Sbeck     while(nchar){
372f0d9efc0Sbeck       if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
373f0d9efc0Sbeck       Rock[ipnt++] ='S';
374f0d9efc0Sbeck       Rock[ipnt++] ='L';
375f0d9efc0Sbeck       lenpos = ipnt;
376f0d9efc0Sbeck       Rock[ipnt++] = SL_SIZE;
377f0d9efc0Sbeck       Rock[ipnt++] = SU_VERSION;
378f0d9efc0Sbeck       Rock[ipnt++] = 0; /* Flags */
379f0d9efc0Sbeck       lenval = 5;
380f0d9efc0Sbeck       while(*cpnt){
381f0d9efc0Sbeck 	cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
382f0d9efc0Sbeck 	if(cpnt1) {
383f0d9efc0Sbeck 	  nchar--;
384f0d9efc0Sbeck 	  *cpnt1 = 0;
385f0d9efc0Sbeck 	};
386f0d9efc0Sbeck 
387f0d9efc0Sbeck 	/* We treat certain components in a special way.  */
388f0d9efc0Sbeck 	if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
389f0d9efc0Sbeck 	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
390f0d9efc0Sbeck 	  Rock[ipnt++] = SL_PARENT;
391f0d9efc0Sbeck 	  Rock[ipnt++] = 0;  /* length is zero */
392f0d9efc0Sbeck 	  lenval += 2;
393f0d9efc0Sbeck 	  nchar -= 2;
394f0d9efc0Sbeck 	} else if(cpnt[0] == '.' && cpnt[1] == 0){
395f0d9efc0Sbeck 	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
396f0d9efc0Sbeck 	  Rock[ipnt++] = SL_CURRENT;
397f0d9efc0Sbeck 	  Rock[ipnt++] = 0;  /* length is zero */
398f0d9efc0Sbeck 	  lenval += 2;
399f0d9efc0Sbeck 	  nchar -= 1;
400f0d9efc0Sbeck 	} else if(cpnt[0] == 0){
401f0d9efc0Sbeck 	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
402f0d9efc0Sbeck 	  Rock[ipnt++] = SL_ROOT;
403f0d9efc0Sbeck 	  Rock[ipnt++] = 0;  /* length is zero */
404f0d9efc0Sbeck 	  lenval += 2;
405f0d9efc0Sbeck 	} else {
406f0d9efc0Sbeck 	  /* If we do not have enough room for a component, start
407f0d9efc0Sbeck 	     a new continuations segment now */
408f0d9efc0Sbeck          if(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) :
409f0d9efc0Sbeck                                  MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt)))
410f0d9efc0Sbeck 	   {
411f0d9efc0Sbeck 	     add_CE_entry();
412f0d9efc0Sbeck 	     if(cpnt1)
413f0d9efc0Sbeck 	       {
414f0d9efc0Sbeck 		 *cpnt1 = '/';
415f0d9efc0Sbeck 		 nchar++;
416f0d9efc0Sbeck 		 cpnt1 = NULL; /* A kluge so that we can restart properly */
417f0d9efc0Sbeck 	       }
418f0d9efc0Sbeck 	     break;
419f0d9efc0Sbeck 	   }
420f0d9efc0Sbeck 	  j0 = strlen((char *) cpnt);
421f0d9efc0Sbeck 	  while(j0) {
422f0d9efc0Sbeck 	    j1 = j0;
423f0d9efc0Sbeck 	    if(j1 > 0xf8) j1 = 0xf8;
424f0d9efc0Sbeck 	    need_ce = 0;
425f0d9efc0Sbeck 	    if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
426f0d9efc0Sbeck 	      j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
427f0d9efc0Sbeck 	      need_ce++;
428f0d9efc0Sbeck 	    }
429f0d9efc0Sbeck 	    Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
430f0d9efc0Sbeck 	    Rock[ipnt++] = j1;
431f0d9efc0Sbeck 	    strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
432f0d9efc0Sbeck 	    ipnt += j1;
433f0d9efc0Sbeck 	    lenval += j1 + 2;
434f0d9efc0Sbeck 	    cpnt += j1;
435f0d9efc0Sbeck 	    nchar -= j1;  /* Number we processed this time */
436f0d9efc0Sbeck 	    j0 -= j1;
437f0d9efc0Sbeck 	    if(need_ce) {
438f0d9efc0Sbeck 	      add_CE_entry();
439f0d9efc0Sbeck 	      if(cpnt1) {
440f0d9efc0Sbeck 		*cpnt1 = '/';
441f0d9efc0Sbeck                 nchar++;
442f0d9efc0Sbeck 		cpnt1 = NULL; /* A kluge so that we can restart properly */
443f0d9efc0Sbeck 	      }
444f0d9efc0Sbeck 	      break;
445f0d9efc0Sbeck 	    }
446f0d9efc0Sbeck 	  }
447f0d9efc0Sbeck 	};
448f0d9efc0Sbeck 	if(cpnt1) {
449f0d9efc0Sbeck 	  cpnt = cpnt1 + 1;
450f0d9efc0Sbeck 	} else
451f0d9efc0Sbeck 	  break;
452f0d9efc0Sbeck       }
453f0d9efc0Sbeck       Rock[lenpos] = lenval;
454f0d9efc0Sbeck       if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
455f0d9efc0Sbeck     } /* while nchar */
456f0d9efc0Sbeck   } /* Is a symbolic link */
457f0d9efc0Sbeck   /*
458f0d9efc0Sbeck    * Add in the Rock Ridge TF time field
459f0d9efc0Sbeck    */
460f0d9efc0Sbeck   if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
461f0d9efc0Sbeck   Rock[ipnt++] ='T';
462f0d9efc0Sbeck   Rock[ipnt++] ='F';
463f0d9efc0Sbeck   Rock[ipnt++] = TF_SIZE;
464f0d9efc0Sbeck   Rock[ipnt++] = SU_VERSION;
465f0d9efc0Sbeck #ifdef __QNX__
466f0d9efc0Sbeck   Rock[ipnt++] = 0x0f;
467f0d9efc0Sbeck #else
468f0d9efc0Sbeck   Rock[ipnt++] = 0x0e;
469f0d9efc0Sbeck #endif
470f0d9efc0Sbeck   flagval |= (1<<7);
471f0d9efc0Sbeck #ifdef __QNX__
472f0d9efc0Sbeck   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
473f0d9efc0Sbeck   ipnt += 7;
474f0d9efc0Sbeck #endif
475f0d9efc0Sbeck   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
476f0d9efc0Sbeck   ipnt += 7;
477f0d9efc0Sbeck   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
478f0d9efc0Sbeck   ipnt += 7;
479f0d9efc0Sbeck   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
480f0d9efc0Sbeck   ipnt += 7;
481f0d9efc0Sbeck 
482f0d9efc0Sbeck   /*
483f0d9efc0Sbeck    * Add in the Rock Ridge RE time field
484f0d9efc0Sbeck    */
485f0d9efc0Sbeck   if(deep_opt & NEED_RE){
486f0d9efc0Sbeck           if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
487f0d9efc0Sbeck 	  Rock[ipnt++] ='R';
488f0d9efc0Sbeck 	  Rock[ipnt++] ='E';
489f0d9efc0Sbeck 	  Rock[ipnt++] = RE_SIZE;
490f0d9efc0Sbeck 	  Rock[ipnt++] = SU_VERSION;
491f0d9efc0Sbeck 	  flagval |= (1<<6);
492f0d9efc0Sbeck   };
493f0d9efc0Sbeck   /*
494f0d9efc0Sbeck    * Add in the Rock Ridge PL record, if required.
495f0d9efc0Sbeck    */
496f0d9efc0Sbeck   if(deep_opt & NEED_PL){
497f0d9efc0Sbeck           if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
498f0d9efc0Sbeck 	  Rock[ipnt++] ='P';
499f0d9efc0Sbeck 	  Rock[ipnt++] ='L';
500f0d9efc0Sbeck 	  Rock[ipnt++] = PL_SIZE;
501f0d9efc0Sbeck 	  Rock[ipnt++] = SU_VERSION;
502f0d9efc0Sbeck 	  set_733((char*)Rock + ipnt, 0);
503f0d9efc0Sbeck 	  ipnt += 8;
504f0d9efc0Sbeck 	  flagval |= (1<<5);
505f0d9efc0Sbeck   };
506f0d9efc0Sbeck 
507f0d9efc0Sbeck   /*
508f0d9efc0Sbeck    * Add in the Rock Ridge CL field, if required.
509f0d9efc0Sbeck    */
510f0d9efc0Sbeck   if(deep_opt & NEED_CL){
511f0d9efc0Sbeck           if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry();
512f0d9efc0Sbeck 	  Rock[ipnt++] ='C';
513f0d9efc0Sbeck 	  Rock[ipnt++] ='L';
514f0d9efc0Sbeck 	  Rock[ipnt++] = CL_SIZE;
515f0d9efc0Sbeck 	  Rock[ipnt++] = SU_VERSION;
516f0d9efc0Sbeck 	  set_733((char*)Rock + ipnt, 0);
517f0d9efc0Sbeck 	  ipnt += 8;
518f0d9efc0Sbeck 	  flagval |= (1<<4);
519f0d9efc0Sbeck   };
520f0d9efc0Sbeck 
521f0d9efc0Sbeck #ifndef VMS
522f0d9efc0Sbeck   /* If transparent compression was requested, fill in the correct
523f0d9efc0Sbeck      field for this file */
524f0d9efc0Sbeck   if(transparent_compression &&
525f0d9efc0Sbeck      S_ISREG(lstatbuf->st_mode) &&
526f0d9efc0Sbeck      strlen(name) > 3 &&
527f0d9efc0Sbeck      strcmp(name + strlen(name) - 3,".gZ") == 0){
528f0d9efc0Sbeck     FILE * zipfile;
529f0d9efc0Sbeck     char * checkname;
530f0d9efc0Sbeck     unsigned int file_size;
531f0d9efc0Sbeck     unsigned char header[8];
532f0d9efc0Sbeck     int OK_flag;
533f0d9efc0Sbeck 
534f0d9efc0Sbeck     /* First open file and verify that the correct algorithm was used */
535f0d9efc0Sbeck     file_size = 0;
536f0d9efc0Sbeck     OK_flag = 1;
537f0d9efc0Sbeck 
538f0d9efc0Sbeck     zipfile = fopen(whole_name, "rb");
539f0d9efc0Sbeck     fread(header, 1, sizeof(header), zipfile);
540f0d9efc0Sbeck 
541f0d9efc0Sbeck     /* Check some magic numbers from gzip. */
542f0d9efc0Sbeck     if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0;
543f0d9efc0Sbeck     /* Make sure file was blocksized. */
544f0d9efc0Sbeck     if(((header[3] & 0x40) == 0)) OK_flag = 0;
545f0d9efc0Sbeck     /* OK, now go to the end of the file and get some more info */
546f0d9efc0Sbeck     if(OK_flag){
547f0d9efc0Sbeck       int status;
548f0d9efc0Sbeck       status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END);
549f0d9efc0Sbeck       if(status == -1) OK_flag = 0;
550f0d9efc0Sbeck     }
551f0d9efc0Sbeck     if(OK_flag){
552f0d9efc0Sbeck       if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header))
553f0d9efc0Sbeck 	OK_flag = 0;
554f0d9efc0Sbeck       else {
555f0d9efc0Sbeck 	int blocksize;
556f0d9efc0Sbeck 	blocksize = (header[3] << 8) | header[2];
557f0d9efc0Sbeck 	file_size = ((unsigned int)header[7] << 24) |
558f0d9efc0Sbeck 		    ((unsigned int)header[6] << 16) |
559f0d9efc0Sbeck 		    ((unsigned int)header[5] << 8)  | header[4];
560f0d9efc0Sbeck #if 0
561f0d9efc0Sbeck 	fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size);
562f0d9efc0Sbeck #endif
563f0d9efc0Sbeck 	if(blocksize != SECTOR_SIZE) OK_flag = 0;
564f0d9efc0Sbeck       }
565f0d9efc0Sbeck     }
566f0d9efc0Sbeck     fclose(zipfile);
567f0d9efc0Sbeck 
568f0d9efc0Sbeck     checkname = strdup(whole_name);
569f0d9efc0Sbeck     checkname[strlen(whole_name)-3] = 0;
570f0d9efc0Sbeck     zipfile = fopen(checkname, "rb");
571f0d9efc0Sbeck     if(zipfile) {
572f0d9efc0Sbeck       OK_flag = 0;
573f0d9efc0Sbeck       fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n");
574f0d9efc0Sbeck       fclose(zipfile);
575f0d9efc0Sbeck     }
576f0d9efc0Sbeck 
577f0d9efc0Sbeck     free(checkname);
578f0d9efc0Sbeck 
579f0d9efc0Sbeck     if(OK_flag){
580f0d9efc0Sbeck       if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry();
581f0d9efc0Sbeck       Rock[ipnt++] ='Z';
582f0d9efc0Sbeck       Rock[ipnt++] ='Z';
583f0d9efc0Sbeck       Rock[ipnt++] = ZZ_SIZE;
584f0d9efc0Sbeck       Rock[ipnt++] = SU_VERSION;
585f0d9efc0Sbeck       Rock[ipnt++] = 'g'; /* Identify compression technique used */
586f0d9efc0Sbeck       Rock[ipnt++] = 'z';
587f0d9efc0Sbeck       Rock[ipnt++] = 3;
588f0d9efc0Sbeck       set_733((char*)Rock + ipnt, file_size); /* Real file size */
589f0d9efc0Sbeck       ipnt += 8;
590f0d9efc0Sbeck     };
591f0d9efc0Sbeck   }
592f0d9efc0Sbeck #endif
593f0d9efc0Sbeck   /*
594f0d9efc0Sbeck    * Add in the Rock Ridge CE field, if required.  We use  this for the
595f0d9efc0Sbeck    * extension record that is stored in the root directory.
596f0d9efc0Sbeck    */
597f0d9efc0Sbeck   if(deep_opt & NEED_CE) add_CE_entry();
598f0d9efc0Sbeck   /*
599f0d9efc0Sbeck    * Done filling in all of the fields.  Now copy it back to a buffer for the
600f0d9efc0Sbeck    * file in question.
601f0d9efc0Sbeck    */
602f0d9efc0Sbeck 
603f0d9efc0Sbeck   /* Now copy this back to the buffer for the file */
604f0d9efc0Sbeck   Rock[flagpos] = flagval;
605f0d9efc0Sbeck 
606f0d9efc0Sbeck   /* If there was a CE, fill in the size field */
607f0d9efc0Sbeck   if(recstart)
608f0d9efc0Sbeck     set_733((char*)Rock + recstart - 8, ipnt - recstart);
609f0d9efc0Sbeck 
610f0d9efc0Sbeck   s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt);
611f0d9efc0Sbeck   s_entry->total_rr_attr_size = ipnt;
612f0d9efc0Sbeck   s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
613f0d9efc0Sbeck   memcpy(s_entry->rr_attributes, Rock, ipnt);
614f0d9efc0Sbeck   return ipnt;
615f0d9efc0Sbeck }
616f0d9efc0Sbeck 
617f0d9efc0Sbeck /* Guaranteed to  return a single sector with the relevant info */
618f0d9efc0Sbeck 
FDECL4(generate_rr_extension_record,char *,id,char *,descriptor,char *,source,int *,size)619f0d9efc0Sbeck char * FDECL4(generate_rr_extension_record, char *, id,  char  *, descriptor,
620f0d9efc0Sbeck 				    char *, source, int  *, size){
621f0d9efc0Sbeck   int lipnt = 0;
622f0d9efc0Sbeck   char * pnt;
623f0d9efc0Sbeck   int len_id, len_des, len_src;
624f0d9efc0Sbeck 
625f0d9efc0Sbeck   len_id = strlen(id);
626f0d9efc0Sbeck   len_des =  strlen(descriptor);
627f0d9efc0Sbeck   len_src = strlen(source);
628f0d9efc0Sbeck   Rock[lipnt++] ='E';
629f0d9efc0Sbeck   Rock[lipnt++] ='R';
630f0d9efc0Sbeck   Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src;
631f0d9efc0Sbeck   Rock[lipnt++] = 1;
632f0d9efc0Sbeck   Rock[lipnt++] = len_id;
633f0d9efc0Sbeck   Rock[lipnt++] = len_des;
634f0d9efc0Sbeck   Rock[lipnt++] = len_src;
635f0d9efc0Sbeck   Rock[lipnt++] = 1;
636f0d9efc0Sbeck 
637f0d9efc0Sbeck   memcpy(Rock  + lipnt, id, len_id);
638f0d9efc0Sbeck   lipnt += len_id;
639f0d9efc0Sbeck 
640f0d9efc0Sbeck   memcpy(Rock  + lipnt, descriptor, len_des);
641f0d9efc0Sbeck   lipnt += len_des;
642f0d9efc0Sbeck 
643f0d9efc0Sbeck   memcpy(Rock  + lipnt, source, len_src);
644f0d9efc0Sbeck   lipnt += len_src;
645f0d9efc0Sbeck 
646f0d9efc0Sbeck   if(lipnt  > SECTOR_SIZE) {
647f0d9efc0Sbeck 	  fprintf(stderr,"Extension record too  long\n");
648f0d9efc0Sbeck 	  exit(1);
649f0d9efc0Sbeck   };
650f0d9efc0Sbeck   pnt = (char *) e_malloc(SECTOR_SIZE);
651f0d9efc0Sbeck   memset(pnt, 0,  SECTOR_SIZE);
652f0d9efc0Sbeck   memcpy(pnt, Rock, lipnt);
653f0d9efc0Sbeck   *size = lipnt;
654f0d9efc0Sbeck   return pnt;
655f0d9efc0Sbeck }
656