1.1.1
by Eduard Bloch
Import upstream version 1.1.0 |
1 |
/*
|
2 |
* This file has been modified for the cdrkit suite.
|
|
3 |
*
|
|
4 |
* The behaviour and appearence of the program code below can differ to a major
|
|
5 |
* extent from the version distributed by the original author(s).
|
|
6 |
*
|
|
7 |
* For details, see Changelog file distributed with the cdrkit package. If you
|
|
8 |
* received this file from another source then ask the distributing person for
|
|
9 |
* a log of modifications.
|
|
10 |
*
|
|
11 |
*/
|
|
12 |
||
13 |
/* @(#)rock.c 1.43 05/05/01 joerg */
|
|
14 |
/*
|
|
15 |
* File rock.c - generate RRIP records for iso9660 filesystems.
|
|
16 |
*
|
|
17 |
* Written by Eric Youngdale (1993).
|
|
18 |
*
|
|
19 |
* Copyright 1993 Yggdrasil Computing, Incorporated
|
|
20 |
* Copyright (c) 1999,2000-2003 J. Schilling
|
|
21 |
*
|
|
22 |
* This program is free software; you can redistribute it and/or modify
|
|
23 |
* it under the terms of the GNU General Public License as published by
|
|
24 |
* the Free Software Foundation; either version 2, or (at your option)
|
|
25 |
* any later version.
|
|
26 |
*
|
|
27 |
* This program is distributed in the hope that it will be useful,
|
|
28 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
29 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
30 |
* GNU General Public License for more details.
|
|
31 |
*
|
|
32 |
* You should have received a copy of the GNU General Public License
|
|
33 |
* along with this program; if not, write to the Free Software
|
|
34 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
35 |
*/
|
|
36 |
||
37 |
#include <mconfig.h> |
|
38 |
#include "genisoimage.h" |
|
39 |
#include <device.h> |
|
40 |
#include <schily.h> |
|
41 |
||
42 |
#define SU_VERSION 1
|
|
43 |
||
44 |
#define SL_ROOT 8
|
|
45 |
#define SL_PARENT 4
|
|
46 |
#define SL_CURRENT 2
|
|
47 |
#define SL_CONTINUE 1
|
|
48 |
||
49 |
#define CE_SIZE 28 /* SUSP Continuation aerea */ |
|
50 |
#define CL_SIZE 12 /* RR Child Link for deep dir relocation */ |
|
51 |
#define ER_SIZE 8 /* RR Extension record for RR signature */ |
|
52 |
#define NM_SIZE 5 /* RR Real name */ |
|
53 |
#define PL_SIZE 12 /* RR Paren Link for deep dir relocation */ |
|
54 |
#define PN_SIZE 20 /* RR POSIX device modes (Major/Minor) */ |
|
55 |
#define PX_SIZE 36 /* RR POSIX Extensions (mode/nlink(uid/gid) */ |
|
56 |
#define RE_SIZE 4 /* RR Relocated directory */ |
|
57 |
#define RR_SIZE 5 /* RR RR Signature in every file */ |
|
58 |
#define SL_SIZE 20 /* RR Symlink */ |
|
59 |
#define ZF_SIZE 16 /* RR* Linux compression extension */ |
|
60 |
#ifdef APPLE_HYB
|
|
61 |
#define AA_SIZE 14 /* size of Apple extension */ |
|
62 |
#endif /* APPLE_HYB */ |
|
63 |
#if defined(__QNX__) && !defined(__QNXNTO__) /* Not on Neutrino! never OK? */ |
|
64 |
#define TF_SIZE (5 + 4 * 7) /* RR Time field */ |
|
65 |
#else
|
|
66 |
#define TF_SIZE (5 + 3 * 7)
|
|
67 |
#endif
|
|
68 |
||
69 |
static void rstrncpy(char *t, char *f, int c, |
|
70 |
struct unls_table *inls, |
|
71 |
struct unls_table *onls); |
|
72 |
static void add_CE_entry(char *field, int line); |
|
73 |
static int gen_xa_attr(mode_t attr); |
|
74 |
static void gen_xa(struct stat *lstatbuf); |
|
75 |
int generate_xa_rr_attributes(char *whole_name, char *name, |
|
76 |
struct directory_entry *s_entry, |
|
77 |
struct stat *statbuf, |
|
78 |
struct stat *lstatbuf, |
|
79 |
int deep_opt); |
|
80 |
char *generate_rr_extension_record(char *id, char *descriptor, char *source, |
|
81 |
int *size); |
|
82 |
/*
|
|
83 |
* If we need to store this number of bytes, make sure we
|
|
84 |
* do not box ourselves in so that we do not have room for
|
|
85 |
* a CE entry for the continuation record
|
|
86 |
*/
|
|
87 |
#define RR_CUR_USE (CE_SIZE + currlen + (ipnt - recstart))
|
|
88 |
||
89 |
#define MAYBE_ADD_CE_ENTRY(BYTES) \
|
|
90 |
(((int)(BYTES)) + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)
|
|
91 |
||
92 |
/*
|
|
93 |
* Buffer to build RR attributes
|
|
94 |
*/
|
|
95 |
static Uchar Rock[16384]; |
|
96 |
static Uchar symlink_buff[PATH_MAX+1]; |
|
97 |
static int ipnt = 0; /* Current "write" offset in Rock[] */ |
|
98 |
static int recstart = 0; /* Start offset in Rock[] for this area */ |
|
99 |
static int currlen = 0; /* # of non RR bytes used in this area */ |
|
100 |
static int mainrec = 0; /* # of RR bytes use in main dir area */ |
|
101 |
static int reclimit; /* Max. # of bytes usable in this area */ |
|
102 |
||
103 |
/* if we are using converted filenames, we don't want the '/' character */
|
|
104 |
static void |
|
105 |
rstrncpy(char *t, char *f, int c, struct unls_table *inls, |
|
106 |
struct unls_table *onls) |
|
107 |
{
|
|
108 |
while (c-- && *f) { |
|
109 |
*t = conv_charset(*f, inls, onls); |
|
110 |
if (*t == '/') { |
|
111 |
*t = '_'; |
|
112 |
}
|
|
113 |
t++; |
|
114 |
f++; |
|
115 |
}
|
|
116 |
}
|
|
117 |
||
118 |
static void |
|
119 |
add_CE_entry(char *field, int line) |
|
120 |
{
|
|
121 |
if (MAYBE_ADD_CE_ENTRY(0)) { |
|
122 |
errmsgno(EX_BAD, |
|
123 |
"Panic: no space, cannot add RR CE entry (%d bytes mising) for %s line %d.\n", |
|
124 |
(CE_SIZE + currlen + (ipnt - recstart) - reclimit), |
|
125 |
field, line); |
|
126 |
errmsgno(EX_BAD, "currlen: %d ipnt: %d, recstart: %d\n", |
|
127 |
currlen, ipnt, recstart); |
|
128 |
errmsgno(EX_BAD, "Send bug report to the maintainer.\n"); |
|
129 |
comerrno(EX_BAD, "Aborting.\n"); |
|
130 |
}
|
|
131 |
||
132 |
if (recstart) |
|
133 |
set_733((char *) Rock + recstart - 8, ipnt + 28 - recstart); |
|
134 |
Rock[ipnt++] = 'C'; |
|
135 |
Rock[ipnt++] = 'E'; |
|
136 |
Rock[ipnt++] = CE_SIZE; |
|
137 |
Rock[ipnt++] = SU_VERSION; |
|
138 |
set_733((char *) Rock + ipnt, 0); |
|
139 |
ipnt += 8; |
|
140 |
set_733((char *) Rock + ipnt, 0); |
|
141 |
ipnt += 8; |
|
142 |
set_733((char *) Rock + ipnt, 0); |
|
143 |
ipnt += 8; |
|
144 |
recstart = ipnt; |
|
145 |
currlen = 0; |
|
146 |
if (!mainrec) |
|
147 |
mainrec = ipnt; |
|
148 |
reclimit = SECTOR_SIZE - 8; /* Limit to one sector */ |
|
149 |
}
|
|
150 |
||
151 |
static int |
|
152 |
gen_xa_attr(mode_t attr) |
|
153 |
{
|
|
154 |
int ret = 0; |
|
155 |
||
156 |
if (attr & S_IRUSR) |
|
157 |
ret |= XA_O_READ; |
|
158 |
if (attr & S_IXUSR) |
|
159 |
ret |= XA_O_EXEC; |
|
160 |
||
161 |
if (attr & S_IRGRP) |
|
162 |
ret |= XA_G_READ; |
|
163 |
if (attr & S_IXGRP) |
|
164 |
ret |= XA_G_EXEC; |
|
165 |
||
166 |
if (attr & S_IROTH) |
|
167 |
ret |= XA_W_READ; |
|
168 |
if (attr & S_IXOTH) |
|
169 |
ret |= XA_W_EXEC; |
|
170 |
||
171 |
ret |= XA_FORM1; |
|
172 |
||
173 |
if (S_ISDIR(attr)) |
|
174 |
ret |= XA_DIR; |
|
175 |
||
176 |
return (ret); |
|
177 |
}
|
|
178 |
||
179 |
static void |
|
180 |
gen_xa(struct stat *lstatbuf) |
|
181 |
{
|
|
182 |
/*
|
|
183 |
* Group ID
|
|
184 |
*/
|
|
185 |
set_722((char *) Rock + ipnt, lstatbuf->st_gid); |
|
186 |
ipnt += 2; |
|
187 |
/*
|
|
188 |
* User ID
|
|
189 |
*/
|
|
190 |
set_722((char *) Rock + ipnt, lstatbuf->st_uid); |
|
191 |
ipnt += 2; |
|
192 |
/*
|
|
193 |
* Attributes
|
|
194 |
*/
|
|
195 |
set_722((char *) Rock + ipnt, gen_xa_attr(lstatbuf->st_mode)); |
|
196 |
ipnt += 2; |
|
197 |
||
198 |
Rock[ipnt++] = 'X'; /* XA Signature */ |
|
199 |
Rock[ipnt++] = 'A'; |
|
200 |
Rock[ipnt++] = 0; /* File number (we always use '0' */ |
|
201 |
||
202 |
Rock[ipnt++] = 0; /* Reserved (5 Byte) */ |
|
203 |
Rock[ipnt++] = 0; |
|
204 |
Rock[ipnt++] = 0; |
|
205 |
Rock[ipnt++] = 0; |
|
206 |
Rock[ipnt++] = 0; |
|
207 |
||
208 |
}
|
|
209 |
||
210 |
int
|
|
211 |
generate_xa_rr_attributes(char *whole_name, char *name, |
|
212 |
struct directory_entry *s_entry, |
|
213 |
struct stat *statbuf, |
|
214 |
struct stat *lstatbuf, |
|
215 |
int deep_opt) |
|
216 |
{
|
|
217 |
int flagpos; |
|
218 |
int flagval; |
|
219 |
int need_ce; |
|
220 |
||
221 |
statbuf = statbuf; /* this shuts up unreferenced compiler */ |
|
222 |
/* warnings */
|
|
223 |
mainrec = recstart = ipnt = 0; |
|
224 |
||
225 |
if (use_XA) { |
|
226 |
gen_xa(lstatbuf); |
|
227 |
}
|
|
228 |
||
229 |
/* reclimit = 0xf8; XXX we now use 254 == 0xfe */
|
|
230 |
reclimit = MAX_ISODIR; |
|
231 |
||
232 |
/* no need to fill in the RR stuff if we won't see the file */
|
|
233 |
if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) |
|
234 |
return (0); |
|
235 |
||
236 |
/*
|
|
237 |
* Obtain the amount of space that is currently used for the directory
|
|
238 |
* record. We may safely use the current name length; because if name
|
|
239 |
* confilcts force us to change the ISO-9660 name later, the name will
|
|
240 |
* never become longer than now.
|
|
241 |
*/
|
|
242 |
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { |
|
243 |
s_entry->isorec.name_len[0] = 1; |
|
244 |
} else { |
|
245 |
s_entry->isorec.name_len[0] = strlen(s_entry->isorec.name); |
|
246 |
}
|
|
247 |
currlen = s_entry->isorec.length[0] = s_entry->isorec.name_len[0] + |
|
248 |
offsetof(struct iso_directory_record, name[0]); |
|
249 |
if (currlen & 1) |
|
250 |
s_entry->isorec.length[0] = ++currlen; |
|
251 |
||
252 |
if (currlen < 33+37) { |
|
253 |
/*
|
|
254 |
* If the ISO-9660 name length is less than 37, we may use
|
|
255 |
* ISO-9660:1988 name rules and for this reason, the name len
|
|
256 |
* may later increase from adding e.g. ".;1"; in this case
|
|
257 |
* just use the upper limit.
|
|
258 |
*/
|
|
259 |
currlen = 33+37; |
|
260 |
}
|
|
261 |
||
262 |
#ifdef APPLE_HYB
|
|
263 |
/* if we have regular file, then add Apple extensions */
|
|
264 |
if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) { |
|
265 |
if (MAYBE_ADD_CE_ENTRY(AA_SIZE)) |
|
266 |
add_CE_entry("AA", __LINE__); |
|
267 |
Rock[ipnt++] = 'A'; /* AppleSignature */ |
|
268 |
Rock[ipnt++] = 'A'; |
|
269 |
Rock[ipnt++] = AA_SIZE; /* includes AppleSignature bytes */ |
|
270 |
Rock[ipnt++] = 0x02; /* SystemUseID */ |
|
271 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.type[0]; |
|
272 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.type[1]; |
|
273 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.type[2]; |
|
274 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.type[3]; |
|
275 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[0]; |
|
276 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[1]; |
|
277 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[2]; |
|
278 |
Rock[ipnt++] = s_entry->hfs_ent->u.file.creator[3]; |
|
279 |
Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff; |
|
280 |
Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff; |
|
281 |
}
|
|
282 |
#endif /* APPLE_HYB */ |
|
283 |
||
284 |
if (!use_RockRidge) |
|
285 |
goto xa_only; |
|
286 |
||
287 |
/* Identify that we are using the SUSP protocol */
|
|
288 |
if (deep_opt & NEED_SP) { |
|
289 |
/*
|
|
290 |
* We may not use a CE record here but we never will need to
|
|
291 |
* do so, as this SP record is only used for the "." entry
|
|
292 |
* of the root directory.
|
|
293 |
*/
|
|
294 |
Rock[ipnt++] = 'S'; |
|
295 |
Rock[ipnt++] = 'P'; |
|
296 |
Rock[ipnt++] = 7; |
|
297 |
Rock[ipnt++] = SU_VERSION; |
|
298 |
Rock[ipnt++] = 0xbe; |
|
299 |
Rock[ipnt++] = 0xef; |
|
300 |
if (use_XA) |
|
301 |
Rock[ipnt++] = sizeof (struct iso_xa_dir_record); |
|
302 |
else
|
|
303 |
Rock[ipnt++] = 0; |
|
304 |
}
|
|
305 |
||
306 |
/* First build the posix name field */
|
|
307 |
if (MAYBE_ADD_CE_ENTRY(RR_SIZE)) |
|
308 |
add_CE_entry("RR", __LINE__); |
|
309 |
Rock[ipnt++] = 'R'; |
|
310 |
Rock[ipnt++] = 'R'; |
|
311 |
Rock[ipnt++] = 5; |
|
312 |
Rock[ipnt++] = SU_VERSION; |
|
313 |
flagpos = ipnt; |
|
314 |
flagval = 0; |
|
315 |
Rock[ipnt++] = 0; /* We go back and fix this later */ |
|
316 |
||
317 |
if (strcmp(name, ".") && strcmp(name, "..")) { |
|
318 |
char *npnt; |
|
319 |
int remain; /* Remaining name length */ |
|
320 |
int use; /* Current name part used */ |
|
321 |
||
322 |
#ifdef APPLE_HYB
|
|
323 |
/* use the HFS name if it exists */
|
|
324 |
if (USE_MAC_NAME(s_entry)) { |
|
325 |
remain = strlen(s_entry->hfs_ent->name); |
|
326 |
npnt = s_entry->hfs_ent->name; |
|
327 |
} else { |
|
328 |
#endif /* APPLE_HYB */ |
|
329 |
||
330 |
remain = strlen(name); |
|
331 |
npnt = name; |
|
332 |
#ifdef APPLE_HYB
|
|
333 |
}
|
|
334 |
#endif /* APPLE_HYB */ |
|
335 |
||
336 |
if (MAYBE_ADD_CE_ENTRY(NM_SIZE+1)) |
|
337 |
add_CE_entry("NM", __LINE__); |
|
338 |
while (remain) { |
|
339 |
use = remain; |
|
340 |
need_ce = 0; |
|
341 |
/* Can we fit this SUSP and a CE entry? */
|
|
342 |
if (MAYBE_ADD_CE_ENTRY(NM_SIZE+use)) { |
|
343 |
use = reclimit - NM_SIZE - RR_CUR_USE; |
|
344 |
need_ce++; |
|
345 |
}
|
|
346 |
/* Only room for 256 per SUSP field */
|
|
347 |
if (use > 0xf8) { |
|
348 |
use = 0xf8; |
|
349 |
need_ce++; |
|
350 |
}
|
|
351 |
if (use < 0) { |
|
352 |
comerrno(EX_BAD, |
|
353 |
"Negative RR name length residual: %d\n", |
|
354 |
use); |
|
355 |
}
|
|
356 |
||
357 |
/* First build the posix name field */
|
|
358 |
Rock[ipnt++] = 'N'; |
|
359 |
Rock[ipnt++] = 'M'; |
|
360 |
Rock[ipnt++] = NM_SIZE + use; |
|
361 |
Rock[ipnt++] = SU_VERSION; |
|
362 |
Rock[ipnt++] = (remain != use ? 1 : 0); |
|
363 |
flagval |= (1 << 3); |
|
364 |
||
365 |
/* convert charsets as required */
|
|
366 |
#ifdef APPLE_HYB
|
|
367 |
if (USE_MAC_NAME(s_entry)) |
|
368 |
rstrncpy((char *) &Rock[ipnt], npnt, use, |
|
369 |
hfs_inls, out_nls); |
|
370 |
else
|
|
371 |
#endif /* APPLE_HYB */ |
|
372 |
rstrncpy((char *) &Rock[ipnt], npnt, use, |
|
373 |
in_nls, out_nls); |
|
374 |
npnt += use; |
|
375 |
ipnt += use; |
|
376 |
remain -= use; |
|
377 |
if (remain && need_ce) |
|
378 |
add_CE_entry("NM", __LINE__); |
|
379 |
}
|
|
380 |
}
|
|
381 |
||
382 |
/* Add the posix modes */
|
|
383 |
if (MAYBE_ADD_CE_ENTRY(PX_SIZE)) |
|
384 |
add_CE_entry("PX", __LINE__); |
|
385 |
Rock[ipnt++] = 'P'; |
|
386 |
Rock[ipnt++] = 'X'; |
|
387 |
Rock[ipnt++] = PX_SIZE; |
|
388 |
Rock[ipnt++] = SU_VERSION; |
|
389 |
flagval |= (1 << 0); |
|
390 |
set_733((char *) Rock + ipnt, lstatbuf->st_mode); |
|
391 |
ipnt += 8; |
|
392 |
set_733((char *) Rock + ipnt, lstatbuf->st_nlink); |
|
393 |
ipnt += 8; |
|
394 |
set_733((char *) Rock + ipnt, lstatbuf->st_uid); |
|
395 |
ipnt += 8; |
|
396 |
set_733((char *) Rock + ipnt, lstatbuf->st_gid); |
|
397 |
ipnt += 8; |
|
398 |
||
399 |
/* Check for special devices */
|
|
400 |
#if defined(S_IFCHR) || defined(S_IFBLK)
|
|
401 |
/*
|
|
402 |
* The code in this if statement used to be #ifdef'd with NON_UNIXFS.
|
|
403 |
* But as statdefs.h always provides the macros S_ISCHR() & S_ISBLK()
|
|
404 |
* and device.h always provides major()/minor() it is not needed
|
|
405 |
* anymore.
|
|
406 |
*/
|
|
407 |
if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) { |
|
408 |
if (MAYBE_ADD_CE_ENTRY(PN_SIZE)) |
|
409 |
add_CE_entry("PN", __LINE__); |
|
410 |
Rock[ipnt++] = 'P'; |
|
411 |
Rock[ipnt++] = 'N'; |
|
412 |
Rock[ipnt++] = PN_SIZE; |
|
413 |
Rock[ipnt++] = SU_VERSION; |
|
414 |
flagval |= (1 << 1); |
|
415 |
#if 1
|
|
416 |
/* This is the new and only code which uses <device.h> */
|
|
417 |
set_733((char *) Rock + ipnt, major(lstatbuf->st_rdev)); |
|
418 |
ipnt += 8; |
|
419 |
set_733((char *) Rock + ipnt, minor(lstatbuf->st_rdev)); |
|
420 |
ipnt += 8; |
|
421 |
#else
|
|
422 |
/*
|
|
423 |
* If we don't have sysmacros.h, then we have to guess as to
|
|
424 |
* how best to pick apart the device number for major/minor.
|
|
425 |
* Note: this may very well be wrong for many systems, so it
|
|
426 |
* is always best to use the major/minor macros if the system
|
|
427 |
* supports it.
|
|
428 |
*/
|
|
429 |
if (sizeof (dev_t) <= 2) { |
|
430 |
set_733((char *)Rock + ipnt, (lstatbuf->st_rdev >> 8)); |
|
431 |
ipnt += 8; |
|
432 |
set_733((char *)Rock + ipnt, lstatbuf->st_rdev & 0xff); |
|
433 |
ipnt += 8; |
|
434 |
} else if (sizeof (dev_t) <= 4) { |
|
435 |
set_733((char *)Rock + ipnt, |
|
436 |
(lstatbuf->st_rdev >> 8) >> 8); |
|
437 |
ipnt += 8; |
|
438 |
set_733((char *)Rock + ipnt, |
|
439 |
lstatbuf->st_rdev & 0xffff); |
|
440 |
ipnt += 8; |
|
441 |
} else { |
|
442 |
set_733((char *)Rock + ipnt, |
|
443 |
(lstatbuf->st_rdev >> 16)>>16); |
|
444 |
ipnt += 8; |
|
445 |
set_733((char *)Rock + ipnt, lstatbuf->st_rdev); |
|
446 |
ipnt += 8; |
|
447 |
}
|
|
448 |
#endif
|
|
449 |
}
|
|
450 |
#endif /* defined(S_IFCHR) || defined(S_IFBLK) */ |
|
451 |
||
452 |
/* Check for and symbolic links. VMS does not have these. */
|
|
453 |
#ifdef S_IFLNK
|
|
454 |
if (S_ISLNK(lstatbuf->st_mode)) { |
|
455 |
int lenpos; |
|
456 |
int lenval; |
|
457 |
int j0; |
|
458 |
int j1; |
|
459 |
int nchar; |
|
460 |
Uchar *cpnt; |
|
461 |
Uchar *cpnt1; |
|
462 |
||
463 |
#ifdef HAVE_READLINK
|
|
464 |
nchar = readlink(whole_name, (char *)symlink_buff, |
|
465 |
sizeof (symlink_buff)-1); |
|
466 |
#else
|
|
467 |
nchar = -1; |
|
468 |
#endif /* HAVE_READLINK */ |
|
469 |
symlink_buff[nchar < 0 ? 0 : nchar] = 0; |
|
470 |
nchar = strlen((char *) symlink_buff); |
|
471 |
set_733(s_entry->isorec.size, 0); |
|
472 |
cpnt = &symlink_buff[0]; |
|
473 |
flagval |= (1 << 2); |
|
474 |
||
475 |
if (!split_SL_field) { |
|
476 |
int sl_bytes = 0; |
|
477 |
||
478 |
for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++) { |
|
479 |
if (*cpnt1 == '/') { |
|
480 |
sl_bytes += 4; |
|
481 |
} else { |
|
482 |
sl_bytes += 1; |
|
483 |
}
|
|
484 |
}
|
|
485 |
if (sl_bytes > 250) { |
|
486 |
/*
|
|
487 |
* the symbolic link won't fit into one
|
|
488 |
* SL System Use Field print an error message
|
|
489 |
* and continue with splited one
|
|
490 |
*/
|
|
491 |
fprintf(stderr, |
|
492 |
"symbolic link ``%s'' to long for one SL System Use Field, splitting", |
|
493 |
cpnt); |
|
494 |
}
|
|
495 |
if (MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) |
|
496 |
add_CE_entry("SL+", __LINE__); |
|
497 |
}
|
|
498 |
while (nchar) { |
|
499 |
if (MAYBE_ADD_CE_ENTRY(SL_SIZE)) |
|
500 |
add_CE_entry("SL", __LINE__); |
|
501 |
Rock[ipnt++] = 'S'; |
|
502 |
Rock[ipnt++] = 'L'; |
|
503 |
lenpos = ipnt; |
|
504 |
Rock[ipnt++] = SL_SIZE; |
|
505 |
Rock[ipnt++] = SU_VERSION; |
|
506 |
Rock[ipnt++] = 0; /* Flags */ |
|
507 |
lenval = 5; |
|
508 |
while (*cpnt) { |
|
509 |
cpnt1 = (Uchar *) |
|
510 |
strchr((char *)cpnt, '/'); |
|
511 |
if (cpnt1) { |
|
512 |
nchar--; |
|
513 |
*cpnt1 = 0; |
|
514 |
}
|
|
515 |
||
516 |
/*
|
|
517 |
* We treat certain components in a special
|
|
518 |
* way.
|
|
519 |
*/
|
|
520 |
if (cpnt[0] == '.' && cpnt[1] == '.' && |
|
521 |
cpnt[2] == 0) { |
|
522 |
if (MAYBE_ADD_CE_ENTRY(2)) { |
|
523 |
add_CE_entry("SL-parent", __LINE__); |
|
524 |
if (cpnt1) { |
|
525 |
*cpnt1 = '/'; |
|
526 |
nchar++; |
|
527 |
/*
|
|
528 |
* A kluge so that we
|
|
529 |
* can restart properly
|
|
530 |
*/
|
|
531 |
cpnt1 = NULL; |
|
532 |
}
|
|
533 |
break; |
|
534 |
}
|
|
535 |
Rock[ipnt++] = SL_PARENT; |
|
536 |
Rock[ipnt++] = 0; /* length is zero */ |
|
537 |
lenval += 2; |
|
538 |
nchar -= 2; |
|
539 |
} else if (cpnt[0] == '.' && cpnt[1] == 0) { |
|
540 |
if (MAYBE_ADD_CE_ENTRY(2)) { |
|
541 |
add_CE_entry("SL-current", __LINE__); |
|
542 |
if (cpnt1) { |
|
543 |
*cpnt1 = '/'; |
|
544 |
nchar++; |
|
545 |
/*
|
|
546 |
* A kluge so that we
|
|
547 |
* can restart properly
|
|
548 |
*/
|
|
549 |
cpnt1 = NULL; |
|
550 |
}
|
|
551 |
break; |
|
552 |
}
|
|
553 |
Rock[ipnt++] = SL_CURRENT; |
|
554 |
Rock[ipnt++] = 0; /* length is zero */ |
|
555 |
lenval += 2; |
|
556 |
nchar -= 1; |
|
557 |
} else if (cpnt[0] == 0) { |
|
558 |
if (MAYBE_ADD_CE_ENTRY(2)) { |
|
559 |
add_CE_entry("SL-root", __LINE__); |
|
560 |
if (cpnt1) { |
|
561 |
*cpnt1 = '/'; |
|
562 |
nchar++; |
|
563 |
/*
|
|
564 |
* A kluge so that we
|
|
565 |
* can restart properly
|
|
566 |
*/
|
|
567 |
cpnt1 = NULL; |
|
568 |
}
|
|
569 |
break; |
|
570 |
}
|
|
571 |
Rock[ipnt++] = SL_ROOT; |
|
572 |
Rock[ipnt++] = 0; /* length is zero */ |
|
573 |
lenval += 2; |
|
574 |
} else { |
|
575 |
/*
|
|
576 |
* If we do not have enough room for a
|
|
577 |
* component, start a new continuations
|
|
578 |
* segment now
|
|
579 |
*/
|
|
580 |
if (split_SL_component ? |
|
581 |
MAYBE_ADD_CE_ENTRY(6) : |
|
582 |
MAYBE_ADD_CE_ENTRY(6 + strlen((char *) cpnt))) { |
|
583 |
add_CE_entry("SL++", __LINE__); |
|
584 |
if (cpnt1) { |
|
585 |
*cpnt1 = '/'; |
|
586 |
nchar++; |
|
587 |
/*
|
|
588 |
* A kluge so that we
|
|
589 |
* can restart properly
|
|
590 |
*/
|
|
591 |
cpnt1 = NULL; |
|
592 |
}
|
|
593 |
break; |
|
594 |
}
|
|
595 |
j0 = strlen((char *) cpnt); |
|
596 |
while (j0) { |
|
597 |
j1 = j0; |
|
598 |
if (j1 > 0xf8) |
|
599 |
j1 = 0xf8; |
|
600 |
need_ce = 0; |
|
601 |
if (j1 + currlen + 2 + CE_SIZE + |
|
602 |
(ipnt - recstart) > |
|
603 |
reclimit) { |
|
604 |
||
605 |
j1 = reclimit - |
|
606 |
(currlen + 2) - |
|
607 |
CE_SIZE - |
|
608 |
(ipnt - recstart); |
|
609 |
need_ce++; |
|
610 |
}
|
|
611 |
Rock[ipnt++] = |
|
612 |
(j1 != j0 ? |
|
613 |
SL_CONTINUE : 0); |
|
614 |
Rock[ipnt++] = j1; |
|
615 |
strncpy((char *)Rock + ipnt, |
|
616 |
(char *) cpnt, j1); |
|
617 |
ipnt += j1; |
|
618 |
lenval += j1 + 2; |
|
619 |
cpnt += j1; |
|
620 |
/*
|
|
621 |
* Number we processed
|
|
622 |
* this time
|
|
623 |
*/
|
|
624 |
nchar -= j1; |
|
625 |
j0 -= j1; |
|
626 |
if (need_ce) { |
|
627 |
add_CE_entry( |
|
628 |
"SL-path-split", |
|
629 |
__LINE__); |
|
630 |
if (cpnt1) { |
|
631 |
*cpnt1 = '/'; |
|
632 |
nchar++; |
|
633 |
/*
|
|
634 |
* A kluge so
|
|
635 |
* that we can
|
|
636 |
* restart
|
|
637 |
* properly
|
|
638 |
*/
|
|
639 |
cpnt1 = NULL; |
|
640 |
}
|
|
641 |
break; |
|
642 |
}
|
|
643 |
}
|
|
644 |
}
|
|
645 |
if (cpnt1) { |
|
646 |
cpnt = cpnt1 + 1; |
|
647 |
} else |
|
648 |
break; |
|
649 |
}
|
|
650 |
Rock[lenpos] = lenval; |
|
651 |
if (nchar) { |
|
652 |
/* We need another SL entry */
|
|
653 |
Rock[lenpos + 2] = SL_CONTINUE; |
|
654 |
}
|
|
655 |
} /* while nchar */ |
|
656 |
} /* Is a symbolic link */ |
|
657 |
#endif /* S_IFLNK */ |
|
658 |
||
659 |
/* Add in the Rock Ridge TF time field */
|
|
660 |
if (MAYBE_ADD_CE_ENTRY(TF_SIZE)) |
|
661 |
add_CE_entry("TF", __LINE__); |
|
662 |
Rock[ipnt++] = 'T'; |
|
663 |
Rock[ipnt++] = 'F'; |
|
664 |
Rock[ipnt++] = TF_SIZE; |
|
665 |
Rock[ipnt++] = SU_VERSION; |
|
666 |
#if defined(__QNX__) && !defined(__QNXNTO__) /* Not on Neutrino! never OK? */ |
|
667 |
Rock[ipnt++] = 0x0f; |
|
668 |
#else
|
|
669 |
Rock[ipnt++] = 0x0e; |
|
670 |
#endif
|
|
671 |
flagval |= (1 << 7); |
|
672 |
||
673 |
#if defined(__QNX__) && !defined(__QNXNTO__) /* Not on Neutrino! never OK? */ |
|
674 |
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime); |
|
675 |
ipnt += 7; |
|
676 |
#endif
|
|
677 |
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime); |
|
678 |
ipnt += 7; |
|
679 |
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime); |
|
680 |
ipnt += 7; |
|
681 |
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime); |
|
682 |
ipnt += 7; |
|
683 |
||
684 |
/* Add in the Rock Ridge RE (relocated dir) field */
|
|
685 |
if (deep_opt & NEED_RE) { |
|
686 |
if (MAYBE_ADD_CE_ENTRY(RE_SIZE)) |
|
687 |
add_CE_entry("RE", __LINE__); |
|
688 |
Rock[ipnt++] = 'R'; |
|
689 |
Rock[ipnt++] = 'E'; |
|
690 |
Rock[ipnt++] = RE_SIZE; |
|
691 |
Rock[ipnt++] = SU_VERSION; |
|
692 |
flagval |= (1 << 6); |
|
693 |
}
|
|
694 |
/* Add in the Rock Ridge PL record, if required. */
|
|
695 |
if (deep_opt & NEED_PL) { |
|
696 |
if (MAYBE_ADD_CE_ENTRY(PL_SIZE)) |
|
697 |
add_CE_entry("PL", __LINE__); |
|
698 |
Rock[ipnt++] = 'P'; |
|
699 |
Rock[ipnt++] = 'L'; |
|
700 |
Rock[ipnt++] = PL_SIZE; |
|
701 |
Rock[ipnt++] = SU_VERSION; |
|
702 |
set_733((char *) Rock + ipnt, 0); |
|
703 |
ipnt += 8; |
|
704 |
flagval |= (1 << 5); |
|
705 |
}
|
|
706 |
||
707 |
/* Add in the Rock Ridge CL field, if required. */
|
|
708 |
if (deep_opt & NEED_CL) { |
|
709 |
if (MAYBE_ADD_CE_ENTRY(CL_SIZE)) |
|
710 |
add_CE_entry("CL", __LINE__); |
|
711 |
Rock[ipnt++] = 'C'; |
|
712 |
Rock[ipnt++] = 'L'; |
|
713 |
Rock[ipnt++] = CL_SIZE; |
|
714 |
Rock[ipnt++] = SU_VERSION; |
|
715 |
set_733((char *) Rock + ipnt, 0); |
|
716 |
ipnt += 8; |
|
717 |
flagval |= (1 << 4); |
|
718 |
}
|
|
719 |
||
720 |
#ifndef VMS
|
|
721 |
/*
|
|
722 |
* If transparent compression was requested, fill in the correct field
|
|
723 |
* for this file, if (and only if) it is actually a compressed file!
|
|
724 |
* This relies only on magic number, but it should in general not
|
|
725 |
* be an issue since if you're using -z odds are most of your
|
|
726 |
* files are already compressed.
|
|
727 |
*
|
|
728 |
* In the future it would be nice if genisoimage actually did the
|
|
729 |
* compression.
|
|
730 |
*/
|
|
731 |
if (transparent_compression && S_ISREG(lstatbuf->st_mode)) { |
|
732 |
static const Uchar zisofs_magic[8] = |
|
733 |
{ 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 }; |
|
734 |
FILE *zffile; |
|
735 |
unsigned int file_size; |
|
736 |
Uchar header[16]; |
|
737 |
int OK_flag; |
|
738 |
int blocksize; |
|
739 |
int headersize; |
|
740 |
||
741 |
/*
|
|
742 |
* First open file and verify that the correct algorithm was
|
|
743 |
* used
|
|
744 |
*/
|
|
745 |
file_size = 0; |
|
746 |
OK_flag = 1; |
|
747 |
||
748 |
memset(header, 0, sizeof (header)); |
|
749 |
||
750 |
zffile = fopen(whole_name, "rb"); |
|
751 |
if (zffile != NULL) { |
|
752 |
if (fread(header, 1, sizeof (header), zffile) != sizeof (header)) |
|
753 |
OK_flag = 0; |
|
754 |
||
755 |
/* Check magic number */
|
|
756 |
if (memcmp(header, zisofs_magic, sizeof (zisofs_magic))) |
|
757 |
OK_flag = 0; |
|
758 |
||
759 |
/* Get the real size of the file */
|
|
760 |
file_size = get_731((char *)header+8); |
|
761 |
||
762 |
/* Get the header size (>> 2) */
|
|
763 |
headersize = header[12]; |
|
764 |
||
765 |
/* Get the block size (log2) */
|
|
766 |
blocksize = header[13]; |
|
767 |
||
768 |
fclose(zffile); |
|
769 |
} else { |
|
770 |
OK_flag = 0; |
|
771 |
blocksize = headersize = 0; /* Make silly GCC quiet */ |
|
772 |
}
|
|
773 |
||
774 |
if (OK_flag) { |
|
775 |
if (MAYBE_ADD_CE_ENTRY(ZF_SIZE)) |
|
776 |
add_CE_entry("ZF", __LINE__); |
|
777 |
Rock[ipnt++] = 'Z'; |
|
778 |
Rock[ipnt++] = 'F'; |
|
779 |
Rock[ipnt++] = ZF_SIZE; |
|
780 |
Rock[ipnt++] = SU_VERSION; |
|
781 |
Rock[ipnt++] = 'p'; /* Algorithm: "paged zlib" */ |
|
782 |
Rock[ipnt++] = 'z'; |
|
783 |
/* 2 bytes for algorithm-specific information */
|
|
784 |
Rock[ipnt++] = headersize; |
|
785 |
Rock[ipnt++] = blocksize; |
|
786 |
set_733((char *) Rock + ipnt, file_size); /* Real file size */ |
|
787 |
ipnt += 8; |
|
788 |
}
|
|
789 |
}
|
|
790 |
#endif
|
|
791 |
/*
|
|
792 |
* Add in the Rock Ridge CE field, if required. We use this for the
|
|
793 |
* extension record that is stored in the root directory.
|
|
794 |
*/
|
|
795 |
if (deep_opt & NEED_CE) |
|
796 |
add_CE_entry("ER", __LINE__); |
|
797 |
||
798 |
/*
|
|
799 |
* Done filling in all of the fields. Now copy it back to a buffer
|
|
800 |
* for the file in question.
|
|
801 |
*/
|
|
802 |
/* Now copy this back to the buffer for the file */
|
|
803 |
Rock[flagpos] = flagval; |
|
804 |
||
805 |
/* If there was a CE, fill in the size field */
|
|
806 |
if (recstart) |
|
807 |
set_733((char *) Rock + recstart - 8, ipnt - recstart); |
|
808 |
||
809 |
xa_only: |
|
810 |
s_entry->rr_attributes = (Uchar *) e_malloc(ipnt); |
|
811 |
s_entry->total_rr_attr_size = ipnt; |
|
812 |
s_entry->rr_attr_size = (mainrec ? mainrec : ipnt); |
|
813 |
memcpy(s_entry->rr_attributes, Rock, ipnt); |
|
814 |
return (ipnt); |
|
815 |
}
|
|
816 |
||
817 |
/*
|
|
818 |
* Guaranteed to return a single sector with the relevant info
|
|
819 |
*/
|
|
820 |
char * |
|
821 |
generate_rr_extension_record(char *id, char *descriptor, char *source, |
|
822 |
int *size) |
|
823 |
{
|
|
824 |
int lipnt = 0; |
|
825 |
char *pnt; |
|
826 |
int len_id; |
|
827 |
int len_des; |
|
828 |
int len_src; |
|
829 |
||
830 |
len_id = strlen(id); |
|
831 |
len_des = strlen(descriptor); |
|
832 |
len_src = strlen(source); |
|
833 |
Rock[lipnt++] = 'E'; |
|
834 |
Rock[lipnt++] = 'R'; |
|
835 |
Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src; |
|
836 |
Rock[lipnt++] = 1; |
|
837 |
Rock[lipnt++] = len_id; |
|
838 |
Rock[lipnt++] = len_des; |
|
839 |
Rock[lipnt++] = len_src; |
|
840 |
Rock[lipnt++] = 1; |
|
841 |
||
842 |
memcpy(Rock + lipnt, id, len_id); |
|
843 |
lipnt += len_id; |
|
844 |
||
845 |
memcpy(Rock + lipnt, descriptor, len_des); |
|
846 |
lipnt += len_des; |
|
847 |
||
848 |
memcpy(Rock + lipnt, source, len_src); |
|
849 |
lipnt += len_src; |
|
850 |
||
851 |
if (lipnt > SECTOR_SIZE) { |
|
852 |
#ifdef USE_LIBSCHILY
|
|
853 |
comerrno(EX_BAD, "Extension record too long\n"); |
|
854 |
#else
|
|
855 |
fprintf(stderr, "Extension record too long\n"); |
|
856 |
exit(1); |
|
857 |
#endif
|
|
858 |
}
|
|
859 |
pnt = (char *) e_malloc(SECTOR_SIZE); |
|
860 |
memset(pnt, 0, SECTOR_SIZE); |
|
861 |
memcpy(pnt, Rock, lipnt); |
|
862 |
*size = lipnt; |
|
863 |
return (pnt); |
|
864 |
}
|