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