1 /*
2 * Program mkisofs.c - generate iso9660 filesystem based upon directory
3 * tree on hard disk.
4
5 Written by Eric Youngdale (1993).
6
7 Copyright 1993 Yggdrasil Computing, Incorporated
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 12/3/99 */
24
25 #include <errno.h>
26 #include "config.h"
27 #include "mkisofs.h"
28 #include "match.h"
29 #include "apple_proto.h"
30
31 #ifdef linux
32 #include <getopt.h>
33 #else
34 #include "getopt.h"
35 #endif
36
37 #include "iso9660.h"
38 #include <ctype.h>
39
40 #ifndef VMS
41 #include <time.h>
42 #else
43 #include <sys/time.h>
44 #include "vms.h"
45 #endif
46
47 #include <stdlib.h>
48 #include <sys/stat.h>
49
50 #ifndef VMS
51 #ifdef HAVE_UNISTD_H
52 #include <unistd.h>
53 #endif
54 #endif
55 #include <fctldefs.h>
56
57 #if defined(__NetBSD__) || defined(__OpenBSD__)
58 #include <sys/time.h>
59 #include <sys/resource.h>
60 #endif
61
62 struct directory * root = NULL;
63
64 #ifdef APPLE_HYB
65 static char version_string[] = "mkhybrid 1.12b5.1";
66 #else
67 static char version_string[] = "mkisofs 1.12b5";
68 #endif /* APPLE_HYB */
69
70 char * outfile;
71 FILE * discimage;
72 unsigned int next_extent = 0;
73 unsigned int last_extent = 0;
74 unsigned int session_start = 0;
75 unsigned int path_table_size = 0;
76 unsigned int path_table[4] = {0,};
77 unsigned int path_blocks = 0;
78
79
80 unsigned int jpath_table_size = 0;
81 unsigned int jpath_table[4] = {0,};
82 unsigned int jpath_blocks = 0;
83
84 struct iso_directory_record root_record;
85 struct iso_directory_record jroot_record;
86
87 char * extension_record = NULL;
88 int extension_record_extent = 0;
89 int extension_record_size = 0;
90
91 /* These variables are associated with command line options */
92 int use_eltorito = 0;
93 int use_RockRidge = 0;
94 int use_Joliet = 0;
95 int verbose = 0;
96 int all_files = 0;
97 int follow_links = 0;
98 int rationalize = 0;
99 int generate_tables = 0;
100 int print_size = 0;
101 int split_output = 0;
102 char * preparer = PREPARER_DEFAULT;
103 char * publisher = PUBLISHER_DEFAULT;
104 char * appid = APPID_DEFAULT;
105 char * copyright = COPYRIGHT_DEFAULT;
106 char * biblio = BIBLIO_DEFAULT;
107 char * abstract = ABSTRACT_DEFAULT;
108 char * volset_id = VOLSET_ID_DEFAULT;
109 char * volume_id = VOLUME_ID_DEFAULT;
110 char * system_id = SYSTEM_ID_DEFAULT;
111 char * boot_catalog = BOOT_CATALOG_DEFAULT;
112 char * boot_image = BOOT_IMAGE_DEFAULT;
113 char * efi_boot_image = EFI_BOOT_IMAGE_DEFAULT;
114 int volume_set_size = 1;
115 int volume_sequence_number = 1;
116
117 int omit_period = 0; /* Violates iso9660, but these are a pain */
118 int transparent_compression = 0; /* So far only works with linux */
119 int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/
120 int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
121 int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with
122 DOS */
123 int allow_leading_dots = 0; /* DOS cannot read names with leading dots */
124 int split_SL_component = 1; /* circumvent a bug in the SunOS driver */
125 int split_SL_field = 1; /* circumvent a bug in the SunOS */
126
127 #ifdef APPLE_HYB
128 int apple_hyb = 0; /* create HFS hybrid flag */
129 int apple_ext = 0; /* create HFS extensions flag */
130 int apple_both = 0; /* common flag (for above) */
131 int hfs_extra = 0; /* extra HFS blocks added to end of ISO vol */
132 int mac_name = 0; /* use Mac name for ISO/Joliet/RR flag */
133 hce_mem *hce; /* libhfs/mkisofs extras */
134 char *hfs_boot_file = 0; /* name of HFS boot file */
135 int gen_pt = 0; /* generate HFS partition table */
136 char *autoname = 0; /* AutoStart filename */
137 char *magic_file = 0; /* name of magic file */
138 int probe = 0; /* search files for HFS/Unix type */
139 int nomacfiles = 0; /* don't look for Mac/Unix files */
140 int hfs_select = 0; /* Mac/Unix types to select */
141 int create_dt = 1; /* create the Desktp files */
142 int bsize = 0; /* Apple File Exchange block size */
143 int hfs_last = MAG_LAST; /* process magic file after map file */
144 char *deftype = DEFTYPE; /* default Apple TYPE */
145 char *defcreator = DEFCREATOR; /* default Apple CREATOR */
146 char *trans_tbl = "TRANS.TBL"; /* default name for translation table */
147 char *hfs_volume_id = NULL; /* HFS volume ID */
148 char *hfs_bless = NULL; /* name of folder to 'bless' (System Folder) */
149
150 #endif /* APPLE_HYB */
151
152 struct rcopts{
153 char * tag;
154 char ** variable;
155 };
156
157 struct rcopts rcopt[] = {
158 {"PREP", &preparer},
159 {"PUBL", &publisher},
160 {"APPI", &appid},
161 {"COPY", ©right},
162 {"BIBL", &biblio},
163 {"ABST", &abstract},
164 {"VOLS", &volset_id},
165 {"VOLI", &volume_id},
166 {"SYSI", &system_id},
167 #ifdef APPLE_HYB
168 {"TYPE", &deftype},
169 {"CREATOR", &defcreator},
170 #endif /* APPLE_HYB */
171 {NULL, NULL}
172 };
173
174 /*
175 * In case it isn't obvious, the option handling code was ripped off from GNU-ld.
176 */
177 struct ld_option
178 {
179 /* The long option information. */
180 struct option opt;
181 /* The short option with the same meaning ('\0' if none). */
182 char shortopt;
183 /* The name of the argument (NULL if none). */
184 const char *arg;
185 /* The documentation string. If this is NULL, this is a synonym for
186 the previous option. */
187 const char *doc;
188 enum
189 {
190 /* Use one dash before long option name. */
191 ONE_DASH,
192 /* Use two dashes before long option name. */
193 TWO_DASHES,
194 /* Don't mention this option in --help output. */
195 NO_HELP
196 } control;
197 };
198
199 /* Codes used for the long options with no short synonyms. 150 isn't
200 special; it's just an arbitrary non-ASCII char value. */
201 #define OPTION_HELP 150
202 #define OPTION_QUIET 151
203 #define OPTION_NOSPLIT_SL_COMPONENT 152
204 #define OPTION_NOSPLIT_SL_FIELD 153
205 #define OPTION_PRINT_SIZE 154
206 #define OPTION_SPLIT_OUTPUT 155
207 #define OPTION_ABSTRACT 156
208 #define OPTION_BIBLIO 157
209 #define OPTION_COPYRIGHT 158
210 #define OPTION_SYSID 159
211 #define OPTION_VOLSET 160
212 #define OPTION_VOLSET_SIZE 161
213 #define OPTION_VOLSET_SEQ_NUM 162
214 #define OPTION_I_HIDE 163
215 #define OPTION_J_HIDE 164
216 #define OPTION_LOG_FILE 165
217 #ifdef APPLE_HYB
218 #define OPTION_CAP 200
219 #define OPTION_NETA 201
220 #define OPTION_DBL 202
221 #define OPTION_ESH 203
222 #define OPTION_FE 204
223 #define OPTION_SGI 205
224 #define OPTION_MBIN 206
225 #define OPTION_SGL 207
226 /* aliases */
227 #define OPTION_USH 208
228 #define OPTION_XIN 209
229
230 #define OPTION_PROBE 220
231 #define OPTION_MACNAME 221
232 #define OPTION_NOMACFILES 222
233 #define OPTION_BOOT_HFS_FILE 223
234 #define OPTION_MAGIC_FILE 224
235
236 #define OPTION_TRANS_TBL 225
237
238 #define OPTION_GEN_PT 226
239
240 #define OPTION_CREATE_DT 227
241 #define OPTION_HFS_HIDE 228
242
243 #define OPTION_AUTOSTART 229
244 #define OPTION_BSIZE 230
245 #define OPTION_HFS_VOLID 231
246
247 #define OPTION_H_LIST 240
248 #define OPTION_P_LIST 241
249 #define OPTION_I_LIST 242
250 #define OPTION_J_LIST 243
251 #define OPTION_X_LIST 244
252
253 #define OPTION_HFS_BLESS 245
254 #endif /* APPLE_HYB */
255
256 static const struct ld_option ld_options[] =
257 {
258 { {"all-files", no_argument, NULL, 'a'},
259 'a', NULL, "Process all files (don't skip backup files)", ONE_DASH },
260 { {"abstract", required_argument, NULL, OPTION_ABSTRACT},
261 '\0', "FILE", "Set Abstract filename" , ONE_DASH },
262 { {"appid", required_argument, NULL, 'A'},
263 'A', "ID", "Set Application ID" , ONE_DASH },
264 { {"biblio", required_argument, NULL, OPTION_BIBLIO},
265 '\0', "FILE", "Set Bibliographic filename" , ONE_DASH },
266 { {"copyright", required_argument, NULL, OPTION_COPYRIGHT},
267 '\0', "FILE", "Set Copyright filename" , ONE_DASH },
268 { {"eltorito-boot", required_argument, NULL, 'b'},
269 'b', "FILE", "Set El Torito boot image name" , ONE_DASH },
270 { {"eltorito-catalog", required_argument, NULL, 'c'},
271 'c', "FILE", "Set El Torito boot catalog name" , ONE_DASH },
272 { {"cdwrite-params", required_argument, NULL, 'C'},
273 'C', "PARAMS", "Magic paramters from cdrecord" , ONE_DASH },
274 { {"omit-period", no_argument, NULL, 'd'},
275 'd', NULL, "Omit trailing periods from filenames", ONE_DASH },
276 { {"disable-deep-relocation", no_argument, NULL, 'D'},
277 'D', NULL, "Disable deep directory relocation", ONE_DASH },
278 { {"eltorito-boot-efi", required_argument, NULL, 'e' },
279 'e', "FILE", "Set El Torito EFI boot image name" , ONE_DASH },
280 { {"follow-links", no_argument, NULL, 'f'},
281 'f', NULL, "Follow symbolic links", ONE_DASH },
282 { {"help", no_argument, NULL, OPTION_HELP},
283 '\0', NULL, "Print option help", ONE_DASH },
284 { {"hide", required_argument, NULL, OPTION_I_HIDE},
285 '\0', "GLOBFILE", "Hide ISO9660/RR file" , ONE_DASH },
286 #ifdef APPLE_HYB
287 /* NON-HFS change */
288 { {"hide-list", required_argument, NULL, OPTION_I_LIST},
289 '\0', "FILE", "list of ISO9660/RR files to hide" , ONE_DASH },
290 #endif /* APPLE_HYB */
291 { {"hide-joliet", required_argument, NULL, OPTION_J_HIDE},
292 '\0', "GLOBFILE", "Hide Joliet file" , ONE_DASH },
293 #ifdef APPLE_HYB
294 /* NON-HFS change */
295 { {"hide-joliet-list", required_argument, NULL, OPTION_J_LIST},
296 '\0', "FILE", "List of Joliet files to hide" , ONE_DASH },
297 #endif /* APPLE_HYB */
298 { {NULL, required_argument, NULL, 'i'},
299 'i', "ADD_FILES", "No longer supported" , TWO_DASHES },
300 { {"joliet", no_argument, NULL, 'J'},
301 'J', NULL, "Generate Joliet directory information", ONE_DASH },
302 { {"full-iso9660-filenames", no_argument, NULL, 'l'},
303 'l', NULL, "Allow full 32 character filenames for iso9660 names", ONE_DASH },
304 { {"allow-leading-dots", no_argument, NULL, 'L'},
305 'L', NULL, "Allow iso9660 filenames to start with '.'", ONE_DASH },
306 { {"log-file", required_argument, NULL, OPTION_LOG_FILE},
307 '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH },
308 { {"exclude", required_argument, NULL, 'm'},
309 'm', "GLOBFILE", "Exclude file name" , ONE_DASH },
310 #ifdef APPLE_HYB
311 { {"exclude-list", required_argument, NULL, OPTION_X_LIST},
312 'm', "FILE", "List of file names to exclude" , ONE_DASH },
313 #endif /* APPLE_HYB */
314 { {"prev-session", required_argument, NULL, 'M'},
315 'M', "FILE", "Set path to previous session to merge" , ONE_DASH },
316 { {"omit-version-number", no_argument, NULL, 'N'},
317 'N', NULL, "Omit version number from iso9660 filename", ONE_DASH },
318 { {"no-split-symlink-components", no_argument, NULL, 0},
319 0, NULL, "Inhibit splitting symlink components" , ONE_DASH },
320 { {"no-split-symlink-fields", no_argument, NULL, 0},
321 0, NULL, "Inhibit splitting symlink fields" , ONE_DASH },
322 { {"output", required_argument, NULL, 'o'},
323 'o', "FILE", "Set output file name" , ONE_DASH },
324 #ifdef APPLE_HYB
325 { {"path-list", required_argument, NULL, OPTION_P_LIST},
326 '\0', "FILE", "list of pathnames to process" , ONE_DASH },
327 #endif /* APPLE_HYB */
328 { {"preparer", required_argument, NULL, 'p'},
329 'p', "PREP", "Set Volume preparer" , ONE_DASH },
330 { {"print-size", no_argument, NULL, OPTION_PRINT_SIZE},
331 '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH },
332 { {"publisher", required_argument, NULL, 'P'},
333 'P', "PUB", "Set Volume publisher" , ONE_DASH },
334 { {"quiet", no_argument, NULL, OPTION_QUIET},
335 '\0', NULL, "Run quietly", ONE_DASH },
336 { {"rational-rock", no_argument, NULL, 'r'},
337 'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH },
338 { {"rock", no_argument, NULL, 'R'},
339 'R', NULL, "Generate Rock Ridge directory information", ONE_DASH },
340 { {"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
341 '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH },
342 { {"sysid", required_argument, NULL, OPTION_SYSID},
343 '\0', "ID", "Set System ID" , ONE_DASH },
344 { {"translation-table", no_argument, NULL, 'T'},
345 'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH },
346 { {"verbose", no_argument, NULL, 'v'},
347 'v', NULL, "Verbose", ONE_DASH },
348 { {"volid", required_argument, NULL, 'V'},
349 'V', "ID", "Set Volume ID" , ONE_DASH },
350 { {"volset", required_argument, NULL, OPTION_VOLSET},
351 '\0', "ID", "Set Volume set ID" , ONE_DASH },
352 { {"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE},
353 '\0', "#", "Set Volume set size" , ONE_DASH },
354 { {"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM},
355 '\0', "#", "Set Volume set sequence number" , ONE_DASH },
356 { {"old-exclude", required_argument, NULL, 'x'},
357 'x', "FILE", "Exclude file name(depreciated)" , ONE_DASH },
358 #ifdef ERIC_neverdef
359 { {"transparent-compression", no_argument, NULL, 'z'},
360 'z', NULL, "Enable transparent compression of files", ONE_DASH },
361 #endif
362 #ifdef APPLE_HYB
363 { {"apple", no_argument, NULL, 'g'},
364 'g', NULL, "Add Apple ISO9660 extensions", ONE_DASH },
365 { {"hfs", no_argument, NULL, 'h'},
366 'h', NULL, "Create ISO9660/HFS hybrid", ONE_DASH },
367 { {"map", required_argument, NULL, 'H'},
368 'H', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
369 { {"magic", required_argument, NULL, OPTION_MAGIC_FILE},
370 '\0', "FILE", "Magic file for HFS TYPE/CREATOR", ONE_DASH},
371 { {"probe", no_argument, NULL, OPTION_PROBE},
372 '\0', NULL, "Probe all files for Unix/HFS file type", ONE_DASH },
373 { {"mac-name", no_argument, NULL, OPTION_MACNAME},
374 '\0', NULL, "Use Macintosh name for ISO9660/Joliet/RockRidge file name",
375 ONE_DASH },
376 { {"no-mac-files", no_argument, NULL, OPTION_NOMACFILES},
377 '\0', NULL, "Do not look for Unix/Mac files", ONE_DASH },
378 { {"boot-hfs-file", required_argument, NULL, OPTION_BOOT_HFS_FILE},
379 '\0', "FILE", "Set HFS boot image name", ONE_DASH},
380 { {"part", no_argument, NULL, OPTION_GEN_PT},
381 '\0', NULL, "Generate HFS partition table", ONE_DASH },
382 { {"cluster-size", required_argument, NULL, OPTION_BSIZE},
383 '\0', "SIZE", "Cluster size for PC Exchange Macintosh files", ONE_DASH},
384 { {"auto", required_argument, NULL, OPTION_AUTOSTART},
385 '\0', "FILE", "Set HFS AutoStart file name", ONE_DASH},
386 { {"no-desktop", no_argument, NULL, OPTION_CREATE_DT},
387 '\0', NULL, "Do not create the HFS (empty) Desktop files", ONE_DASH },
388 { {"hide-hfs", required_argument, NULL, OPTION_HFS_HIDE},
389 '\0', "GLOBFILE", "Hide HFS file" , ONE_DASH },
390 { {"hide-hfs-list", required_argument, NULL, OPTION_H_LIST},
391 '\0', "GLOBFILE", "List of HFS files to hide" , ONE_DASH },
392 { {"table-name", required_argument, NULL, OPTION_TRANS_TBL},
393 '\0', "TABLE_NAME", "translation table file name", ONE_DASH },
394 { {"hfs-volid", required_argument, NULL, OPTION_HFS_VOLID},
395 '\0', "HFS_VOLID", "Volume name for the HFS partition", ONE_DASH },
396 {{"hfs-bless", required_argument, NULL, OPTION_HFS_BLESS},
397 '\0', "FOLDER_NAME", "Name of Folder to be blessed", ONE_DASH},
398 { {"cap", no_argument, NULL, OPTION_CAP},
399 '\0', NULL, "Look for AUFS CAP Macintosh files", TWO_DASHES },
400 { {"netatalk", no_argument, NULL, OPTION_NETA},
401 '\0', NULL, "Look for NETATALK Macintosh files", TWO_DASHES },
402 { {"double", no_argument, NULL, OPTION_DBL},
403 '\0', NULL, "Look for AppleDouble Macintosh files", TWO_DASHES },
404 { {"ethershare", no_argument, NULL, OPTION_ESH},
405 '\0', NULL, "Look for Helios EtherShare Macintosh files", TWO_DASHES },
406 { {"exchange", no_argument, NULL, OPTION_FE},
407 '\0', NULL, "Look for PC Exchange Macintosh files", TWO_DASHES },
408 { {"sgi", no_argument, NULL, OPTION_SGI},
409 '\0', NULL, "Look for SGI Macintosh files", TWO_DASHES },
410 { {"macbin", no_argument, NULL, OPTION_MBIN},
411 '\0', NULL, "Look for MacBinary Macintosh files", TWO_DASHES },
412 { {"single", no_argument, NULL, OPTION_SGL},
413 '\0', NULL, "Look for AppleSingle Macintosh files", TWO_DASHES },
414 { {"ushare", no_argument, NULL, OPTION_USH},
415 '\0', NULL, "Look for IPT UShare Macintosh files", TWO_DASHES },
416 { {"xinet", no_argument, NULL, OPTION_XIN},
417 '\0', NULL, "Look for XINET Macintosh files", TWO_DASHES },
418 #endif /* APPLE_HYB */
419 };
420
421 #define OPTION_COUNT (sizeof ld_options / sizeof ld_options[0])
422
423 #if defined(ultrix) || defined(_AUX_SOURCE)
strdup(s)424 char *strdup(s)
425 char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;}
426 #endif
427
428 void read_rcfile __PR((char * appname));
429 void usage __PR((void));
430 static void hide_reloc_dir __PR((void));
431
FDECL1(read_rcfile,char *,appname)432 void FDECL1(read_rcfile, char *, appname)
433 {
434 FILE * rcfile;
435 struct rcopts * rco;
436 char * pnt, *pnt1;
437 char linebuffer[256];
438 static char rcfn[] = ".mkisofsrc";
439 char filename[1000];
440 int linum;
441
442 strcpy(filename, rcfn);
443 rcfile = fopen(filename, "r");
444 if (!rcfile && errno != ENOENT)
445 perror(filename);
446
447 if (!rcfile)
448 {
449 pnt = getenv("MKISOFSRC");
450 if (pnt && strlen(pnt) <= sizeof(filename))
451 {
452 strcpy(filename, pnt);
453 rcfile = fopen(filename, "r");
454 if (!rcfile && errno != ENOENT)
455 perror(filename);
456 }
457 }
458
459 if (!rcfile)
460 {
461 pnt = getenv("HOME");
462 if (pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename))
463 {
464 strcpy(filename, pnt);
465 strcat(filename, "/");
466 strcat(filename, rcfn);
467 rcfile = fopen(filename, "r");
468 if (!rcfile && errno != ENOENT)
469 perror(filename);
470 }
471 }
472 if (!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename))
473 {
474 strcpy(filename, appname);
475 pnt = strrchr(filename, '/');
476 if (pnt)
477 {
478 strcpy(pnt + 1, rcfn);
479 rcfile = fopen(filename, "r");
480 if (!rcfile && errno != ENOENT)
481 perror(filename);
482 }
483 }
484 if (!rcfile)
485 return;
486 if ( verbose > 0 )
487 {
488 fprintf(stderr, "Using \"%s\"\n", filename);
489 }
490
491 /* OK, we got it. Now read in the lines and parse them */
492 linum = 0;
493 while (fgets(linebuffer, sizeof(linebuffer), rcfile))
494 {
495 char *name;
496 char *name_end;
497 ++linum;
498 /* skip any leading white space */
499 pnt = linebuffer;
500 while (*pnt == ' ' || *pnt == '\t')
501 ++pnt;
502 /* If we are looking at a # character, this line is a comment. */
503 if (*pnt == '#')
504 continue;
505 /* The name should begin in the left margin. Make sure it is in
506 upper case. Stop when we see white space or a comment. */
507 name = pnt;
508 while (*pnt && isalpha((unsigned char)*pnt))
509 {
510 if(islower((unsigned char)*pnt))
511 *pnt = toupper((unsigned char)*pnt);
512 pnt++;
513 }
514 if (name == pnt)
515 {
516 fprintf(stderr, "%s:%d: name required\n", filename, linum);
517 continue;
518 }
519 name_end = pnt;
520 /* Skip past white space after the name */
521 while (*pnt == ' ' || *pnt == '\t')
522 pnt++;
523 /* silently ignore errors in the rc file. */
524 if (*pnt != '=')
525 {
526 fprintf(stderr, "%s:%d: equals sign required\n", filename, linum);
527 continue;
528 }
529 /* Skip pas the = sign, and any white space following it */
530 pnt++; /* Skip past '=' sign */
531 while (*pnt == ' ' || *pnt == '\t')
532 pnt++;
533
534 /* now it is safe to NUL terminate the name */
535
536 *name_end = 0;
537
538 /* Now get rid of trailing newline */
539
540 pnt1 = pnt;
541 while (*pnt1)
542 {
543 if (*pnt1 == '\n')
544 {
545 *pnt1 = 0;
546 break;
547 }
548 pnt1++;
549 };
550 /* OK, now figure out which option we have */
551 for(rco = rcopt; rco->tag; rco++) {
552 if(strcmp(rco->tag, name) == 0)
553 {
554 *rco->variable = strdup(pnt);
555 break;
556 };
557 }
558 if (rco->tag == NULL)
559 {
560 fprintf(stderr, "%s:%d: field name \"%s\" unknown\n", filename, linum,
561 name);
562 }
563 }
564 if (ferror(rcfile))
565 perror(filename);
566 fclose(rcfile);
567 }
568
569 char * path_table_l = NULL;
570 char * path_table_m = NULL;
571
572 char * jpath_table_l = NULL;
573 char * jpath_table_m = NULL;
574
575 int goof = 0;
576
577 #ifndef TRUE
578 #define TRUE 1
579 #endif
580
581 #ifndef FALSE
582 #define FALSE 0
583 #endif
584
usage()585 void usage(){
586 #ifdef APPLE_HYB
587 const char * program_name = "mkhybrid";
588 #else
589 const char * program_name = "mkisofs";
590 #endif /* APPLE_HYB */
591
592 #if 0
593 fprintf(stderr,"Usage:\n");
594 fprintf(stderr,
595 "mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \
596 [-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer]"
597 "[-P publisher] [ -A app_id ] [-z] \n \
598 [-b boot_image_name] [-c boot_catalog-name] \
599 [-x path -x path ...] path\n");
600 #endif
601
602 int i;
603 /* const char **targets, **pp;*/
604
605 fprintf (stderr, "Usage: %s [options] file...\n", program_name);
606
607 fprintf (stderr, "Options:\n");
608 for (i = 0; i < OPTION_COUNT; i++)
609 {
610 if (ld_options[i].doc != NULL)
611 {
612 int comma;
613 int len;
614 int j;
615
616 fprintf (stderr, " ");
617
618 comma = FALSE;
619 len = 2;
620
621 j = i;
622 do
623 {
624 if (ld_options[j].shortopt != '\0'
625 && ld_options[j].control != NO_HELP)
626 {
627 fprintf (stderr, "%s-%c", comma ? ", " : "", ld_options[j].shortopt);
628 len += (comma ? 2 : 0) + 2;
629 if (ld_options[j].arg != NULL)
630 {
631 if (ld_options[j].opt.has_arg != optional_argument)
632 {
633 fprintf (stderr, " ");
634 ++len;
635 }
636 fprintf (stderr, "%s", ld_options[j].arg);
637 len += strlen (ld_options[j].arg);
638 }
639 comma = TRUE;
640 }
641 ++j;
642 }
643 while (j < OPTION_COUNT && ld_options[j].doc == NULL);
644
645 j = i;
646 do
647 {
648 if (ld_options[j].opt.name != NULL
649 && ld_options[j].control != NO_HELP)
650 {
651 fprintf (stderr, "%s-%s%s",
652 comma ? ", " : "",
653 ld_options[j].control == TWO_DASHES ? "-" : "",
654 ld_options[j].opt.name);
655 len += ((comma ? 2 : 0)
656 + 1
657 + (ld_options[j].control == TWO_DASHES ? 1 : 0)
658 + strlen (ld_options[j].opt.name));
659 if (ld_options[j].arg != NULL)
660 {
661 fprintf (stderr, " %s", ld_options[j].arg);
662 len += 1 + strlen (ld_options[j].arg);
663 }
664 comma = TRUE;
665 }
666 ++j;
667 }
668 while (j < OPTION_COUNT && ld_options[j].doc == NULL);
669
670 if (len >= 30)
671 {
672 fprintf (stderr, "\n");
673 len = 0;
674 }
675
676 for (; len < 30; len++)
677 fputc (' ', stderr);
678
679 fprintf (stderr, "%s\n", ld_options[i].doc);
680 }
681 }
682 exit(1);
683 }
684
685
686 /*
687 * Fill in date in the iso9660 format
688 *
689 * The standards state that the timezone offset is in multiples of 15
690 * minutes, and is what you add to GMT to get the localtime. The U.S.
691 * is always at a negative offset, from -5h to -8h (can vary a little
692 * with DST, I guess). The Linux iso9660 filesystem has had the sign
693 * of this wrong for ages (mkisofs had it wrong too for the longest time).
694 */
FDECL2(iso9660_date,char *,result,time_t,crtime)695 int FDECL2(iso9660_date,char *, result, time_t, crtime){
696 struct tm *local;
697 local = localtime(&crtime);
698 result[0] = local->tm_year;
699 result[1] = local->tm_mon + 1;
700 result[2] = local->tm_mday;
701 result[3] = local->tm_hour;
702 result[4] = local->tm_min;
703 result[5] = local->tm_sec;
704
705 /*
706 * Must recalculate proper timezone offset each time,
707 * as some files use daylight savings time and some don't...
708 */
709 result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */
710 local = gmtime(&crtime);
711 local->tm_year -= result[0];
712 local->tm_yday -= result[6];
713 local->tm_hour -= result[3];
714 local->tm_min -= result[4];
715 if (local->tm_year < 0)
716 {
717 local->tm_yday = -1;
718 }
719 else
720 {
721 if (local->tm_year > 0) local->tm_yday = 1;
722 }
723
724 result[6] = -(local->tm_min + 60*(local->tm_hour + 24*local->tm_yday)) / 15;
725
726 return 0;
727 }
728
729 /* hide "./rr_moved" if all its contents are hidden */
730 static void
hide_reloc_dir()731 hide_reloc_dir()
732 {
733 struct directory_entry * s_entry;
734
735 for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) {
736 if(strcmp(s_entry->name,".")==0 || strcmp(s_entry->name,"..")==0)
737 continue;
738
739 if((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
740 return;
741 }
742
743 /* all entries are hidden, so hide this directory */
744 reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
745 reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY;
746 }
747
748 /* get pathnames from the command line, and then from given file */
749 static char *
FDECL5(get_pnames,int,argc,char **,argv,int,opt,char *,pname,FILE *,fp)750 FDECL5(get_pnames, int, argc, char **, argv, int, opt, char *, pname, FILE *, fp)
751 {
752 if (opt < argc)
753 return (argv[opt]);
754
755 if (fp == NULL)
756 return ((char *)0);
757
758 if (fscanf(fp, "%s", pname) != EOF)
759 return (pname);
760
761 return ((char *)0);
762 }
763
764 extern char * cdwrite_data;
765
FDECL2(main,int,argc,char **,argv)766 int FDECL2(main, int, argc, char **, argv){
767 struct directory_entry de;
768 #ifdef HAVE_SBRK
769 unsigned long mem_start;
770 #endif
771 struct stat statbuf;
772 char * scan_tree;
773 char * merge_image = NULL;
774 struct iso_directory_record * mrootp = NULL;
775 struct output_fragment * opnt;
776 int longind;
777 char shortopts[OPTION_COUNT * 3 + 2];
778 struct option longopts[OPTION_COUNT + 1];
779 int c;
780 char *log_file = 0;
781 #ifdef APPLE_HYB
782 char *afpfile = ""; /* mapping file for TYPE/CREATOR */
783 char *pathnames = 0;
784 FILE *pfp = NULL;
785 char pname[1024], *arg;
786 int no_path_names = 0;
787 #endif /* APPLE_HYB */
788
789 if (argc < 2)
790 usage();
791
792 /* Get the defaults from the .mkisofsrc file */
793 read_rcfile(argv[0]);
794
795 outfile = NULL;
796
797 /*
798 * Copy long option initialization from GNU-ld.
799 */
800 /* Starting the short option string with '-' is for programs that
801 expect options and other ARGV-elements in any order and that care about
802 the ordering of the two. We describe each non-option ARGV-element
803 as if it were the argument of an option with character code 1. */
804 {
805 int i, is, il;
806 shortopts[0] = '-';
807 is = 1;
808 il = 0;
809 for (i = 0; i < OPTION_COUNT; i++)
810 {
811 if (ld_options[i].shortopt != '\0')
812 {
813 shortopts[is] = ld_options[i].shortopt;
814 ++is;
815 if (ld_options[i].opt.has_arg == required_argument
816 || ld_options[i].opt.has_arg == optional_argument)
817 {
818 shortopts[is] = ':';
819 ++is;
820 if (ld_options[i].opt.has_arg == optional_argument)
821 {
822 shortopts[is] = ':';
823 ++is;
824 }
825 }
826 }
827 if (ld_options[i].opt.name != NULL)
828 {
829 longopts[il] = ld_options[i].opt;
830 ++il;
831 }
832 }
833 shortopts[is] = '\0';
834 longopts[il].name = NULL;
835 }
836
837 while ((c = getopt_long_only (argc, argv, shortopts, longopts, &longind)) != EOF)
838 switch (c)
839 {
840 case 1:
841 /*
842 * A filename that we take as input.
843 */
844 optind--;
845 goto parse_input_files;
846 case 'C':
847 /*
848 * This is a temporary hack until cdwrite gets the proper hooks in
849 * it.
850 */
851 cdwrite_data = optarg;
852 break;
853 case 'i':
854 fprintf(stderr, "-i option no longer supported.\n");
855 exit(1);
856 break;
857 case 'J':
858 use_Joliet++;
859 break;
860 case 'a':
861 all_files++;
862 break;
863 case 'b':
864 use_eltorito++;
865 boot_image = optarg; /* pathname of the boot image on cd */
866 if (boot_image == NULL) {
867 fprintf(stderr,"Required boot image pathname missing\n");
868 exit(1);
869 }
870 break;
871 case 'e':
872 use_eltorito++;
873 efi_boot_image = optarg;
874 if (efi_boot_image == NULL) {
875 fprintf(stderr,"Required EFI boot image pathname missing\n");
876 exit(1);
877 }
878 break;
879 case 'c':
880 use_eltorito++;
881 boot_catalog = optarg; /* pathname of the boot image on cd */
882 if (boot_catalog == NULL) {
883 fprintf(stderr,"Required boot catalog pathname missing\n");
884 exit(1);
885 }
886 break;
887 case OPTION_ABSTRACT:
888 abstract = optarg;
889 if(strlen(abstract) > 37) {
890 fprintf(stderr,"Abstract filename string too long\n");
891 exit(1);
892 };
893 break;
894 case 'A':
895 appid = optarg;
896 if(strlen(appid) > 128) {
897 fprintf(stderr,"Application-id string too long\n");
898 exit(1);
899 };
900 break;
901 case OPTION_BIBLIO:
902 biblio = optarg;
903 if(strlen(biblio) > 37) {
904 fprintf(stderr,"Bibliographic filename string too long\n");
905 exit(1);
906 };
907 break;
908 case OPTION_COPYRIGHT:
909 copyright = optarg;
910 if(strlen(copyright) > 37) {
911 fprintf(stderr,"Copyright filename string too long\n");
912 exit(1);
913 };
914 break;
915 case 'd':
916 omit_period++;
917 break;
918 case 'D':
919 RR_relocation_depth = 32767;
920 break;
921 case 'f':
922 follow_links++;
923 break;
924 case 'l':
925 full_iso9660_filenames++;
926 break;
927 case 'L':
928 allow_leading_dots++;
929 break;
930 case OPTION_LOG_FILE:
931 log_file = optarg;
932 break;
933 case 'M':
934 merge_image = optarg;
935 break;
936 case 'N':
937 omit_version_number++;
938 break;
939 case 'o':
940 outfile = optarg;
941 break;
942 case 'p':
943 preparer = optarg;
944 if(strlen(preparer) > 128) {
945 fprintf(stderr,"Preparer string too long\n");
946 exit(1);
947 };
948 break;
949 case OPTION_PRINT_SIZE:
950 print_size++;
951 break;
952 case 'P':
953 publisher = optarg;
954 if(strlen(publisher) > 128) {
955 fprintf(stderr,"Publisher string too long\n");
956 exit(1);
957 };
958 break;
959 case OPTION_QUIET:
960 verbose = 0;
961 break;
962 case 'R':
963 use_RockRidge++;
964 break;
965 case 'r':
966 rationalize++;
967 use_RockRidge++;
968 break;
969 case OPTION_SPLIT_OUTPUT:
970 split_output++;
971 break;
972 case OPTION_SYSID:
973 system_id = optarg;
974 if(strlen(system_id) > 32) {
975 fprintf(stderr,"System ID string too long\n");
976 exit(1);
977 };
978 break;
979 #ifdef APPLE_HYB
980 case OPTION_TRANS_TBL:
981 trans_tbl = optarg;
982 /* fall through */
983 #endif /* APPLE_HYB */
984 case 'T':
985 generate_tables++;
986 break;
987 case 'V':
988 volume_id = optarg;
989 if(strlen(volume_id) > 32) {
990 fprintf(stderr,"Volume ID string too long\n");
991 exit(1);
992 };
993 break;
994 case OPTION_VOLSET:
995 volset_id = optarg;
996 if(strlen(volset_id) > 128) {
997 fprintf(stderr,"Volume set ID string too long\n");
998 exit(1);
999 };
1000 break;
1001 case OPTION_VOLSET_SIZE:
1002 volume_set_size = atoi(optarg);
1003 break;
1004 case OPTION_VOLSET_SEQ_NUM:
1005 volume_sequence_number = atoi(optarg);
1006 if (volume_sequence_number > volume_set_size) {
1007 fprintf(stderr,"Volume set sequence number too big\n");
1008 exit(1);
1009 }
1010 break;
1011 case 'v':
1012 verbose++;
1013 break;
1014 case 'z':
1015 #ifdef VMS
1016 fprintf(stderr,"Transparent compression not supported with VMS\n");
1017 exit(1);
1018 #else
1019 transparent_compression++;
1020 #endif
1021 break;
1022 case 'x':
1023 case 'm':
1024 /*
1025 * Somehow two options to do basically the same thing got added somewhere along
1026 * the way. The 'match' code supports limited globbing, so this is the one
1027 * that got selected. Unfortunately the 'x' switch is probably more intuitive.
1028 */
1029 add_match(optarg);
1030 break;
1031 case OPTION_I_HIDE:
1032 i_add_match(optarg);
1033 break;
1034 case OPTION_J_HIDE:
1035 j_add_match(optarg);
1036 break;
1037 case OPTION_HELP:
1038 usage ();
1039 exit (0);
1040 break;
1041 case OPTION_NOSPLIT_SL_COMPONENT:
1042 split_SL_component = 0;
1043 break;
1044 case OPTION_NOSPLIT_SL_FIELD:
1045 split_SL_field = 0;
1046 break;
1047 #ifdef APPLE_HYB
1048 case 'H':
1049 afpfile = optarg;
1050 hfs_last = MAP_LAST;
1051 break;
1052 case 'h':
1053 apple_hyb = 1;
1054 break;
1055 case 'g':
1056 apple_ext = 1;
1057 break;
1058 case OPTION_PROBE:
1059 probe = 1;
1060 break;
1061 case OPTION_MACNAME:
1062 mac_name = 1;
1063 break;
1064 case OPTION_NOMACFILES:
1065 nomacfiles = 1;
1066 break;
1067 case OPTION_BOOT_HFS_FILE:
1068 hfs_boot_file = optarg;
1069 /* fall through */
1070 case OPTION_GEN_PT:
1071 gen_pt = 1;
1072 break;
1073 case OPTION_MAGIC_FILE:
1074 magic_file = optarg;
1075 hfs_last = MAG_LAST;
1076 break;
1077 case OPTION_AUTOSTART:
1078 autoname = optarg;
1079 /* gen_pt = 1; */
1080 break;
1081 case OPTION_BSIZE:
1082 bsize = atoi(optarg);
1083 break;
1084 case OPTION_HFS_VOLID:
1085 hfs_volume_id = optarg;
1086 break;
1087 case OPTION_HFS_BLESS:
1088 hfs_bless = optarg;
1089 break;
1090 /* Mac/Unix types to include */
1091 case OPTION_CAP:
1092 hfs_select |= DO_CAP;
1093 break;
1094 case OPTION_NETA:
1095 hfs_select |= DO_NETA;
1096 break;
1097 case OPTION_DBL:
1098 hfs_select |= DO_DBL;
1099 break;
1100 case OPTION_ESH:
1101 case OPTION_USH:
1102 hfs_select |= DO_ESH;
1103 break;
1104 case OPTION_FE:
1105 hfs_select |= DO_FEU;
1106 hfs_select |= DO_FEL;
1107 break;
1108 case OPTION_SGI:
1109 case OPTION_XIN:
1110 hfs_select |= DO_SGI;
1111 break;
1112 case OPTION_MBIN:
1113 hfs_select |= DO_MBIN;
1114 break;
1115 case OPTION_SGL:
1116 hfs_select |= DO_SGL;
1117 break;
1118 case OPTION_CREATE_DT:
1119 create_dt = 0;
1120 break;
1121 case OPTION_HFS_HIDE:
1122 hfs_add_match(optarg);
1123 break;
1124 case OPTION_H_LIST:
1125 hfs_add_list(optarg);
1126 break;
1127 /* NON-HFS change
1128 The next options will probably appear in mkisofs in the future */
1129 case OPTION_P_LIST:
1130 pathnames = optarg;
1131 break;
1132 case OPTION_X_LIST:
1133 add_list(optarg);
1134 break;
1135 case OPTION_I_LIST:
1136 i_add_list(optarg);
1137 break;
1138 case OPTION_J_LIST:
1139 j_add_list(optarg);
1140 break;
1141 #endif /* APPLE_HYB */
1142 default:
1143 usage();
1144 exit(1);
1145 }
1146
1147 parse_input_files:
1148
1149 #if defined(__NetBSD__) || defined(__OpenBSD__)
1150 {
1151 struct rlimit rlp;
1152 if (getrlimit(RLIMIT_DATA,&rlp) == -1)
1153 perror("Warning: getrlimit");
1154 else {
1155 rlp.rlim_cur=33554432;
1156 if (setrlimit(RLIMIT_DATA,&rlp) == -1)
1157 perror("Warning: setrlimit");
1158 }
1159 }
1160 #endif
1161 #ifdef HAVE_SBRK
1162 mem_start = (unsigned long) sbrk(0);
1163 #endif
1164
1165 /* if the -hide-joliet option has been given, set the Joliet option */
1166 if (!use_Joliet && j_ishidden())
1167 use_Joliet++;
1168
1169 #ifdef APPLE_HYB
1170 if (apple_hyb && apple_ext) {
1171 fprintf(stderr,"can't have both -apple and -hfs options");
1172 exit (1);
1173 }
1174
1175 /* if -probe, -macname, any hfs selection and/or mapping file is given,
1176 but no HFS option, then select apple_hyb */
1177 if (!apple_hyb && !apple_ext) {
1178 if (*afpfile || probe || mac_name || nomacfiles || hfs_select || hfs_boot_file || magic_file || hfs_ishidden() || gen_pt || autoname || bsize)
1179 apple_hyb = 1;
1180 }
1181
1182 if (apple_ext && hfs_boot_file) {
1183 fprintf(stderr,"can't have -hfs-boot-file with -apple\n");
1184 exit (1);
1185 }
1186
1187 if (hfs_select)
1188 /* if we have selected certain types of Mac/Unix files, then turn off
1189 probe and nomacfiles */
1190 probe = nomacfiles = 0;
1191
1192 if (apple_hyb || apple_ext)
1193 apple_both = 1;
1194
1195 if (apple_both) {
1196 /* set up the TYPE/CREATOR mappings */
1197 hfs_init(afpfile, 0, probe, nomacfiles, hfs_select);
1198 }
1199
1200 if (apple_ext && !use_RockRidge) {
1201 /* use RockRidge to set the SystemUse field ... */
1202 use_RockRidge++;
1203 rationalize++;
1204 }
1205
1206 #endif /* APPLE_HYB */
1207
1208 if(verbose > 1) fprintf(stderr,"%s\n", version_string);
1209
1210 if(cdwrite_data == NULL && merge_image != NULL)
1211 {
1212 fprintf(stderr,"Multisession usage bug: Must specify -C if -M is used.\n");
1213 exit(0);
1214 }
1215
1216 if(cdwrite_data != NULL && merge_image == NULL)
1217 {
1218 fprintf(stderr,"Warning: -C specified without -M: old session data will not be merged.\n");
1219 }
1220
1221 /* The first step is to scan the directory tree, and take some notes */
1222
1223 scan_tree = argv[optind];
1224
1225
1226 if(!scan_tree){
1227 usage();
1228 exit(1);
1229 };
1230
1231 #ifndef VMS
1232 if(scan_tree[strlen(scan_tree)-1] != '/') {
1233 scan_tree = (char *) e_malloc(strlen(argv[optind])+2);
1234 strcpy(scan_tree, argv[optind]);
1235 strcat(scan_tree, "/");
1236 };
1237 #endif
1238
1239 if(use_RockRidge){
1240 #if 1
1241 extension_record = generate_rr_extension_record("RRIP_1991A",
1242 "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
1243 "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size);
1244 #else
1245 extension_record = generate_rr_extension_record("IEEE_P1282",
1246 "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
1247 "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size);
1248 #endif
1249 }
1250
1251 if (log_file) {
1252 FILE *lfp;
1253 int i;
1254
1255 /* open log file - test that we can open OK */
1256 if ((lfp = fopen(log_file, "w")) == NULL) {
1257 fprintf(stderr,"can't open logfile: %s\n", log_file);
1258 exit (1);
1259 }
1260 fclose(lfp);
1261
1262 /* redirect all stderr message to log_file */
1263 fprintf(stderr, "re-directing all messages to %s\n", log_file);
1264 fflush(stderr);
1265
1266 /* associate stderr with the log file */
1267 if (freopen(log_file, "w", stderr) == NULL) {
1268 fprintf(stderr,"can't open logfile: %s\n", log_file);
1269 exit (1);
1270 }
1271 if(verbose > 1) {
1272 for (i=0;i<argc;i++)
1273 fprintf(stderr,"%s ", argv[i]);
1274
1275 fprintf(stderr,"\n%s\n", version_string);
1276 }
1277 }
1278
1279 /*
1280 * See if boot catalog file exists in root directory, if not
1281 * we will create it.
1282 */
1283 if (use_eltorito)
1284 init_boot_catalog(argv[optind]);
1285
1286 /*
1287 * Find the device and inode number of the root directory.
1288 * Record this in the hash table so we don't scan it more than
1289 * once.
1290 */
1291 stat_filter(argv[optind], &statbuf);
1292 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
1293
1294 memset(&de, 0, sizeof(de));
1295
1296 de.filedir = root; /* We need this to bootstrap */
1297
1298 if (cdwrite_data != NULL && merge_image == NULL) {
1299 /* in case we want to add a new session, but don't want to merge old one */
1300 get_session_start(NULL);
1301 }
1302
1303 if( merge_image != NULL )
1304 {
1305 mrootp = merge_isofs(merge_image);
1306 if( mrootp == NULL )
1307 {
1308 /*
1309 * Complain and die.
1310 */
1311 fprintf(stderr,"Unable to open previous session image %s\n",
1312 merge_image);
1313 exit(1);
1314 }
1315
1316 memcpy(&de.isorec.extent, mrootp->extent, 8);
1317 }
1318
1319 /*
1320 * Create an empty root directory. If we ever scan it for real, we will fill in the
1321 * contents.
1322 */
1323 find_or_create_directory(NULL, "", &de, TRUE);
1324
1325 #ifdef APPLE_HYB
1326 /* NON-HFS change: see if we have a list of pathnames to process */
1327 if (pathnames) {
1328 /* "-" means take list from the standard input */
1329 if (strcmp(pathnames, "-")) {
1330 if ((pfp = fopen(pathnames, "r")) == NULL) {
1331 fprintf(stderr, "unable to open pathname list %s\n",pathnames);
1332 exit (1);
1333 }
1334 }
1335 else
1336 pfp = stdin;
1337 }
1338 #endif /* APPLE_HYB */
1339
1340 /*
1341 * Scan the actual directory (and any we find below it)
1342 * for files to write out to the output image. Note - we
1343 * take multiple source directories and keep merging them
1344 * onto the image.
1345 */
1346 #if APPLE_HYB
1347 /* NON-HFS change */
1348 while((arg = get_pnames(argc, argv, optind, pname, pfp)) != NULL)
1349 #else
1350 while(optind < argc)
1351 #endif /* APPLE_HYB */
1352 {
1353 char * node;
1354 struct directory * graft_dir;
1355 struct stat st;
1356 char * short_name;
1357 int status;
1358 char graft_point[1024];
1359
1360 /*
1361 * We would like a syntax like:
1362 *
1363 * /tmp=/usr/tmp/xxx
1364 *
1365 * where the user can specify a place to graft each
1366 * component of the tree. To do this, we may have to create
1367 * directories along the way, of course.
1368 * Secondly, I would like to allow the user to do something
1369 * like:
1370 *
1371 * /home/baz/RMAIL=/u3/users/baz/RMAIL
1372 *
1373 * so that normal files could also be injected into the tree
1374 * at an arbitrary point.
1375 *
1376 * The idea is that the last component of whatever is being
1377 * entered would take the name from the last component of
1378 * whatever the user specifies.
1379 *
1380 * The default will be that the file is injected at the
1381 * root of the image tree.
1382 */
1383 #ifdef APPLE_HYB
1384 /* NON-HFS change */
1385 node = strchr(arg, '=');
1386 #else
1387 node = strchr(argv[optind], '=');
1388 #endif /* APPLE_HYB */
1389 short_name = NULL;
1390
1391 if( node != NULL )
1392 {
1393 char * pnt;
1394 char * xpnt;
1395
1396 *node = '\0';
1397 #ifdef APPLE_HYB
1398 /* NON-HFS change */
1399 strcpy(graft_point, arg);
1400 #else
1401 strcpy(graft_point, argv[optind]);
1402 #endif /* APPLE_HYB */
1403 *node = '=';
1404 node++;
1405
1406 graft_dir = root;
1407 xpnt = graft_point;
1408 if( *xpnt == PATH_SEPARATOR )
1409 {
1410 xpnt++;
1411 }
1412
1413 /*
1414 * Loop down deeper and deeper until we
1415 * find the correct insertion spot.
1416 */
1417 while(1==1)
1418 {
1419 pnt = strchr(xpnt, PATH_SEPARATOR);
1420 if( pnt == NULL )
1421 {
1422 if( *xpnt != '\0' )
1423 {
1424 short_name = xpnt;
1425 }
1426 break;
1427 }
1428 *pnt = '\0';
1429 graft_dir = find_or_create_directory(graft_dir,
1430 graft_point,
1431 NULL, TRUE);
1432 *pnt = PATH_SEPARATOR;
1433 xpnt = pnt + 1;
1434 }
1435 }
1436 else
1437 {
1438 graft_dir = root;
1439 #ifdef APPLE_HYB
1440 /* NON-HFS change */
1441 node = arg;
1442 #else
1443 node = argv[optind];
1444 #endif /* APPLE_HYB */
1445 }
1446
1447 /*
1448 * Now see whether the user wants to add a regular file,
1449 * or a directory at this point.
1450 */
1451 status = stat_filter(node, &st);
1452 if( status != 0 )
1453 {
1454 /*
1455 * This is a fatal error - the user won't be getting what
1456 * they want if we were to proceed.
1457 */
1458 fprintf(stderr, "Invalid node - %s\n", node);
1459 exit(1);
1460 }
1461 else
1462 {
1463 if( S_ISDIR(st.st_mode) )
1464 {
1465 if (!scan_directory_tree(graft_dir, node, &de))
1466 {
1467 exit(1);
1468 }
1469 }
1470 else
1471 {
1472 if( short_name == NULL )
1473 {
1474 short_name = strrchr(node, PATH_SEPARATOR);
1475 if( short_name == NULL || short_name < node )
1476 {
1477 short_name = node;
1478 }
1479 else
1480 {
1481 short_name++;
1482 }
1483 }
1484 #ifdef APPLE_HYB
1485 if( !insert_file_entry(graft_dir, node, short_name, 0) )
1486 #else
1487 if( !insert_file_entry(graft_dir, node, short_name) )
1488 #endif /* APPLE_HYB */
1489 {
1490 exit(1);
1491 }
1492 }
1493 }
1494
1495 optind++;
1496 #ifdef APPLE_HYB
1497 /* NON-HFS change */
1498 no_path_names = 0;
1499 #endif /* APPLE_HYB */
1500 }
1501
1502 #ifdef APPLE_HYB
1503 /* NON-HFS change */
1504 if (pfp && pfp != stdin)
1505 fclose(pfp);
1506
1507 /* exit if we don't have any pathnames to process - not going to happen
1508 at the moment as we have to have at least one path on the command line */
1509 if(no_path_names){
1510 usage();
1511 exit(1);
1512 };
1513 #endif /* APPLE_HYB */
1514
1515 /*
1516 * Now merge in any previous sessions. This is driven on the source
1517 * side, since we may need to create some additional directories.
1518 */
1519 if( merge_image != NULL )
1520 {
1521 merge_previous_session(root, mrootp);
1522 }
1523 #ifdef APPLE_HYB
1524 /* free up any HFS filename mapping memory */
1525 if (apple_both)
1526 clean_hfs();
1527 #endif /* APPLE_HYB */
1528
1529 /* hide "./rr_moved" if all its contents have been hidden */
1530 if (reloc_dir && i_ishidden())
1531 hide_reloc_dir();
1532
1533 /*
1534 * Sort the directories in the required order (by ISO9660). Also,
1535 * choose the names for the 8.3 filesystem if required, and do
1536 * any other post-scan work.
1537 */
1538 goof += sort_tree(root);
1539
1540 if( use_Joliet )
1541 {
1542 goof += joliet_sort_tree(root);
1543 }
1544
1545 if (goof)
1546 {
1547 fprintf(stderr, "Joliet tree sort failed.\n");
1548 exit(1);
1549 }
1550
1551 /*
1552 * Fix a couple of things in the root directory so that everything
1553 * is self consistent.
1554 */
1555 root->self = root->contents; /* Fix this up so that the path
1556 tables get done right */
1557
1558 /*
1559 * OK, ready to write the file. Open it up, and generate the thing.
1560 */
1561 if (print_size){
1562 discimage = fopen("/dev/null", "wb");
1563 if (!discimage){
1564 fprintf(stderr,"Unable to open /dev/null\n");
1565 exit(1);
1566 }
1567 } else if (outfile){
1568 discimage = fopen(outfile, "wb");
1569 if (!discimage){
1570 fprintf(stderr,"Unable to open disc image file\n");
1571 exit(1);
1572
1573 };
1574 } else {
1575 discimage = stdout;
1576
1577 #if defined(__CYGWIN32__)
1578 setmode(fileno(stdout), O_BINARY);
1579 #endif
1580 }
1581
1582 /* Now assign addresses on the disc for the path table. */
1583
1584 path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11;
1585 if (path_blocks & 1) path_blocks++;
1586
1587 jpath_blocks = (jpath_table_size + (SECTOR_SIZE - 1)) >> 11;
1588 if (jpath_blocks & 1) jpath_blocks++;
1589
1590 /*
1591 * Start to set up the linked list that we use to track the
1592 * contents of the disc.
1593 */
1594 outputlist_insert(&padblock_desc);
1595
1596 /*
1597 * PVD for disc.
1598 */
1599 outputlist_insert(&voldesc_desc);
1600
1601 /*
1602 * SVD for El Torito. MUST be immediately after the PVD!
1603 */
1604 if( use_eltorito)
1605 {
1606 outputlist_insert(&torito_desc);
1607 }
1608
1609 /*
1610 * SVD for Joliet.
1611 */
1612 if( use_Joliet)
1613 {
1614 outputlist_insert(&joliet_desc);
1615 }
1616
1617 /*
1618 * Finally the last volume desctiptor.
1619 */
1620 outputlist_insert(&end_vol);
1621
1622
1623 outputlist_insert(&pathtable_desc);
1624 if( use_Joliet)
1625 {
1626 outputlist_insert(&jpathtable_desc);
1627 }
1628
1629 outputlist_insert(&dirtree_desc);
1630 if( use_Joliet)
1631 {
1632 outputlist_insert(&jdirtree_desc);
1633 }
1634
1635 outputlist_insert(&dirtree_clean);
1636
1637 if(extension_record)
1638 {
1639 outputlist_insert(&extension_desc);
1640 }
1641
1642 outputlist_insert(&files_desc);
1643
1644 /*
1645 * Allow room for the various headers we will be writing. There
1646 * will always be a primary and an end volume descriptor.
1647 */
1648 last_extent = session_start;
1649
1650 /*
1651 * Calculate the size of all of the components of the disc, and assign
1652 * extent numbers.
1653 */
1654 for(opnt = out_list; opnt; opnt = opnt->of_next )
1655 {
1656 if( opnt->of_size != NULL )
1657 {
1658 (*opnt->of_size)(last_extent);
1659 }
1660 }
1661
1662 /*
1663 * Generate the contents of any of the sections that we want to generate.
1664 * Not all of the fragments will do anything here - most will generate the
1665 * data on the fly when we get to the write pass.
1666 */
1667 for(opnt = out_list; opnt; opnt = opnt->of_next )
1668 {
1669 if( opnt->of_generate != NULL )
1670 {
1671 (*opnt->of_generate)();
1672 }
1673 }
1674
1675 if( in_image != NULL )
1676 {
1677 fclose(in_image);
1678 }
1679
1680 /*
1681 * Now go through the list of fragments and write the data that corresponds to
1682 * each one.
1683 */
1684 for(opnt = out_list; opnt; opnt = opnt->of_next )
1685 {
1686 if( opnt->of_write != NULL )
1687 {
1688 (*opnt->of_write)(discimage);
1689 }
1690 }
1691
1692 if( verbose > 0 )
1693 {
1694 #ifdef HAVE_SBRK
1695 fprintf(stderr,"Max brk space used %x\n",
1696 (unsigned int)(((unsigned long)sbrk(0)) - mem_start));
1697 #endif
1698 fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9);
1699 }
1700 #ifdef APPLE_HYB
1701 last_extent += hfs_extra;
1702 #endif /* APPLE_HYB */
1703
1704 #ifdef VMS
1705 return 1;
1706 #else
1707 return 0;
1708 #endif
1709 }
1710
1711 void *
FDECL1(e_malloc,size_t,size)1712 FDECL1(e_malloc, size_t, size)
1713 {
1714 void* pt = 0;
1715 if( (size > 0) && ((pt=malloc(size))==NULL) ) {
1716 fprintf(stderr, "Not enough memory\n");
1717 exit (1);
1718 }
1719 return pt;
1720 }
1721