Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / genisoimage / genisoimage.c
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 /*
14  *
15  * Patched version with stuff from the Debian's cdrtools.
16  * Replaced various warnings/disclaimers with more simple ones.
17  *
18  * Eduard Bloch <blade@debian.org>
19 */
20 /* @(#)mkisofs.c        1.167 06/01/30 joerg */
21 /* Parts from @(#)mkisofs.c     1.206 07/02/26 joerg */
22 /*
23  * Program genisoimage.c - generate iso9660 filesystem  based upon directory
24  * tree on hard disk.
25  *
26  * Written by Eric Youngdale (1993).
27  *
28  * Copyright 1993 Yggdrasil Computing, Incorporated
29  * Copyright (c) 1999,2000-2004 J. Schilling
30  *
31  * This program is free software; you can redistribute it and/or modify
32  * it under the terms of the GNU General Public License as published by
33  * the Free Software Foundation; either version 2, or (at your option)
34  * any later version.
35  *
36  * This program is distributed in the hope that it will be useful,
37  * but WITHOUT ANY WARRANTY; without even the implied warranty of
38  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39  * GNU General Public License for more details.
40  *
41  * You should have received a copy of the GNU General Public License
42  * along with this program; if not, write to the Free Software
43  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44  */
45
46 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 */
47
48 #include <mconfig.h>
49 #include "genisoimage.h"
50 #include <errno.h>
51 #include <timedefs.h>
52 #include <fctldefs.h>
53 #include <ctype.h>
54 #include "match.h"
55 #include "exclude.h"
56 #include <unls.h>       /* For UNICODE translation */
57 #include <schily.h>
58 #ifdef UDF
59 #include "udf.h"
60 #endif
61
62 #ifdef  NEED_O_BINARY
63 #include <io.h>                                 /* for setmode() prototype */
64 #endif
65
66 #ifdef HAVE_GETOPT_H
67 #include <getopt.h>
68 #else
69 #include "getopt.h"
70 extern int      optind;
71 extern char     *optarg;
72 #endif
73
74 #ifdef VMS
75 #include "vms.h"
76 #endif
77
78 #ifdef  no_more_needed
79 #ifdef __NetBSD__
80 #include <sys/resource.h>
81 #endif
82 #endif  /* no_more_needed */
83
84 #ifdef USE_ICONV
85 #include <locale.h>
86 #include <langinfo.h>
87 #endif
88
89 struct directory *root = NULL;
90 int             path_ind;
91
92 char    version_string[] = "genisoimage " CDRKIT_VERSION;
93
94 char            *outfile;
95 FILE            *discimage;
96 unsigned int    next_extent     = 0;
97 unsigned int    last_extent     = 0;
98 unsigned int    session_start   = 0;
99 unsigned int    path_table_size = 0;
100 unsigned int    path_table[4]   = {0, };
101 unsigned int    path_blocks     = 0;
102
103
104 unsigned int    jpath_table_size = 0;
105 unsigned int    jpath_table[4]  = {0, };
106 unsigned int    jpath_blocks    = 0;
107
108 struct iso_directory_record root_record;
109 struct iso_directory_record jroot_record;
110
111 char    *extension_record = NULL;
112 int     extension_record_extent = 0;
113 int     extension_record_size = 0;
114
115 /* These variables are associated with command line options */
116 int     check_oldnames = 0;
117 int     check_session = 0;
118 int     use_eltorito = 0;
119 int     hard_disk_boot = 0;
120 int     not_bootable = 0;
121 int     no_emul_boot = 0;
122 int     load_addr = 0;
123 int     load_size = 0;
124 int     boot_info_table = 0;
125 int     use_alphaboot = 0;
126 int     use_sparcboot = 0;
127 int     use_hppaboot = 0;
128 int     use_mipsboot = 0;
129 int     use_mipselboot = 0;
130 int     use_sunx86boot = 0;
131 int     use_genboot = 0;
132 int     use_RockRidge = 0;
133 int     use_XA = 0;
134 int     osecsize = 0;   /* Output-sector size, 0 means default secsize 2048 */
135 int     use_Joliet = 0;
136 int     jlen = JMAX;    /* maximum Joliet file name length */
137 int     verbose = 1;
138 int     debug = 0;
139 int     gui = 0;
140 int     all_files = 1;  /* New default is to include all files */
141 int     follow_links = 0;
142 #ifdef  IS_CYGWIN
143 int     cache_inodes = 0; /* Do not cache inodes on Cygwin by default */
144 #else
145 int     cache_inodes = 1; /* Cache inodes if OS has unique inodes */
146 #endif
147 int     rationalize = 0;
148 int     rationalize_uid = 0;
149 int     rationalize_gid = 0;
150 int     rationalize_filemode = 0;
151 int     rationalize_dirmode = 0;
152 uid_t   uid_to_use = 0;         /* when rationalizing uid */
153 gid_t   gid_to_use = 0;         /* when rationalizing gid */
154 int     filemode_to_use = 0;    /* if non-zero, when rationalizing file mode */
155 int     dirmode_to_use = 0;     /* if non-zero, when rationalizing dir mode */
156 int     new_dir_mode = 0555;
157 int     generate_tables = 0;
158 int     dopad = 1;      /* Now default to do padding */
159 int     print_size = 0;
160 int     split_output = 0;
161 char    *icharset = NULL;       /* input charset to convert to UNICODE */
162 char    *ocharset = NULL;       /* output charset to convert from UNICODE */
163 char    *preparer = PREPARER_DEFAULT;
164 char    *publisher = PUBLISHER_DEFAULT;
165 char    *appid = APPID_DEFAULT;
166 char    *copyright = COPYRIGHT_DEFAULT;
167 char    *biblio = BIBLIO_DEFAULT;
168 char    *abstract = ABSTRACT_DEFAULT;
169 char    *volset_id = VOLSET_ID_DEFAULT;
170 char    *volume_id = VOLUME_ID_DEFAULT;
171 char    *system_id = SYSTEM_ID_DEFAULT;
172 char    *boot_catalog = BOOT_CATALOG_DEFAULT;
173 char    *boot_image = BOOT_IMAGE_DEFAULT;
174 char    *genboot_image = BOOT_IMAGE_DEFAULT;
175 int     ucs_level = 3;          /* We now have Unicode tables so use level 3 */
176 int     volume_set_size = 1;
177 int     volume_sequence_number = 1;
178
179 struct eltorito_boot_entry_info *first_boot_entry = NULL;
180 struct eltorito_boot_entry_info *last_boot_entry = NULL;
181 struct eltorito_boot_entry_info *current_boot_entry = NULL;
182
183 int     use_graft_ptrs;         /* Use graft points */
184 int     jhide_trans_tbl;        /* Hide TRANS.TBL from Joliet tree */
185 int     hide_rr_moved;          /* Name RR_MOVED .rr_moved in Rock Ridge tree */
186 int     omit_period = 0;        /* Violates iso9660, but these are a pain */
187 int     transparent_compression = 0; /* So far only works with linux */
188 int     omit_version_number = 0; /* May violate iso9660, but noone uses vers */
189 int     no_rr = 0;              /* Do not use RR attributes from old session */
190 int     force_rr = 0;           /* Force to use RR attributes from old session */
191 Uint    RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
192 int     iso9660_level = 1;
193 int     iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */
194 int     full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */
195 int     relaxed_filenames = 0;  /* For Amiga.  Disc will not work with DOS */
196 int     allow_lowercase = 0;    /* Allow lower case letters */
197 int     allow_multidot = 0;     /* Allow more than on dot in filename */
198 int     iso_translate = 1;      /* 1 == enables '#', '-' and '~' removal */
199 int     allow_leading_dots = 0; /* DOS cannot read names with leading dots */
200 int     allow_limited_size = 0; /* Let the user to allow the trick explicitely */
201 #ifdef  VMS
202 int     use_fileversion = 1;    /* Use file version # from filesystem */
203 #else
204 int     use_fileversion = 0;    /* Use file version # from filesystem */
205 #endif
206 int     split_SL_component = 1; /* circumvent a bug in the SunOS driver */
207 int     split_SL_field = 1;     /* circumvent a bug in the SunOS */
208 char    *trans_tbl = "TRANS.TBL"; /* default name for translation table */
209 int     stream_media_size = 0;  /* # of blocks on the media */
210 char    *stream_filename = NULL; /* Stream file, 0 to use default STREAM.IMG */
211
212 #ifdef APPLE_HYB
213 int     apple_hyb = 0;          /* create HFS hybrid flag */
214 int     apple_ext = 0;          /* create HFS extensions flag */
215 int     apple_both = 0;         /* common flag (for above) */
216 int     hfs_extra = 0;          /* extra HFS blocks added to end of ISO vol */
217 int     use_mac_name = 0;       /* use Mac name for ISO/Joliet/RR flag */
218 hce_mem *hce;                   /* libhfs/genisoimage extras */
219 char    *hfs_boot_file = 0;     /* name of HFS boot file */
220 int     gen_pt = 0;             /* generate HFS partition table */
221 char    *autoname = 0;          /* AutoStart filename */
222 char    *magic_filename = 0;    /* name of magic file */
223 int     probe = 0;              /* search files for HFS/Unix type */
224 int     nomacfiles = 0;         /* don't look for Mac/Unix files */
225 int     hfs_select = 0;         /* Mac/Unix types to select */
226 int     create_dt = 1;          /* create the Desktp files */
227 int     afe_size = 0;           /* Apple File Exchange block size */
228 int     hfs_last = MAG_LAST;    /* process magic file after map file */
229 char    *deftype = APPLE_TYPE_DEFAULT;  /* default Apple TYPE */
230 char    *defcreator = APPLE_CREATOR_DEFAULT;    /* default Apple CREATOR */
231 char    *hfs_volume_id = NULL;  /* HFS volume ID */
232 int     icon_pos = 0;           /* Keep icon position */
233 char    *hfs_icharset = NULL;   /* input HFS charset name */
234 char    *hfs_ocharset = NULL;   /* output HFS charset name */
235 int     hfs_lock = 1;           /* lock HFS volume (read-only) */
236 char    *hfs_bless = NULL;      /* name of folder to 'bless' (System Folder) */
237 char    *hfs_parms = NULL;      /* low level HFS parameters */
238
239 #ifdef PREP_BOOT
240 char    *prep_boot_image[4];
241 int     use_prep_boot = 0;
242 int     use_chrp_boot = 0;
243 #endif  /* PREP_BOOT */
244 #endif  /* APPLE_HYB */
245
246 #ifdef UDF
247 int     use_udf = 0;
248 #endif
249
250 #ifdef DVD_VIDEO
251 int     dvd_video = 0;
252 #endif
253
254 #ifdef SORTING
255 int     do_sort = 0;            /* sort file data */
256 #endif /* SORTING */
257
258 #ifdef USE_ICONV
259 int   iconv_possible;
260 #endif
261
262 struct unls_table *in_nls = NULL;  /* input UNICODE conversion table */
263 struct unls_table *out_nls = NULL; /* output UNICODE conversion table */
264 #ifdef APPLE_HYB
265 struct unls_table *hfs_inls = NULL; /* input HFS UNICODE conversion table */
266 struct unls_table *hfs_onls = NULL; /* output HFS UNICODE conversion table */
267 #endif /* APPLE_HYB */
268
269 struct rcopts {
270         char            *tag;
271         char            **variable;
272 };
273
274 struct rcopts rcopt[] = {
275         {"PREP", &preparer},
276         {"PUBL", &publisher},
277         {"APPI", &appid},
278         {"COPY", &copyright},
279         {"BIBL", &biblio},
280         {"ABST", &abstract},
281         {"VOLS", &volset_id},
282         {"VOLI", &volume_id},
283         {"SYSI", &system_id},
284 #ifdef APPLE_HYB
285         {"HFS_TYPE", &deftype},
286         {"HFS_CREATOR", &defcreator},
287 #endif  /* APPLE_HYB */
288         {NULL, NULL}
289 };
290
291 char            *merge_warn_msg=0; /* use as pointer and boolean */
292
293 /*
294  * In case it isn't obvious, the option handling code was ripped off
295  * from GNU-ld.
296  */
297 struct ld_option {
298         /* The long option information.  */
299         struct option   opt;
300         /* The short option with the same meaning ('\0' if none).  */
301         char            shortopt;
302         /* The name of the argument (NULL if none).  */
303         const char      *arg;
304         /*
305          * The documentation string.  If this is NULL, this is a synonym for
306          * the previous option.
307          */
308         const char      *doc;
309         enum {
310                 /* Use one dash before long option name.  */
311                 ONE_DASH,
312                 /* Use two dashes before long option name.  */
313                 TWO_DASHES,
314                 /* Don't mention this option in --help output.  */
315                 NO_HELP
316         } control;
317 };
318
319 /*
320  * Codes used for the long options with no short synonyms. Note that all these
321  * values must not be ASCII or EBCDIC.
322  */
323 #define OPTION_HELP                     1000
324 #define OPTION_QUIET                    1001
325 #define OPTION_NOSPLIT_SL_COMPONENT     1002
326 #define OPTION_NOSPLIT_SL_FIELD         1003
327 #define OPTION_PRINT_SIZE               1004
328 #define OPTION_SPLIT_OUTPUT             1005
329 #define OPTION_ABSTRACT                 1006
330 #define OPTION_BIBLIO                   1007
331 #define OPTION_COPYRIGHT                1008
332 #define OPTION_SYSID                    1009
333 #define OPTION_VOLSET                   1010
334 #define OPTION_VOLSET_SIZE              1011
335 #define OPTION_VOLSET_SEQ_NUM           1012
336 #define OPTION_I_HIDE                   1013
337 #define OPTION_J_HIDE                   1014
338 #define OPTION_LOG_FILE                 1015
339 #define OPTION_PVERSION                 1016
340 #define OPTION_NOBAK                    1017
341 #define OPTION_SPARCLABEL               1018
342 #define OPTION_HARD_DISK_BOOT           1019
343 #define OPTION_NO_EMUL_BOOT             1020
344 #define OPTION_NO_BOOT                  1021
345 #define OPTION_BOOT_LOAD_ADDR           1022
346 #define OPTION_BOOT_LOAD_SIZE           1023
347 #define OPTION_BOOT_INFO_TABLE          1024
348 #define OPTION_HIDE_TRANS_TBL           1025
349 #define OPTION_HIDE_RR_MOVED            1026
350 #define OPTION_GUI                      1027
351 #define OPTION_TRANS_TBL                1028
352 #define OPTION_P_LIST                   1029
353 #define OPTION_I_LIST                   1030
354 #define OPTION_J_LIST                   1031
355 #define OPTION_X_LIST                   1032
356 #define OPTION_NO_RR                    1033
357 #define OPTION_JCHARSET                 1034
358 #define OPTION_PAD                      1035
359 #define OPTION_H_HIDE                   1036
360 #define OPTION_H_LIST                   1037
361 #define OPTION_CHECK_OLDNAMES           1038
362
363 #ifdef SORTING
364 #define OPTION_SORT                     1039
365 #endif /* SORTING */
366 #define OPTION_UCS_LEVEL                1040
367 #define OPTION_ISO_TRANSLATE            1041
368 #define OPTION_ISO_LEVEL                1042
369 #define OPTION_RELAXED_FILENAMES        1043
370 #define OPTION_ALLOW_LOWERCASE          1044
371 #define OPTION_ALLOW_MULTIDOT           1045
372 #define OPTION_USE_FILEVERSION          1046
373 #define OPTION_MAX_FILENAMES            1047
374 #define OPTION_ALT_BOOT                 1048
375 #define OPTION_USE_GRAFT                1049
376
377 #define OPTION_INPUT_CHARSET            1050
378 #define OPTION_OUTPUT_CHARSET           1051
379
380 #define OPTION_NOPAD                    1052
381 #define OPTION_UID                      1053
382 #define OPTION_GID                      1054
383 #define OPTION_FILEMODE                 1055
384 #define OPTION_DIRMODE                  1056
385 #define OPTION_NEW_DIR_MODE             1057
386 #define OPTION_CACHE_INODES             1058
387 #define OPTION_NOCACHE_INODES           1059
388
389 #define OPTION_CHECK_SESSION            1060
390 #define OPTION_FORCE_RR                 1061
391
392 #define OPTION_DEBUG                    1062
393
394 #define OPTION_JLONG                    1063
395
396 #define OPTION_STREAM_FILE_NAME         1064
397 #define OPTION_STREAM_CD_SIZE           1065
398
399 #define OPTION_XA                       1066
400 #define OPTION_XA_RATIONALIZED          1067
401
402 #define OPTION_SUNX86BOOT               1068
403 #define OPTION_SUNX86LABEL              1069
404
405 #define OPTION_ALLOW_LEADING_DOTS       1070
406 #define OPTION_PUBLISHER                1071
407
408 #ifdef          JIGDO_TEMPLATE
409 #define OPTION_JTT_OUTPUT               1101
410 #define OPTION_JTJ_OUTPUT               1102
411 #define OPTION_JT_MIN_SIZE              1103
412 #define OPTION_JT_PATH_MAP              1104
413 #define OPTION_JT_MD5_LIST              1105
414 #define OPTION_JT_INCLUDE               1106
415 #define OPTION_JT_EXCLUDE               1107
416 #define OPTION_JT_COMPRESS_ALGO 1108
417
418 #define OPTION_JT_CHECKSUM_ALGO_ISO   1120
419 #define OPTION_JT_CHECKSUM_ALGO_TMPL  1121
420 #endif
421
422 #define OPTION_BOOTALPHA                1200
423
424 #define OPTION_HPPA_CMDLINE             1210
425 #define OPTION_HPPA_KERNEL_32           1211
426 #define OPTION_HPPA_KERNEL_64           1212
427 #define OPTION_HPPA_BOOTLOADER          1213
428 #define OPTION_HPPA_RAMDISK             1214
429
430 #define OPTION_BOOTMIPS                 1220
431
432 #define OPTION_BOOTMIPSEL               1230
433
434 #ifdef UDF
435 #define OPTION_UDF                      1500
436 #endif
437 #ifdef DVD_VIDEO
438 #define OPTION_DVD                      1501
439 #endif
440
441 #ifdef APPLE_HYB
442 #define OPTION_CAP                      2000
443 #define OPTION_NETA                     2001
444 #define OPTION_DBL                      2002
445 #define OPTION_ESH                      2003
446 #define OPTION_FE                       2004
447 #define OPTION_SGI                      2005
448 #define OPTION_MBIN                     2006
449 #define OPTION_SGL                      2007
450 /* aliases */
451 #define OPTION_USH                      2008
452 #define OPTION_XIN                      2009
453
454 #define OPTION_DAVE                     2010
455 #define OPTION_SFM                      2011
456 #define OPTION_XDBL                     2012
457 #define OPTION_XHFS                     2013
458
459 #define OPTION_PROBE                    2020
460 #define OPTION_MACNAME                  2021
461 #define OPTION_NOMACFILES               2022
462 #define OPTION_BOOT_HFS_FILE            2023
463 #define OPTION_MAGIC_FILE               2024
464
465 #define OPTION_HFS_LIST                 2025
466
467 #define OPTION_GEN_PT                   2026
468
469 #define OPTION_CREATE_DT                2027
470 #define OPTION_HFS_HIDE                 2028
471
472 #define OPTION_AUTOSTART                2029
473 #define OPTION_BSIZE                    2030
474 #define OPTION_HFS_VOLID                2031
475 #define OPTION_PREP_BOOT                2032
476 #define OPTION_ICON_POS                 2033
477
478 #define OPTION_HFS_TYPE                 2034
479 #define OPTION_HFS_CREATOR              2035
480
481 #define OPTION_ROOT_INFO                2036
482
483 #define OPTION_HFS_INPUT_CHARSET        2037
484 #define OPTION_HFS_OUTPUT_CHARSET       2038
485
486 #define OPTION_HFS_UNLOCK               2039
487 #define OPTION_HFS_BLESS                2040
488 #define OPTION_HFS_PARMS                2041
489
490 #define OPTION_CHRP_BOOT                2042
491
492 #define OPTION_RELOC_ROOT               2043
493 #define OPTION_RELOC_OLD_ROOT           2044
494
495 #define OPTION_MAP_FILE                 2045
496
497 #define OPTION_ALLOW_LIMITED_SIZE 2046
498
499 #endif  /* APPLE_HYB */
500
501 static int      save_pname = 0;
502
503 static const struct ld_option ld_options[] =
504 {
505         {{"nobak", no_argument, NULL, OPTION_NOBAK},
506         '\0', NULL, "Do not include backup files", ONE_DASH},
507         {{"no-bak", no_argument, NULL, OPTION_NOBAK},
508         '\0', NULL, "Do not include backup files", ONE_DASH},
509         {{"abstract", required_argument, NULL, OPTION_ABSTRACT},
510         '\0', "FILE", "Set Abstract filename", ONE_DASH},
511         {{"appid", required_argument, NULL, 'A'},
512         'A', "ID", "Set Application ID", ONE_DASH},
513         {{"biblio", required_argument, NULL, OPTION_BIBLIO},
514         '\0', "FILE", "Set Bibliographic filename", ONE_DASH},
515         {{"cache-inodes", no_argument, NULL, OPTION_CACHE_INODES},
516         '\0', NULL, "Cache inodes (needed to detect hard links)", ONE_DASH},
517         {{"no-cache-inodes", no_argument, NULL, OPTION_NOCACHE_INODES},
518         '\0', NULL, "Do not cache inodes (if filesystem has no unique unides)", ONE_DASH},
519         {{"check-oldnames", no_argument, NULL, OPTION_CHECK_OLDNAMES},
520         '\0', NULL, "Check all imported ISO9660 names from old session", ONE_DASH},
521         {{"check-session", required_argument, NULL, OPTION_CHECK_SESSION},
522         '\0', "FILE", "Check all ISO9660 names from previous session", ONE_DASH},
523         {{"copyright", required_argument, NULL, OPTION_COPYRIGHT},
524         '\0', "FILE", "Set Copyright filename", ONE_DASH},
525         {{"debug", no_argument, NULL, OPTION_DEBUG},
526         '\0', NULL, "Set debug flag", ONE_DASH},
527         {{"eltorito-boot", required_argument, NULL, 'b'},
528         'b', "FILE", "Set El Torito boot image name", ONE_DASH},
529         {{"eltorito-alt-boot", no_argument, NULL, OPTION_ALT_BOOT},
530         '\0', NULL, "Start specifying alternative El Torito boot parameters", ONE_DASH},
531         {{"sparc-boot", required_argument, NULL, 'B'},
532         'B', "FILES", "Set sparc boot image names", ONE_DASH},
533         {{"sunx86-boot", required_argument, NULL, OPTION_SUNX86BOOT},
534         '\0', "FILES", "Set sunx86 boot image names", ONE_DASH},
535         {{"generic-boot", required_argument, NULL, 'G'},
536         'G', "FILE", "Set generic boot image name", ONE_DASH},
537         {{"sparc-label", required_argument, NULL, OPTION_SPARCLABEL},
538         '\0', "label text", "Set sparc boot disk label", ONE_DASH},
539         {{"sunx86-label", required_argument, NULL, OPTION_SUNX86LABEL},
540         '\0', "label text", "Set sunx86 boot disk label", ONE_DASH},
541         {{"eltorito-catalog", required_argument, NULL, 'c'},
542         'c', "FILE", "Set El Torito boot catalog name", ONE_DASH},
543         {{"cdrecord-params", required_argument, NULL, 'C'},
544         'C', "PARAMS", "Magic paramters from cdrecord", ONE_DASH},
545         {{"omit-period", no_argument, NULL, 'd'},
546         'd', NULL, "Omit trailing periods from filenames (violates ISO9660)", ONE_DASH},
547         {{"dir-mode", required_argument, NULL, OPTION_DIRMODE},
548         '\0', "mode", "Make the mode of all directories this mode.", ONE_DASH},
549         {{"disable-deep-relocation", no_argument, NULL, 'D'},
550         'D', NULL, "Disable deep directory relocation (violates ISO9660)", ONE_DASH},
551         {{"file-mode", required_argument, NULL, OPTION_FILEMODE},
552         '\0', "mode", "Make the mode of all plain files this mode.", ONE_DASH},
553         {{"follow-links", no_argument, NULL, 'f'},
554         'f', NULL, "Follow symbolic links", ONE_DASH},
555         {{"gid", required_argument, NULL, OPTION_GID},
556         '\0', "gid", "Make the group owner of all files this gid.",
557         ONE_DASH},
558         {{"graft-points", no_argument, NULL, OPTION_USE_GRAFT},
559         '\0', NULL, "Allow to use graft points for filenames", ONE_DASH},
560         {{"root", required_argument, NULL, OPTION_RELOC_ROOT},
561         '\0', "DIR", "Set root directory for all new files and directories", ONE_DASH},
562         {{"old-root", required_argument, NULL, OPTION_RELOC_OLD_ROOT},
563         '\0', "DIR", "Set root directory in previous session that is searched for files", ONE_DASH},
564         {{"help", no_argument, NULL, OPTION_HELP},
565         '\0', NULL, "Print option help", ONE_DASH},
566         {{"hide", required_argument, NULL, OPTION_I_HIDE},
567         '\0', "GLOBFILE", "Hide ISO9660/RR file", ONE_DASH},
568         {{"hide-list", required_argument, NULL, OPTION_I_LIST},
569         '\0', "FILE", "File with list of ISO9660/RR files to hide", ONE_DASH},
570         {{"hidden", required_argument, NULL, OPTION_H_HIDE},
571         '\0', "GLOBFILE", "Set hidden attribute on ISO9660 file", ONE_DASH},
572         {{"hidden-list", required_argument, NULL, OPTION_H_LIST},
573         '\0', "FILE", "File with list of ISO9660 files with hidden attribute", ONE_DASH},
574         {{"hide-joliet", required_argument, NULL, OPTION_J_HIDE},
575         '\0', "GLOBFILE", "Hide Joliet file", ONE_DASH},
576         {{"hide-joliet-list", required_argument, NULL, OPTION_J_LIST},
577         '\0', "FILE", "File with list of Joliet files to hide", ONE_DASH},
578         {{"hide-joliet-trans-tbl", no_argument, NULL, OPTION_HIDE_TRANS_TBL},
579         '\0', NULL, "Hide TRANS.TBL from Joliet tree", ONE_DASH},
580         {{"hide-rr-moved", no_argument, NULL, OPTION_HIDE_RR_MOVED},
581         '\0', NULL, "Rename RR_MOVED to .rr_moved in Rock Ridge tree", ONE_DASH},
582         {{"gui", no_argument, NULL, OPTION_GUI},
583         '\0', NULL, "Switch behaviour for GUI", ONE_DASH},
584         {{NULL, required_argument, NULL, 'i'},
585         'i', "ADD_FILES", "No longer supported", TWO_DASHES},
586         {{"input-charset", required_argument, NULL, OPTION_INPUT_CHARSET},
587         '\0', "CHARSET", "Local input charset for file name conversion", ONE_DASH},
588         {{"output-charset", required_argument, NULL, OPTION_OUTPUT_CHARSET},
589         '\0', "CHARSET", "Output charset for file name conversion", ONE_DASH},
590         {{"iso-level", required_argument, NULL, OPTION_ISO_LEVEL},
591         '\0', "LEVEL", "Set ISO9660 conformance level (1..3) or 4 for ISO9660 version 2", ONE_DASH},
592         {{"joliet", no_argument, NULL, 'J'},
593         'J', NULL, "Generate Joliet directory information", ONE_DASH},
594         {{"joliet-long", no_argument, NULL, OPTION_JLONG},
595         '\0', NULL, "Allow Joliet file names to be 103 Unicode characters", ONE_DASH},
596         {{"jcharset", required_argument, NULL, OPTION_JCHARSET},
597         '\0', "CHARSET", "Local charset for Joliet directory information", ONE_DASH},
598         {{"full-iso9660-filenames", no_argument, NULL, 'l'},
599         'l', NULL, "Allow full 31 character filenames for ISO9660 names", ONE_DASH},
600         {{"max-iso9660-filenames", no_argument, NULL, OPTION_MAX_FILENAMES},
601         '\0', NULL, "Allow 37 character filenames for ISO9660 names (violates ISO9660)", ONE_DASH},
602
603         {{"allow-limited-size", no_argument, NULL, OPTION_ALLOW_LIMITED_SIZE},
604         '\0', NULL, "Allow different file sizes in ISO9660/UDF on large files", ONE_DASH},
605
606         {{"allow-leading-dots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS},
607         '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
608         {{"ldots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS},
609         '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
610         {{"allow-leading-dots", no_argument, NULL, 'L'},
611         'L', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
612
613         {{"log-file", required_argument, NULL, OPTION_LOG_FILE},
614         '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH},
615         {{"exclude", required_argument, NULL, 'm'},
616         'm', "GLOBFILE", "Exclude file name", ONE_DASH},
617         {{"exclude-list", required_argument, NULL, OPTION_X_LIST},
618         '\0', "FILE", "File with list of file names to exclude", ONE_DASH},
619         {{"pad", no_argument, NULL, OPTION_PAD},
620         0, NULL, "Pad output to a multiple of 32k (default)", ONE_DASH},
621         {{"no-pad", no_argument, NULL, OPTION_NOPAD},
622         0, NULL, "Do not pad output to a multiple of 32k", ONE_DASH},
623         {{"prev-session", required_argument, NULL, 'M'},
624         'M', "FILE", "Set path to previous session to merge", ONE_DASH},
625         {{"dev", required_argument, NULL, 'M'},
626         '\0', "SCSIdev", "Set path to previous session to merge", ONE_DASH},
627         {{"omit-version-number", no_argument, NULL, 'N'},
628         'N', NULL, "Omit version number from ISO9660 filename (violates ISO9660)", ONE_DASH},
629         {{"new-dir-mode", required_argument, NULL, OPTION_NEW_DIR_MODE},
630         '\0', "mode", "Mode used when creating new directories.", ONE_DASH},
631         {{"force-rr", no_argument, NULL, OPTION_FORCE_RR},
632         0, NULL, "Inhibit automatic Rock Ridge detection for previous session", ONE_DASH},
633         {{"no-rr", no_argument, NULL, OPTION_NO_RR},
634         0, NULL, "Inhibit reading of Rock Ridge attributes from previous session", ONE_DASH},
635         {{"no-split-symlink-components", no_argument, NULL, OPTION_NOSPLIT_SL_COMPONENT},
636         0, NULL, "Inhibit splitting symlink components", ONE_DASH},
637         {{"no-split-symlink-fields", no_argument, NULL, OPTION_NOSPLIT_SL_FIELD},
638         0, NULL, "Inhibit splitting symlink fields", ONE_DASH},
639         {{"output", required_argument, NULL, 'o'},
640         'o', "FILE", "Set output file name", ONE_DASH},
641         {{"path-list", required_argument, NULL, OPTION_P_LIST},
642         '\0', "FILE", "File with list of pathnames to process", ONE_DASH},
643         {{"preparer", required_argument, NULL, 'p'},
644         'p', "PREP", "Set Volume preparer", ONE_DASH},
645         {{"print-size", no_argument, NULL, OPTION_PRINT_SIZE},
646         '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH},
647         {{"publisher", required_argument, NULL, OPTION_PUBLISHER},
648         '\0', "PUB", "Set Volume publisher", ONE_DASH},
649         {{"publisher", required_argument, NULL, 'P'},
650         'P', "PUB", "Set Volume publisher", ONE_DASH},
651         {{"quiet", no_argument, NULL, OPTION_QUIET},
652         '\0', NULL, "Run quietly", ONE_DASH},
653         {{"rational-rock", no_argument, NULL, 'r'},
654         'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH},
655         {{"rock", no_argument, NULL, 'R'},
656         'R', NULL, "Generate Rock Ridge directory information", ONE_DASH},
657         {{"sectype", required_argument, NULL, 's'},
658         's', "TYPE", "Set output sector type to e.g. data/xa1/raw", ONE_DASH},
659
660         {{"alpha-boot", required_argument, NULL, OPTION_BOOTALPHA},
661         '\0', "FILE", "Set alpha boot image name (relative to image root)", ONE_DASH},
662
663         {{"hppa-cmdline", required_argument, NULL, OPTION_HPPA_CMDLINE},
664         '\0', "CMDLINE", "Set hppa boot command line (relative to image root)", ONE_DASH},
665         {{"hppa-kernel-32", required_argument, NULL, OPTION_HPPA_KERNEL_32},
666         '\0', "FILE", "Set hppa 32-bit image name (relative to image root)", ONE_DASH},
667         {{"hppa-kernel-64", required_argument, NULL, OPTION_HPPA_KERNEL_64},
668         '\0', "FILE", "Set hppa 64-bit image name (relative to image root)", ONE_DASH},
669         {{"hppa-bootloader", required_argument, NULL, OPTION_HPPA_BOOTLOADER},
670         '\0', "FILE", "Set hppa boot loader file name (relative to image root)", ONE_DASH},
671         {{"hppa-ramdisk", required_argument, NULL, OPTION_HPPA_RAMDISK},
672         '\0', "FILE", "Set hppa ramdisk file name (relative to image root)", ONE_DASH},
673
674         {{"mips-boot", required_argument, NULL, OPTION_BOOTMIPS},
675         '\0', "FILE", "Set mips boot image name (relative to image root)", ONE_DASH},
676
677         {{"mipsel-boot", required_argument, NULL, OPTION_BOOTMIPSEL},
678         '\0', "FILE", "Set mipsel boot image name (relative to image root)", ONE_DASH},
679
680 #ifdef JIGDO_TEMPLATE
681         {{"jigdo-jigdo", required_argument, NULL, OPTION_JTJ_OUTPUT},
682         '\0', "FILE", "Produce a jigdo .jigdo file as well as the .iso", ONE_DASH },
683         {{"jigdo-template", required_argument, NULL, OPTION_JTT_OUTPUT},
684         '\0', "FILE", "Produce a jigdo .template file as well as the .iso", ONE_DASH },
685         {{"jigdo-min-file-size", required_argument, NULL, OPTION_JT_MIN_SIZE},
686         '\0', "SIZE", "Minimum size for a file to be listed in the jigdo file", ONE_DASH },
687         {{"jigdo-force-md5", required_argument, NULL, OPTION_JT_INCLUDE},
688         '\0', "PATTERN", "Pattern(s) where files MUST match an externally-supplied MD5sum", ONE_DASH },
689         {{"jigdo-exclude", required_argument, NULL, OPTION_JT_EXCLUDE},
690         '\0', "PATTERN", "Pattern(s) to exclude from the jigdo file", ONE_DASH },
691         {{"jigdo-map", required_argument, NULL, OPTION_JT_PATH_MAP},
692         '\0', "PATTERN1=PATTERN2", "Pattern(s) to map paths (e.g. Debian=/mirror/debian)", ONE_DASH },
693         {{"md5-list", required_argument, NULL, OPTION_JT_MD5_LIST},
694         '\0', "FILE", "File containing MD5 sums of the files that should be checked", ONE_DASH },
695     {{"jigdo-template-compress", required_argument, NULL, OPTION_JT_COMPRESS_ALGO},
696      '\0', "ALGORITHM", "Choose to use gzip or bzip2 compression for template data; default is gzip", ONE_DASH },
697         {{"checksum_algorithm_iso", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_ISO},
698         '\0', "alg1,alg2,...", "Specify the checksum types desired for the output image", ONE_DASH},
699         {{"checksum_algorithm_template", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_TMPL},
700         '\0', "alg1,alg2,...", "Specify the checksum types desired for the output jigdo template", ONE_DASH},
701 #endif
702
703 #ifdef SORTING
704         { {"sort", required_argument, NULL, OPTION_SORT},
705         '\0', "FILE", "Sort file content locations according to rules in FILE", ONE_DASH },
706 #endif /* SORTING */
707
708         {{"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
709         '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH},
710         {{"stream-file-name", required_argument, NULL, OPTION_STREAM_FILE_NAME},
711         '\0', "FILE_NAME", "Set the stream file ISO9660 name (incl. version)", ONE_DASH},
712         {{"stream-media-size", required_argument, NULL, OPTION_STREAM_CD_SIZE},
713         '\0', "#", "Set the size of your CD media in sectors", ONE_DASH},
714         {{"sysid", required_argument, NULL, OPTION_SYSID},
715         '\0', "ID", "Set System ID", ONE_DASH},
716         {{"translation-table", no_argument, NULL, 'T'},
717         'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH},
718         {{"table-name", required_argument, NULL, OPTION_TRANS_TBL},
719         '\0', "TABLE_NAME", "Translation table file name", ONE_DASH},
720         {{"ucs-level", required_argument, NULL, OPTION_UCS_LEVEL},
721         '\0', "LEVEL", "Set Joliet UCS level (1..3)", ONE_DASH},
722
723 #ifdef UDF
724         {{"udf", no_argument, NULL, OPTION_UDF},
725         '\0', NULL, "Generate UDF file system", ONE_DASH},
726 #endif
727
728 #ifdef DVD_VIDEO
729         {{"dvd-video", no_argument, NULL, OPTION_DVD},
730         '\0', NULL, "Generate DVD-Video compliant UDF file system", ONE_DASH},
731 #endif
732
733         {{"uid", required_argument, NULL, OPTION_UID},
734         '\0', "uid", "Make the owner of all files this uid.",
735         ONE_DASH},
736         {{"untranslated-filenames", no_argument, NULL, 'U'},
737         /* CSTYLED */
738         'U', NULL, "Allow Untranslated filenames (for HPUX & AIX - violates ISO9660). Forces -l, -d, -N, -allow-leading-dots, -relaxed-filenames, -allow-lowercase, -allow-multidot", ONE_DASH},
739         {{"relaxed-filenames", no_argument, NULL, OPTION_RELAXED_FILENAMES},
740         '\0', NULL, "Allow 7 bit ASCII except lower case characters (violates ISO9660)", ONE_DASH},
741         {{"no-iso-translate", no_argument, NULL, OPTION_ISO_TRANSLATE},
742         '\0', NULL, "Do not translate illegal ISO characters '~', '-' and '#' (violates ISO9660)", ONE_DASH},
743         {{"allow-lowercase", no_argument, NULL, OPTION_ALLOW_LOWERCASE},
744         '\0', NULL, "Allow lower case characters in addition to the current character set (violates ISO9660)", ONE_DASH},
745         {{"allow-multidot", no_argument, NULL, OPTION_ALLOW_MULTIDOT},
746         '\0', NULL, "Allow more than one dot in filenames (e.g. .tar.gz) (violates ISO9660)", ONE_DASH},
747         {{"use-fileversion", no_argument, NULL, OPTION_USE_FILEVERSION},
748         '\0', "LEVEL", "Use file version # from filesystem", ONE_DASH},
749         {{"verbose", no_argument, NULL, 'v'},
750         'v', NULL, "Verbose", ONE_DASH},
751         {{"version", no_argument, NULL, OPTION_PVERSION},
752         '\0', NULL, "Print the current version", ONE_DASH},
753         {{"volid", required_argument, NULL, 'V'},
754         'V', "ID", "Set Volume ID", ONE_DASH},
755         {{"volset", required_argument, NULL, OPTION_VOLSET},
756         '\0', "ID", "Set Volume set ID", ONE_DASH},
757         {{"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE},
758         '\0', "#", "Set Volume set size", ONE_DASH},
759         {{"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM},
760         '\0', "#", "Set Volume set sequence number", ONE_DASH},
761         {{"old-exclude", required_argument, NULL, 'x'},
762         'x', "FILE", "Exclude file name(depreciated)", ONE_DASH},
763         {{"hard-disk-boot", no_argument, NULL, OPTION_HARD_DISK_BOOT},
764         '\0', NULL, "Boot image is a hard disk image", ONE_DASH},
765         {{"no-emul-boot", no_argument, NULL, OPTION_NO_EMUL_BOOT},
766         '\0', NULL, "Boot image is 'no emulation' image", ONE_DASH},
767         {{"no-boot", no_argument, NULL, OPTION_NO_BOOT},
768         '\0', NULL, "Boot image is not bootable", ONE_DASH},
769         {{"boot-load-seg", required_argument, NULL, OPTION_BOOT_LOAD_ADDR},
770         '\0', "#", "Set load segment for boot image", ONE_DASH},
771         {{"boot-load-size", required_argument, NULL, OPTION_BOOT_LOAD_SIZE},
772         '\0', "#", "Set numbers of load sectors", ONE_DASH},
773         {{"boot-info-table", no_argument, NULL, OPTION_BOOT_INFO_TABLE},
774         '\0', NULL, "Patch boot image with info table", ONE_DASH},
775         {{"XA", no_argument, NULL, OPTION_XA},
776         '\0', NULL, "Generate XA directory attruibutes", ONE_DASH},
777         {{"xa", no_argument, NULL, OPTION_XA_RATIONALIZED},
778         '\0', NULL, "Generate rationalized XA directory attruibutes", ONE_DASH},
779         {{"transparent-compression", no_argument, NULL, 'z'},
780         'z', NULL, "Enable transparent compression of files", ONE_DASH},
781
782 #ifdef APPLE_HYB
783         {{"hfs-type", required_argument, NULL, OPTION_HFS_TYPE},
784         '\0', "TYPE", "Set HFS default TYPE", ONE_DASH},
785         {{"hfs-creator", required_argument, NULL, OPTION_HFS_CREATOR},
786         '\0', "CREATOR", "Set HFS default CREATOR", ONE_DASH},
787         {{"apple", no_argument, NULL, 'g'},
788         'g', NULL, "Add Apple ISO9660 extensions", ONE_DASH},
789         {{"hfs", no_argument, NULL, 'h'},
790         'h', NULL, "Create ISO9660/HFS hybrid", ONE_DASH},
791         {{"map", required_argument, NULL, OPTION_MAP_FILE},
792         '\0', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
793         {{"map", required_argument, NULL, 'H'},
794         'H', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
795         {{"magic", required_argument, NULL, OPTION_MAGIC_FILE},
796         '\0', "FILE", "Magic file for HFS TYPE/CREATOR", ONE_DASH},
797         {{"probe", no_argument, NULL, OPTION_PROBE},
798         '\0', NULL, "Probe all files for Apple/Unix file types", ONE_DASH},
799         {{"mac-name", no_argument, NULL, OPTION_MACNAME},
800         '\0', NULL, "Use Macintosh name for ISO9660/Joliet/RockRidge file name",
801         ONE_DASH},
802         {{"no-mac-files", no_argument, NULL, OPTION_NOMACFILES},
803         '\0', NULL, "Do not look for Unix/Mac files (depreciated)", ONE_DASH},
804         {{"boot-hfs-file", required_argument, NULL, OPTION_BOOT_HFS_FILE},
805         '\0', "FILE", "Set HFS boot image name", ONE_DASH},
806         {{"part", no_argument, NULL, OPTION_GEN_PT},
807         '\0', NULL, "Generate HFS partition table", ONE_DASH},
808         {{"cluster-size", required_argument, NULL, OPTION_BSIZE},
809         '\0', "SIZE", "Cluster size for PC Exchange Macintosh files", ONE_DASH},
810         {{"auto", required_argument, NULL, OPTION_AUTOSTART},
811         '\0', "FILE", "Set HFS AutoStart file name", ONE_DASH},
812         {{"no-desktop", no_argument, NULL, OPTION_CREATE_DT},
813         '\0', NULL, "Do not create the HFS (empty) Desktop files", ONE_DASH},
814         {{"hide-hfs", required_argument, NULL, OPTION_HFS_HIDE},
815         '\0', "GLOBFILE", "Hide HFS file", ONE_DASH},
816         {{"hide-hfs-list", required_argument, NULL, OPTION_HFS_LIST},
817         '\0', "FILE", "List of HFS files to hide", ONE_DASH},
818         {{"hfs-volid", required_argument, NULL, OPTION_HFS_VOLID},
819         '\0', "HFS_VOLID", "Volume name for the HFS partition", ONE_DASH},
820         {{"icon-position", no_argument, NULL, OPTION_ICON_POS},
821         '\0', NULL, "Keep HFS icon position", ONE_DASH},
822         {{"root-info", required_argument, NULL, OPTION_ROOT_INFO},
823         '\0', "FILE", "finderinfo for root folder", ONE_DASH},
824         {{"input-hfs-charset", required_argument, NULL, OPTION_HFS_INPUT_CHARSET},
825         '\0', "CHARSET", "Local input charset for HFS file name conversion", ONE_DASH},
826         {{"output-hfs-charset", required_argument, NULL, OPTION_HFS_OUTPUT_CHARSET},
827         '\0', "CHARSET", "Output charset for HFS file name conversion", ONE_DASH},
828         {{"hfs-unlock", no_argument, NULL, OPTION_HFS_UNLOCK},
829         '\0', NULL, "Leave HFS Volume unlocked", ONE_DASH},
830         {{"hfs-bless", required_argument, NULL, OPTION_HFS_BLESS},
831         '\0', "FOLDER_NAME", "Name of Folder to be blessed", ONE_DASH},
832         {{"hfs-parms", required_argument, NULL, OPTION_HFS_PARMS},
833         '\0', "PARAMETERS", "Comma separated list of HFS parameters", ONE_DASH},
834 #ifdef PREP_BOOT
835         {{"prep-boot", required_argument, NULL, OPTION_PREP_BOOT},
836         '\0', "FILE", "PReP boot image file -- up to 4 are allowed", ONE_DASH},
837         {{"chrp-boot", no_argument, NULL, OPTION_CHRP_BOOT},
838         '\0', NULL, "Add CHRP boot header", ONE_DASH},
839 #endif  /* PREP_BOOT */
840         {{"cap", no_argument, NULL, OPTION_CAP},
841         '\0', NULL, "Look for AUFS CAP Macintosh files", TWO_DASHES},
842         {{"netatalk", no_argument, NULL, OPTION_NETA},
843         '\0', NULL, "Look for NETATALK Macintosh files", TWO_DASHES},
844         {{"double", no_argument, NULL, OPTION_DBL},
845         '\0', NULL, "Look for AppleDouble Macintosh files", TWO_DASHES},
846         {{"ethershare", no_argument, NULL, OPTION_ESH},
847         '\0', NULL, "Look for Helios EtherShare Macintosh files", TWO_DASHES},
848         {{"exchange", no_argument, NULL, OPTION_FE},
849         '\0', NULL, "Look for PC Exchange Macintosh files", TWO_DASHES},
850         {{"sgi", no_argument, NULL, OPTION_SGI},
851         '\0', NULL, "Look for SGI Macintosh files", TWO_DASHES},
852         {{"macbin", no_argument, NULL, OPTION_MBIN},
853         '\0', NULL, "Look for MacBinary Macintosh files", TWO_DASHES},
854         {{"single", no_argument, NULL, OPTION_SGL},
855         '\0', NULL, "Look for AppleSingle Macintosh files", TWO_DASHES},
856         {{"ushare", no_argument, NULL, OPTION_USH},
857         '\0', NULL, "Look for IPT UShare Macintosh files", TWO_DASHES},
858         {{"xinet", no_argument, NULL, OPTION_XIN},
859         '\0', NULL, "Look for XINET Macintosh files", TWO_DASHES},
860         {{"dave", no_argument, NULL, OPTION_DAVE},
861         '\0', NULL, "Look for DAVE Macintosh files", TWO_DASHES},
862         {{"sfm", no_argument, NULL, OPTION_SFM},
863         '\0', NULL, "Look for SFM Macintosh files", TWO_DASHES},
864         {{"osx-double", no_argument, NULL, OPTION_XDBL},
865         '\0', NULL, "Look for MacOS X AppleDouble Macintosh files", TWO_DASHES},
866         {{"osx-hfs", no_argument, NULL, OPTION_XHFS},
867         '\0', NULL, "Look for MacOS X HFS Macintosh files", TWO_DASHES},
868 #endif  /* APPLE_HYB */
869 };
870
871 #define OPTION_COUNT (sizeof ld_options / sizeof (ld_options[0]))
872
873 static  void    read_rcfile(char *appname);
874 static  void    susage(int excode);
875 static  void    usage(int excode);
876 int     iso9660_date(char *result, time_t crtime);
877 static  void    hide_reloc_dir(void);
878 static  char *get_pnames(int argc, char **argv, int opt, char *pname, 
879                                                                   int pnsize, FILE *fp);
880 char *findgequal(char *s);
881 static  char *escstrcpy(char *to, char *from);
882 void *e_malloc(size_t size);
883
884 static int
885 read_one_rcfile(char *filename)
886 {
887         int linum = 0;
888         char linebuffer[256];
889         FILE *fp;
890
891         if (!filename)
892                 return 0;
893
894         fp = fopen(filename, "r");
895         if (!fp) {
896                 if (errno == ENOENT)
897                         return 0;
898 #ifdef  USE_LIBSCHILY
899                 errmsg("Cannot open '%s'.\n", filename);
900 #else
901                 perror(filename);
902 #endif
903                 return 0;
904         }
905         if (verbose > 0)
906                 fprintf(stderr, "Using \"%s\"\n", filename);
907
908         while (fgets(linebuffer, sizeof(linebuffer), fp)) {
909                 char *name, *p, *p1;
910                 struct rcopts *rco;
911
912                 ++linum;
913                 /* skip any leading white space */
914                 for (p = linebuffer; *p == ' ' || *p == '\t'; p++)
915                         ;
916                 /* Skip comments and blank lines */
917                 if (!*p || *p == '\n' || *p == '\r' || *p == '#')
918                         continue;
919                 /*
920                  * The name should begin in the left margin.  Make sure it is
921                  * in upper case.  Stop when we see white space or a comment.
922                  */
923                 name = p;
924                 while (*p && (isalpha((unsigned char) *p) || *p == '_'))
925                         *p++ = toupper((unsigned char) *p);
926
927                 if (name == p) {
928                         fprintf(stderr, "%s:%d: name required\n", filename,
929                                         linum);
930                         continue;
931                 }
932
933                 p1 = p;
934                 /* Skip past white space after the name */
935                 while (*p == ' ' || *p == '\t')
936                         p++;
937                 /* silently ignore errors in the rc file. */
938                 if (*p != '=') {
939                         fprintf(stderr, "%s:%d: equals sign required after '%.*s'\n",
940                                                 filename, linum,
941                                                 (int)(p1-name), name);
942                         continue;
943                 }
944                 *p1 = 0;
945
946                 /* Skip pas the = sign, and any white space following it */
947                 p++;
948                 while (*p == ' ' || *p == '\t')
949                         p++;
950
951                 /* Get rid of trailing newline */
952                 for (p1 = p; *p1 && *p1 != '\n' && *p1 != '\r'; p1++)
953                         ;
954                 *p1 = 0;
955
956                 /* Figure out which option we have */
957                 for (rco = rcopt; rco->tag; rco++)
958                         if (strcmp(rco->tag, name) == 0) {
959                                 /* memleak if we ever do this more than once */
960                                 *rco->variable = strdup(p);
961                                 break;
962                         }
963
964                 if (!rco->tag) {
965                         fprintf(stderr, "%s:%d: field name '%s' unknown\n",
966                                 filename, linum,
967                                 name);
968                 }
969         }
970         if (ferror(fp)) {
971 #ifdef  USE_LIBSCHILY
972                 errmsg("Read error on '%s'.\n", filename);
973 #else
974                 perror(filename);
975 #endif
976                 fclose(fp);
977                 return 0;
978         }
979         fclose(fp);
980         return 1;
981 }
982
983 #define ETCDIR "/etc"
984 #define RCFILENAME "genisoimagerc"
985 #define OLD_RCFILENAME "mkisofsrc"
986
987 static void
988 read_rcfile(char *appname)
989 {
990         char *p;
991         char filename[1000];
992
993         if (read_one_rcfile(getenv("GENISOIMAGERC")))
994                 return;
995         if (read_one_rcfile(getenv("MKISOFSRC")))
996                 return;
997         if (read_one_rcfile("." RCFILENAME))
998                 return;
999         if (read_one_rcfile("." OLD_RCFILENAME))
1000                 return;
1001
1002         p = getenv("HOME");
1003         if (p && strlen(p) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
1004                 strcpy(filename, p);
1005                 p = filename + strlen(filename);
1006                 *p++ = PATH_SEPARATOR;
1007                 strcpy(p, "." RCFILENAME);
1008                 if (read_one_rcfile(filename))
1009                         return;
1010                 strcpy(p, "." OLD_RCFILENAME);
1011                 if (read_one_rcfile(filename))
1012                         return;
1013         }
1014
1015         if (read_one_rcfile(ETCDIR SPATH_SEPARATOR RCFILENAME))
1016                 return;
1017
1018         if (appname &&
1019             strlen(appname) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
1020                 strcpy(filename, appname);
1021                 p = strrchr(filename, PATH_SEPARATOR);
1022                 if (p) {
1023                         strcpy(p + 1, RCFILENAME);
1024                         if (read_one_rcfile(filename))
1025                                 return;
1026                 }
1027         }
1028 }
1029
1030 char    *path_table_l = NULL;
1031 char    *path_table_m = NULL;
1032
1033 char    *jpath_table_l = NULL;
1034 char    *jpath_table_m = NULL;
1035
1036 int     goof = 0;
1037
1038 #ifndef TRUE
1039 #define TRUE 1
1040 #endif
1041
1042 #ifndef FALSE
1043 #define FALSE 0
1044 #endif
1045
1046 static void
1047 susage(int excode)
1048 {
1049         const char      *program_name = "genisoimage";
1050
1051         fprintf(stderr, "Usage: %s [options] -o file directory ...\n", program_name);
1052         fprintf(stderr, "\nUse %s -help\n", program_name);
1053         fprintf(stderr, "to get a list of valid options.\n");
1054         fprintf(stderr, "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
1055
1056         exit(excode);
1057 }
1058
1059 static void
1060 usage(int excode)
1061 {
1062         const char      *program_name = "genisoimage";
1063
1064         int     i;
1065
1066 /*      const char **targets, **pp;*/
1067
1068         fprintf(stderr, "Usage: %s [options] file...\n", program_name);
1069
1070         fprintf(stderr, "Options:\n");
1071         for (i = 0; i < (int)OPTION_COUNT; i++) {
1072                 if (ld_options[i].doc != NULL) {
1073                         int     comma;
1074                         int     len;
1075                         int     j;
1076
1077                         fprintf(stderr, "  ");
1078
1079                         comma = FALSE;
1080                         len = 2;
1081
1082                         j = i;
1083                         do {
1084                                 if (ld_options[j].shortopt != '\0' &&
1085                                         ld_options[j].control != NO_HELP) {
1086                                         fprintf(stderr, "%s-%c",
1087                                                 comma ? ", " : "",
1088                                                 ld_options[j].shortopt);
1089                                         len += (comma ? 2 : 0) + 2;
1090                                         if (ld_options[j].arg != NULL) {
1091                                                 if (ld_options[j].opt.has_arg != optional_argument) {
1092                                                         fprintf(stderr, " ");
1093                                                         ++len;
1094                                                 }
1095                                                 fprintf(stderr, "%s",
1096                                                         ld_options[j].arg);
1097                                                 len += strlen(ld_options[j].arg);
1098                                         }
1099                                         comma = TRUE;
1100                                 }
1101                                 ++j;
1102                         }
1103                         while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
1104
1105                         j = i;
1106                         do {
1107                                 if (ld_options[j].opt.name != NULL &&
1108                                         ld_options[j].control != NO_HELP) {
1109                                         fprintf(stderr, "%s-%s%s",
1110                                                 comma ? ", " : "",
1111                                                 ld_options[j].control == TWO_DASHES ? "-" : "",
1112                                                 ld_options[j].opt.name);
1113                                         len += ((comma ? 2 : 0)
1114                                                 + 1
1115                                                 + (ld_options[j].control == TWO_DASHES ? 1 : 0)
1116                                                 + strlen(ld_options[j].opt.name));
1117                                         if (ld_options[j].arg != NULL) {
1118                                                 fprintf(stderr, " %s",
1119                                                         ld_options[j].arg);
1120                                                 len += 1 +
1121                                                     strlen(ld_options[j].arg);
1122                                         }
1123                                         comma = TRUE;
1124                                 }
1125                                 ++j;
1126                         }
1127                         while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
1128
1129                         if (len >= 30) {
1130                                 fprintf(stderr, "\n");
1131                                 len = 0;
1132                         }
1133                         for (; len < 30; len++)
1134                                 fputc(' ', stderr);
1135
1136                         fprintf(stderr, "%s\n", ld_options[i].doc);
1137                 }
1138         }
1139         fprintf(stderr, 
1140         "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
1141         exit(excode);
1142 }
1143
1144
1145 /*
1146  * Fill in date in the iso9660 format
1147  *
1148  * The standards  state that the timezone offset is in multiples of 15
1149  * minutes, and is what you add to GMT to get the localtime.  The U.S.
1150  * is always at a negative offset, from -5h to -8h (can vary a little
1151  * with DST,  I guess).  The Linux iso9660 filesystem has had the sign
1152  * of this wrong for ages (genisoimage had it wrong too for the longest time).
1153  */
1154 int
1155 iso9660_date(char *result, time_t crtime)
1156 {
1157         struct tm       *local;
1158
1159         local = localtime(&crtime);
1160         result[0] = local->tm_year;
1161         result[1] = local->tm_mon + 1;
1162         result[2] = local->tm_mday;
1163         result[3] = local->tm_hour;
1164         result[4] = local->tm_min;
1165         result[5] = local->tm_sec;
1166
1167         /*
1168          * Must recalculate proper timezone offset each time, as some files use
1169          * daylight savings time and some don't...
1170          */
1171         result[6] = local->tm_yday;     /* save yday 'cause gmtime zaps it */
1172         local = gmtime(&crtime);
1173         local->tm_year -= result[0];
1174         local->tm_yday -= result[6];
1175         local->tm_hour -= result[3];
1176         local->tm_min -= result[4];
1177         if (local->tm_year < 0) {
1178                 local->tm_yday = -1;
1179         } else {
1180                 if (local->tm_year > 0)
1181                         local->tm_yday = 1;
1182         }
1183
1184         result[6] = -(local->tm_min + 60 *
1185                         (local->tm_hour + 24 * local->tm_yday)) / 15;
1186
1187         return (0);
1188 }
1189
1190 /* hide "./rr_moved" if all its contents are hidden */
1191 static void
1192 hide_reloc_dir()
1193 {
1194         struct directory_entry *s_entry;
1195
1196         for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) {
1197                 if (strcmp(s_entry->name, ".") == 0 ||
1198                                 strcmp(s_entry->name, "..") == 0)
1199                         continue;
1200
1201                 if ((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
1202                         return;
1203         }
1204
1205         /* all entries are hidden, so hide this directory */
1206         reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
1207         reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY;
1208 }
1209
1210 /*
1211  * get pathnames from the command line, and then from given file
1212  */
1213 static char *
1214 get_pnames(int argc, char **argv, int opt, char *pname, int pnsize, FILE *fp)
1215 {
1216         int     len;
1217
1218         /* we may of already read the first line from the pathnames file */
1219         if (save_pname) {
1220                 save_pname = 0;
1221                 return (pname);
1222         }
1223
1224         if (opt < argc)
1225                 return (argv[opt]);
1226
1227         if (fp == NULL)
1228                 return ((char *) 0);
1229
1230         if (fgets(pname, pnsize, fp)) {
1231                 /* Discard newline */
1232                 len = strlen(pname);
1233                 if (pname[len - 1] == '\n') {
1234                         pname[len - 1] = '\0';
1235                 }
1236                 return (pname);
1237         }
1238         return ((char *) 0);
1239 }
1240
1241 extern char     *cdrecord_data;
1242
1243 int main(int argc, char *argv[])
1244 {
1245         struct directory_entry de;
1246
1247 #ifdef HAVE_SBRK
1248         unsigned long   mem_start;
1249
1250 #endif
1251         struct stat     statbuf;
1252         char            *merge_image = NULL;
1253         char            *reloc_root = NULL;
1254         char            *reloc_old_root = NULL;
1255         struct iso_directory_record *mrootp = NULL;
1256         struct output_fragment *opnt;
1257         int             longind;
1258         char            shortopts[OPTION_COUNT * 3 + 2];
1259         struct option   longopts[OPTION_COUNT + 1];
1260         int             c;
1261         int             n;
1262         char            *log_file = 0;
1263         char            *node = NULL;
1264         char            *pathnames = 0;
1265         FILE            *pfp = NULL;
1266         char            pname[2*PATH_MAX + 1 + 1];      /* may be too short */
1267         char            *arg;                           /* if '\\' present  */
1268         char            nodename[PATH_MAX + 1];
1269         int             no_path_names = 1;
1270         int             warn_violate = 0;
1271         int             have_cmd_line_pathspec = 0;
1272         int             rationalize_all = 0;
1273         char            *mkisofs_call = 0; /* use as pointer and boolean */
1274
1275 #ifdef APPLE_HYB
1276         char            *afpfile = "";  /* mapping file for TYPE/CREATOR */
1277         int             hfs_ct = 0;
1278         char            *root_info = 0;
1279 #endif  /* APPLE_HYB */
1280
1281   /* abusing arg */
1282   mkisofs_call=strstr(argv[0], "mkisofs");
1283   if(mkisofs_call && '\0' == mkisofs_call[7]) /* lame cheater detected */
1284      argv[0]="genisoimage";
1285
1286 #ifdef __EMX__
1287         /* This gives wildcard expansion with Non-Posix shells with EMX */
1288         _wildcard(&argc, &argv);
1289 #endif
1290         save_args(argc, argv);
1291
1292         if (argc < 2) {
1293 #ifdef  USE_LIBSCHILY
1294                 errmsgno(EX_BAD, "Missing pathspec.\n");
1295 #endif
1296                 susage(1);
1297         }
1298         /* Get the defaults from the .genisoimagerc file */
1299         read_rcfile(argv[0]);
1300
1301         outfile = NULL;
1302
1303         /*
1304          * Copy long option initialization from GNU-ld.
1305          */
1306         /*
1307          * Starting the short option string with '-' is for programs that
1308          * expect options and other ARGV-elements in any order and that care
1309          * about the ordering of the two.  We describe each non-option
1310          * ARGV-element as if it were the argument of an option with
1311          * character code 1.
1312          */
1313         {
1314                 int             i,
1315                                 is,
1316                                 il;
1317
1318                 shortopts[0] = '-';
1319                 is = 1;
1320                 il = 0;
1321                 for (i = 0; i < (int)OPTION_COUNT; i++) {
1322                         if (ld_options[i].shortopt != '\0') {
1323                                 shortopts[is] = ld_options[i].shortopt;
1324                                 ++is;
1325                                 if (ld_options[i].opt.has_arg ==
1326                                         required_argument ||
1327                                         ld_options[i].opt.has_arg ==
1328                                                         optional_argument) {
1329                                         shortopts[is] = ':';
1330                                         ++is;
1331                                         if (ld_options[i].opt.has_arg ==
1332                                                         optional_argument) {
1333                                                 shortopts[is] = ':';
1334                                                 ++is;
1335                                         }
1336                                 }
1337                         }
1338                         if (ld_options[i].opt.name != NULL) {
1339                                 longopts[il] = ld_options[i].opt;
1340                                 ++il;
1341                         }
1342                 }
1343                 shortopts[is] = '\0';
1344                 longopts[il].name = NULL;
1345         }
1346
1347         while ((c = getopt_long_only(argc, argv, shortopts,
1348                                                 longopts, &longind)) != EOF)
1349                 switch (c) {
1350                 case 1:
1351                         /* A filename that we take as input. */
1352                         optind--;
1353                         have_cmd_line_pathspec = 1;
1354                         goto parse_input_files;
1355
1356                 case OPTION_USE_GRAFT:
1357                         use_graft_ptrs = 1;
1358                         break;
1359                 case 'C':
1360                         /*
1361                          * This is a temporary hack until cdrecord gets the
1362                          * proper hooks in it.
1363                          */
1364                         cdrecord_data = optarg;
1365                         break;
1366                 case OPTION_GUI:
1367                         gui++;
1368                         break;
1369                 case 'i':
1370 #ifdef  USE_LIBSCHILY
1371                         comerrno(EX_BAD, "-i option no longer supported.\n");
1372 #else
1373                         fprintf(stderr, "-i option no longer supported.\n");
1374                         exit(1);
1375 #endif
1376                         break;
1377                 case OPTION_ISO_LEVEL:
1378                         iso9660_level = atoi(optarg);
1379
1380                         switch (iso9660_level) {
1381
1382                         case 1:
1383                                 /*
1384                                  * Only on file section
1385                                  * 8.3 d or d1 characters for files
1386                                  * 8   d or d1 characters for directories
1387                                  */
1388                                 break;
1389                         case 2:
1390                                 /*
1391                                  * Only on file section
1392                                  */
1393                                 break;
1394                         case 3:
1395                                 /*
1396                                  * No restrictions
1397                                  */
1398                                 break;
1399                         case 4:
1400                                 /*
1401                                  * This is ISO-9660:1988 (ISO-9660 version 2)
1402                                  */
1403                                 iso9660_namelen = MAX_ISONAME_V2; /* allow 207 chars */
1404                                 full_iso9660_filenames++;       /* 31+ chars    */
1405                                 omit_version_number++;
1406                                 RR_relocation_depth = 32767;
1407
1408                                 /*
1409                                  * From -U ...
1410                                  */
1411                                 omit_period++;                  /* trailing dot */
1412                                 allow_leading_dots++;
1413                                 relaxed_filenames++;            /* all chars    */
1414                                 allow_lowercase++;              /* even lowcase */
1415                                 allow_multidot++;               /* > 1 dots     */
1416                                 break;
1417
1418                         default:
1419                                 comerrno(EX_BAD, "Illegal iso9660 Level %d, use 1..3 or 4.\n",
1420                                                         iso9660_level);
1421                         }
1422                         break;
1423                 case 'J':
1424                         use_Joliet++;
1425                         break;
1426                 case OPTION_JLONG:
1427                         use_Joliet++;
1428                         jlen = JLONGMAX;
1429                         break;
1430                 case OPTION_JCHARSET:
1431                         use_Joliet++;
1432                         /* FALLTHROUGH */
1433                 case OPTION_INPUT_CHARSET:
1434                         icharset = optarg;
1435                         break;
1436                 case OPTION_OUTPUT_CHARSET:
1437                         ocharset = optarg;
1438                         break;
1439 #ifdef JIGDO_TEMPLATE
1440                 case OPTION_JTT_OUTPUT:
1441                         jtemplate_out = optarg;
1442                         break;
1443                 case OPTION_JTJ_OUTPUT:
1444                         jjigdo_out = optarg;
1445                         break;
1446                 case OPTION_JT_MD5_LIST:
1447                         jmd5_list = optarg;
1448                         break;
1449                 case OPTION_JT_MIN_SIZE:
1450                         jte_min_size = atoi(optarg);
1451                         if (jte_min_size < MIN_JIGDO_FILE_SIZE) {
1452                                 fprintf(stderr, "Jigdo min size %d too small; using default %d instead\n", jte_min_size, MIN_JIGDO_FILE_SIZE);
1453                                 jte_min_size = MIN_JIGDO_FILE_SIZE;
1454                         }
1455                         break;
1456                 case OPTION_JT_INCLUDE:
1457                         if (jte_add_include(optarg)) {
1458 #ifdef  USE_LIBSCHILY
1459                                 comerrno(EX_BAD,
1460                                          "Failed to build jigdo-include list\n");
1461 #else
1462                                 fprintf(stderr,
1463                                         "Failed to build jigdo-include list\n");
1464                                 exit(1);
1465 #endif
1466                         }
1467                         break;
1468                 case OPTION_JT_EXCLUDE:
1469                         if (jte_add_exclude(optarg)) {
1470 #ifdef  USE_LIBSCHILY
1471                                 comerrno(EX_BAD,
1472                                          "Failed to build jigdo-exclude list\n");
1473 #else
1474                                 fprintf(stderr,
1475                                         "Failed to build jigdo-exclude list\n");
1476                                 exit(1);
1477 #endif
1478                         }
1479                         break;
1480                 case OPTION_JT_PATH_MAP:
1481                         if (jte_add_mapping(optarg)) {
1482 #ifdef  USE_LIBSCHILY
1483                                 comerrno(EX_BAD,
1484                                          "Failed to build jigdo mapping list\n");
1485 #else
1486                                 fprintf(stderr,
1487                                         "Failed to build jigdo mapping list\n");
1488                                 exit(1);
1489 #endif
1490                         }
1491                         break;
1492         case OPTION_JT_COMPRESS_ALGO:
1493             if (!strcasecmp(optarg, "gzip"))
1494                 jte_template_compression = JTE_TEMP_GZIP;
1495             else if (!strcasecmp(optarg, "bzip2"))
1496                 jte_template_compression = JTE_TEMP_BZIP2;
1497             else
1498             {
1499 #ifdef USE_LIBSCHILY
1500                 comerrno(EX_BAD, "Compression algorithm %s unknown\n", optarg);
1501 #else
1502                 fprintf(stderr, "Compression algorithm %s unknown\n", optarg);
1503                 exit(1);
1504 #endif
1505             }
1506             break;
1507
1508         case OPTION_JT_CHECKSUM_ALGO_ISO:
1509             if (parse_checksum_algo(optarg, &checksum_algo_iso))
1510             {
1511 #ifdef USE_LIBSCHILY
1512                 comerrno(EX_BAD, "Problem with ISO checksum choices: %s \n", optarg);
1513 #else
1514                 fprintf(stderr, "Problem with ISO checksum choices: %s\n", optarg);
1515                 exit(1);
1516 #endif
1517             }
1518
1519             break;
1520
1521         case OPTION_JT_CHECKSUM_ALGO_TMPL:
1522             if (parse_checksum_algo(optarg, &checksum_algo_tmpl))
1523             {
1524 #ifdef USE_LIBSCHILY
1525                 comerrno(EX_BAD, "Problem with template checksum choices: %s \n", optarg);
1526 #else
1527                 fprintf(stderr, "Problem with template checksum choices: %s\n", optarg);
1528                 exit(1);
1529 #endif
1530             }
1531             break;
1532
1533 #endif /* JIGDO_TEMPLATE */
1534                 case OPTION_NOBAK:
1535                         all_files = 0;
1536                         break;
1537                 case 'b':
1538                         do_sort++;              /* We sort bootcat/botimage */
1539                         use_eltorito++;
1540                         boot_image = optarg;    /* pathname of the boot image */
1541                                                 /* on disk */
1542                         if (boot_image == NULL) {
1543 #ifdef  USE_LIBSCHILY
1544                                 comerrno(EX_BAD,
1545                                 "Required Eltorito boot image pathname missing\n");
1546 #else
1547                                 fprintf(stderr,
1548                                 "Required Eltorito boot image pathname missing\n");
1549                                 exit(1);
1550 #endif
1551                         }
1552                         get_boot_entry();
1553                         current_boot_entry->boot_image = boot_image;
1554                         break;
1555                 case OPTION_ALT_BOOT:
1556                         /*
1557                          * Start new boot entry parameter list.
1558                          */
1559                         new_boot_entry();
1560                         break;
1561                 case OPTION_BOOTALPHA:
1562                         use_alphaboot++;
1563                         /* list of pathnames of boot images */
1564                         add_boot_alpha_filename(optarg);
1565                         break;
1566                 case OPTION_HPPA_CMDLINE:
1567                         use_hppaboot++;
1568                         add_boot_hppa_cmdline(optarg);
1569                         break;
1570                 case OPTION_HPPA_KERNEL_32:
1571                         use_hppaboot++;
1572                         add_boot_hppa_kernel_32(optarg);
1573                         break;
1574                 case OPTION_HPPA_KERNEL_64:
1575                         use_hppaboot++;
1576                         add_boot_hppa_kernel_64(optarg);
1577                         break;
1578                 case OPTION_HPPA_BOOTLOADER:
1579                         use_hppaboot++;
1580                         add_boot_hppa_bootloader(optarg);
1581                         break;
1582                 case OPTION_HPPA_RAMDISK:
1583                         use_hppaboot++;
1584                         /* list of pathnames of boot images */
1585                         add_boot_hppa_ramdisk(optarg);
1586                         break;
1587                 case OPTION_BOOTMIPS:
1588                         use_mipsboot++;
1589                         /* list of pathnames of boot images */
1590                         add_boot_mips_filename(optarg);
1591                         break;
1592                 case OPTION_BOOTMIPSEL:
1593                         use_mipselboot++;
1594                         add_boot_mipsel_filename(optarg);
1595                         break;
1596                 case 'B':
1597                         if (use_sunx86boot)
1598                                 comerrno(EX_BAD,
1599                                 "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
1600                         use_sparcboot++;
1601                         /* list of pathnames of boot images */
1602                         scan_sparc_boot(optarg);
1603                         break;
1604                 case OPTION_SUNX86BOOT:
1605                         if (use_sparcboot)
1606                                 comerrno(EX_BAD,
1607                                 "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
1608                         use_sunx86boot++;
1609                         /* list of pathnames of boot images */
1610                         scan_sunx86_boot(optarg);
1611                         break;
1612                 case 'G':
1613                         use_genboot++;
1614                         /* pathname of the boot image on disk */
1615                         genboot_image = optarg;
1616                         if (genboot_image == NULL) {
1617 #ifdef  USE_LIBSCHILY
1618                                 comerrno(EX_BAD,
1619                                 "Required generic boot image pathname missing\n");
1620 #else
1621                                 fprintf(stderr,
1622                                 "Required generic boot image pathname missing\n");
1623                                 exit(1);
1624 #endif
1625                         }
1626                         break;
1627                 case OPTION_SPARCLABEL:
1628                         /* Sun disk label string */
1629                         sparc_boot_label(optarg);
1630                         break;
1631                 case OPTION_SUNX86LABEL:
1632                         /* Sun disk label string */
1633                         sunx86_boot_label(optarg);
1634                         break;
1635                 case 'c':
1636                         use_eltorito++;
1637                         /* pathname of the boot image on cd */
1638                         boot_catalog = optarg;
1639                         if (boot_catalog == NULL) {
1640 #ifdef  USE_LIBSCHILY
1641                                 comerrno(EX_BAD,
1642                                 "Required boot catalog pathname missing\n");
1643 #else
1644                                 fprintf(stderr,
1645                                 "Required boot catalog pathname missing\n");
1646                                 exit(1);
1647 #endif
1648                         }
1649                         break;
1650                 case OPTION_ABSTRACT:
1651                         abstract = optarg;
1652                         if (strlen(abstract) > 37) {
1653 #ifdef  USE_LIBSCHILY
1654                                 comerrno(EX_BAD,
1655                                 "Abstract filename string too long\n");
1656 #else
1657                                 fprintf(stderr,
1658                                 "Abstract filename string too long\n");
1659                                 exit(1);
1660 #endif
1661                         }
1662                         break;
1663                 case 'A':
1664                         appid = optarg;
1665                         if (strlen(appid) > 128) {
1666 #ifdef  USE_LIBSCHILY
1667                                 comerrno(EX_BAD,
1668                                 "Application-id string too long\n");
1669 #else
1670                                 fprintf(stderr,
1671                                 "Application-id string too long\n");
1672                                 exit(1);
1673 #endif
1674                         }
1675                         break;
1676                 case OPTION_BIBLIO:
1677                         biblio = optarg;
1678                         if (strlen(biblio) > 37) {
1679 #ifdef  USE_LIBSCHILY
1680                                 comerrno(EX_BAD,
1681                                 "Bibliographic filename string too long\n");
1682 #else
1683                                 fprintf(stderr,
1684                                 "Bibliographic filename string too long\n");
1685                                 exit(1);
1686 #endif
1687                         }
1688                         break;
1689                 case OPTION_CACHE_INODES:
1690                         cache_inodes = 1;
1691                         break;
1692                 case OPTION_NOCACHE_INODES:
1693                         cache_inodes = 0;
1694                         break;
1695                 case OPTION_CHECK_OLDNAMES:
1696                         check_oldnames++;
1697                         break;
1698                 case OPTION_CHECK_SESSION:
1699                         check_session++;
1700                         check_oldnames++;
1701                         merge_image = optarg;
1702                         outfile = "/dev/null";
1703                         /*
1704                          * cdrecord_data is handled specially in multi.c
1705                          * as we cannot write to all strings.
1706                          * If genisoimage is called with -C xx,yy
1707                          * our default is overwritten.
1708                          */
1709 /*                      cdrecord_data = "0,0";*/
1710                         break;
1711                 case OPTION_COPYRIGHT:
1712                         copyright = optarg;
1713                         if (strlen(copyright) > 37) {
1714 #ifdef  USE_LIBSCHILY
1715                                 comerrno(EX_BAD,
1716                                 "Copyright filename string too long\n");
1717 #else
1718                                 fprintf(stderr,
1719                                 "Copyright filename string too long\n");
1720                                 exit(1);
1721 #endif
1722                         }
1723                         break;
1724                 case OPTION_DEBUG:
1725                         debug++;
1726                         break;
1727                 case 'd':
1728                         omit_period++;
1729                         warn_violate++;
1730                         break;
1731                 case 'D':
1732                         RR_relocation_depth = 32767;
1733                         break;
1734                 case 'f':
1735                         follow_links++;
1736                         break;
1737                 case 'l':
1738                         full_iso9660_filenames++;
1739                         break;
1740                 case OPTION_MAX_FILENAMES:
1741                         iso9660_namelen = MAX_ISONAME_V1; /* allow 37 chars */
1742                         full_iso9660_filenames++;
1743                         omit_version_number++;
1744                         warn_violate++;
1745                         break;
1746                 case 'L':
1747                         /* FALLTHRU */
1748                 case OPTION_ALLOW_LEADING_DOTS:
1749                         allow_leading_dots++;
1750                         warn_violate++;
1751                         break;
1752                 case OPTION_LOG_FILE:
1753                         log_file = optarg;
1754                         break;
1755                 case 'M':
1756                         merge_image = optarg;
1757                         break;
1758                 case OPTION_RELOC_ROOT:
1759                         reloc_root = optarg;
1760                         break;
1761                 case OPTION_RELOC_OLD_ROOT:
1762                         reloc_old_root = optarg;
1763                         break;
1764                 case 'N':
1765                         omit_version_number++;
1766                         warn_violate++;
1767                         break;
1768                 case OPTION_FORCE_RR:
1769                         force_rr++;
1770                         break;
1771                 case OPTION_NO_RR:
1772                         no_rr++;
1773                         break;
1774                 case 'o':
1775                         outfile = optarg;
1776                         break;
1777                 case OPTION_PAD:
1778                         dopad++;
1779                         break;
1780                 case OPTION_NOPAD:
1781                         dopad = 0;
1782                         break;
1783                 case OPTION_P_LIST:
1784                         pathnames = optarg;
1785                         break;
1786                 case 'p':
1787                         preparer = optarg;
1788                         if (strlen(preparer) > 128) {
1789 #ifdef  USE_LIBSCHILY
1790                                 comerrno(EX_BAD, "Preparer string too long\n");
1791 #else
1792                                 fprintf(stderr, "Preparer string too long\n");
1793                                 exit(1);
1794 #endif
1795                         }
1796                         break;
1797                 case OPTION_PRINT_SIZE:
1798                         print_size++;
1799                         break;
1800                 case 'P':
1801                         /* FALLTHRU */
1802                 case OPTION_PUBLISHER:
1803                         publisher = optarg;
1804                         if (strlen(publisher) > 128) {
1805 #ifdef  USE_LIBSCHILY
1806                                 comerrno(EX_BAD,
1807                                                 "Publisher string too long\n");
1808 #else
1809                                 fprintf(stderr, "Publisher string too long\n");
1810                                 exit(1);
1811 #endif
1812                         }
1813                         break;
1814                 case OPTION_QUIET:
1815                         verbose = 0;
1816                         break;
1817                 case 'R':
1818                         use_RockRidge++;
1819                         break;
1820                 case 'r':
1821                         rationalize_all++;
1822                         use_RockRidge++;
1823                         break;
1824                 case OPTION_XA:
1825                         use_XA++;
1826                         break;
1827                 case OPTION_XA_RATIONALIZED:
1828                         rationalize_all++;
1829                         use_XA++;
1830                         break;
1831
1832                 case 's':
1833                         if (strcmp(optarg, "data") == 0)
1834                                 osecsize = 2048;
1835                         else if (strcmp(optarg, "xa1") == 0)
1836                                 osecsize = 2056;
1837                         else if (strcmp(optarg, "raw") == 0) {
1838                                 osecsize = 2352;
1839                                 comerrno(EX_BAD,
1840                                         "Unsupported sector type '%s'.\n",
1841                                         optarg);
1842                         }
1843                         break;
1844                 case 'S':
1845 #ifdef  USE_LIBSCHILY
1846                         errmsgno(EX_BAD, "Option -%c is reserved for future use.\n", c);
1847 #else
1848                         fprintf(stderr, "Option -%c is reserved for future use.\n", c);
1849 #endif
1850                         susage(1);
1851                         /* NOTREACHED */
1852
1853                 case OPTION_NEW_DIR_MODE:
1854                         rationalize++;
1855                 {
1856                         char    *end = 0;
1857
1858                         new_dir_mode = strtol(optarg, &end, 8);
1859                         if (!end || *end != 0 ||
1860                             new_dir_mode < 0 || new_dir_mode > 07777) {
1861 #ifdef  USE_LIBSCHILY
1862                                 comerrno(EX_BAD, "Bad mode for -new-dir-mode\n");
1863 #else
1864                                 fprintf(stderr, "Bad mode for -new-dir-mode\n");
1865                                 exit(1);
1866 #endif
1867                         }
1868                         break;
1869                 }
1870
1871                 case OPTION_UID:
1872                         rationalize++;
1873                         use_RockRidge++;
1874                         rationalize_uid++;
1875                 {
1876                         char    *end = 0;
1877
1878                         uid_to_use = strtol(optarg, &end, 0);
1879                         if (!end || *end != 0) {
1880 #ifdef  USE_LIBSCHILY
1881                                 comerrno(EX_BAD, "Bad value for -uid\n");
1882 #else
1883                                 fprintf(stderr, "Bad value for -uid\n");
1884                                 exit(1);
1885 #endif
1886                         }
1887                         break;
1888                 }
1889
1890                 case OPTION_GID:
1891                         rationalize++;
1892                         use_RockRidge++;
1893                         rationalize_gid++;
1894                 {
1895                         char    *end = 0;
1896
1897                         gid_to_use = strtol(optarg, &end, 0);
1898                         if (!end || *end != 0) {
1899 #ifdef  USE_LIBSCHILY
1900                                 comerrno(EX_BAD, "Bad value for -gid\n");
1901 #else
1902                                 fprintf(stderr, "Bad value for -gid\n");
1903                                 exit(1);
1904 #endif
1905                         }
1906                         break;
1907                 }
1908
1909                 case OPTION_FILEMODE:
1910                         rationalize++;
1911                         use_RockRidge++;
1912                         rationalize_filemode++;
1913                 {
1914                         char    *end = 0;
1915
1916                         filemode_to_use = strtol(optarg, &end, 8);
1917                         if (!end || *end != 0 ||
1918                             filemode_to_use < 0 || filemode_to_use > 07777) {
1919 #ifdef  USE_LIBSCHILY
1920                                 comerrno(EX_BAD, "Bad mode for -file-mode\n");
1921 #else
1922                                 fprintf(stderr, "Bad mode for -file-mode\n");
1923                                 exit(1);
1924 #endif
1925                         }
1926                         break;
1927                 }
1928
1929                 case OPTION_DIRMODE:
1930                         rationalize++;
1931                         use_RockRidge++;
1932                         rationalize_dirmode++;
1933                 {
1934                         char    *end = 0;
1935
1936                         dirmode_to_use = strtol(optarg, &end, 8);
1937                         if (!end || *end != 0 ||
1938                             dirmode_to_use < 0 || dirmode_to_use > 07777) {
1939 #ifdef  USE_LIBSCHILY
1940                                 comerrno(EX_BAD, "Bad mode for -dir-mode\n");
1941 #else
1942                                 fprintf(stderr, "Bad mode for -dir-mode\n");
1943                                 exit(1);
1944 #endif
1945                         }
1946                         break;
1947                 }
1948
1949 #ifdef SORTING
1950                 case OPTION_SORT:
1951                         do_sort++;
1952                         add_sort_list(optarg);
1953                         break;
1954 #endif /* SORTING */
1955
1956                 case OPTION_SPLIT_OUTPUT:
1957                         split_output++;
1958                         break;
1959
1960                 case OPTION_STREAM_FILE_NAME:
1961                         stream_filename = optarg;
1962                         break;
1963
1964                 case OPTION_STREAM_CD_SIZE:
1965                         stream_media_size = atoi(optarg);
1966                         break;
1967
1968                 case OPTION_SYSID:
1969                         system_id = optarg;
1970                         if (strlen(system_id) > 32) {
1971 #ifdef  USE_LIBSCHILY
1972                                 comerrno(EX_BAD,
1973                                                 "System ID string too long\n");
1974 #else
1975                                 fprintf(stderr, "System ID string too long\n");
1976                                 exit(1);
1977 #endif
1978                         }
1979                         break;
1980                 case OPTION_TRANS_TBL:
1981                         trans_tbl = optarg;
1982                         /* FALLTHRU */
1983                 case 'T':
1984                         generate_tables++;
1985                         break;
1986                 case OPTION_UCS_LEVEL:
1987                         ucs_level = atoi(optarg);
1988                         if (ucs_level < 1 || ucs_level > 3)
1989                                 comerrno(EX_BAD, "Illegal UCS Level %d, use 1..3.\n",
1990                                                         ucs_level);
1991                         break;
1992 #ifdef UDF
1993                 case OPTION_UDF:
1994                         use_udf++;
1995                         break;
1996 #endif
1997
1998 #ifdef DVD_VIDEO
1999                 case OPTION_DVD:
2000                         use_udf++;
2001                         dvd_video++;
2002                         break;
2003 #endif
2004                 case OPTION_USE_FILEVERSION:
2005                         use_fileversion++;
2006                         break;
2007                 case 'U':
2008                         /*
2009                          * Minimal (only truncation of 31+ characters)
2010                          * translation of filenames.
2011                          *
2012                          * Forces -l, -d, -N, -allow-leading-dots,
2013                          * -relaxed-filenames,
2014                          * -allow-lowercase, -allow-multidot
2015                          *
2016                          * This is for HP-UX, which does not recognize ANY
2017                          * extentions (Rock Ridge, Joliet), causing pain when
2018                          * loading software. pfs_mount can be used to read the
2019                          * extensions, but the untranslated filenames can be
2020                          * read by the "native" cdfs mounter. Completely
2021                          * violates iso9660.
2022                          */
2023                         full_iso9660_filenames++;       /* 31 chars     */
2024                         omit_period++;                  /* trailing dot */
2025                         allow_leading_dots++;
2026                         omit_version_number++;
2027                         relaxed_filenames++;            /* all chars    */
2028                         allow_lowercase++;              /* even lowcase */
2029                         allow_multidot++;               /* > 1 dots     */
2030                         warn_violate++;
2031                         break;
2032
2033                 case OPTION_RELAXED_FILENAMES:
2034                         relaxed_filenames++;
2035                         warn_violate++;
2036                         break;
2037                 case OPTION_ALLOW_LOWERCASE:
2038                         allow_lowercase++;
2039                         warn_violate++;
2040                         break;
2041                 case OPTION_ALLOW_MULTIDOT:
2042                         allow_multidot++;
2043                         warn_violate++;
2044                         break;
2045                 case OPTION_ISO_TRANSLATE:
2046                         iso_translate = 0;
2047                         warn_violate++;
2048                         break;
2049                 case 'V':
2050                         volume_id = optarg;
2051                         if (strlen(volume_id) > 32) {
2052 #ifdef  USE_LIBSCHILY
2053                                 comerrno(EX_BAD,
2054                                         "Volume ID string too long\n");
2055 #else
2056                                 fprintf(stderr,
2057                                         "Volume ID string too long\n");
2058                                 exit(1);
2059 #endif
2060                         }
2061                         break;
2062                 case OPTION_VOLSET:
2063                         volset_id = optarg;
2064                         if (strlen(volset_id) > 128) {
2065 #ifdef  USE_LIBSCHILY
2066                                 comerrno(EX_BAD,
2067                                 "Volume set ID string too long\n");
2068 #else
2069                                 fprintf(stderr,
2070                                 "Volume set ID string too long\n");
2071                                 exit(1);
2072 #endif
2073                         }
2074                         break;
2075                 case OPTION_VOLSET_SIZE:
2076                         volume_set_size = atoi(optarg);
2077                         if (volume_set_size <= 0) {
2078 #ifdef  USE_LIBSCHILY
2079                                 comerrno(EX_BAD,
2080                                 "Illegal Volume Set Size %s\n", optarg);
2081 #else
2082                                 fprintf(stderr,
2083                                 "Illegal Volume Set Size %s\n", optarg);
2084                                 exit(1);
2085 #endif
2086                         }
2087                         if (volume_set_size > 1) {
2088 #ifdef  USE_LIBSCHILY
2089                                 comerrno(EX_BAD,
2090                                 "Volume Set Size > 1 not yet supported\n");
2091 #else
2092                                 fprintf(stderr,
2093                                 "Volume Set Size > 1 not yet supported\n");
2094                                 exit(1);
2095 #endif
2096                         }
2097                         break;
2098                 case OPTION_VOLSET_SEQ_NUM:
2099                         volume_sequence_number = atoi(optarg);
2100                         if (volume_sequence_number > volume_set_size) {
2101 #ifdef  USE_LIBSCHILY
2102                                 comerrno(EX_BAD,
2103                                 "Volume set sequence number too big\n");
2104 #else
2105                                 fprintf(stderr,
2106                                 "Volume set sequence number too big\n");
2107                                 exit(1);
2108 #endif
2109                         }
2110                         break;
2111                 case 'v':
2112                         verbose++;
2113                         break;
2114                 case 'z':
2115 #ifdef VMS
2116 #ifdef  USE_LIBSCHILY
2117                         comerrno(EX_BAD,
2118                         "Transparent compression not supported with VMS\n");
2119 #else
2120                         fprintf(stderr,
2121                         "Transparent compression not supported with VMS\n");
2122                         exit(1);
2123 #endif
2124 #else
2125                         transparent_compression++;
2126 #endif
2127                         break;
2128                 case 'x':
2129                 case 'm':
2130                         /*
2131                          * Somehow two options to do basically the same thing
2132                          * got added somewhere along the way.  The 'match'
2133                          * code supports limited globbing, so this is the one
2134                          * that got selected. Unfortunately the 'x' switch is
2135                          * probably more intuitive.
2136                          */
2137                         add_match(optarg);
2138                         break;
2139                 case OPTION_X_LIST:
2140                         add_list(optarg);
2141                         break;
2142                 case OPTION_I_HIDE:
2143                         i_add_match(optarg);
2144                         break;
2145                 case OPTION_I_LIST:
2146                         i_add_list(optarg);
2147                         break;
2148                 case OPTION_H_HIDE:
2149                         h_add_match(optarg);
2150                         break;
2151                 case OPTION_H_LIST:
2152                         h_add_list(optarg);
2153                         break;
2154                 case OPTION_J_HIDE:
2155                         j_add_match(optarg);
2156                         break;
2157                 case OPTION_J_LIST:
2158                         j_add_list(optarg);
2159                         break;
2160                 case OPTION_HIDE_TRANS_TBL:
2161                         jhide_trans_tbl++;
2162                         break;
2163                 case OPTION_HIDE_RR_MOVED:
2164                         hide_rr_moved++;
2165                         break;
2166                 case OPTION_HELP:
2167                         usage(0);
2168                         break;
2169                 case OPTION_PVERSION:
2170       if(mkisofs_call)
2171          printf("mkisofs 2.01 is not what you see here. This line is only a fake for too clever\n"
2172                "GUIs and other frontend applications. In fact, this program is:\n");
2173                         printf("%s (%s)\n", version_string, HOST_SYSTEM);
2174                         exit(0);
2175                         break;
2176                 case OPTION_NOSPLIT_SL_COMPONENT:
2177                         split_SL_component = 0;
2178                         break;
2179                 case OPTION_NOSPLIT_SL_FIELD:
2180                         split_SL_field = 0;
2181                         break;
2182                 case OPTION_HARD_DISK_BOOT:
2183                         use_eltorito++;
2184                         hard_disk_boot++;
2185                         get_boot_entry();
2186                         current_boot_entry->hard_disk_boot = 1;
2187                         break;
2188                 case OPTION_NO_EMUL_BOOT:
2189                         use_eltorito++;
2190                         no_emul_boot++;
2191                         get_boot_entry();
2192                         current_boot_entry->no_emul_boot = 1;
2193                         break;
2194                 case OPTION_NO_BOOT:
2195                         use_eltorito++;
2196                         not_bootable++;
2197                         get_boot_entry();
2198                         current_boot_entry->not_bootable = 1;
2199                         break;
2200                 case OPTION_BOOT_LOAD_ADDR:
2201                         use_eltorito++;
2202                         {
2203                                 long    val;
2204                                 char    *ptr;
2205
2206                                 val = strtol(optarg, &ptr, 0);
2207                                 if (*ptr || val < 0 || val >= 0x10000) {
2208 #ifdef  USE_LIBSCHILY
2209                                         comerrno(EX_BAD, "Boot image load address invalid.\n");
2210 #else
2211                                         fprintf(stderr, "Boot image load address invalid.\n");
2212                                         exit(1);
2213 #endif
2214                                 }
2215                                 load_addr = val;
2216                         }
2217                         get_boot_entry();
2218                         current_boot_entry->load_addr = load_addr;
2219                         break;
2220                 case OPTION_BOOT_LOAD_SIZE:
2221                         use_eltorito++;
2222                         {
2223                                 long    val;
2224                                 char    *ptr;
2225
2226                                 val = strtol(optarg, &ptr, 0);
2227                                 if (*ptr || val < 0 || val >= 0x10000) {
2228 #ifdef  USE_LIBSCHILY
2229                                         comerrno(EX_BAD,
2230                                         "Boot image load size invalid.\n");
2231 #else
2232                                         fprintf(stderr,
2233                                         "Boot image load size invalid.\n");
2234                                         exit(1);
2235 #endif
2236                                 }
2237                                 load_size = val;
2238                         }
2239                         get_boot_entry();
2240                         current_boot_entry->load_size = load_size;
2241                         break;
2242                 case OPTION_BOOT_INFO_TABLE:
2243                         use_eltorito++;
2244                         boot_info_table++;
2245                         get_boot_entry();
2246                         current_boot_entry->boot_info_table = 1;
2247                         break;
2248 #ifdef APPLE_HYB
2249                 case OPTION_HFS_TYPE:
2250                         deftype = optarg;
2251                         hfs_ct++;
2252                         if (strlen(deftype) != 4) {
2253 #ifdef  USE_LIBSCHILY
2254                                 comerrno(EX_BAD,
2255                                 "HFS default TYPE string has illegal length.\n");
2256 #else
2257                                 fprintf(stderr,
2258                                 "HFS default TYPE string has illegal length.\n");
2259                                 exit(1);
2260 #endif
2261                         }
2262                         break;
2263                 case OPTION_HFS_CREATOR:
2264                         defcreator = optarg;
2265                         hfs_ct++;
2266                         if (strlen(defcreator) != 4) {
2267 #ifdef  USE_LIBSCHILY
2268                                 comerrno(EX_BAD,
2269                                 "HFS default CREATOR string has illegal length.\n");
2270 #else
2271                                 fprintf(stderr,
2272                                 "HFS default CREATOR string has illegal length.\n");
2273                                 exit(1);
2274 #endif
2275                         }
2276                         break;
2277                 case 'H':
2278                         /* FALLTHRU */
2279                 case OPTION_MAP_FILE:
2280                         afpfile = optarg;
2281                         hfs_last = MAP_LAST;
2282                         break;
2283                 case 'h':
2284                         apple_hyb = 1;
2285                         break;
2286                 case 'g':
2287                         apple_ext = 1;
2288                         break;
2289                 case OPTION_PROBE:
2290                         probe = 1;
2291                         break;
2292                 case OPTION_MACNAME:
2293                         use_mac_name = 1;
2294                         break;
2295                 case OPTION_NOMACFILES:
2296 #ifdef  USE_LIBSCHILY
2297                         errmsgno(EX_BAD,
2298                         "Warning: -no-mac-files no longer used ... ignoring\n");
2299 #else
2300                         fprintf(stderr,
2301                         "Warning: -no-mac-files no longer used ... ignoring\n");
2302 #endif
2303                         break;
2304                 case OPTION_BOOT_HFS_FILE:
2305                         hfs_boot_file = optarg;
2306                         /* FALLTHRU */
2307                 case OPTION_GEN_PT:
2308                         gen_pt = 1;
2309                         break;
2310                 case OPTION_MAGIC_FILE:
2311 #ifndef USE_MAGIC
2312                         fprintf(stderr, "This program has been compiled without magic library support.\n"
2313                                 "Ignoring the -magic option.\n");
2314 #endif
2315                         magic_filename = optarg;
2316                         hfs_last = MAG_LAST;
2317                         break;
2318                 case OPTION_AUTOSTART:
2319                         autoname = optarg;
2320                         /* gen_pt = 1; */
2321                         break;
2322                 case OPTION_BSIZE:
2323                         afe_size = atoi(optarg);
2324                         hfs_select |= DO_FEU;
2325                         hfs_select |= DO_FEL;
2326                         break;
2327                 case OPTION_HFS_VOLID:
2328                         hfs_volume_id = optarg;
2329                         break;
2330                 case OPTION_ROOT_INFO:
2331                         root_info = optarg;
2332                         /* FALLTHRU */
2333                 case OPTION_ICON_POS:
2334                         icon_pos = 1;
2335                         break;
2336                 /* Mac/Unix types to include */
2337                 case OPTION_CAP:
2338                         hfs_select |= DO_CAP;
2339                         break;
2340                 case OPTION_NETA:
2341                         hfs_select |= DO_NETA;
2342                         break;
2343                 case OPTION_DBL:
2344                         hfs_select |= DO_DBL;
2345                         break;
2346                 case OPTION_ESH:
2347                 case OPTION_USH:
2348                         hfs_select |= DO_ESH;
2349                         break;
2350                 case OPTION_FE:
2351                         hfs_select |= DO_FEU;
2352                         hfs_select |= DO_FEL;
2353                         break;
2354                 case OPTION_SGI:
2355                 case OPTION_XIN:
2356                         hfs_select |= DO_SGI;
2357                         break;
2358                 case OPTION_MBIN:
2359                         hfs_select |= DO_MBIN;
2360                         break;
2361                 case OPTION_SGL:
2362                         hfs_select |= DO_SGL;
2363                         break;
2364                 case OPTION_DAVE:
2365                         hfs_select |= DO_DAVE;
2366                         break;
2367                 case OPTION_SFM:
2368                         hfs_select |= DO_SFM;
2369                         break;
2370                 case OPTION_XDBL:
2371                         hfs_select |= DO_XDBL;
2372                         break;
2373                 case OPTION_XHFS:
2374 #ifdef IS_MACOS_X
2375                         hfs_select |= DO_XHFS;
2376 #else /* IS_MACOS_X */
2377 #ifdef  USE_LIBSCHILY
2378                         errmsgno(EX_BAD,
2379                         "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
2380 #else /* USE_LIBSCHILY */
2381                         fprintf(stderr,
2382                         "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
2383 #endif /* USE_LIBSCHILY */
2384 #endif /* IS_MACOS_X */
2385                         break;
2386                 case OPTION_CREATE_DT:
2387                         create_dt = 0;
2388                         break;
2389                 case OPTION_HFS_HIDE:
2390                         hfs_add_match(optarg);
2391                         break;
2392                 case OPTION_HFS_LIST:
2393                         hfs_add_list(optarg);
2394                         break;
2395                 case OPTION_HFS_INPUT_CHARSET:
2396                         use_mac_name = 1;
2397                         hfs_icharset = optarg;
2398                         break;
2399                 case OPTION_HFS_OUTPUT_CHARSET:
2400                         hfs_ocharset = optarg;
2401                         break;
2402                 case OPTION_HFS_UNLOCK:
2403                         hfs_lock = 0;
2404                         break;
2405                 case OPTION_HFS_BLESS:
2406                         hfs_bless = optarg;
2407                         break;
2408                 case OPTION_HFS_PARMS:
2409                         hfs_parms = strdup(optarg);
2410                         break;
2411 #ifdef PREP_BOOT
2412                 case OPTION_PREP_BOOT:
2413                         use_prep_boot++;
2414                         if (use_prep_boot > 4 - use_chrp_boot) {
2415 #ifdef  USE_LIBSCHILY
2416                                 comerrno(EX_BAD,
2417                                 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2418 #else
2419                                 fprintf(stderr,
2420                                 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2421 #endif
2422                                 exit(1);
2423                         }
2424                         /* pathname of the boot image on cd */
2425                         prep_boot_image[use_prep_boot - 1] = optarg;
2426                         if (prep_boot_image[use_prep_boot - 1] == NULL) {
2427 #ifdef  USE_LIBSCHILY
2428                                 comerrno(EX_BAD,
2429                                 "Required PReP boot image pathname missing\n");
2430 #else
2431                                 fprintf(stderr,
2432                                 "Required PReP boot image pathname missing\n");
2433 #endif
2434                                 exit(1);
2435                         }
2436                         break;
2437                 case OPTION_CHRP_BOOT:
2438                         if (use_chrp_boot)
2439                                 break;          /* silently allow duplicates */
2440                         use_chrp_boot = 1;
2441                         if (use_prep_boot > 3) {
2442 #ifdef USE_LIBSCHILY
2443                                 comerrno(EX_BAD,
2444                                 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2445 #else
2446                                 fprintf(stderr,
2447                                 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2448 #endif
2449                                 exit(1);
2450                         }
2451                         break;
2452 #endif  /* PREP_BOOT */
2453 #endif  /* APPLE_HYB */
2454                 case OPTION_ALLOW_LIMITED_SIZE:
2455                         allow_limited_size++;
2456       use_udf++;
2457                         break;
2458                 default:
2459                         susage(1);
2460                 }
2461         /*
2462          * "--" was found, the next argument is a pathspec
2463          */
2464         if (argc != optind)
2465                 have_cmd_line_pathspec = 1;
2466
2467 parse_input_files:
2468         path_ind = optind;
2469
2470         /*
2471          * XXX This is a hack until we have a decent separate name handling
2472          * XXX for UDF filenames.
2473          */
2474         if (dvd_video && use_Joliet) {
2475                 use_Joliet = 0;
2476                 fprintf(stderr, "Warning: Disabling Joliet support for DVD-Video.\n");
2477         }
2478         if (use_udf && !use_Joliet)
2479                 jlen = 255;
2480
2481         if (preparer) {
2482                 if (strlen(preparer) > 128) {
2483                         comerrno(EX_BAD, "Preparer string too long\n");
2484                 }
2485         }
2486         if (publisher) {
2487                 if (strlen(publisher) > 128) {
2488                         comerrno(EX_BAD,
2489                                 "Publisher string too long\n");
2490                 }
2491         }
2492         if (stream_filename) {
2493                 if (strlen(stream_filename) > MAX_ISONAME)
2494                         comerrno(EX_BAD,
2495                                  "stream-file-name too long (%d), max is %d.\n",
2496                                  (int)strlen(stream_filename), (int)MAX_ISONAME);
2497                 if (strchr(stream_filename, '/'))
2498                         comerrno(EX_BAD, "Illegal character '/' in stream-file-name.\n");
2499                 iso9660_level = 4;
2500         } else {
2501                 stream_filename = "STREAM.IMG;1";
2502         }
2503         if (system_id) {
2504                 if (strlen(system_id) > 32) {
2505                         comerrno(EX_BAD,
2506                                         "System ID string too long\n");
2507                 }
2508         }
2509
2510
2511         if (use_RockRidge && (iso9660_namelen > MAX_ISONAME_V2_RR))
2512                 iso9660_namelen = MAX_ISONAME_V2_RR;
2513
2514         if (warn_violate) /* this one is enough for quiet mode, print others warnings only in more verbose modes */
2515                 fprintf(stderr, "Warning: creating filesystem that does not conform to ISO-9660.\n");
2516         if (iso9660_level > 3 && verbose>0)
2517                 fprintf(stderr, "Warning: Creating ISO-9660:1999 (version 2) filesystem.\n");
2518         if (iso9660_namelen > LEN_ISONAME && verbose>0)
2519                 fprintf(stderr, "Warning: ISO-9660 filenames longer than %d may cause buffer overflows in the OS.\n",
2520                         LEN_ISONAME);
2521         if (use_Joliet && !use_RockRidge && verbose>0) {
2522                 fprintf(stderr,
2523                       "Warning: creating filesystem with Joliet extensions but without Rock Ridge\n"
2524                       "         extensions. It is highly recommended to add Rock Ridge.\n");
2525         }
2526         if (transparent_compression && verbose>0) {
2527                 fprintf(stderr, "Warning: using transparent compression. This is a nonstandard Rock Ridge\n");
2528                 fprintf(stderr, "         extension. The resulting filesystem can only be transparently\n");
2529                 fprintf(stderr, "         read on Linux. On other operating systems you need to call\n");
2530                 fprintf(stderr, "         mkzftree by hand to decompress the files.\n");
2531         }
2532         if (transparent_compression && !use_RockRidge && verbose>0) {
2533                 fprintf(stderr, "Warning: transparent decompression is a Linux Rock Ridge extension, but\n");
2534                 fprintf(stderr, "         creating filesystem without Rock Ridge attributes; files\n");
2535                 fprintf(stderr, "         will not be transparently decompressed.\n");
2536         }
2537     if(follow_links && verbose>0)
2538         fprintf(stderr,
2539                 "Warning: -follow-links does not always work correctly; be careful.\n");
2540
2541         init_unls();            /* Initialize UNICODE tables */
2542
2543         /* initialize code tables from a file - if they exists */
2544         init_unls_file(icharset);
2545         init_unls_file(ocharset);
2546 #ifdef APPLE_HYB
2547         init_unls_file(hfs_icharset);
2548         init_unls_file(hfs_ocharset);
2549 #endif /* APPLE_HYB */
2550
2551 #ifdef USE_ICONV
2552         iconv_possible = !(iso9660_level >= 4 || ((ocharset &&
2553                 strcmp(ocharset, icharset ? icharset : "")) &&
2554                 use_RockRidge) || apple_ext || apple_hyb);
2555
2556         setlocale(LC_CTYPE, "");
2557         
2558         if (icharset == NULL && iconv_possible) {
2559                 char *charset = nl_langinfo(CODESET);
2560                 /* set to detected value but only if it is not pure US-ASCII */
2561         if(charset) { /* workaround for SunOS, iconv is case-sensitive */
2562                         char *t;
2563                         charset = strdup(charset);
2564                         for(t=charset;*t!='\0';t++)
2565                                 *t=tolower(*t);
2566                 }
2567
2568                 if(strcmp(charset, "ansi_x3.4-1968") != 0)
2569                         icharset = charset;
2570
2571                 if(icharset && verbose > 0)
2572                         fprintf(stderr, "I: -input-charset not specified, using %s (detected in locale settings)\n",
2573                         icharset);
2574         }
2575
2576         if(iconv_possible) {
2577                 /*
2578                  * don't care if initialization fails
2579                  */
2580                 init_nls_iconv(icharset);
2581                 init_nls_iconv(ocharset);
2582         }
2583 #endif
2584
2585         if (icharset == NULL) {
2586 #if     (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
2587                 in_nls = load_unls("cp437");
2588 #else
2589                 in_nls = load_unls("iso8859-1");
2590 #endif
2591         } else {
2592                 if (strcmp(icharset, "default") == 0)
2593                         in_nls = load_unls_default();
2594                 else
2595                         in_nls = load_unls(icharset);
2596         }
2597         /*
2598          * set the output charset to the same as the input or the given output
2599          * charset
2600          */
2601         if (ocharset == NULL) {
2602                 out_nls = in_nls;
2603         } else {
2604                 if (strcmp(ocharset, "default") == 0)
2605                         out_nls = load_unls_default();
2606                 else
2607                         out_nls = load_unls(ocharset);
2608         }
2609         if (in_nls == NULL || out_nls == NULL) { /* Unknown charset specified */
2610                 fprintf(stderr, "Unknown charset\nKnown charsets are:\n");
2611                 list_unls();    /* List all known charset names */
2612 #ifdef USE_ICONV
2613         fprintf(stderr, "\nAdditional input charsets are available for Joliet through the iconv support."
2614                 "\nRun \"iconv -l\" to display them. Iconv charsets cannot be used with HFS, Apple"
2615                 "\nextension, ISO9660 version 2 or Rock Ridge.\n");
2616 #endif
2617                 exit(1);
2618         }
2619
2620
2621 #ifdef APPLE_HYB
2622         if (hfs_icharset == NULL || strcmp(hfs_icharset, "mac-roman")) {
2623                 hfs_inls = load_unls("cp10000");
2624         } else {
2625                 if (strcmp(hfs_icharset, "default") == 0)
2626                         hfs_inls = load_unls_default();
2627                 else
2628                         hfs_inls = load_unls(hfs_icharset);
2629         }
2630         if (hfs_ocharset == NULL) {
2631                 hfs_onls = hfs_inls;
2632         } else {
2633                 if (strcmp(hfs_ocharset, "default") == 0)
2634                         hfs_onls = load_unls_default();
2635                 else if (strcmp(hfs_ocharset, "mac-roman") == 0)
2636                         hfs_onls = load_unls("cp10000");
2637                 else
2638                         hfs_onls = load_unls(hfs_ocharset);
2639         }
2640
2641         if (hfs_inls == NULL || hfs_onls == NULL) {
2642                 fprintf(stderr, "Unknown HFS charset\nKnown charsets are:\n");
2643                 list_unls();
2644                 exit(1);
2645         }
2646 #endif /* APPLE_HYB */
2647
2648         if (merge_image != NULL) {
2649                 if (open_merge_image(merge_image) < 0) {
2650                         /* Complain and die. */
2651 #ifdef  USE_LIBSCHILY
2652                         comerr("Unable to open previous session image '%s'.\n",
2653                                 merge_image);
2654 #else
2655                         fprintf(stderr,
2656                                 "Unable to open previous session image '%s'.\n",
2657                                 merge_image);
2658                         exit(1);
2659 #endif
2660                 }
2661         }
2662         /* We don't need root privilleges anymore. */
2663 #ifdef  HAVE_SETREUID
2664         if (setreuid(-1, getuid()) < 0)
2665 #else
2666 #ifdef  HAVE_SETEUID
2667         if (seteuid(getuid()) < 0)
2668 #else
2669         if (setuid(getuid()) < 0)
2670 #endif
2671 #endif
2672 #ifdef  USE_LIBSCHILY
2673                 comerr("Panic cannot set back effective uid.\n");
2674 #else
2675         {
2676                 perror("Panic cannot set back effective uid.");
2677                 exit(1);
2678         }
2679 #endif
2680
2681
2682 #ifdef  no_more_needed
2683 #ifdef __NetBSD__
2684         {
2685                 int             resource;
2686                 struct rlimit   rlp;
2687
2688                 if (getrlimit(RLIMIT_DATA, &rlp) == -1)
2689                         perror("Warning: getrlimit failed");
2690                 else {
2691                         rlp.rlim_cur = 33554432;
2692                         if (setrlimit(RLIMIT_DATA, &rlp) == -1)
2693                                 perror("Warning: setrlimit failed");
2694                 }
2695         }
2696 #endif
2697 #endif  /* no_more_needed */
2698 #ifdef HAVE_SBRK
2699         mem_start = (unsigned long) sbrk(0);
2700 #endif
2701
2702         /*
2703          * if the -hide-joliet option has been given, set the Joliet option
2704          */
2705         if (!use_Joliet && j_ishidden())
2706                 use_Joliet++;
2707
2708 #ifdef APPLE_HYB
2709         if (apple_hyb && apple_ext) {
2710 #ifdef  USE_LIBSCHILY
2711                 comerrno(EX_BAD, "Can't have both -apple and -hfs options");
2712 #else
2713                 fprintf(stderr, "Can't have both -apple and -hfs options");
2714                 exit(1);
2715 #endif
2716         }
2717         /*
2718          * if -probe, -macname, any hfs selection and/or mapping file is given,
2719          * but no HFS option, then select apple_hyb
2720          */
2721         if (!apple_hyb && !apple_ext) {
2722                 if (*afpfile || probe || use_mac_name || hfs_select ||
2723                                 hfs_boot_file || magic_filename ||
2724                                 hfs_ishidden() || gen_pt || autoname ||
2725                                 afe_size || icon_pos || hfs_ct ||
2726                                 hfs_icharset || hfs_ocharset) {
2727                         apple_hyb = 1;
2728                 }
2729         }
2730         if (apple_ext && hfs_boot_file) {
2731 #ifdef  USE_LIBSCHILY
2732                 comerrno(EX_BAD, "Can't have -hfs-boot-file with -apple\n");
2733 #else
2734                 fprintf(stderr, "Can't have -hfs-boot-file with -apple\n");
2735                 exit(1);
2736 #endif
2737         }
2738         if (apple_ext && autoname) {
2739 #ifdef  USE_LIBSCHILY
2740                 comerrno(EX_BAD, "Can't have -auto with -apple\n");
2741 #else
2742                 fprintf(stderr, "Can't have -auto with -apple\n");
2743                 exit(1);
2744 #endif
2745         }
2746         if (apple_hyb && (use_sparcboot || use_sunx86boot)) {
2747 #ifdef  USE_LIBSCHILY
2748                 comerrno(EX_BAD, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
2749 #else
2750                 fprintf(stderr, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
2751                 exit(1);
2752 #endif
2753         }
2754         if (apple_hyb && use_genboot) {
2755 #ifdef  USE_LIBSCHILY
2756                 comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n");
2757 #else
2758                 fprintf(stderr, "Can't have -hfs with -generic-boot\n");
2759                 exit(1);
2760 #endif
2761         }
2762 #ifdef PREP_BOOT
2763         if (apple_ext && use_prep_boot) {
2764 #ifdef  USE_LIBSCHILY
2765                 comerrno(EX_BAD, "Can't have -prep-boot with -apple\n");
2766 #else
2767                 fprintf(stderr, "Can't have -prep-boot with -apple\n");
2768                 exit(1);
2769 #endif
2770         }
2771 #endif  /* PREP_BOOT */
2772
2773         if (apple_hyb || apple_ext)
2774                 apple_both = 1;
2775
2776         if (probe)
2777                 /* we need to search for all types of Apple/Unix files */
2778                 hfs_select = ~0;
2779
2780         if (apple_both && verbose && !(hfs_select || *afpfile || magic_filename)) {
2781 #ifdef  USE_LIBSCHILY
2782                 errmsgno(EX_BAD,
2783                 "Warning: no Apple/Unix files will be decoded/mapped\n");
2784 #else
2785                 fprintf(stderr,
2786                 "Warning: no Apple/Unix files will be decoded/mapped\n");
2787 #endif
2788         }
2789         if (apple_both && verbose && !afe_size &&
2790                                         (hfs_select & (DO_FEU | DO_FEL))) {
2791 #ifdef  USE_LIBSCHILY
2792                 errmsgno(EX_BAD,
2793                 "Warning: assuming PC Exchange cluster size of 512 bytes\n");
2794 #else
2795                 fprintf(stderr,
2796                 "Warning: assuming PC Exchange cluster size of 512 bytes\n");
2797 #endif
2798                 afe_size = 512;
2799         }
2800         if (apple_both) {
2801                 /* set up the TYPE/CREATOR mappings */
2802                 hfs_init(afpfile, 0, hfs_select);
2803         }
2804         if (apple_ext && !use_RockRidge) {
2805 #ifdef  nonono
2806                 /* use RockRidge to set the SystemUse field ... */
2807                 use_RockRidge++;
2808                 rationalize_all++;
2809 #else
2810                 /* EMPTY */
2811 #endif
2812         }
2813         if (apple_ext && !(use_XA || use_RockRidge)) {
2814                 comerrno(EX_BAD, "Need either -XA/-xa or -R/-r for -apple to become active.\n");
2815         }
2816
2817 #endif  /* APPLE_HYB */
2818
2819         if (rationalize_all) {
2820                 rationalize++;
2821                 rationalize_uid++;
2822                 rationalize_gid++;
2823                 rationalize_filemode++;
2824                 rationalize_dirmode++;
2825         }
2826
2827         if (verbose > 1) {
2828                 fprintf(stderr, "%s (%s)\n", version_string, HOST_SYSTEM);
2829         }
2830         if (cdrecord_data == NULL && !check_session && merge_image != NULL) {
2831 #ifdef  USE_LIBSCHILY
2832                 comerrno(EX_BAD,
2833                 "Multisession usage bug: Must specify -C if -M is used.\n");
2834 #else
2835                 fprintf(stderr,
2836                 "Multisession usage bug: Must specify -C if -M is used.\n");
2837                 exit(1);
2838 #endif
2839         }
2840         if (cdrecord_data != NULL && merge_image == NULL) {
2841 #ifdef  USE_LIBSCHILY
2842                 errmsgno(EX_BAD,
2843                 "Warning: -C specified without -M: old session data will not be merged.\n");
2844 #else
2845                 fprintf(stderr,
2846                 "Warning: -C specified without -M: old session data will not be merged.\n");
2847 #endif
2848         }
2849 #ifdef APPLE_HYB
2850         if (merge_image != NULL && apple_hyb) {
2851 #ifdef  USE_LIBSCHILY
2852                 errmsgno(EX_BAD,
2853                 "Warning: files from previous sessions will not be included in the HFS volume.\n");
2854 #else
2855                 fprintf(stderr,
2856                 "Warning: files from previous sessions will not be included in the HFS volume.\n");
2857 #endif
2858         }
2859 #endif  /* APPLE_HYB */
2860
2861         /*
2862          * see if we have a list of pathnames to process
2863          */
2864         if (pathnames) {
2865                 /* "-" means take list from the standard input */
2866                 if (strcmp(pathnames, "-")) {
2867                         if ((pfp = fopen(pathnames, "r")) == NULL) {
2868 #ifdef  USE_LIBSCHILY
2869                                 comerr("Unable to open pathname list %s.\n",
2870                                                                 pathnames);
2871 #else
2872                                 fprintf(stderr,
2873                                         "Unable to open pathname list %s.\n",
2874                                                                 pathnames);
2875                                 exit(1);
2876 #endif
2877                         }
2878                 } else
2879                         pfp = stdin;
2880         }
2881
2882         /* The first step is to scan the directory tree, and take some notes */
2883
2884         if ((arg = get_pnames(argc, argv, optind, pname,
2885                                         sizeof (pname), pfp)) == NULL) {
2886                 if (check_session == 0 && !stream_media_size) {
2887 #ifdef  USE_LIBSCHILY
2888                         errmsgno(EX_BAD, "Missing pathspec.\n");
2889 #endif
2890                         susage(1);
2891                 }
2892         }
2893
2894         /*
2895          * if we don't have a pathspec, then save the pathspec found
2896          * in the pathnames file (stored in pname) - we don't want
2897          * to skip this pathspec when we read the pathnames file again
2898          */
2899         if (!have_cmd_line_pathspec && !stream_media_size) {
2900                 save_pname = 1;
2901         }
2902         if (stream_media_size) {
2903                 if (use_XA || use_RockRidge || use_udf || use_Joliet)
2904                         comerrno(EX_BAD,
2905                         "Cannot use XA, Rock Ridge, UDF or Joliet with -stream-media-size\n");
2906                 if (merge_image)
2907                         comerrno(EX_BAD,
2908                         "Cannot use multi session with -stream-media-size\n");
2909                 if (use_eltorito || use_sparcboot || use_sunx86boot ||
2910                     use_genboot || use_prep_boot || hfs_boot_file)
2911                         comerrno(EX_BAD,
2912                         "Cannot use boot options with -stream-media-size\n");
2913                 if (apple_hyb)
2914                         comerrno(EX_BAD,
2915                         "Cannot use Apple hybrid options with -stream-media-size\n");
2916         }
2917
2918         if (use_RockRidge) {
2919                 /* BEGIN CSTYLED */
2920 #if 1
2921                 extension_record = generate_rr_extension_record("RRIP_1991A",
2922                         "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
2923                         "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE.  SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.",
2924                         &extension_record_size);
2925 #else
2926                 extension_record = generate_rr_extension_record("IEEE_P1282",
2927                         "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
2928                         "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.",
2929                         &extension_record_size);
2930 #endif
2931                 /* END CSTYLED */
2932         }
2933         if (log_file) {
2934                 FILE            *lfp;
2935                 int             i;
2936
2937                 /* open log file - test that we can open OK */
2938                 if ((lfp = fopen(log_file, "w")) == NULL) {
2939 #ifdef  USE_LIBSCHILY
2940                         comerr("Can't open logfile: '%s'.\n", log_file);
2941 #else
2942                         fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
2943                         exit(1);
2944 #endif
2945                 }
2946                 fclose(lfp);
2947
2948                 /* redirect all stderr message to log_file */
2949                 fprintf(stderr, "re-directing all messages to %s\n", log_file);
2950                 fflush(stderr);
2951
2952                 /* associate stderr with the log file */
2953                 if (freopen(log_file, "w", stderr) == NULL) {
2954 #ifdef  USE_LIBSCHILY
2955                         comerr("Can't open logfile: '%s'.\n", log_file);
2956 #else
2957                         fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
2958                         exit(1);
2959 #endif
2960                 }
2961                 if (verbose > 1) {
2962                         for (i = 0; i < argc; i++)
2963                                 fprintf(stderr, "%s ", argv[i]);
2964
2965                         fprintf(stderr, "\n%s (%s)\n",
2966                                 version_string, HOST_SYSTEM);
2967                 }
2968         }
2969         /* Find name of root directory. */
2970         if (arg != NULL)
2971                 node = findgequal(arg);
2972         if (!use_graft_ptrs)
2973                 node = NULL;
2974         if (node == NULL) {
2975                 if (use_graft_ptrs && arg != NULL)
2976                         node = escstrcpy(nodename, arg);
2977                 else
2978                         node = arg;
2979         } else {
2980                 /*
2981                  * Remove '\\' escape chars which are located
2982                  * before '\\' and '=' chars
2983                  */
2984                 node = escstrcpy(nodename, ++node);
2985         }
2986
2987         /*
2988          * See if boot catalog file exists in root directory, if not we will
2989          * create it.
2990          */
2991         if (use_eltorito)
2992                 init_boot_catalog(node);
2993
2994         /*
2995          * Find the device and inode number of the root directory. Record this
2996          * in the hash table so we don't scan it more than once.
2997          */
2998         stat_filter(node, &statbuf);
2999         add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
3000
3001         memset(&de, 0, sizeof (de));
3002
3003         /*
3004          * PO:
3005          * Isn't root NULL at this time anyway?
3006          * I think it is created by the first call to
3007          * find_or_create_directory() below.
3008          */
3009         de.filedir = root;      /* We need this to bootstrap */
3010
3011         if (cdrecord_data != NULL && merge_image == NULL) {
3012                 /*
3013                  * in case we want to add a new session, but don't want to
3014                  * merge old one
3015                  */
3016                 get_session_start(NULL);
3017         }
3018         if (merge_image != NULL) {
3019                 char    sector[SECTOR_SIZE];
3020
3021                 errno = 0;
3022                 mrootp = merge_isofs(merge_image);
3023                 if (mrootp == NULL) {
3024                         /* Complain and die. */
3025 #ifdef  USE_LIBSCHILY
3026                         if (errno == 0)
3027                                 errno = -1;
3028                         comerr("Unable to find previous session PVD '%s'.\n",
3029                                 merge_image);
3030 #else
3031                         fprintf(stderr,
3032                                 "Unable to find previous session PVD '%s'.\n",
3033                                 merge_image);
3034                         exit(1);
3035 #endif
3036                 }
3037                 memcpy(de.isorec.extent, mrootp->extent, 8);
3038
3039                 /*
3040                  * Look for RR Attributes in '.' entry of root dir.
3041                  * This is the first ISO directory entry in the root dir.
3042                  */
3043                 c = isonum_733((unsigned char *)mrootp->extent);
3044 #ifdef  USE_SCG
3045                 readsecs(c, sector, 1);
3046 #else
3047     lseek(fileno(in_image), c*2048, SEEK_SET);
3048     read(fileno(in_image), sector, sizeof (sector));
3049 #endif
3050                 c = rr_flags((struct iso_directory_record *)sector);
3051                 if (c & RR_FLAG_XA)
3052                         fprintf(stderr, "XA signatures found\n");
3053                 if (c & RR_FLAG_AA)
3054                         fprintf(stderr, "AA signatures found\n");
3055                 if (c & ~(RR_FLAG_XA|RR_FLAG_AA)) {
3056                         if (c & RR_FLAG_SP) {
3057                                 fprintf(stderr, "Rock Ridge signatures found\n");
3058                         } else {
3059                                 fprintf(stderr, "Bad Rock Ridge signatures found (SU record missing)\n");
3060                                 if (!force_rr)
3061                                         no_rr++;
3062                         }
3063                 } else {
3064                         fprintf(stderr, "NO Rock Ridge present\n");
3065                         if ((c & (RR_FLAG_XA|RR_FLAG_AA)) == 0) {
3066                                 if (!force_rr)
3067                                         no_rr++;
3068                         }
3069                 }
3070                 if (no_rr)
3071                         fprintf(stderr, "Disabling Rock Ridge / XA / AA\n");
3072         }
3073         /*
3074          * Create an empty root directory. If we ever scan it for real,
3075          * we will fill in the contents.
3076          */
3077         find_or_create_directory(NULL, "", &de, TRUE, NULL);
3078
3079 #ifdef APPLE_HYB
3080         /* may need to set window layout of the volume */
3081         if (root_info)
3082                 set_root_info(root_info);
3083 #endif /* APPLE_HYB */
3084
3085         if(optind < argc-1)
3086                 merge_warn_msg="NOTE: multiple source directories have been specified and merged into the root\n"
3087                         "of the filesystem. Check your program arguments. genisoimage is not tar.\n";
3088
3089         /*
3090          * Scan the actual directory (and any we find below it) for files to
3091          * write out to the output image.  Note - we take multiple source
3092          * directories and keep merging them onto the image.
3093          */
3094 if (check_session == 0)
3095         while ((arg = get_pnames(argc, argv, optind, pname,
3096                                         sizeof (pname), pfp)) != NULL) {
3097                 struct directory *graft_dir;
3098                 struct stat     st;
3099                 char            *short_name;
3100                 int             status;
3101                 char            graft_point[PATH_MAX + 1];
3102
3103                 /*
3104                  * We would like a syntax like:
3105                  *
3106                  *      /tmp=/usr/tmp/xxx
3107                  *
3108                  * where the user can specify a place to graft each component
3109                  * of the tree.  To do this, we may have to create directories
3110                  * along the way, of course. Secondly, I would like to allow
3111                  * the user to do something like:
3112                  *
3113                  *      /home/baz/RMAIL=/u3/users/baz/RMAIL
3114                  *
3115                  * so that normal files could also be injected into the tree
3116                  * at an arbitrary point.
3117                  *
3118                  * The idea is that the last component of whatever is being
3119                  * entered would take the name from the last component of
3120                  * whatever the user specifies.
3121                  *
3122                  * The default will be that the file is injected at the root of
3123                  * the image tree.
3124                  */
3125                 node = findgequal(arg);
3126                 if (!use_graft_ptrs)
3127                         node = NULL;
3128                 /*
3129                  * Remove '\\' escape chars which are located
3130                  * before '\\' and '=' chars ---> below in escstrcpy()
3131                  */
3132
3133                 short_name = NULL;
3134
3135                 if (node != NULL || reloc_root) {
3136                         char            *pnt;
3137                         char            *xpnt;
3138                         size_t          len;
3139                         int             node_is_dir;
3140
3141                         /* insert -root prefix */
3142                         if (reloc_root != NULL) {
3143                                 strcpy(graft_point, reloc_root);
3144                                 len = strlen(graft_point);
3145                                 if (graft_point[len] != '/') {
3146                                         graft_point[len++] = '/';
3147                                         graft_point[len] = '\0';
3148                                 }
3149                         } else {
3150                                 len = 0;
3151                         }
3152
3153                         if (node) {
3154                                 *node = '\0';
3155                                 escstrcpy(&graft_point[len], arg);
3156                                 *node = '=';
3157                         }
3158
3159                         /*
3160                          * Remove unwanted "./" & "/" sequences from start...
3161                          */
3162                         do {
3163                                 xpnt = graft_point;
3164                                 while (xpnt[0] == '.' && xpnt[1] == '/')
3165                                         xpnt += 2;
3166                                 while (*xpnt == PATH_SEPARATOR) {
3167                                         xpnt++;
3168                                 }
3169                                 memmove(graft_point, xpnt, strlen(xpnt)+1);
3170                         } while (xpnt > graft_point);
3171
3172                         if (node) {
3173                                 node = escstrcpy(nodename, ++node);
3174                         } else {
3175                                 node = arg;
3176                         }
3177
3178                         graft_dir = root;
3179                         xpnt = graft_point;
3180
3181                         /*
3182                          * If "node" points to a directory, then graft_point
3183                          * needs to point to a directory too.
3184                          */
3185                         if (follow_links)
3186                                 status = stat_filter(node, &st);
3187                         else
3188                                 status = lstat_filter(node, &st);
3189
3190                         node_is_dir = S_ISDIR(st.st_mode);
3191                         if (status == 0 && node_is_dir) {
3192                                 len = strlen(graft_point);
3193
3194                                 if ((len <= (sizeof (graft_point) -1)) &&
3195                                     graft_point[len-1] != '/') {
3196                                         graft_point[len++] = '/';
3197                                         graft_point[len] = '\0';
3198                                 }
3199                         }
3200                         if (debug)
3201                                 fprintf(stderr, "GRAFT:'%s'\n", xpnt);
3202                         /*
3203                          * Loop down deeper and deeper until we find the
3204                          * correct insertion spot.
3205                          * Canonicalize the filename while parsing it.
3206                          */
3207                         for (;;) {
3208                                 struct stat* stat_template;
3209
3210                                 do {
3211                                         while (xpnt[0] == '.' && xpnt[1] == '/')
3212                                                 xpnt += 2;
3213                                         while (xpnt[0] == '/')
3214                                                 xpnt += 1;
3215                                         if (xpnt[0] == '.' && xpnt[1] == '.' && xpnt[2] == '/') {
3216                                                 if (graft_dir && graft_dir != root) {
3217                                                         graft_dir = graft_dir->parent;
3218                                                         xpnt += 2;
3219                                                 }
3220                                         }
3221                                 } while ((xpnt[0] == '/') || (xpnt[0] == '.' && xpnt[1] == '/'));
3222                                 pnt = strchr(xpnt, PATH_SEPARATOR);
3223                                 if (pnt == NULL) {
3224                                         if (*xpnt != '\0') {
3225                                                 short_name = xpnt;
3226                                         }
3227                                         break;
3228                                 }
3229                                 *pnt = '\0';
3230                                 if (debug) {
3231                                         fprintf(stderr, "GRAFT Point:'%s' in '%s : %s' (%s)\n",
3232                                                 xpnt,
3233                                                 graft_dir->whole_name,
3234                                                 graft_dir->de_name,
3235                                                 graft_point);
3236                                 }
3237                                 /*
3238                                  * If the node being grafted is a
3239                                  * directory, then we want the last
3240                                  * directory in this graft chain to have
3241                                  * the ownership and permissions of the
3242                                  * source node.  Other directories in the
3243                                  * chain get default ownership and
3244                                  * permissions.
3245                                  */
3246                                 stat_template = 
3247                                   (pnt[1] == '\0' && node_is_dir) ? &st : 0;
3248
3249                                 graft_dir = find_or_create_directory(graft_dir,
3250                                         graft_point, NULL, TRUE, 
3251                                         stat_template);
3252
3253                                 *pnt = PATH_SEPARATOR;
3254                                 xpnt = pnt + 1;
3255                         }
3256                 } else {
3257                         graft_dir = root;
3258                         if (use_graft_ptrs)
3259                                 node = escstrcpy(nodename, arg);
3260                         else
3261                                 node = arg;
3262                 }
3263
3264                 /*
3265                  * Get information on the node
3266                  */
3267                 if (follow_links)
3268                         status = stat_filter(node, &st);
3269                 else
3270                         status = lstat_filter(node, &st);
3271                 if (status != 0) {
3272                         /*
3273                          * This is a fatal error - the user won't be getting
3274                          * what they want if we were to proceed.
3275                          */
3276 #ifdef  USE_LIBSCHILY
3277                         comerr("Invalid node - '%s'.\n", node);
3278 #else
3279                         fprintf(stderr, "Invalid node - '%s'.\n", node);
3280                         exit(1);
3281 #endif
3282                 } else {
3283                         /*
3284                          * Now see whether the user wants to add a regular
3285                          * file or a directory at this point.
3286                          */
3287                         if (S_ISDIR(st.st_mode)) {
3288                                 if (debug) {
3289                                         fprintf(stderr, "graft_dir: '%s : %s', node: '%s', (scan)\n",
3290                                                 graft_dir->whole_name,
3291                                                 graft_dir->de_name, node);
3292                                 }
3293                                 if (!scan_directory_tree(graft_dir,
3294                                                                 node, &de)) {
3295                                         exit(1);
3296                                 }
3297                                 if (debug) {
3298                                         fprintf(stderr, "scan done\n");
3299                                 }
3300                         } else {
3301                                 if (short_name == NULL) {
3302                                         short_name = strrchr(node,
3303                                                         PATH_SEPARATOR);
3304                                         if (short_name == NULL ||
3305                                                         short_name < node) {
3306                                                 short_name = node;
3307                                         } else {
3308                                                 short_name++;
3309                                         }
3310                                 }
3311                                 if (debug) {
3312                                         fprintf(stderr, "graft_dir: '%s : %s', node: '%s', short_name: '%s'\n",
3313                                                 graft_dir->whole_name,
3314                                                 graft_dir->de_name, node,
3315                                                 short_name);
3316                                 }
3317 #ifdef APPLE_HYB
3318                                 if (!insert_file_entry(graft_dir, node,
3319                                                                 short_name, 0))
3320 #else
3321                                 if (!insert_file_entry(graft_dir, node,
3322                                                                 short_name))
3323 #endif  /* APPLE_HYB */
3324                                 {
3325                                         /*
3326                                          * Should we ignore this?
3327                                          */
3328 /*                                      exit(1);*/
3329                                         /* EMPTY */
3330                                 }
3331                         }
3332                 }
3333
3334                 optind++;
3335                 no_path_names = 0;
3336         }
3337
3338         if (pfp && pfp != stdin)
3339                 fclose(pfp);
3340
3341         /*
3342          * exit if we don't have any pathnames to process
3343          * - not going to happen at the moment as we have to have at least one
3344          * path on the command line
3345          */
3346         if (no_path_names && !check_session && !stream_media_size) {
3347 #ifdef  USE_LIBSCHILY
3348                 errmsgno(EX_BAD, "No pathnames found.\n");
3349 #endif
3350                 susage(1);
3351         }
3352         /*
3353          * Now merge in any previous sessions.  This is driven on the source
3354          * side, since we may need to create some additional directories.
3355          */
3356         if (merge_image != NULL) {
3357                 if (merge_previous_session(root, mrootp,
3358                                         reloc_root, reloc_old_root) < 0) {
3359 #ifdef  USE_LIBSCHILY
3360                         comerrno(EX_BAD, "Cannot merge previous session.\n");
3361 #else
3362                         fprintf(stderr, "Cannot merge previous session.\n");
3363                         exit(1);
3364 #endif
3365                 }
3366                 close_merge_image();
3367
3368                 /*
3369                  * set up parent_dir and filedir in relocated entries which
3370                  * were read from previous session so that
3371                  * finish_cl_pl_entries can do its job
3372                  */
3373                 match_cl_re_entries();
3374         }
3375 #ifdef APPLE_HYB
3376         /* free up any HFS filename mapping memory */
3377         if (apple_both)
3378                 clean_hfs();
3379 #endif  /* APPLE_HYB */
3380
3381         /* hide "./rr_moved" if all its contents have been hidden */
3382         if (reloc_dir && i_ishidden())
3383                 hide_reloc_dir();
3384
3385         /* insert the boot catalog if required */
3386         if (use_eltorito)
3387                 insert_boot_cat();
3388
3389         /*
3390          * Free up any matching memory
3391          */
3392         for (n = 0; n < MAX_MAT; n++)
3393                 gen_del_match(n);
3394
3395 #ifdef SORTING
3396         del_sort();
3397 #endif /* SORTING */
3398
3399         /*
3400          * Sort the directories in the required order (by ISO9660).  Also,
3401          * choose the names for the 8.3 filesystem if required, and do any
3402          * other post-scan work.
3403          */
3404         goof += sort_tree(root);
3405
3406         if (goof) {
3407                 fprintf(stderr, "ISO9660/Rock Ridge tree sort failed.\n");
3408                 if(merge_warn_msg)
3409                         fprintf(stderr, merge_warn_msg);
3410                 exit(1);
3411         }
3412 #ifdef UDF
3413         if (use_Joliet || use_udf) {
3414 #else
3415         if (use_Joliet) {
3416 #endif
3417                 goof += joliet_sort_tree(root);
3418         }
3419         if (goof) {
3420                 fprintf(stderr, "Joliet tree sort failed. The -joliet-long switch may help you.\n");
3421                 if(merge_warn_msg)
3422                         fprintf(stderr, merge_warn_msg);
3423                 exit(1);
3424         }
3425         /*
3426          * Fix a couple of things in the root directory so that everything is
3427          * self consistent. Fix this up so that the path tables get done right.
3428          */
3429         root->self = root->contents;
3430
3431         /* OK, ready to write the file.  Open it up, and generate the thing. */
3432         if (print_size) {
3433                 discimage = fopen("/dev/null", "wb");
3434                 if (!discimage) {
3435 #ifdef  USE_LIBSCHILY
3436                         comerr("Unable to open /dev/null\n");
3437 #else
3438                         fprintf(stderr, "Unable to open /dev/null\n");
3439                         exit(1);
3440 #endif
3441                 }
3442         } else if (outfile && (strcmp (outfile, "-")) != 0) {
3443                 discimage = fopen(outfile, "wb");
3444                 if (!discimage) {
3445 #ifdef  USE_LIBSCHILY
3446                         comerr("Unable to open disc image file '%s'.\n", outfile);
3447 #else
3448                         fprintf(stderr, "Unable to open disc image file '%s'.\n", outfile);
3449                         exit(1);
3450 #endif
3451                 }
3452                 if (jtemplate_out || jjigdo_out) {
3453                         if (!jtemplate_out || !jjigdo_out || !jmd5_list) {
3454 #ifdef USE_LIBSCHILY
3455                                 comerr("Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
3456 #else
3457                                 fprintf(stderr, "Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
3458                                 exit(1);
3459 #endif
3460                         }
3461                         jtjigdo = fopen(jjigdo_out, "wb");
3462                         jttemplate = fopen(jtemplate_out, "wb");
3463                         if (!jtjigdo || !jttemplate) {
3464 #ifdef USE_LIBSCHILY
3465                                 comerr("Unable to open jigdo template image file\n");
3466 #else
3467                                 fprintf(stderr, "Unable to open jigdo template image file\n");
3468                                 exit(1);
3469 #endif
3470                         }
3471                         write_jt_header(jttemplate, jtjigdo);
3472                 }
3473         } else if ((outfile == NULL)
3474                && isatty (fileno (stdout))) {
3475                 /* FIXME: a cleaner way to override this check? */
3476                 fputs (("image not written to a terminal.\n"
3477                 "Use -o - to force the output.\n"),
3478                        stderr);
3479                 exit (1);
3480         } else {
3481                 discimage = stdout;
3482
3483 #ifdef  NEED_O_BINARY
3484                 setmode(fileno(stdout), O_BINARY);
3485 #endif
3486         }
3487
3488         /* Now assign addresses on the disc for the path table. */
3489
3490         path_blocks = ISO_BLOCKS(path_table_size);
3491         if (path_blocks & 1)
3492                 path_blocks++;
3493
3494         jpath_blocks = ISO_BLOCKS(jpath_table_size);
3495         if (jpath_blocks & 1)
3496                 jpath_blocks++;
3497
3498         /*
3499          * Start to set up the linked list that we use to track the contents
3500          * of the disc.
3501          */
3502 #ifdef APPLE_HYB
3503 #ifdef PREP_BOOT
3504         if (apple_hyb || use_prep_boot || use_chrp_boot)
3505 #else   /* PREP_BOOT */
3506         if (apple_hyb)
3507 #endif  /* PREP_BOOT */
3508                 outputlist_insert(&hfs_desc);
3509 #endif  /* APPLE_HYB */
3510         if (use_sparcboot || use_sunx86boot)
3511                 outputlist_insert(&sunlabel_desc);
3512         if (use_alphaboot)
3513                 outputlist_insert(&alphaboot_desc);
3514         if (use_hppaboot)
3515                 outputlist_insert(&hppaboot_desc);
3516         if (use_alphaboot || use_hppaboot)
3517                 outputlist_insert(&alpha_hppa_boot_desc);
3518         if (use_mipsboot)
3519                 outputlist_insert(&mipsboot_desc);
3520         if (use_mipselboot)
3521                 outputlist_insert(&mipselboot_desc);
3522         if (use_genboot)
3523                 outputlist_insert(&genboot_desc);
3524         outputlist_insert(&startpad_desc);
3525
3526         /* PVD for disc. */
3527         outputlist_insert(&voldesc_desc);
3528
3529         /* SVD for El Torito. MUST be immediately after the PVD! */
3530         if (use_eltorito) {
3531                 outputlist_insert(&torito_desc);
3532         }
3533         /* Enhanced PVD for disc. neded if we write ISO-9660:1999 */
3534         if (iso9660_level > 3)
3535                 outputlist_insert(&xvoldesc_desc);
3536
3537         /* SVD for Joliet. */
3538         if (use_Joliet) {
3539                 outputlist_insert(&joliet_desc);
3540         }
3541         /* Finally the last volume descriptor. */
3542         outputlist_insert(&end_vol);
3543
3544 #ifdef UDF
3545         if (use_udf) {
3546                 outputlist_insert(&udf_vol_recognition_area_frag);
3547         }
3548 #endif
3549
3550         /* Insert the version descriptor. */
3551         outputlist_insert(&version_desc);
3552
3553 #ifdef UDF
3554         if (use_udf) {
3555                 /*
3556                  * Most of the space before sector 256 is wasted when
3557                  * UDF is turned on. The waste could be reduced by
3558                  * putting the ISO9660/Joliet structures before the
3559                  * pad_to_sector_256; the problem is that they might
3560                  * overshoot sector 256, so there would have to be some
3561                  * ugly logic to detect this case and rearrange things
3562                  * appropriately. I don't know if it's worth it.
3563                  */
3564                 outputlist_insert(&udf_pad_to_sector_32_frag);
3565                 outputlist_insert(&udf_main_seq_frag);
3566                 outputlist_insert(&udf_main_seq_copy_frag);
3567                 outputlist_insert(&udf_integ_seq_frag);
3568                 outputlist_insert(&udf_pad_to_sector_256_frag);
3569                 outputlist_insert(&udf_anchor_vol_desc_frag);
3570                 outputlist_insert(&udf_file_set_desc_frag);
3571                 outputlist_insert(&udf_dirtree_frag);
3572                 outputlist_insert(&udf_file_entries_frag);
3573         }
3574 #endif
3575
3576         /* Now start with path tables and directory tree info. */
3577         if (!stream_media_size)
3578                 outputlist_insert(&pathtable_desc);
3579         else
3580                 outputlist_insert(&strpath_desc);
3581
3582         if (use_Joliet) {
3583                 outputlist_insert(&jpathtable_desc);
3584         }
3585
3586         if (!stream_media_size)
3587                 outputlist_insert(&dirtree_desc);
3588
3589         if (use_Joliet) {
3590                 outputlist_insert(&jdirtree_desc);
3591         }
3592         outputlist_insert(&dirtree_clean);
3593
3594         if (extension_record) {
3595                 outputlist_insert(&extension_desc);
3596         }
3597
3598         if (!stream_media_size) {
3599                 outputlist_insert(&files_desc);
3600         } else {
3601                 outputlist_insert(&strfile_desc);
3602                 outputlist_insert(&strdir_desc);
3603         }
3604
3605         /*
3606          * Allow room for the various headers we will be writing.
3607          * There will always be a primary and an end volume descriptor.
3608          */
3609         last_extent = session_start;
3610
3611         /*
3612          * Calculate the size of all of the components of the disc, and assign
3613          * extent numbers.
3614          */
3615         for (opnt = out_list; opnt; opnt = opnt->of_next) {
3616                 opnt->of_start_extent = last_extent;
3617                 if (opnt->of_size != NULL) {
3618                         (*opnt->of_size) (last_extent);
3619                 }
3620         }
3621
3622         /*
3623          * Generate the contents of any of the sections that we want to
3624          * generate. Not all of the fragments will do anything here
3625          * - most will generate the data on the fly when we get to the write
3626          * pass.
3627          */
3628         for (opnt = out_list; opnt; opnt = opnt->of_next) {
3629                 if (opnt->of_generate != NULL) {
3630                         (*opnt->of_generate) ();
3631                 }
3632         }
3633
3634         /*
3635          * Padding just after the ISO-9660 filesystem.
3636          *
3637          * files_desc does not have an of_size function. For this
3638          * reason, we must insert us after the files content has been
3639          * generated.
3640          */
3641 #ifdef UDF
3642         if (use_udf) {
3643                 /* Single anchor volume descriptor pointer at end */
3644                 outputlist_insert(&udf_end_anchor_vol_desc_frag);
3645                 if (udf_end_anchor_vol_desc_frag.of_size != NULL) {
3646                         (*udf_end_anchor_vol_desc_frag.of_size) (last_extent);
3647                 }
3648                 if (dopad) {
3649                         /*
3650                          * Pad with anchor volume descriptor pointer
3651                          * blocks instead of zeroes.
3652                          */
3653                         outputlist_insert(&udf_padend_avdp_frag);
3654                         if (udf_padend_avdp_frag.of_size != NULL) {
3655                                 (*udf_padend_avdp_frag.of_size) (last_extent);
3656                         }
3657                 }
3658         } else
3659 #endif
3660         if (dopad && !(use_sparcboot || use_sunx86boot)) {
3661                 outputlist_insert(&endpad_desc);
3662                 if (endpad_desc.of_size != NULL) {
3663                         (*endpad_desc.of_size) (last_extent);
3664                 }
3665         }
3666         c = 0;
3667         if (use_sparcboot) {
3668                 if (dopad) {
3669                         /* Padding before the boot partitions. */
3670                         outputlist_insert(&interpad_desc);
3671                         if (interpad_desc.of_size != NULL) {
3672                                 (*interpad_desc.of_size) (last_extent);
3673                         }
3674                 }
3675                 c = make_sun_label();
3676                 last_extent += c;
3677                 outputlist_insert(&sunboot_desc);
3678                 if (dopad) {
3679                         outputlist_insert(&endpad_desc);
3680                         if (endpad_desc.of_size != NULL) {
3681                                 (*endpad_desc.of_size) (last_extent);
3682                         }
3683                 }
3684         } else if (use_sunx86boot) {
3685                 if (dopad) {
3686                         /* Padding before the boot partitions. */
3687                         outputlist_insert(&interpad_desc);
3688                         if (interpad_desc.of_size != NULL) {
3689                                 (*interpad_desc.of_size) (last_extent);
3690                         }
3691                 }
3692                 c = make_sunx86_label();
3693                 last_extent += c;
3694                 outputlist_insert(&sunboot_desc);
3695                 if (dopad) {
3696                         outputlist_insert(&endpad_desc);
3697                         if (endpad_desc.of_size != NULL) {
3698                                 (*endpad_desc.of_size) (last_extent);
3699                         }
3700                 }
3701         }
3702         if (print_size > 0) {
3703                 if (verbose > 0)
3704                         fprintf(stderr,
3705                         "Total extents scheduled to be written = %u\n",
3706                         (last_extent - session_start));
3707                 printf("%u\n", (last_extent - session_start));
3708                 exit(0);
3709         }
3710         /*
3711          * Now go through the list of fragments and write the data that
3712          * corresponds to each one.
3713          */
3714         for (opnt = out_list; opnt; opnt = opnt->of_next) {
3715                 Uint    oext;
3716
3717                 oext = last_extent_written;
3718                 if (opnt->of_start_extent != 0 &&
3719                     opnt->of_start_extent != last_extent_written) {
3720                         /*
3721                          * Consistency check.
3722                          * XXX Should make sure that all entries have
3723                          * XXXX of_start_extent set up correctly.
3724                          */
3725                         comerrno(EX_BAD,
3726                         "Implementation botch: %s should start at %u but starts at %u.\n",
3727                         opnt->of_name, opnt->of_start_extent, last_extent_written);
3728                 }
3729                 if (opnt->of_write != NULL) {
3730                         if (verbose > 1)
3731                                 fprintf(stderr, "Writing:   %-40sStart Block %u\n",
3732                                         opnt->of_name, last_extent_written);
3733                         (*opnt->of_write) (discimage);
3734                         if (verbose > 1)
3735                                 fprintf(stderr, "Done with: %-40sBlock(s)    %u\n",
3736                                         opnt->of_name, last_extent_written-oext);
3737                 }
3738         }
3739         if (last_extent != last_extent_written) {
3740                 comerrno(EX_BAD,
3741                 "Implementation botch: FS should end at %u but ends at %u.\n",
3742                                 last_extent, last_extent_written);
3743         }
3744
3745         if (jttemplate) {
3746                 write_jt_footer();
3747                 fclose(jttemplate);
3748         }
3749         if (jtjigdo)
3750                 fclose(jtjigdo);
3751
3752         if (verbose > 0) {
3753 #ifdef HAVE_SBRK
3754                 fprintf(stderr, "Max brk space used %x\n",
3755                         (unsigned int)(((unsigned long) sbrk(0)) - mem_start));
3756 #endif
3757                 fprintf(stderr, "%u extents written (%u MB)\n",
3758                         last_extent, last_extent >> 9);
3759         }
3760 #ifdef VMS
3761         return (1);
3762 #else
3763         return (0);
3764 #endif
3765 }
3766
3767 /*
3768  * Find unescaped equal sign in graft pointer string.
3769  */
3770 char *
3771 findgequal(char *s)
3772 {
3773         char    *p = s;
3774
3775         while ((p = strchr(p, '=')) != NULL) {
3776                 if (p > s && p[-1] != '\\')
3777                         return (p);
3778                 p++;
3779         }
3780         return (NULL);
3781 }
3782
3783 /*
3784  * Find unescaped equal sign in string.
3785  */
3786 static char *
3787 escstrcpy(char *to, char *from)
3788 {
3789         char    *p = to;
3790
3791         if (debug)
3792                 fprintf(stderr, "FROM: '%s'\n", from);
3793
3794         while ((*p = *from++) != '\0') {
3795                 if (*p == '\\') {
3796                         if ((*p = *from++) == '\0')
3797                                 break;
3798                         if (*p != '\\' && *p != '=') {
3799                                 p[1] = p[0];
3800                                 *p++ = '\\';
3801                         }
3802                 }
3803                 p++;
3804         }
3805         if (debug)
3806                 fprintf(stderr, "ESC:  '%s'\n", to);
3807         return (to);
3808 }
3809
3810 void *
3811 e_malloc(size_t size)
3812 {
3813         void            *pt = 0;
3814
3815         if ((size > 0) && ((pt = malloc(size)) == NULL)) {
3816 #ifdef  USE_LIBSCHILY
3817                 comerr("Not enough memory\n");
3818 #else
3819                 fprintf(stderr, "Not enough memory\n");
3820                 exit(1);
3821 #endif
3822         }
3823         /*
3824          * Not all code is clean yet.
3825          * Filling all allocated data with zeroes will help
3826          * to avoid core dumps.
3827          */
3828   if (size > 0) /* a workaround for gcc bug gcc.gnu.org/PR25639 */
3829      memset(pt, 0, size);
3830         return (pt);
3831 }