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