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