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