2 * This file has been modified for the cdrkit suite.
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).
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.
15 * Patched version with stuff from the Debian's cdrtools.
16 * Replaced various warnings/disclaimers with more simple ones.
18 * Eduard Bloch <blade@debian.org>
20 /* @(#)mkisofs.c 1.167 06/01/30 joerg */
21 /* Parts from @(#)mkisofs.c 1.206 07/02/26 joerg */
23 * Program genisoimage.c - generate iso9660 filesystem based upon directory
26 * Written by Eric Youngdale (1993).
28 * Copyright 1993 Yggdrasil Computing, Incorporated
29 * Copyright (c) 1999,2000-2004 J. Schilling
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)
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.
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.
46 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 */
49 #include "genisoimage.h"
56 #include <unls.h> /* For UNICODE translation */
63 #include <io.h> /* for setmode() prototype */
80 #include <sys/resource.h>
82 #endif /* no_more_needed */
89 struct directory *root = NULL;
92 char version_string[] = "genisoimage " CDRKIT_VERSION;
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;
104 unsigned int jpath_table_size = 0;
105 unsigned int jpath_table[4] = {0, };
106 unsigned int jpath_blocks = 0;
108 struct iso_directory_record root_record;
109 struct iso_directory_record jroot_record;
111 char *extension_record = NULL;
112 int extension_record_extent = 0;
113 int extension_record_size = 0;
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;
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;
132 int use_RockRidge = 0;
134 int osecsize = 0; /* Output-sector size, 0 means default secsize 2048 */
136 int jlen = JMAX; /* maximum Joliet file name length */
140 int all_files = 1; /* New default is to include all files */
141 int follow_links = 0;
143 int cache_inodes = 0; /* Do not cache inodes on Cygwin by default */
145 int cache_inodes = 1; /* Cache inodes if OS has unique inodes */
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 */
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;
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;
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 */
202 int use_fileversion = 1; /* Use file version # from filesystem */
204 int use_fileversion = 0; /* Use file version # from filesystem */
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 */
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 */
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 */
255 int do_sort = 0; /* sort file data */
262 struct unls_table *in_nls = NULL; /* input UNICODE conversion table */
263 struct unls_table *out_nls = NULL; /* output UNICODE conversion table */
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 */
274 struct rcopts rcopt[] = {
276 {"PUBL", &publisher},
278 {"COPY", ©right},
281 {"VOLS", &volset_id},
282 {"VOLI", &volume_id},
283 {"SYSI", &system_id},
285 {"HFS_TYPE", &deftype},
286 {"HFS_CREATOR", &defcreator},
287 #endif /* APPLE_HYB */
291 char *merge_warn_msg=0; /* use as pointer and boolean */
294 * In case it isn't obvious, the option handling code was ripped off
298 /* The long option information. */
300 /* The short option with the same meaning ('\0' if none). */
302 /* The name of the argument (NULL if none). */
305 * The documentation string. If this is NULL, this is a synonym for
306 * the previous option.
310 /* Use one dash before long option name. */
312 /* Use two dashes before long option name. */
314 /* Don't mention this option in --help output. */
320 * Codes used for the long options with no short synonyms. Note that all these
321 * values must not be ASCII or EBCDIC.
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
364 #define OPTION_SORT 1039
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
377 #define OPTION_INPUT_CHARSET 1050
378 #define OPTION_OUTPUT_CHARSET 1051
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
389 #define OPTION_CHECK_SESSION 1060
390 #define OPTION_FORCE_RR 1061
392 #define OPTION_DEBUG 1062
394 #define OPTION_JLONG 1063
396 #define OPTION_STREAM_FILE_NAME 1064
397 #define OPTION_STREAM_CD_SIZE 1065
399 #define OPTION_XA 1066
400 #define OPTION_XA_RATIONALIZED 1067
402 #define OPTION_SUNX86BOOT 1068
403 #define OPTION_SUNX86LABEL 1069
405 #define OPTION_ALLOW_LEADING_DOTS 1070
406 #define OPTION_PUBLISHER 1071
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
418 #define OPTION_JT_CHECKSUM_ALGO_ISO 1120
419 #define OPTION_JT_CHECKSUM_ALGO_TMPL 1121
422 #define OPTION_BOOTALPHA 1200
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
430 #define OPTION_BOOTMIPS 1220
432 #define OPTION_BOOTMIPSEL 1230
435 #define OPTION_UDF 1500
438 #define OPTION_DVD 1501
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
451 #define OPTION_USH 2008
452 #define OPTION_XIN 2009
454 #define OPTION_DAVE 2010
455 #define OPTION_SFM 2011
456 #define OPTION_XDBL 2012
457 #define OPTION_XHFS 2013
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
465 #define OPTION_HFS_LIST 2025
467 #define OPTION_GEN_PT 2026
469 #define OPTION_CREATE_DT 2027
470 #define OPTION_HFS_HIDE 2028
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
478 #define OPTION_HFS_TYPE 2034
479 #define OPTION_HFS_CREATOR 2035
481 #define OPTION_ROOT_INFO 2036
483 #define OPTION_HFS_INPUT_CHARSET 2037
484 #define OPTION_HFS_OUTPUT_CHARSET 2038
486 #define OPTION_HFS_UNLOCK 2039
487 #define OPTION_HFS_BLESS 2040
488 #define OPTION_HFS_PARMS 2041
490 #define OPTION_CHRP_BOOT 2042
492 #define OPTION_RELOC_ROOT 2043
493 #define OPTION_RELOC_OLD_ROOT 2044
495 #define OPTION_MAP_FILE 2045
497 #define OPTION_ALLOW_LIMITED_SIZE 2046
499 #endif /* APPLE_HYB */
501 static int save_pname = 0;
503 static const struct ld_option ld_options[] =
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.",
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},
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},
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},
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},
660 {{"alpha-boot", required_argument, NULL, OPTION_BOOTALPHA},
661 '\0', "FILE", "Set alpha boot image name (relative to image root)", ONE_DASH},
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},
674 {{"mips-boot", required_argument, NULL, OPTION_BOOTMIPS},
675 '\0', "FILE", "Set mips boot image name (relative to image root)", ONE_DASH},
677 {{"mipsel-boot", required_argument, NULL, OPTION_BOOTMIPSEL},
678 '\0', "FILE", "Set mipsel boot image name (relative to image root)", ONE_DASH},
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},
704 { {"sort", required_argument, NULL, OPTION_SORT},
705 '\0', "FILE", "Sort file content locations according to rules in FILE", ONE_DASH },
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},
724 {{"udf", no_argument, NULL, OPTION_UDF},
725 '\0', NULL, "Generate UDF file system", ONE_DASH},
729 {{"dvd-video", no_argument, NULL, OPTION_DVD},
730 '\0', NULL, "Generate DVD-Video compliant UDF file system", ONE_DASH},
733 {{"uid", required_argument, NULL, OPTION_UID},
734 '\0', "uid", "Make the owner of all files this uid.",
736 {{"untranslated-filenames", no_argument, NULL, 'U'},
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},
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",
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},
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 */
871 #define OPTION_COUNT (sizeof ld_options / sizeof (ld_options[0]))
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);
885 read_one_rcfile(char *filename)
888 char linebuffer[256];
894 fp = fopen(filename, "r");
899 errmsg("Cannot open '%s'.\n", filename);
906 fprintf(stderr, "Using \"%s\"\n", filename);
908 while (fgets(linebuffer, sizeof(linebuffer), fp)) {
913 /* skip any leading white space */
914 for (p = linebuffer; *p == ' ' || *p == '\t'; p++)
916 /* Skip comments and blank lines */
917 if (!*p || *p == '\n' || *p == '\r' || *p == '#')
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.
924 while (*p && (isalpha((unsigned char) *p) || *p == '_'))
925 *p++ = toupper((unsigned char) *p);
928 fprintf(stderr, "%s:%d: name required\n", filename,
934 /* Skip past white space after the name */
935 while (*p == ' ' || *p == '\t')
937 /* silently ignore errors in the rc file. */
939 fprintf(stderr, "%s:%d: equals sign required after '%.*s'\n",
941 (int)(p1-name), name);
946 /* Skip pas the = sign, and any white space following it */
948 while (*p == ' ' || *p == '\t')
951 /* Get rid of trailing newline */
952 for (p1 = p; *p1 && *p1 != '\n' && *p1 != '\r'; p1++)
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);
965 fprintf(stderr, "%s:%d: field name '%s' unknown\n",
972 errmsg("Read error on '%s'.\n", filename);
983 #define ETCDIR "/etc"
984 #define RCFILENAME "genisoimagerc"
985 #define OLD_RCFILENAME "mkisofsrc"
988 read_rcfile(char *appname)
993 if (read_one_rcfile(getenv("GENISOIMAGERC")))
995 if (read_one_rcfile(getenv("MKISOFSRC")))
997 if (read_one_rcfile("." RCFILENAME))
999 if (read_one_rcfile("." OLD_RCFILENAME))
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))
1010 strcpy(p, "." OLD_RCFILENAME);
1011 if (read_one_rcfile(filename))
1015 if (read_one_rcfile(ETCDIR SPATH_SEPARATOR RCFILENAME))
1019 strlen(appname) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
1020 strcpy(filename, appname);
1021 p = strrchr(filename, PATH_SEPARATOR);
1023 strcpy(p + 1, RCFILENAME);
1024 if (read_one_rcfile(filename))
1030 char *path_table_l = NULL;
1031 char *path_table_m = NULL;
1033 char *jpath_table_l = NULL;
1034 char *jpath_table_m = NULL;
1049 const char *program_name = "genisoimage";
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");
1062 const char *program_name = "genisoimage";
1066 /* const char **targets, **pp;*/
1068 fprintf(stderr, "Usage: %s [options] file...\n", program_name);
1070 fprintf(stderr, "Options:\n");
1071 for (i = 0; i < (int)OPTION_COUNT; i++) {
1072 if (ld_options[i].doc != NULL) {
1077 fprintf(stderr, " ");
1084 if (ld_options[j].shortopt != '\0' &&
1085 ld_options[j].control != NO_HELP) {
1086 fprintf(stderr, "%s-%c",
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, " ");
1095 fprintf(stderr, "%s",
1097 len += strlen(ld_options[j].arg);
1103 while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
1107 if (ld_options[j].opt.name != NULL &&
1108 ld_options[j].control != NO_HELP) {
1109 fprintf(stderr, "%s-%s%s",
1111 ld_options[j].control == TWO_DASHES ? "-" : "",
1112 ld_options[j].opt.name);
1113 len += ((comma ? 2 : 0)
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",
1121 strlen(ld_options[j].arg);
1127 while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
1130 fprintf(stderr, "\n");
1133 for (; len < 30; len++)
1136 fprintf(stderr, "%s\n", ld_options[i].doc);
1140 "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
1146 * Fill in date in the iso9660 format
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).
1155 iso9660_date(char *result, time_t crtime)
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;
1168 * Must recalculate proper timezone offset each time, as some files use
1169 * daylight savings time and some don't...
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;
1180 if (local->tm_year > 0)
1184 result[6] = -(local->tm_min + 60 *
1185 (local->tm_hour + 24 * local->tm_yday)) / 15;
1190 /* hide "./rr_moved" if all its contents are hidden */
1194 struct directory_entry *s_entry;
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)
1201 if ((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
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;
1211 * get pathnames from the command line, and then from given file
1214 get_pnames(int argc, char **argv, int opt, char *pname, int pnsize, FILE *fp)
1218 /* we may of already read the first line from the pathnames file */
1228 return ((char *) 0);
1230 if (fgets(pname, pnsize, fp)) {
1231 /* Discard newline */
1232 len = strlen(pname);
1233 if (pname[len - 1] == '\n') {
1234 pname[len - 1] = '\0';
1238 return ((char *) 0);
1241 extern char *cdrecord_data;
1243 int main(int argc, char *argv[])
1245 struct directory_entry de;
1248 unsigned long mem_start;
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;
1258 char shortopts[OPTION_COUNT * 3 + 2];
1259 struct option longopts[OPTION_COUNT + 1];
1264 char *pathnames = 0;
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 */
1276 char *afpfile = ""; /* mapping file for TYPE/CREATOR */
1278 char *root_info = 0;
1279 #endif /* APPLE_HYB */
1282 mkisofs_call=strstr(argv[0], "mkisofs");
1283 if(mkisofs_call && '\0' == mkisofs_call[7]) /* lame cheater detected */
1284 argv[0]="genisoimage";
1287 /* This gives wildcard expansion with Non-Posix shells with EMX */
1288 _wildcard(&argc, &argv);
1290 save_args(argc, argv);
1293 #ifdef USE_LIBSCHILY
1294 errmsgno(EX_BAD, "Missing pathspec.\n");
1298 /* Get the defaults from the .genisoimagerc file */
1299 read_rcfile(argv[0]);
1304 * Copy long option initialization from GNU-ld.
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
1321 for (i = 0; i < (int)OPTION_COUNT; i++) {
1322 if (ld_options[i].shortopt != '\0') {
1323 shortopts[is] = ld_options[i].shortopt;
1325 if (ld_options[i].opt.has_arg ==
1326 required_argument ||
1327 ld_options[i].opt.has_arg ==
1328 optional_argument) {
1329 shortopts[is] = ':';
1331 if (ld_options[i].opt.has_arg ==
1332 optional_argument) {
1333 shortopts[is] = ':';
1338 if (ld_options[i].opt.name != NULL) {
1339 longopts[il] = ld_options[i].opt;
1343 shortopts[is] = '\0';
1344 longopts[il].name = NULL;
1347 while ((c = getopt_long_only(argc, argv, shortopts,
1348 longopts, &longind)) != EOF)
1351 /* A filename that we take as input. */
1353 have_cmd_line_pathspec = 1;
1354 goto parse_input_files;
1356 case OPTION_USE_GRAFT:
1361 * This is a temporary hack until cdrecord gets the
1362 * proper hooks in it.
1364 cdrecord_data = optarg;
1370 #ifdef USE_LIBSCHILY
1371 comerrno(EX_BAD, "-i option no longer supported.\n");
1373 fprintf(stderr, "-i option no longer supported.\n");
1377 case OPTION_ISO_LEVEL:
1378 iso9660_level = atoi(optarg);
1380 switch (iso9660_level) {
1384 * Only on file section
1385 * 8.3 d or d1 characters for files
1386 * 8 d or d1 characters for directories
1391 * Only on file section
1401 * This is ISO-9660:1988 (ISO-9660 version 2)
1403 iso9660_namelen = MAX_ISONAME_V2; /* allow 207 chars */
1404 full_iso9660_filenames++; /* 31+ chars */
1405 omit_version_number++;
1406 RR_relocation_depth = 32767;
1411 omit_period++; /* trailing dot */
1412 allow_leading_dots++;
1413 relaxed_filenames++; /* all chars */
1414 allow_lowercase++; /* even lowcase */
1415 allow_multidot++; /* > 1 dots */
1419 comerrno(EX_BAD, "Illegal iso9660 Level %d, use 1..3 or 4.\n",
1430 case OPTION_JCHARSET:
1433 case OPTION_INPUT_CHARSET:
1436 case OPTION_OUTPUT_CHARSET:
1439 #ifdef JIGDO_TEMPLATE
1440 case OPTION_JTT_OUTPUT:
1441 jtemplate_out = optarg;
1443 case OPTION_JTJ_OUTPUT:
1444 jjigdo_out = optarg;
1446 case OPTION_JT_MD5_LIST:
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;
1456 case OPTION_JT_INCLUDE:
1457 if (jte_add_include(optarg)) {
1458 #ifdef USE_LIBSCHILY
1460 "Failed to build jigdo-include list\n");
1463 "Failed to build jigdo-include list\n");
1468 case OPTION_JT_EXCLUDE:
1469 if (jte_add_exclude(optarg)) {
1470 #ifdef USE_LIBSCHILY
1472 "Failed to build jigdo-exclude list\n");
1475 "Failed to build jigdo-exclude list\n");
1480 case OPTION_JT_PATH_MAP:
1481 if (jte_add_mapping(optarg)) {
1482 #ifdef USE_LIBSCHILY
1484 "Failed to build jigdo mapping list\n");
1487 "Failed to build jigdo mapping list\n");
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;
1499 #ifdef USE_LIBSCHILY
1500 comerrno(EX_BAD, "Compression algorithm %s unknown\n", optarg);
1502 fprintf(stderr, "Compression algorithm %s unknown\n", optarg);
1508 case OPTION_JT_CHECKSUM_ALGO_ISO:
1509 if (parse_checksum_algo(optarg, &checksum_algo_iso))
1511 #ifdef USE_LIBSCHILY
1512 comerrno(EX_BAD, "Problem with ISO checksum choices: %s \n", optarg);
1514 fprintf(stderr, "Problem with ISO checksum choices: %s\n", optarg);
1521 case OPTION_JT_CHECKSUM_ALGO_TMPL:
1522 if (parse_checksum_algo(optarg, &checksum_algo_tmpl))
1524 #ifdef USE_LIBSCHILY
1525 comerrno(EX_BAD, "Problem with template checksum choices: %s \n", optarg);
1527 fprintf(stderr, "Problem with template checksum choices: %s\n", optarg);
1533 #endif /* JIGDO_TEMPLATE */
1538 do_sort++; /* We sort bootcat/botimage */
1540 boot_image = optarg; /* pathname of the boot image */
1542 if (boot_image == NULL) {
1543 #ifdef USE_LIBSCHILY
1545 "Required Eltorito boot image pathname missing\n");
1548 "Required Eltorito boot image pathname missing\n");
1553 current_boot_entry->boot_image = boot_image;
1555 case OPTION_ALT_BOOT:
1557 * Start new boot entry parameter list.
1561 case OPTION_BOOTALPHA:
1563 /* list of pathnames of boot images */
1564 add_boot_alpha_filename(optarg);
1566 case OPTION_HPPA_CMDLINE:
1568 add_boot_hppa_cmdline(optarg);
1570 case OPTION_HPPA_KERNEL_32:
1572 add_boot_hppa_kernel_32(optarg);
1574 case OPTION_HPPA_KERNEL_64:
1576 add_boot_hppa_kernel_64(optarg);
1578 case OPTION_HPPA_BOOTLOADER:
1580 add_boot_hppa_bootloader(optarg);
1582 case OPTION_HPPA_RAMDISK:
1584 /* list of pathnames of boot images */
1585 add_boot_hppa_ramdisk(optarg);
1587 case OPTION_BOOTMIPS:
1589 /* list of pathnames of boot images */
1590 add_boot_mips_filename(optarg);
1592 case OPTION_BOOTMIPSEL:
1594 add_boot_mipsel_filename(optarg);
1599 "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
1601 /* list of pathnames of boot images */
1602 scan_sparc_boot(optarg);
1604 case OPTION_SUNX86BOOT:
1607 "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
1609 /* list of pathnames of boot images */
1610 scan_sunx86_boot(optarg);
1614 /* pathname of the boot image on disk */
1615 genboot_image = optarg;
1616 if (genboot_image == NULL) {
1617 #ifdef USE_LIBSCHILY
1619 "Required generic boot image pathname missing\n");
1622 "Required generic boot image pathname missing\n");
1627 case OPTION_SPARCLABEL:
1628 /* Sun disk label string */
1629 sparc_boot_label(optarg);
1631 case OPTION_SUNX86LABEL:
1632 /* Sun disk label string */
1633 sunx86_boot_label(optarg);
1637 /* pathname of the boot image on cd */
1638 boot_catalog = optarg;
1639 if (boot_catalog == NULL) {
1640 #ifdef USE_LIBSCHILY
1642 "Required boot catalog pathname missing\n");
1645 "Required boot catalog pathname missing\n");
1650 case OPTION_ABSTRACT:
1652 if (strlen(abstract) > 37) {
1653 #ifdef USE_LIBSCHILY
1655 "Abstract filename string too long\n");
1658 "Abstract filename string too long\n");
1665 if (strlen(appid) > 128) {
1666 #ifdef USE_LIBSCHILY
1668 "Application-id string too long\n");
1671 "Application-id string too long\n");
1678 if (strlen(biblio) > 37) {
1679 #ifdef USE_LIBSCHILY
1681 "Bibliographic filename string too long\n");
1684 "Bibliographic filename string too long\n");
1689 case OPTION_CACHE_INODES:
1692 case OPTION_NOCACHE_INODES:
1695 case OPTION_CHECK_OLDNAMES:
1698 case OPTION_CHECK_SESSION:
1701 merge_image = optarg;
1702 outfile = "/dev/null";
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.
1709 /* cdrecord_data = "0,0";*/
1711 case OPTION_COPYRIGHT:
1713 if (strlen(copyright) > 37) {
1714 #ifdef USE_LIBSCHILY
1716 "Copyright filename string too long\n");
1719 "Copyright filename string too long\n");
1732 RR_relocation_depth = 32767;
1738 full_iso9660_filenames++;
1740 case OPTION_MAX_FILENAMES:
1741 iso9660_namelen = MAX_ISONAME_V1; /* allow 37 chars */
1742 full_iso9660_filenames++;
1743 omit_version_number++;
1748 case OPTION_ALLOW_LEADING_DOTS:
1749 allow_leading_dots++;
1752 case OPTION_LOG_FILE:
1756 merge_image = optarg;
1758 case OPTION_RELOC_ROOT:
1759 reloc_root = optarg;
1761 case OPTION_RELOC_OLD_ROOT:
1762 reloc_old_root = optarg;
1765 omit_version_number++;
1768 case OPTION_FORCE_RR:
1788 if (strlen(preparer) > 128) {
1789 #ifdef USE_LIBSCHILY
1790 comerrno(EX_BAD, "Preparer string too long\n");
1792 fprintf(stderr, "Preparer string too long\n");
1797 case OPTION_PRINT_SIZE:
1802 case OPTION_PUBLISHER:
1804 if (strlen(publisher) > 128) {
1805 #ifdef USE_LIBSCHILY
1807 "Publisher string too long\n");
1809 fprintf(stderr, "Publisher string too long\n");
1827 case OPTION_XA_RATIONALIZED:
1833 if (strcmp(optarg, "data") == 0)
1835 else if (strcmp(optarg, "xa1") == 0)
1837 else if (strcmp(optarg, "raw") == 0) {
1840 "Unsupported sector type '%s'.\n",
1845 #ifdef USE_LIBSCHILY
1846 errmsgno(EX_BAD, "Option -%c is reserved for future use.\n", c);
1848 fprintf(stderr, "Option -%c is reserved for future use.\n", c);
1853 case OPTION_NEW_DIR_MODE:
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");
1864 fprintf(stderr, "Bad mode for -new-dir-mode\n");
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");
1883 fprintf(stderr, "Bad value for -uid\n");
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");
1902 fprintf(stderr, "Bad value for -gid\n");
1909 case OPTION_FILEMODE:
1912 rationalize_filemode++;
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");
1922 fprintf(stderr, "Bad mode for -file-mode\n");
1929 case OPTION_DIRMODE:
1932 rationalize_dirmode++;
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");
1942 fprintf(stderr, "Bad mode for -dir-mode\n");
1952 add_sort_list(optarg);
1954 #endif /* SORTING */
1956 case OPTION_SPLIT_OUTPUT:
1960 case OPTION_STREAM_FILE_NAME:
1961 stream_filename = optarg;
1964 case OPTION_STREAM_CD_SIZE:
1965 stream_media_size = atoi(optarg);
1970 if (strlen(system_id) > 32) {
1971 #ifdef USE_LIBSCHILY
1973 "System ID string too long\n");
1975 fprintf(stderr, "System ID string too long\n");
1980 case OPTION_TRANS_TBL:
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",
2004 case OPTION_USE_FILEVERSION:
2009 * Minimal (only truncation of 31+ characters)
2010 * translation of filenames.
2012 * Forces -l, -d, -N, -allow-leading-dots,
2013 * -relaxed-filenames,
2014 * -allow-lowercase, -allow-multidot
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
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 */
2033 case OPTION_RELAXED_FILENAMES:
2034 relaxed_filenames++;
2037 case OPTION_ALLOW_LOWERCASE:
2041 case OPTION_ALLOW_MULTIDOT:
2045 case OPTION_ISO_TRANSLATE:
2051 if (strlen(volume_id) > 32) {
2052 #ifdef USE_LIBSCHILY
2054 "Volume ID string too long\n");
2057 "Volume ID string too long\n");
2064 if (strlen(volset_id) > 128) {
2065 #ifdef USE_LIBSCHILY
2067 "Volume set ID string too long\n");
2070 "Volume set ID string too long\n");
2075 case OPTION_VOLSET_SIZE:
2076 volume_set_size = atoi(optarg);
2077 if (volume_set_size <= 0) {
2078 #ifdef USE_LIBSCHILY
2080 "Illegal Volume Set Size %s\n", optarg);
2083 "Illegal Volume Set Size %s\n", optarg);
2087 if (volume_set_size > 1) {
2088 #ifdef USE_LIBSCHILY
2090 "Volume Set Size > 1 not yet supported\n");
2093 "Volume Set Size > 1 not yet supported\n");
2098 case OPTION_VOLSET_SEQ_NUM:
2099 volume_sequence_number = atoi(optarg);
2100 if (volume_sequence_number > volume_set_size) {
2101 #ifdef USE_LIBSCHILY
2103 "Volume set sequence number too big\n");
2106 "Volume set sequence number too big\n");
2116 #ifdef USE_LIBSCHILY
2118 "Transparent compression not supported with VMS\n");
2121 "Transparent compression not supported with VMS\n");
2125 transparent_compression++;
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.
2143 i_add_match(optarg);
2149 h_add_match(optarg);
2155 j_add_match(optarg);
2160 case OPTION_HIDE_TRANS_TBL:
2163 case OPTION_HIDE_RR_MOVED:
2169 case OPTION_PVERSION:
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);
2176 case OPTION_NOSPLIT_SL_COMPONENT:
2177 split_SL_component = 0;
2179 case OPTION_NOSPLIT_SL_FIELD:
2182 case OPTION_HARD_DISK_BOOT:
2186 current_boot_entry->hard_disk_boot = 1;
2188 case OPTION_NO_EMUL_BOOT:
2192 current_boot_entry->no_emul_boot = 1;
2194 case OPTION_NO_BOOT:
2198 current_boot_entry->not_bootable = 1;
2200 case OPTION_BOOT_LOAD_ADDR:
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");
2211 fprintf(stderr, "Boot image load address invalid.\n");
2218 current_boot_entry->load_addr = load_addr;
2220 case OPTION_BOOT_LOAD_SIZE:
2226 val = strtol(optarg, &ptr, 0);
2227 if (*ptr || val < 0 || val >= 0x10000) {
2228 #ifdef USE_LIBSCHILY
2230 "Boot image load size invalid.\n");
2233 "Boot image load size invalid.\n");
2240 current_boot_entry->load_size = load_size;
2242 case OPTION_BOOT_INFO_TABLE:
2246 current_boot_entry->boot_info_table = 1;
2249 case OPTION_HFS_TYPE:
2252 if (strlen(deftype) != 4) {
2253 #ifdef USE_LIBSCHILY
2255 "HFS default TYPE string has illegal length.\n");
2258 "HFS default TYPE string has illegal length.\n");
2263 case OPTION_HFS_CREATOR:
2264 defcreator = optarg;
2266 if (strlen(defcreator) != 4) {
2267 #ifdef USE_LIBSCHILY
2269 "HFS default CREATOR string has illegal length.\n");
2272 "HFS default CREATOR string has illegal length.\n");
2279 case OPTION_MAP_FILE:
2281 hfs_last = MAP_LAST;
2292 case OPTION_MACNAME:
2295 case OPTION_NOMACFILES:
2296 #ifdef USE_LIBSCHILY
2298 "Warning: -no-mac-files no longer used ... ignoring\n");
2301 "Warning: -no-mac-files no longer used ... ignoring\n");
2304 case OPTION_BOOT_HFS_FILE:
2305 hfs_boot_file = optarg;
2310 case OPTION_MAGIC_FILE:
2312 fprintf(stderr, "This program has been compiled without magic library support.\n"
2313 "Ignoring the -magic option.\n");
2315 magic_filename = optarg;
2316 hfs_last = MAG_LAST;
2318 case OPTION_AUTOSTART:
2323 afe_size = atoi(optarg);
2324 hfs_select |= DO_FEU;
2325 hfs_select |= DO_FEL;
2327 case OPTION_HFS_VOLID:
2328 hfs_volume_id = optarg;
2330 case OPTION_ROOT_INFO:
2333 case OPTION_ICON_POS:
2336 /* Mac/Unix types to include */
2338 hfs_select |= DO_CAP;
2341 hfs_select |= DO_NETA;
2344 hfs_select |= DO_DBL;
2348 hfs_select |= DO_ESH;
2351 hfs_select |= DO_FEU;
2352 hfs_select |= DO_FEL;
2356 hfs_select |= DO_SGI;
2359 hfs_select |= DO_MBIN;
2362 hfs_select |= DO_SGL;
2365 hfs_select |= DO_DAVE;
2368 hfs_select |= DO_SFM;
2371 hfs_select |= DO_XDBL;
2375 hfs_select |= DO_XHFS;
2376 #else /* IS_MACOS_X */
2377 #ifdef USE_LIBSCHILY
2379 "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
2380 #else /* USE_LIBSCHILY */
2382 "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
2383 #endif /* USE_LIBSCHILY */
2384 #endif /* IS_MACOS_X */
2386 case OPTION_CREATE_DT:
2389 case OPTION_HFS_HIDE:
2390 hfs_add_match(optarg);
2392 case OPTION_HFS_LIST:
2393 hfs_add_list(optarg);
2395 case OPTION_HFS_INPUT_CHARSET:
2397 hfs_icharset = optarg;
2399 case OPTION_HFS_OUTPUT_CHARSET:
2400 hfs_ocharset = optarg;
2402 case OPTION_HFS_UNLOCK:
2405 case OPTION_HFS_BLESS:
2408 case OPTION_HFS_PARMS:
2409 hfs_parms = strdup(optarg);
2412 case OPTION_PREP_BOOT:
2414 if (use_prep_boot > 4 - use_chrp_boot) {
2415 #ifdef USE_LIBSCHILY
2417 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2420 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
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
2429 "Required PReP boot image pathname missing\n");
2432 "Required PReP boot image pathname missing\n");
2437 case OPTION_CHRP_BOOT:
2439 break; /* silently allow duplicates */
2441 if (use_prep_boot > 3) {
2442 #ifdef USE_LIBSCHILY
2444 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2447 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2452 #endif /* PREP_BOOT */
2453 #endif /* APPLE_HYB */
2454 case OPTION_ALLOW_LIMITED_SIZE:
2455 allow_limited_size++;
2462 * "--" was found, the next argument is a pathspec
2465 have_cmd_line_pathspec = 1;
2471 * XXX This is a hack until we have a decent separate name handling
2472 * XXX for UDF filenames.
2474 if (dvd_video && use_Joliet) {
2476 fprintf(stderr, "Warning: Disabling Joliet support for DVD-Video.\n");
2478 if (use_udf && !use_Joliet)
2482 if (strlen(preparer) > 128) {
2483 comerrno(EX_BAD, "Preparer string too long\n");
2487 if (strlen(publisher) > 128) {
2489 "Publisher string too long\n");
2492 if (stream_filename) {
2493 if (strlen(stream_filename) > MAX_ISONAME)
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");
2501 stream_filename = "STREAM.IMG;1";
2504 if (strlen(system_id) > 32) {
2506 "System ID string too long\n");
2511 if (use_RockRidge && (iso9660_namelen > MAX_ISONAME_V2_RR))
2512 iso9660_namelen = MAX_ISONAME_V2_RR;
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",
2521 if (use_Joliet && !use_RockRidge && verbose>0) {
2523 "Warning: creating filesystem with Joliet extensions but without Rock Ridge\n"
2524 " extensions. It is highly recommended to add Rock Ridge.\n");
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");
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");
2537 if(follow_links && verbose>0)
2539 "Warning: -follow-links does not always work correctly; be careful.\n");
2541 init_unls(); /* Initialize UNICODE tables */
2543 /* initialize code tables from a file - if they exists */
2544 init_unls_file(icharset);
2545 init_unls_file(ocharset);
2547 init_unls_file(hfs_icharset);
2548 init_unls_file(hfs_ocharset);
2549 #endif /* APPLE_HYB */
2552 iconv_possible = !(iso9660_level >= 4 || ((ocharset &&
2553 strcmp(ocharset, icharset ? icharset : "")) &&
2554 use_RockRidge) || apple_ext || apple_hyb);
2556 setlocale(LC_CTYPE, "");
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 */
2563 charset = strdup(charset);
2564 for(t=charset;*t!='\0';t++)
2568 if(strcmp(charset, "ansi_x3.4-1968") != 0)
2571 if(icharset && verbose > 0)
2572 fprintf(stderr, "I: -input-charset not specified, using %s (detected in locale settings)\n",
2576 if(iconv_possible) {
2578 * don't care if initialization fails
2580 init_nls_iconv(icharset);
2581 init_nls_iconv(ocharset);
2585 if (icharset == NULL) {
2586 #if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
2587 in_nls = load_unls("cp437");
2589 in_nls = load_unls("iso8859-1");
2592 if (strcmp(icharset, "default") == 0)
2593 in_nls = load_unls_default();
2595 in_nls = load_unls(icharset);
2598 * set the output charset to the same as the input or the given output
2601 if (ocharset == NULL) {
2604 if (strcmp(ocharset, "default") == 0)
2605 out_nls = load_unls_default();
2607 out_nls = load_unls(ocharset);
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 */
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");
2622 if (hfs_icharset == NULL || strcmp(hfs_icharset, "mac-roman")) {
2623 hfs_inls = load_unls("cp10000");
2625 if (strcmp(hfs_icharset, "default") == 0)
2626 hfs_inls = load_unls_default();
2628 hfs_inls = load_unls(hfs_icharset);
2630 if (hfs_ocharset == NULL) {
2631 hfs_onls = hfs_inls;
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");
2638 hfs_onls = load_unls(hfs_ocharset);
2641 if (hfs_inls == NULL || hfs_onls == NULL) {
2642 fprintf(stderr, "Unknown HFS charset\nKnown charsets are:\n");
2646 #endif /* APPLE_HYB */
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",
2656 "Unable to open previous session image '%s'.\n",
2662 /* We don't need root privilleges anymore. */
2663 #ifdef HAVE_SETREUID
2664 if (setreuid(-1, getuid()) < 0)
2667 if (seteuid(getuid()) < 0)
2669 if (setuid(getuid()) < 0)
2672 #ifdef USE_LIBSCHILY
2673 comerr("Panic cannot set back effective uid.\n");
2676 perror("Panic cannot set back effective uid.");
2682 #ifdef no_more_needed
2688 if (getrlimit(RLIMIT_DATA, &rlp) == -1)
2689 perror("Warning: getrlimit failed");
2691 rlp.rlim_cur = 33554432;
2692 if (setrlimit(RLIMIT_DATA, &rlp) == -1)
2693 perror("Warning: setrlimit failed");
2697 #endif /* no_more_needed */
2699 mem_start = (unsigned long) sbrk(0);
2703 * if the -hide-joliet option has been given, set the Joliet option
2705 if (!use_Joliet && j_ishidden())
2709 if (apple_hyb && apple_ext) {
2710 #ifdef USE_LIBSCHILY
2711 comerrno(EX_BAD, "Can't have both -apple and -hfs options");
2713 fprintf(stderr, "Can't have both -apple and -hfs options");
2718 * if -probe, -macname, any hfs selection and/or mapping file is given,
2719 * but no HFS option, then select apple_hyb
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) {
2730 if (apple_ext && hfs_boot_file) {
2731 #ifdef USE_LIBSCHILY
2732 comerrno(EX_BAD, "Can't have -hfs-boot-file with -apple\n");
2734 fprintf(stderr, "Can't have -hfs-boot-file with -apple\n");
2738 if (apple_ext && autoname) {
2739 #ifdef USE_LIBSCHILY
2740 comerrno(EX_BAD, "Can't have -auto with -apple\n");
2742 fprintf(stderr, "Can't have -auto with -apple\n");
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");
2750 fprintf(stderr, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
2754 if (apple_hyb && use_genboot) {
2755 #ifdef USE_LIBSCHILY
2756 comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n");
2758 fprintf(stderr, "Can't have -hfs with -generic-boot\n");
2763 if (apple_ext && use_prep_boot) {
2764 #ifdef USE_LIBSCHILY
2765 comerrno(EX_BAD, "Can't have -prep-boot with -apple\n");
2767 fprintf(stderr, "Can't have -prep-boot with -apple\n");
2771 #endif /* PREP_BOOT */
2773 if (apple_hyb || apple_ext)
2777 /* we need to search for all types of Apple/Unix files */
2780 if (apple_both && verbose && !(hfs_select || *afpfile || magic_filename)) {
2781 #ifdef USE_LIBSCHILY
2783 "Warning: no Apple/Unix files will be decoded/mapped\n");
2786 "Warning: no Apple/Unix files will be decoded/mapped\n");
2789 if (apple_both && verbose && !afe_size &&
2790 (hfs_select & (DO_FEU | DO_FEL))) {
2791 #ifdef USE_LIBSCHILY
2793 "Warning: assuming PC Exchange cluster size of 512 bytes\n");
2796 "Warning: assuming PC Exchange cluster size of 512 bytes\n");
2801 /* set up the TYPE/CREATOR mappings */
2802 hfs_init(afpfile, 0, hfs_select);
2804 if (apple_ext && !use_RockRidge) {
2806 /* use RockRidge to set the SystemUse field ... */
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");
2817 #endif /* APPLE_HYB */
2819 if (rationalize_all) {
2823 rationalize_filemode++;
2824 rationalize_dirmode++;
2828 fprintf(stderr, "%s (%s)\n", version_string, HOST_SYSTEM);
2830 if (cdrecord_data == NULL && !check_session && merge_image != NULL) {
2831 #ifdef USE_LIBSCHILY
2833 "Multisession usage bug: Must specify -C if -M is used.\n");
2836 "Multisession usage bug: Must specify -C if -M is used.\n");
2840 if (cdrecord_data != NULL && merge_image == NULL) {
2841 #ifdef USE_LIBSCHILY
2843 "Warning: -C specified without -M: old session data will not be merged.\n");
2846 "Warning: -C specified without -M: old session data will not be merged.\n");
2850 if (merge_image != NULL && apple_hyb) {
2851 #ifdef USE_LIBSCHILY
2853 "Warning: files from previous sessions will not be included in the HFS volume.\n");
2856 "Warning: files from previous sessions will not be included in the HFS volume.\n");
2859 #endif /* APPLE_HYB */
2862 * see if we have a list of pathnames to process
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",
2873 "Unable to open pathname list %s.\n",
2882 /* The first step is to scan the directory tree, and take some notes */
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");
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
2899 if (!have_cmd_line_pathspec && !stream_media_size) {
2902 if (stream_media_size) {
2903 if (use_XA || use_RockRidge || use_udf || use_Joliet)
2905 "Cannot use XA, Rock Ridge, UDF or Joliet with -stream-media-size\n");
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)
2912 "Cannot use boot options with -stream-media-size\n");
2915 "Cannot use Apple hybrid options with -stream-media-size\n");
2918 if (use_RockRidge) {
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);
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);
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);
2942 fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
2948 /* redirect all stderr message to log_file */
2949 fprintf(stderr, "re-directing all messages to %s\n", log_file);
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);
2957 fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
2962 for (i = 0; i < argc; i++)
2963 fprintf(stderr, "%s ", argv[i]);
2965 fprintf(stderr, "\n%s (%s)\n",
2966 version_string, HOST_SYSTEM);
2969 /* Find name of root directory. */
2971 node = findgequal(arg);
2972 if (!use_graft_ptrs)
2975 if (use_graft_ptrs && arg != NULL)
2976 node = escstrcpy(nodename, arg);
2981 * Remove '\\' escape chars which are located
2982 * before '\\' and '=' chars
2984 node = escstrcpy(nodename, ++node);
2988 * See if boot catalog file exists in root directory, if not we will
2992 init_boot_catalog(node);
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.
2998 stat_filter(node, &statbuf);
2999 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
3001 memset(&de, 0, sizeof (de));
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.
3009 de.filedir = root; /* We need this to bootstrap */
3011 if (cdrecord_data != NULL && merge_image == NULL) {
3013 * in case we want to add a new session, but don't want to
3016 get_session_start(NULL);
3018 if (merge_image != NULL) {
3019 char sector[SECTOR_SIZE];
3022 mrootp = merge_isofs(merge_image);
3023 if (mrootp == NULL) {
3024 /* Complain and die. */
3025 #ifdef USE_LIBSCHILY
3028 comerr("Unable to find previous session PVD '%s'.\n",
3032 "Unable to find previous session PVD '%s'.\n",
3037 memcpy(de.isorec.extent, mrootp->extent, 8);
3040 * Look for RR Attributes in '.' entry of root dir.
3041 * This is the first ISO directory entry in the root dir.
3043 c = isonum_733((unsigned char *)mrootp->extent);
3045 readsecs(c, sector, 1);
3047 lseek(fileno(in_image), c*2048, SEEK_SET);
3048 read(fileno(in_image), sector, sizeof (sector));
3050 c = rr_flags((struct iso_directory_record *)sector);
3052 fprintf(stderr, "XA signatures found\n");
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");
3059 fprintf(stderr, "Bad Rock Ridge signatures found (SU record missing)\n");
3064 fprintf(stderr, "NO Rock Ridge present\n");
3065 if ((c & (RR_FLAG_XA|RR_FLAG_AA)) == 0) {
3071 fprintf(stderr, "Disabling Rock Ridge / XA / AA\n");
3074 * Create an empty root directory. If we ever scan it for real,
3075 * we will fill in the contents.
3077 find_or_create_directory(NULL, "", &de, TRUE, NULL);
3080 /* may need to set window layout of the volume */
3082 set_root_info(root_info);
3083 #endif /* APPLE_HYB */
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";
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.
3094 if (check_session == 0)
3095 while ((arg = get_pnames(argc, argv, optind, pname,
3096 sizeof (pname), pfp)) != NULL) {
3097 struct directory *graft_dir;
3101 char graft_point[PATH_MAX + 1];
3104 * We would like a syntax like:
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:
3113 * /home/baz/RMAIL=/u3/users/baz/RMAIL
3115 * so that normal files could also be injected into the tree
3116 * at an arbitrary point.
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.
3122 * The default will be that the file is injected at the root of
3125 node = findgequal(arg);
3126 if (!use_graft_ptrs)
3129 * Remove '\\' escape chars which are located
3130 * before '\\' and '=' chars ---> below in escstrcpy()
3135 if (node != NULL || reloc_root) {
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';
3155 escstrcpy(&graft_point[len], arg);
3160 * Remove unwanted "./" & "/" sequences from start...
3164 while (xpnt[0] == '.' && xpnt[1] == '/')
3166 while (*xpnt == PATH_SEPARATOR) {
3169 memmove(graft_point, xpnt, strlen(xpnt)+1);
3170 } while (xpnt > graft_point);
3173 node = escstrcpy(nodename, ++node);
3182 * If "node" points to a directory, then graft_point
3183 * needs to point to a directory too.
3186 status = stat_filter(node, &st);
3188 status = lstat_filter(node, &st);
3190 node_is_dir = S_ISDIR(st.st_mode);
3191 if (status == 0 && node_is_dir) {
3192 len = strlen(graft_point);
3194 if ((len <= (sizeof (graft_point) -1)) &&
3195 graft_point[len-1] != '/') {
3196 graft_point[len++] = '/';
3197 graft_point[len] = '\0';
3201 fprintf(stderr, "GRAFT:'%s'\n", xpnt);
3203 * Loop down deeper and deeper until we find the
3204 * correct insertion spot.
3205 * Canonicalize the filename while parsing it.
3208 struct stat* stat_template;
3211 while (xpnt[0] == '.' && xpnt[1] == '/')
3213 while (xpnt[0] == '/')
3215 if (xpnt[0] == '.' && xpnt[1] == '.' && xpnt[2] == '/') {
3216 if (graft_dir && graft_dir != root) {
3217 graft_dir = graft_dir->parent;
3221 } while ((xpnt[0] == '/') || (xpnt[0] == '.' && xpnt[1] == '/'));
3222 pnt = strchr(xpnt, PATH_SEPARATOR);
3224 if (*xpnt != '\0') {
3231 fprintf(stderr, "GRAFT Point:'%s' in '%s : %s' (%s)\n",
3233 graft_dir->whole_name,
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
3247 (pnt[1] == '\0' && node_is_dir) ? &st : 0;
3249 graft_dir = find_or_create_directory(graft_dir,
3250 graft_point, NULL, TRUE,
3253 *pnt = PATH_SEPARATOR;
3259 node = escstrcpy(nodename, arg);
3265 * Get information on the node
3268 status = stat_filter(node, &st);
3270 status = lstat_filter(node, &st);
3273 * This is a fatal error - the user won't be getting
3274 * what they want if we were to proceed.
3276 #ifdef USE_LIBSCHILY
3277 comerr("Invalid node - '%s'.\n", node);
3279 fprintf(stderr, "Invalid node - '%s'.\n", node);
3284 * Now see whether the user wants to add a regular
3285 * file or a directory at this point.
3287 if (S_ISDIR(st.st_mode)) {
3289 fprintf(stderr, "graft_dir: '%s : %s', node: '%s', (scan)\n",
3290 graft_dir->whole_name,
3291 graft_dir->de_name, node);
3293 if (!scan_directory_tree(graft_dir,
3298 fprintf(stderr, "scan done\n");
3301 if (short_name == NULL) {
3302 short_name = strrchr(node,
3304 if (short_name == NULL ||
3305 short_name < node) {
3312 fprintf(stderr, "graft_dir: '%s : %s', node: '%s', short_name: '%s'\n",
3313 graft_dir->whole_name,
3314 graft_dir->de_name, node,
3318 if (!insert_file_entry(graft_dir, node,
3321 if (!insert_file_entry(graft_dir, node,
3323 #endif /* APPLE_HYB */
3326 * Should we ignore this?
3338 if (pfp && pfp != stdin)
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
3346 if (no_path_names && !check_session && !stream_media_size) {
3347 #ifdef USE_LIBSCHILY
3348 errmsgno(EX_BAD, "No pathnames found.\n");
3353 * Now merge in any previous sessions. This is driven on the source
3354 * side, since we may need to create some additional directories.
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");
3362 fprintf(stderr, "Cannot merge previous session.\n");
3366 close_merge_image();
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
3373 match_cl_re_entries();
3376 /* free up any HFS filename mapping memory */
3379 #endif /* APPLE_HYB */
3381 /* hide "./rr_moved" if all its contents have been hidden */
3382 if (reloc_dir && i_ishidden())
3385 /* insert the boot catalog if required */
3390 * Free up any matching memory
3392 for (n = 0; n < MAX_MAT; n++)
3397 #endif /* SORTING */
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.
3404 goof += sort_tree(root);
3407 fprintf(stderr, "ISO9660/Rock Ridge tree sort failed.\n");
3409 fprintf(stderr, merge_warn_msg);
3413 if (use_Joliet || use_udf) {
3417 goof += joliet_sort_tree(root);
3420 fprintf(stderr, "Joliet tree sort failed. The -joliet-long switch may help you.\n");
3422 fprintf(stderr, merge_warn_msg);
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.
3429 root->self = root->contents;
3431 /* OK, ready to write the file. Open it up, and generate the thing. */
3433 discimage = fopen("/dev/null", "wb");
3435 #ifdef USE_LIBSCHILY
3436 comerr("Unable to open /dev/null\n");
3438 fprintf(stderr, "Unable to open /dev/null\n");
3442 } else if (outfile && (strcmp (outfile, "-")) != 0) {
3443 discimage = fopen(outfile, "wb");
3445 #ifdef USE_LIBSCHILY
3446 comerr("Unable to open disc image file '%s'.\n", outfile);
3448 fprintf(stderr, "Unable to open disc image file '%s'.\n", outfile);
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");
3457 fprintf(stderr, "Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
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");
3467 fprintf(stderr, "Unable to open jigdo template image file\n");
3471 write_jt_header(jttemplate, jtjigdo);
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"),
3483 #ifdef NEED_O_BINARY
3484 setmode(fileno(stdout), O_BINARY);
3488 /* Now assign addresses on the disc for the path table. */
3490 path_blocks = ISO_BLOCKS(path_table_size);
3491 if (path_blocks & 1)
3494 jpath_blocks = ISO_BLOCKS(jpath_table_size);
3495 if (jpath_blocks & 1)
3499 * Start to set up the linked list that we use to track the contents
3504 if (apple_hyb || use_prep_boot || use_chrp_boot)
3505 #else /* PREP_BOOT */
3507 #endif /* PREP_BOOT */
3508 outputlist_insert(&hfs_desc);
3509 #endif /* APPLE_HYB */
3510 if (use_sparcboot || use_sunx86boot)
3511 outputlist_insert(&sunlabel_desc);
3513 outputlist_insert(&alphaboot_desc);
3515 outputlist_insert(&hppaboot_desc);
3516 if (use_alphaboot || use_hppaboot)
3517 outputlist_insert(&alpha_hppa_boot_desc);
3519 outputlist_insert(&mipsboot_desc);
3521 outputlist_insert(&mipselboot_desc);
3523 outputlist_insert(&genboot_desc);
3524 outputlist_insert(&startpad_desc);
3527 outputlist_insert(&voldesc_desc);
3529 /* SVD for El Torito. MUST be immediately after the PVD! */
3531 outputlist_insert(&torito_desc);
3533 /* Enhanced PVD for disc. neded if we write ISO-9660:1999 */
3534 if (iso9660_level > 3)
3535 outputlist_insert(&xvoldesc_desc);
3537 /* SVD for Joliet. */
3539 outputlist_insert(&joliet_desc);
3541 /* Finally the last volume descriptor. */
3542 outputlist_insert(&end_vol);
3546 outputlist_insert(&udf_vol_recognition_area_frag);
3550 /* Insert the version descriptor. */
3551 outputlist_insert(&version_desc);
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.
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);
3576 /* Now start with path tables and directory tree info. */
3577 if (!stream_media_size)
3578 outputlist_insert(&pathtable_desc);
3580 outputlist_insert(&strpath_desc);
3583 outputlist_insert(&jpathtable_desc);
3586 if (!stream_media_size)
3587 outputlist_insert(&dirtree_desc);
3590 outputlist_insert(&jdirtree_desc);
3592 outputlist_insert(&dirtree_clean);
3594 if (extension_record) {
3595 outputlist_insert(&extension_desc);
3598 if (!stream_media_size) {
3599 outputlist_insert(&files_desc);
3601 outputlist_insert(&strfile_desc);
3602 outputlist_insert(&strdir_desc);
3606 * Allow room for the various headers we will be writing.
3607 * There will always be a primary and an end volume descriptor.
3609 last_extent = session_start;
3612 * Calculate the size of all of the components of the disc, and assign
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);
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
3628 for (opnt = out_list; opnt; opnt = opnt->of_next) {
3629 if (opnt->of_generate != NULL) {
3630 (*opnt->of_generate) ();
3635 * Padding just after the ISO-9660 filesystem.
3637 * files_desc does not have an of_size function. For this
3638 * reason, we must insert us after the files content has been
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);
3650 * Pad with anchor volume descriptor pointer
3651 * blocks instead of zeroes.
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);
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);
3667 if (use_sparcboot) {
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);
3675 c = make_sun_label();
3677 outputlist_insert(&sunboot_desc);
3679 outputlist_insert(&endpad_desc);
3680 if (endpad_desc.of_size != NULL) {
3681 (*endpad_desc.of_size) (last_extent);
3684 } else if (use_sunx86boot) {
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);
3692 c = make_sunx86_label();
3694 outputlist_insert(&sunboot_desc);
3696 outputlist_insert(&endpad_desc);
3697 if (endpad_desc.of_size != NULL) {
3698 (*endpad_desc.of_size) (last_extent);
3702 if (print_size > 0) {
3705 "Total extents scheduled to be written = %u\n",
3706 (last_extent - session_start));
3707 printf("%u\n", (last_extent - session_start));
3711 * Now go through the list of fragments and write the data that
3712 * corresponds to each one.
3714 for (opnt = out_list; opnt; opnt = opnt->of_next) {
3717 oext = last_extent_written;
3718 if (opnt->of_start_extent != 0 &&
3719 opnt->of_start_extent != last_extent_written) {
3721 * Consistency check.
3722 * XXX Should make sure that all entries have
3723 * XXXX of_start_extent set up correctly.
3726 "Implementation botch: %s should start at %u but starts at %u.\n",
3727 opnt->of_name, opnt->of_start_extent, last_extent_written);
3729 if (opnt->of_write != NULL) {
3731 fprintf(stderr, "Writing: %-40sStart Block %u\n",
3732 opnt->of_name, last_extent_written);
3733 (*opnt->of_write) (discimage);
3735 fprintf(stderr, "Done with: %-40sBlock(s) %u\n",
3736 opnt->of_name, last_extent_written-oext);
3739 if (last_extent != last_extent_written) {
3741 "Implementation botch: FS should end at %u but ends at %u.\n",
3742 last_extent, last_extent_written);
3754 fprintf(stderr, "Max brk space used %x\n",
3755 (unsigned int)(((unsigned long) sbrk(0)) - mem_start));
3757 fprintf(stderr, "%u extents written (%u MB)\n",
3758 last_extent, last_extent >> 9);
3768 * Find unescaped equal sign in graft pointer string.
3775 while ((p = strchr(p, '=')) != NULL) {
3776 if (p > s && p[-1] != '\\')
3784 * Find unescaped equal sign in string.
3787 escstrcpy(char *to, char *from)
3792 fprintf(stderr, "FROM: '%s'\n", from);
3794 while ((*p = *from++) != '\0') {
3796 if ((*p = *from++) == '\0')
3798 if (*p != '\\' && *p != '=') {
3806 fprintf(stderr, "ESC: '%s'\n", to);
3811 e_malloc(size_t size)
3815 if ((size > 0) && ((pt = malloc(size)) == NULL)) {
3816 #ifdef USE_LIBSCHILY
3817 comerr("Not enough memory\n");
3819 fprintf(stderr, "Not enough memory\n");
3824 * Not all code is clean yet.
3825 * Filling all allocated data with zeroes will help
3826 * to avoid core dumps.
3828 if (size > 0) /* a workaround for gcc bug gcc.gnu.org/PR25639 */
3829 memset(pt, 0, size);