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 */
22 /* Parts from @(#)mkisofs.c 1.238 08/06/13 joerg */
24 * Program genisoimage.c - generate iso9660 filesystem based upon directory
27 * Written by Eric Youngdale (1993).
29 * Copyright 1993 Yggdrasil Computing, Incorporated
30 * Copyright (c) 1999,2000-2004 J. Schilling
32 * This program is free software; you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License as published by
34 * the Free Software Foundation; either version 2, or (at your option)
37 * This program is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 * GNU General Public License for more details.
42 * You should have received a copy of the GNU General Public License
43 * along with this program; if not, write to the Free Software
44 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
47 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 */
50 #include "genisoimage.h"
57 #include <unls.h> /* For UNICODE translation */
64 #include <io.h> /* for setmode() prototype */
81 #include <sys/resource.h>
83 #endif /* no_more_needed */
90 struct directory *root = NULL;
93 char version_string[] = "genisoimage " CDRKIT_VERSION;
97 unsigned int next_extent = 0;
98 unsigned int last_extent = 0;
99 unsigned int session_start = 0;
100 unsigned int path_table_size = 0;
101 unsigned int path_table[4] = {0, };
102 unsigned int path_blocks = 0;
105 unsigned int jpath_table_size = 0;
106 unsigned int jpath_table[4] = {0, };
107 unsigned int jpath_blocks = 0;
109 struct iso_directory_record root_record;
110 struct iso_directory_record jroot_record;
112 char *extension_record = NULL;
113 int extension_record_extent = 0;
114 int extension_record_size = 0;
116 /* These variables are associated with command line options */
117 int check_oldnames = 0;
118 int check_session = 0;
119 int use_eltorito = 0;
120 int hard_disk_boot = 0;
121 int not_bootable = 0;
122 int no_emul_boot = 0;
125 int boot_info_table = 0;
126 int use_alphaboot = 0;
127 int use_sparcboot = 0;
128 int use_hppaboot = 0;
129 int use_mipsboot = 0;
130 int use_mipselboot = 0;
131 int use_sunx86boot = 0;
133 int use_RockRidge = 0;
135 int osecsize = 0; /* Output-sector size, 0 means default secsize 2048 */
137 int jlen = JMAX; /* maximum Joliet file name length */
141 int all_files = 1; /* New default is to include all files */
142 int follow_links = 0;
144 int cache_inodes = 0; /* Do not cache inodes on Cygwin by default */
146 int cache_inodes = 1; /* Cache inodes if OS has unique inodes */
149 int rationalize_uid = 0;
150 int rationalize_gid = 0;
151 int rationalize_filemode = 0;
152 int rationalize_dirmode = 0;
153 uid_t uid_to_use = 0; /* when rationalizing uid */
154 gid_t gid_to_use = 0; /* when rationalizing gid */
155 int filemode_to_use = 0; /* if non-zero, when rationalizing file mode */
156 int dirmode_to_use = 0; /* if non-zero, when rationalizing dir mode */
157 int new_dir_mode = 0555;
158 int generate_tables = 0;
159 int dopad = 1; /* Now default to do padding */
161 int split_output = 0;
162 char *icharset = NULL; /* input charset to convert to UNICODE */
163 char *ocharset = NULL; /* output charset to convert from UNICODE */
164 char *preparer = PREPARER_DEFAULT;
165 char *publisher = PUBLISHER_DEFAULT;
166 char *appid = APPID_DEFAULT;
167 char *copyright = COPYRIGHT_DEFAULT;
168 char *biblio = BIBLIO_DEFAULT;
169 char *abstract = ABSTRACT_DEFAULT;
170 char *volset_id = VOLSET_ID_DEFAULT;
171 char *volume_id = VOLUME_ID_DEFAULT;
172 char *system_id = SYSTEM_ID_DEFAULT;
173 char *boot_catalog = BOOT_CATALOG_DEFAULT;
174 char *boot_image = BOOT_IMAGE_DEFAULT;
175 char *genboot_image = BOOT_IMAGE_DEFAULT;
176 int ucs_level = 3; /* We now have Unicode tables so use level 3 */
177 int volume_set_size = 1;
178 int volume_sequence_number = 1;
180 struct eltorito_boot_entry_info *first_boot_entry = NULL;
181 struct eltorito_boot_entry_info *last_boot_entry = NULL;
182 struct eltorito_boot_entry_info *current_boot_entry = NULL;
184 int use_graft_ptrs; /* Use graft points */
185 int jhide_trans_tbl; /* Hide TRANS.TBL from Joliet tree */
186 int hide_rr_moved; /* Name RR_MOVED .rr_moved in Rock Ridge tree */
187 int omit_period = 0; /* Violates iso9660, but these are a pain */
188 int transparent_compression = 0; /* So far only works with linux */
189 int omit_version_number = 0; /* May violate iso9660, but noone uses vers */
190 int no_rr = 0; /* Do not use RR attributes from old session */
191 int force_rr = 0; /* Force to use RR attributes from old session */
192 Uint RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
193 int do_largefiles = 0; /* Whether to allow multi-extent files */
194 off_t maxnonlarge = (off_t)0xFFFFFFFF;
195 int iso9660_level = 1;
196 int iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */
197 int full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */
198 int relaxed_filenames = 0; /* For Amiga. Disc will not work with DOS */
199 int allow_lowercase = 0; /* Allow lower case letters */
200 int allow_multidot = 0; /* Allow more than on dot in filename */
201 int iso_translate = 1; /* 1 == enables '#', '-' and '~' removal */
202 int allow_leading_dots = 0; /* DOS cannot read names with leading dots */
203 int allow_limited_size = 0; /* Let the user to allow the trick explicitely */
205 int use_fileversion = 1; /* Use file version # from filesystem */
207 int use_fileversion = 0; /* Use file version # from filesystem */
209 int split_SL_component = 1; /* circumvent a bug in the SunOS driver */
210 int split_SL_field = 1; /* circumvent a bug in the SunOS */
211 char *trans_tbl = "TRANS.TBL"; /* default name for translation table */
212 int stream_media_size = 0; /* # of blocks on the media */
213 char *stream_filename = NULL; /* Stream file, 0 to use default STREAM.IMG */
216 int apple_hyb = 0; /* create HFS hybrid flag */
217 int apple_ext = 0; /* create HFS extensions flag */
218 int apple_both = 0; /* common flag (for above) */
219 int hfs_extra = 0; /* extra HFS blocks added to end of ISO vol */
220 int use_mac_name = 0; /* use Mac name for ISO/Joliet/RR flag */
221 hce_mem *hce; /* libhfs/genisoimage extras */
222 char *hfs_boot_file = 0; /* name of HFS boot file */
223 int gen_pt = 0; /* generate HFS partition table */
224 char *autoname = 0; /* AutoStart filename */
225 char *magic_filename = 0; /* name of magic file */
226 int probe = 0; /* search files for HFS/Unix type */
227 int nomacfiles = 0; /* don't look for Mac/Unix files */
228 int hfs_select = 0; /* Mac/Unix types to select */
229 int create_dt = 1; /* create the Desktp files */
230 int afe_size = 0; /* Apple File Exchange block size */
231 int hfs_last = MAG_LAST; /* process magic file after map file */
232 char *deftype = APPLE_TYPE_DEFAULT; /* default Apple TYPE */
233 char *defcreator = APPLE_CREATOR_DEFAULT; /* default Apple CREATOR */
234 char *hfs_volume_id = NULL; /* HFS volume ID */
235 int icon_pos = 0; /* Keep icon position */
236 char *hfs_icharset = NULL; /* input HFS charset name */
237 char *hfs_ocharset = NULL; /* output HFS charset name */
238 int hfs_lock = 1; /* lock HFS volume (read-only) */
239 char *hfs_bless = NULL; /* name of folder to 'bless' (System Folder) */
240 char *hfs_parms = NULL; /* low level HFS parameters */
243 char *prep_boot_image[4];
244 int use_prep_boot = 0;
245 int use_chrp_boot = 0;
246 #endif /* PREP_BOOT */
247 #endif /* APPLE_HYB */
258 int do_sort = 0; /* sort file data */
265 struct unls_table *in_nls = NULL; /* input UNICODE conversion table */
266 struct unls_table *out_nls = NULL; /* output UNICODE conversion table */
268 struct unls_table *hfs_inls = NULL; /* input HFS UNICODE conversion table */
269 struct unls_table *hfs_onls = NULL; /* output HFS UNICODE conversion table */
270 #endif /* APPLE_HYB */
277 struct rcopts rcopt[] = {
279 {"PUBL", &publisher},
281 {"COPY", ©right},
284 {"VOLS", &volset_id},
285 {"VOLI", &volume_id},
286 {"SYSI", &system_id},
288 {"HFS_TYPE", &deftype},
289 {"HFS_CREATOR", &defcreator},
290 #endif /* APPLE_HYB */
294 char *merge_warn_msg=0; /* use as pointer and boolean */
297 * In case it isn't obvious, the option handling code was ripped off
301 /* The long option information. */
303 /* The short option with the same meaning ('\0' if none). */
305 /* The name of the argument (NULL if none). */
308 * The documentation string. If this is NULL, this is a synonym for
309 * the previous option.
313 /* Use one dash before long option name. */
315 /* Use two dashes before long option name. */
317 /* Don't mention this option in --help output. */
323 * Codes used for the long options with no short synonyms. Note that all these
324 * values must not be ASCII or EBCDIC.
326 #define OPTION_HELP 1000
327 #define OPTION_QUIET 1001
328 #define OPTION_NOSPLIT_SL_COMPONENT 1002
329 #define OPTION_NOSPLIT_SL_FIELD 1003
330 #define OPTION_PRINT_SIZE 1004
331 #define OPTION_SPLIT_OUTPUT 1005
332 #define OPTION_ABSTRACT 1006
333 #define OPTION_BIBLIO 1007
334 #define OPTION_COPYRIGHT 1008
335 #define OPTION_SYSID 1009
336 #define OPTION_VOLSET 1010
337 #define OPTION_VOLSET_SIZE 1011
338 #define OPTION_VOLSET_SEQ_NUM 1012
339 #define OPTION_I_HIDE 1013
340 #define OPTION_J_HIDE 1014
341 #define OPTION_LOG_FILE 1015
342 #define OPTION_PVERSION 1016
343 #define OPTION_NOBAK 1017
344 #define OPTION_SPARCLABEL 1018
345 #define OPTION_HARD_DISK_BOOT 1019
346 #define OPTION_NO_EMUL_BOOT 1020
347 #define OPTION_NO_BOOT 1021
348 #define OPTION_BOOT_LOAD_ADDR 1022
349 #define OPTION_BOOT_LOAD_SIZE 1023
350 #define OPTION_BOOT_INFO_TABLE 1024
351 #define OPTION_HIDE_TRANS_TBL 1025
352 #define OPTION_HIDE_RR_MOVED 1026
353 #define OPTION_GUI 1027
354 #define OPTION_TRANS_TBL 1028
355 #define OPTION_P_LIST 1029
356 #define OPTION_I_LIST 1030
357 #define OPTION_J_LIST 1031
358 #define OPTION_X_LIST 1032
359 #define OPTION_NO_RR 1033
360 #define OPTION_JCHARSET 1034
361 #define OPTION_PAD 1035
362 #define OPTION_H_HIDE 1036
363 #define OPTION_H_LIST 1037
364 #define OPTION_CHECK_OLDNAMES 1038
367 #define OPTION_SORT 1039
369 #define OPTION_UCS_LEVEL 1040
370 #define OPTION_ISO_TRANSLATE 1041
371 #define OPTION_ISO_LEVEL 1042
372 #define OPTION_RELAXED_FILENAMES 1043
373 #define OPTION_ALLOW_LOWERCASE 1044
374 #define OPTION_ALLOW_MULTIDOT 1045
375 #define OPTION_USE_FILEVERSION 1046
376 #define OPTION_MAX_FILENAMES 1047
377 #define OPTION_ALT_BOOT 1048
378 #define OPTION_USE_GRAFT 1049
380 #define OPTION_INPUT_CHARSET 1050
381 #define OPTION_OUTPUT_CHARSET 1051
383 #define OPTION_NOPAD 1052
384 #define OPTION_UID 1053
385 #define OPTION_GID 1054
386 #define OPTION_FILEMODE 1055
387 #define OPTION_DIRMODE 1056
388 #define OPTION_NEW_DIR_MODE 1057
389 #define OPTION_CACHE_INODES 1058
390 #define OPTION_NOCACHE_INODES 1059
392 #define OPTION_CHECK_SESSION 1060
393 #define OPTION_FORCE_RR 1061
395 #define OPTION_DEBUG 1062
397 #define OPTION_JLONG 1063
399 #define OPTION_STREAM_FILE_NAME 1064
400 #define OPTION_STREAM_CD_SIZE 1065
402 #define OPTION_XA 1066
403 #define OPTION_XA_RATIONALIZED 1067
405 #define OPTION_SUNX86BOOT 1068
406 #define OPTION_SUNX86LABEL 1069
408 #define OPTION_ALLOW_LEADING_DOTS 1070
409 #define OPTION_PUBLISHER 1071
411 #ifdef JIGDO_TEMPLATE
412 #define OPTION_JTT_OUTPUT 1101
413 #define OPTION_JTJ_OUTPUT 1102
414 #define OPTION_JT_MIN_SIZE 1103
415 #define OPTION_JT_PATH_MAP 1104
416 #define OPTION_JT_MD5_LIST 1105
417 #define OPTION_JT_INCLUDE 1106
418 #define OPTION_JT_EXCLUDE 1107
419 #define OPTION_JT_COMPRESS_ALGO 1108
421 #define OPTION_JT_CHECKSUM_ALGO_ISO 1120
422 #define OPTION_JT_CHECKSUM_ALGO_TMPL 1121
425 #define OPTION_BOOTALPHA 1200
427 #define OPTION_HPPA_CMDLINE 1210
428 #define OPTION_HPPA_KERNEL_32 1211
429 #define OPTION_HPPA_KERNEL_64 1212
430 #define OPTION_HPPA_BOOTLOADER 1213
431 #define OPTION_HPPA_RAMDISK 1214
433 #define OPTION_BOOTMIPS 1220
435 #define OPTION_BOOTMIPSEL 1230
438 #define OPTION_UDF 1500
441 #define OPTION_DVD 1501
445 #define OPTION_CAP 2000
446 #define OPTION_NETA 2001
447 #define OPTION_DBL 2002
448 #define OPTION_ESH 2003
449 #define OPTION_FE 2004
450 #define OPTION_SGI 2005
451 #define OPTION_MBIN 2006
452 #define OPTION_SGL 2007
454 #define OPTION_USH 2008
455 #define OPTION_XIN 2009
457 #define OPTION_DAVE 2010
458 #define OPTION_SFM 2011
459 #define OPTION_XDBL 2012
460 #define OPTION_XHFS 2013
462 #define OPTION_PROBE 2020
463 #define OPTION_MACNAME 2021
464 #define OPTION_NOMACFILES 2022
465 #define OPTION_BOOT_HFS_FILE 2023
466 #define OPTION_MAGIC_FILE 2024
468 #define OPTION_HFS_LIST 2025
470 #define OPTION_GEN_PT 2026
472 #define OPTION_CREATE_DT 2027
473 #define OPTION_HFS_HIDE 2028
475 #define OPTION_AUTOSTART 2029
476 #define OPTION_BSIZE 2030
477 #define OPTION_HFS_VOLID 2031
478 #define OPTION_PREP_BOOT 2032
479 #define OPTION_ICON_POS 2033
481 #define OPTION_HFS_TYPE 2034
482 #define OPTION_HFS_CREATOR 2035
484 #define OPTION_ROOT_INFO 2036
486 #define OPTION_HFS_INPUT_CHARSET 2037
487 #define OPTION_HFS_OUTPUT_CHARSET 2038
489 #define OPTION_HFS_UNLOCK 2039
490 #define OPTION_HFS_BLESS 2040
491 #define OPTION_HFS_PARMS 2041
493 #define OPTION_CHRP_BOOT 2042
495 #define OPTION_RELOC_ROOT 2043
496 #define OPTION_RELOC_OLD_ROOT 2044
498 #define OPTION_MAP_FILE 2045
500 #define OPTION_ALLOW_LIMITED_SIZE 2046
502 #endif /* APPLE_HYB */
504 static int save_pname = 0;
506 static const struct ld_option ld_options[] =
508 {{"nobak", no_argument, NULL, OPTION_NOBAK},
509 '\0', NULL, "Do not include backup files", ONE_DASH},
510 {{"no-bak", no_argument, NULL, OPTION_NOBAK},
511 '\0', NULL, "Do not include backup files", ONE_DASH},
512 {{"abstract", required_argument, NULL, OPTION_ABSTRACT},
513 '\0', "FILE", "Set Abstract filename", ONE_DASH},
514 {{"appid", required_argument, NULL, 'A'},
515 'A', "ID", "Set Application ID", ONE_DASH},
516 {{"biblio", required_argument, NULL, OPTION_BIBLIO},
517 '\0', "FILE", "Set Bibliographic filename", ONE_DASH},
518 {{"cache-inodes", no_argument, NULL, OPTION_CACHE_INODES},
519 '\0', NULL, "Cache inodes (needed to detect hard links)", ONE_DASH},
520 {{"no-cache-inodes", no_argument, NULL, OPTION_NOCACHE_INODES},
521 '\0', NULL, "Do not cache inodes (if filesystem has no unique unides)", ONE_DASH},
522 {{"check-oldnames", no_argument, NULL, OPTION_CHECK_OLDNAMES},
523 '\0', NULL, "Check all imported ISO9660 names from old session", ONE_DASH},
524 {{"check-session", required_argument, NULL, OPTION_CHECK_SESSION},
525 '\0', "FILE", "Check all ISO9660 names from previous session", ONE_DASH},
526 {{"copyright", required_argument, NULL, OPTION_COPYRIGHT},
527 '\0', "FILE", "Set Copyright filename", ONE_DASH},
528 {{"debug", no_argument, NULL, OPTION_DEBUG},
529 '\0', NULL, "Set debug flag", ONE_DASH},
530 {{"eltorito-boot", required_argument, NULL, 'b'},
531 'b', "FILE", "Set El Torito boot image name", ONE_DASH},
532 {{"eltorito-alt-boot", no_argument, NULL, OPTION_ALT_BOOT},
533 '\0', NULL, "Start specifying alternative El Torito boot parameters", ONE_DASH},
534 {{"sparc-boot", required_argument, NULL, 'B'},
535 'B', "FILES", "Set sparc boot image names", ONE_DASH},
536 {{"sunx86-boot", required_argument, NULL, OPTION_SUNX86BOOT},
537 '\0', "FILES", "Set sunx86 boot image names", ONE_DASH},
538 {{"generic-boot", required_argument, NULL, 'G'},
539 'G', "FILE", "Set generic boot image name", ONE_DASH},
540 {{"sparc-label", required_argument, NULL, OPTION_SPARCLABEL},
541 '\0', "label text", "Set sparc boot disk label", ONE_DASH},
542 {{"sunx86-label", required_argument, NULL, OPTION_SUNX86LABEL},
543 '\0', "label text", "Set sunx86 boot disk label", ONE_DASH},
544 {{"eltorito-catalog", required_argument, NULL, 'c'},
545 'c', "FILE", "Set El Torito boot catalog name", ONE_DASH},
546 {{"cdrecord-params", required_argument, NULL, 'C'},
547 'C', "PARAMS", "Magic paramters from cdrecord", ONE_DASH},
548 {{"omit-period", no_argument, NULL, 'd'},
549 'd', NULL, "Omit trailing periods from filenames (violates ISO9660)", ONE_DASH},
550 {{"dir-mode", required_argument, NULL, OPTION_DIRMODE},
551 '\0', "mode", "Make the mode of all directories this mode.", ONE_DASH},
552 {{"disable-deep-relocation", no_argument, NULL, 'D'},
553 'D', NULL, "Disable deep directory relocation (violates ISO9660)", ONE_DASH},
554 {{"file-mode", required_argument, NULL, OPTION_FILEMODE},
555 '\0', "mode", "Make the mode of all plain files this mode.", ONE_DASH},
556 {{"follow-links", no_argument, NULL, 'f'},
557 'f', NULL, "Follow symbolic links", ONE_DASH},
558 {{"gid", required_argument, NULL, OPTION_GID},
559 '\0', "gid", "Make the group owner of all files this gid.",
561 {{"graft-points", no_argument, NULL, OPTION_USE_GRAFT},
562 '\0', NULL, "Allow to use graft points for filenames", ONE_DASH},
563 {{"root", required_argument, NULL, OPTION_RELOC_ROOT},
564 '\0', "DIR", "Set root directory for all new files and directories", ONE_DASH},
565 {{"old-root", required_argument, NULL, OPTION_RELOC_OLD_ROOT},
566 '\0', "DIR", "Set root directory in previous session that is searched for files", ONE_DASH},
567 {{"help", no_argument, NULL, OPTION_HELP},
568 '\0', NULL, "Print option help", ONE_DASH},
569 {{"hide", required_argument, NULL, OPTION_I_HIDE},
570 '\0', "GLOBFILE", "Hide ISO9660/RR file", ONE_DASH},
571 {{"hide-list", required_argument, NULL, OPTION_I_LIST},
572 '\0', "FILE", "File with list of ISO9660/RR files to hide", ONE_DASH},
573 {{"hidden", required_argument, NULL, OPTION_H_HIDE},
574 '\0', "GLOBFILE", "Set hidden attribute on ISO9660 file", ONE_DASH},
575 {{"hidden-list", required_argument, NULL, OPTION_H_LIST},
576 '\0', "FILE", "File with list of ISO9660 files with hidden attribute", ONE_DASH},
577 {{"hide-joliet", required_argument, NULL, OPTION_J_HIDE},
578 '\0', "GLOBFILE", "Hide Joliet file", ONE_DASH},
579 {{"hide-joliet-list", required_argument, NULL, OPTION_J_LIST},
580 '\0', "FILE", "File with list of Joliet files to hide", ONE_DASH},
581 {{"hide-joliet-trans-tbl", no_argument, NULL, OPTION_HIDE_TRANS_TBL},
582 '\0', NULL, "Hide TRANS.TBL from Joliet tree", ONE_DASH},
583 {{"hide-rr-moved", no_argument, NULL, OPTION_HIDE_RR_MOVED},
584 '\0', NULL, "Rename RR_MOVED to .rr_moved in Rock Ridge tree", ONE_DASH},
585 {{"gui", no_argument, NULL, OPTION_GUI},
586 '\0', NULL, "Switch behaviour for GUI", ONE_DASH},
587 {{NULL, required_argument, NULL, 'i'},
588 'i', "ADD_FILES", "No longer supported", TWO_DASHES},
589 {{"input-charset", required_argument, NULL, OPTION_INPUT_CHARSET},
590 '\0', "CHARSET", "Local input charset for file name conversion", ONE_DASH},
591 {{"output-charset", required_argument, NULL, OPTION_OUTPUT_CHARSET},
592 '\0', "CHARSET", "Output charset for file name conversion", ONE_DASH},
593 {{"iso-level", required_argument, NULL, OPTION_ISO_LEVEL},
594 '\0', "LEVEL", "Set ISO9660 conformance level (1..3) or 4 for ISO9660 version 2", ONE_DASH},
595 {{"joliet", no_argument, NULL, 'J'},
596 'J', NULL, "Generate Joliet directory information", ONE_DASH},
597 {{"joliet-long", no_argument, NULL, OPTION_JLONG},
598 '\0', NULL, "Allow Joliet file names to be 103 Unicode characters", ONE_DASH},
599 {{"jcharset", required_argument, NULL, OPTION_JCHARSET},
600 '\0', "CHARSET", "Local charset for Joliet directory information", ONE_DASH},
601 {{"full-iso9660-filenames", no_argument, NULL, 'l'},
602 'l', NULL, "Allow full 31 character filenames for ISO9660 names", ONE_DASH},
603 {{"max-iso9660-filenames", no_argument, NULL, OPTION_MAX_FILENAMES},
604 '\0', NULL, "Allow 37 character filenames for ISO9660 names (violates ISO9660)", ONE_DASH},
606 {{"allow-limited-size", no_argument, NULL, OPTION_ALLOW_LIMITED_SIZE},
607 '\0', NULL, "Allow different file sizes in ISO9660/UDF on large files", ONE_DASH},
609 {{"allow-leading-dots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS},
610 '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
611 {{"ldots", no_argument, NULL, OPTION_ALLOW_LEADING_DOTS},
612 '\0', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
613 {{"allow-leading-dots", no_argument, NULL, 'L'},
614 'L', NULL, "Allow ISO9660 filenames to start with '.' (violates ISO9660)", ONE_DASH},
616 {{"log-file", required_argument, NULL, OPTION_LOG_FILE},
617 '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH},
618 {{"exclude", required_argument, NULL, 'm'},
619 'm', "GLOBFILE", "Exclude file name", ONE_DASH},
620 {{"exclude-list", required_argument, NULL, OPTION_X_LIST},
621 '\0', "FILE", "File with list of file names to exclude", ONE_DASH},
622 {{"pad", no_argument, NULL, OPTION_PAD},
623 0, NULL, "Pad output to a multiple of 32k (default)", ONE_DASH},
624 {{"no-pad", no_argument, NULL, OPTION_NOPAD},
625 0, NULL, "Do not pad output to a multiple of 32k", ONE_DASH},
626 {{"prev-session", required_argument, NULL, 'M'},
627 'M', "FILE", "Set path to previous session to merge", ONE_DASH},
628 {{"dev", required_argument, NULL, 'M'},
629 '\0', "SCSIdev", "Set path to previous session to merge", ONE_DASH},
630 {{"omit-version-number", no_argument, NULL, 'N'},
631 'N', NULL, "Omit version number from ISO9660 filename (violates ISO9660)", ONE_DASH},
632 {{"new-dir-mode", required_argument, NULL, OPTION_NEW_DIR_MODE},
633 '\0', "mode", "Mode used when creating new directories.", ONE_DASH},
634 {{"force-rr", no_argument, NULL, OPTION_FORCE_RR},
635 0, NULL, "Inhibit automatic Rock Ridge detection for previous session", ONE_DASH},
636 {{"no-rr", no_argument, NULL, OPTION_NO_RR},
637 0, NULL, "Inhibit reading of Rock Ridge attributes from previous session", ONE_DASH},
638 {{"no-split-symlink-components", no_argument, NULL, OPTION_NOSPLIT_SL_COMPONENT},
639 0, NULL, "Inhibit splitting symlink components", ONE_DASH},
640 {{"no-split-symlink-fields", no_argument, NULL, OPTION_NOSPLIT_SL_FIELD},
641 0, NULL, "Inhibit splitting symlink fields", ONE_DASH},
642 {{"output", required_argument, NULL, 'o'},
643 'o', "FILE", "Set output file name", ONE_DASH},
644 {{"path-list", required_argument, NULL, OPTION_P_LIST},
645 '\0', "FILE", "File with list of pathnames to process", ONE_DASH},
646 {{"preparer", required_argument, NULL, 'p'},
647 'p', "PREP", "Set Volume preparer", ONE_DASH},
648 {{"print-size", no_argument, NULL, OPTION_PRINT_SIZE},
649 '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH},
650 {{"publisher", required_argument, NULL, OPTION_PUBLISHER},
651 '\0', "PUB", "Set Volume publisher", ONE_DASH},
652 {{"publisher", required_argument, NULL, 'P'},
653 'P', "PUB", "Set Volume publisher", ONE_DASH},
654 {{"quiet", no_argument, NULL, OPTION_QUIET},
655 '\0', NULL, "Run quietly", ONE_DASH},
656 {{"rational-rock", no_argument, NULL, 'r'},
657 'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH},
658 {{"rock", no_argument, NULL, 'R'},
659 'R', NULL, "Generate Rock Ridge directory information", ONE_DASH},
660 {{"sectype", required_argument, NULL, 's'},
661 's', "TYPE", "Set output sector type to e.g. data/xa1/raw", ONE_DASH},
663 {{"alpha-boot", required_argument, NULL, OPTION_BOOTALPHA},
664 '\0', "FILE", "Set alpha boot image name (relative to image root)", ONE_DASH},
666 {{"hppa-cmdline", required_argument, NULL, OPTION_HPPA_CMDLINE},
667 '\0', "CMDLINE", "Set hppa boot command line (relative to image root)", ONE_DASH},
668 {{"hppa-kernel-32", required_argument, NULL, OPTION_HPPA_KERNEL_32},
669 '\0', "FILE", "Set hppa 32-bit image name (relative to image root)", ONE_DASH},
670 {{"hppa-kernel-64", required_argument, NULL, OPTION_HPPA_KERNEL_64},
671 '\0', "FILE", "Set hppa 64-bit image name (relative to image root)", ONE_DASH},
672 {{"hppa-bootloader", required_argument, NULL, OPTION_HPPA_BOOTLOADER},
673 '\0', "FILE", "Set hppa boot loader file name (relative to image root)", ONE_DASH},
674 {{"hppa-ramdisk", required_argument, NULL, OPTION_HPPA_RAMDISK},
675 '\0', "FILE", "Set hppa ramdisk file name (relative to image root)", ONE_DASH},
677 {{"mips-boot", required_argument, NULL, OPTION_BOOTMIPS},
678 '\0', "FILE", "Set mips boot image name (relative to image root)", ONE_DASH},
680 {{"mipsel-boot", required_argument, NULL, OPTION_BOOTMIPSEL},
681 '\0', "FILE", "Set mipsel boot image name (relative to image root)", ONE_DASH},
683 #ifdef JIGDO_TEMPLATE
684 {{"jigdo-jigdo", required_argument, NULL, OPTION_JTJ_OUTPUT},
685 '\0', "FILE", "Produce a jigdo .jigdo file as well as the .iso", ONE_DASH },
686 {{"jigdo-template", required_argument, NULL, OPTION_JTT_OUTPUT},
687 '\0', "FILE", "Produce a jigdo .template file as well as the .iso", ONE_DASH },
688 {{"jigdo-min-file-size", required_argument, NULL, OPTION_JT_MIN_SIZE},
689 '\0', "SIZE", "Minimum size for a file to be listed in the jigdo file", ONE_DASH },
690 {{"jigdo-force-md5", required_argument, NULL, OPTION_JT_INCLUDE},
691 '\0', "PATTERN", "Pattern(s) where files MUST match an externally-supplied MD5sum", ONE_DASH },
692 {{"jigdo-exclude", required_argument, NULL, OPTION_JT_EXCLUDE},
693 '\0', "PATTERN", "Pattern(s) to exclude from the jigdo file", ONE_DASH },
694 {{"jigdo-map", required_argument, NULL, OPTION_JT_PATH_MAP},
695 '\0', "PATTERN1=PATTERN2", "Pattern(s) to map paths (e.g. Debian=/mirror/debian)", ONE_DASH },
696 {{"md5-list", required_argument, NULL, OPTION_JT_MD5_LIST},
697 '\0', "FILE", "File containing MD5 sums of the files that should be checked", ONE_DASH },
698 {{"jigdo-template-compress", required_argument, NULL, OPTION_JT_COMPRESS_ALGO},
699 '\0', "ALGORITHM", "Choose to use gzip or bzip2 compression for template data; default is gzip", ONE_DASH },
700 {{"checksum_algorithm_iso", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_ISO},
701 '\0', "alg1,alg2,...", "Specify the checksum types desired for the output image", ONE_DASH},
702 {{"checksum_algorithm_template", required_argument, NULL, OPTION_JT_CHECKSUM_ALGO_TMPL},
703 '\0', "alg1,alg2,...", "Specify the checksum types desired for the output jigdo template", ONE_DASH},
707 { {"sort", required_argument, NULL, OPTION_SORT},
708 '\0', "FILE", "Sort file content locations according to rules in FILE", ONE_DASH },
711 {{"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
712 '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH},
713 {{"stream-file-name", required_argument, NULL, OPTION_STREAM_FILE_NAME},
714 '\0', "FILE_NAME", "Set the stream file ISO9660 name (incl. version)", ONE_DASH},
715 {{"stream-media-size", required_argument, NULL, OPTION_STREAM_CD_SIZE},
716 '\0', "#", "Set the size of your CD media in sectors", ONE_DASH},
717 {{"sysid", required_argument, NULL, OPTION_SYSID},
718 '\0', "ID", "Set System ID", ONE_DASH},
719 {{"translation-table", no_argument, NULL, 'T'},
720 'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH},
721 {{"table-name", required_argument, NULL, OPTION_TRANS_TBL},
722 '\0', "TABLE_NAME", "Translation table file name", ONE_DASH},
723 {{"ucs-level", required_argument, NULL, OPTION_UCS_LEVEL},
724 '\0', "LEVEL", "Set Joliet UCS level (1..3)", ONE_DASH},
727 {{"udf", no_argument, NULL, OPTION_UDF},
728 '\0', NULL, "Generate UDF file system", ONE_DASH},
732 {{"dvd-video", no_argument, NULL, OPTION_DVD},
733 '\0', NULL, "Generate DVD-Video compliant UDF file system", ONE_DASH},
736 {{"uid", required_argument, NULL, OPTION_UID},
737 '\0', "uid", "Make the owner of all files this uid.",
739 {{"untranslated-filenames", no_argument, NULL, 'U'},
741 'U', NULL, "Allow Untranslated filenames (for HPUX & AIX - violates ISO9660). Forces -l, -d, -N, -allow-leading-dots, -relaxed-filenames, -allow-lowercase, -allow-multidot", ONE_DASH},
742 {{"relaxed-filenames", no_argument, NULL, OPTION_RELAXED_FILENAMES},
743 '\0', NULL, "Allow 7 bit ASCII except lower case characters (violates ISO9660)", ONE_DASH},
744 {{"no-iso-translate", no_argument, NULL, OPTION_ISO_TRANSLATE},
745 '\0', NULL, "Do not translate illegal ISO characters '~', '-' and '#' (violates ISO9660)", ONE_DASH},
746 {{"allow-lowercase", no_argument, NULL, OPTION_ALLOW_LOWERCASE},
747 '\0', NULL, "Allow lower case characters in addition to the current character set (violates ISO9660)", ONE_DASH},
748 {{"allow-multidot", no_argument, NULL, OPTION_ALLOW_MULTIDOT},
749 '\0', NULL, "Allow more than one dot in filenames (e.g. .tar.gz) (violates ISO9660)", ONE_DASH},
750 {{"use-fileversion", no_argument, NULL, OPTION_USE_FILEVERSION},
751 '\0', "LEVEL", "Use file version # from filesystem", ONE_DASH},
752 {{"verbose", no_argument, NULL, 'v'},
753 'v', NULL, "Verbose", ONE_DASH},
754 {{"version", no_argument, NULL, OPTION_PVERSION},
755 '\0', NULL, "Print the current version", ONE_DASH},
756 {{"volid", required_argument, NULL, 'V'},
757 'V', "ID", "Set Volume ID", ONE_DASH},
758 {{"volset", required_argument, NULL, OPTION_VOLSET},
759 '\0', "ID", "Set Volume set ID", ONE_DASH},
760 {{"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE},
761 '\0', "#", "Set Volume set size", ONE_DASH},
762 {{"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM},
763 '\0', "#", "Set Volume set sequence number", ONE_DASH},
764 {{"old-exclude", required_argument, NULL, 'x'},
765 'x', "FILE", "Exclude file name(depreciated)", ONE_DASH},
766 {{"hard-disk-boot", no_argument, NULL, OPTION_HARD_DISK_BOOT},
767 '\0', NULL, "Boot image is a hard disk image", ONE_DASH},
768 {{"no-emul-boot", no_argument, NULL, OPTION_NO_EMUL_BOOT},
769 '\0', NULL, "Boot image is 'no emulation' image", ONE_DASH},
770 {{"no-boot", no_argument, NULL, OPTION_NO_BOOT},
771 '\0', NULL, "Boot image is not bootable", ONE_DASH},
772 {{"boot-load-seg", required_argument, NULL, OPTION_BOOT_LOAD_ADDR},
773 '\0', "#", "Set load segment for boot image", ONE_DASH},
774 {{"boot-load-size", required_argument, NULL, OPTION_BOOT_LOAD_SIZE},
775 '\0', "#", "Set numbers of load sectors", ONE_DASH},
776 {{"boot-info-table", no_argument, NULL, OPTION_BOOT_INFO_TABLE},
777 '\0', NULL, "Patch boot image with info table", ONE_DASH},
778 {{"XA", no_argument, NULL, OPTION_XA},
779 '\0', NULL, "Generate XA directory attruibutes", ONE_DASH},
780 {{"xa", no_argument, NULL, OPTION_XA_RATIONALIZED},
781 '\0', NULL, "Generate rationalized XA directory attruibutes", ONE_DASH},
782 {{"transparent-compression", no_argument, NULL, 'z'},
783 'z', NULL, "Enable transparent compression of files", ONE_DASH},
786 {{"hfs-type", required_argument, NULL, OPTION_HFS_TYPE},
787 '\0', "TYPE", "Set HFS default TYPE", ONE_DASH},
788 {{"hfs-creator", required_argument, NULL, OPTION_HFS_CREATOR},
789 '\0', "CREATOR", "Set HFS default CREATOR", ONE_DASH},
790 {{"apple", no_argument, NULL, 'g'},
791 'g', NULL, "Add Apple ISO9660 extensions", ONE_DASH},
792 {{"hfs", no_argument, NULL, 'h'},
793 'h', NULL, "Create ISO9660/HFS hybrid", ONE_DASH},
794 {{"map", required_argument, NULL, OPTION_MAP_FILE},
795 '\0', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
796 {{"map", required_argument, NULL, 'H'},
797 'H', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH},
798 {{"magic", required_argument, NULL, OPTION_MAGIC_FILE},
799 '\0', "FILE", "Magic file for HFS TYPE/CREATOR", ONE_DASH},
800 {{"probe", no_argument, NULL, OPTION_PROBE},
801 '\0', NULL, "Probe all files for Apple/Unix file types", ONE_DASH},
802 {{"mac-name", no_argument, NULL, OPTION_MACNAME},
803 '\0', NULL, "Use Macintosh name for ISO9660/Joliet/RockRidge file name",
805 {{"no-mac-files", no_argument, NULL, OPTION_NOMACFILES},
806 '\0', NULL, "Do not look for Unix/Mac files (depreciated)", ONE_DASH},
807 {{"boot-hfs-file", required_argument, NULL, OPTION_BOOT_HFS_FILE},
808 '\0', "FILE", "Set HFS boot image name", ONE_DASH},
809 {{"part", no_argument, NULL, OPTION_GEN_PT},
810 '\0', NULL, "Generate HFS partition table", ONE_DASH},
811 {{"cluster-size", required_argument, NULL, OPTION_BSIZE},
812 '\0', "SIZE", "Cluster size for PC Exchange Macintosh files", ONE_DASH},
813 {{"auto", required_argument, NULL, OPTION_AUTOSTART},
814 '\0', "FILE", "Set HFS AutoStart file name", ONE_DASH},
815 {{"no-desktop", no_argument, NULL, OPTION_CREATE_DT},
816 '\0', NULL, "Do not create the HFS (empty) Desktop files", ONE_DASH},
817 {{"hide-hfs", required_argument, NULL, OPTION_HFS_HIDE},
818 '\0', "GLOBFILE", "Hide HFS file", ONE_DASH},
819 {{"hide-hfs-list", required_argument, NULL, OPTION_HFS_LIST},
820 '\0', "FILE", "List of HFS files to hide", ONE_DASH},
821 {{"hfs-volid", required_argument, NULL, OPTION_HFS_VOLID},
822 '\0', "HFS_VOLID", "Volume name for the HFS partition", ONE_DASH},
823 {{"icon-position", no_argument, NULL, OPTION_ICON_POS},
824 '\0', NULL, "Keep HFS icon position", ONE_DASH},
825 {{"root-info", required_argument, NULL, OPTION_ROOT_INFO},
826 '\0', "FILE", "finderinfo for root folder", ONE_DASH},
827 {{"input-hfs-charset", required_argument, NULL, OPTION_HFS_INPUT_CHARSET},
828 '\0', "CHARSET", "Local input charset for HFS file name conversion", ONE_DASH},
829 {{"output-hfs-charset", required_argument, NULL, OPTION_HFS_OUTPUT_CHARSET},
830 '\0', "CHARSET", "Output charset for HFS file name conversion", ONE_DASH},
831 {{"hfs-unlock", no_argument, NULL, OPTION_HFS_UNLOCK},
832 '\0', NULL, "Leave HFS Volume unlocked", ONE_DASH},
833 {{"hfs-bless", required_argument, NULL, OPTION_HFS_BLESS},
834 '\0', "FOLDER_NAME", "Name of Folder to be blessed", ONE_DASH},
835 {{"hfs-parms", required_argument, NULL, OPTION_HFS_PARMS},
836 '\0', "PARAMETERS", "Comma separated list of HFS parameters", ONE_DASH},
838 {{"prep-boot", required_argument, NULL, OPTION_PREP_BOOT},
839 '\0', "FILE", "PReP boot image file -- up to 4 are allowed", ONE_DASH},
840 {{"chrp-boot", no_argument, NULL, OPTION_CHRP_BOOT},
841 '\0', NULL, "Add CHRP boot header", ONE_DASH},
842 #endif /* PREP_BOOT */
843 {{"cap", no_argument, NULL, OPTION_CAP},
844 '\0', NULL, "Look for AUFS CAP Macintosh files", TWO_DASHES},
845 {{"netatalk", no_argument, NULL, OPTION_NETA},
846 '\0', NULL, "Look for NETATALK Macintosh files", TWO_DASHES},
847 {{"double", no_argument, NULL, OPTION_DBL},
848 '\0', NULL, "Look for AppleDouble Macintosh files", TWO_DASHES},
849 {{"ethershare", no_argument, NULL, OPTION_ESH},
850 '\0', NULL, "Look for Helios EtherShare Macintosh files", TWO_DASHES},
851 {{"exchange", no_argument, NULL, OPTION_FE},
852 '\0', NULL, "Look for PC Exchange Macintosh files", TWO_DASHES},
853 {{"sgi", no_argument, NULL, OPTION_SGI},
854 '\0', NULL, "Look for SGI Macintosh files", TWO_DASHES},
855 {{"macbin", no_argument, NULL, OPTION_MBIN},
856 '\0', NULL, "Look for MacBinary Macintosh files", TWO_DASHES},
857 {{"single", no_argument, NULL, OPTION_SGL},
858 '\0', NULL, "Look for AppleSingle Macintosh files", TWO_DASHES},
859 {{"ushare", no_argument, NULL, OPTION_USH},
860 '\0', NULL, "Look for IPT UShare Macintosh files", TWO_DASHES},
861 {{"xinet", no_argument, NULL, OPTION_XIN},
862 '\0', NULL, "Look for XINET Macintosh files", TWO_DASHES},
863 {{"dave", no_argument, NULL, OPTION_DAVE},
864 '\0', NULL, "Look for DAVE Macintosh files", TWO_DASHES},
865 {{"sfm", no_argument, NULL, OPTION_SFM},
866 '\0', NULL, "Look for SFM Macintosh files", TWO_DASHES},
867 {{"osx-double", no_argument, NULL, OPTION_XDBL},
868 '\0', NULL, "Look for MacOS X AppleDouble Macintosh files", TWO_DASHES},
869 {{"osx-hfs", no_argument, NULL, OPTION_XHFS},
870 '\0', NULL, "Look for MacOS X HFS Macintosh files", TWO_DASHES},
871 #endif /* APPLE_HYB */
874 #define OPTION_COUNT (sizeof ld_options / sizeof (ld_options[0]))
876 static void read_rcfile(char *appname);
877 static void susage(int excode);
878 static void usage(int excode);
879 int iso9660_date(char *result, time_t crtime);
880 static void hide_reloc_dir(void);
881 static char *get_pnames(int argc, char **argv, int opt, char *pname,
882 int pnsize, FILE *fp);
883 char *findgequal(char *s);
884 static char *escstrcpy(char *to, char *from);
885 void *e_malloc(size_t size);
888 read_one_rcfile(char *filename)
891 char linebuffer[256];
897 fp = fopen(filename, "r");
902 errmsg("Cannot open '%s'.\n", filename);
909 fprintf(stderr, "Using \"%s\"\n", filename);
911 while (fgets(linebuffer, sizeof(linebuffer), fp)) {
916 /* skip any leading white space */
917 for (p = linebuffer; *p == ' ' || *p == '\t'; p++)
919 /* Skip comments and blank lines */
920 if (!*p || *p == '\n' || *p == '\r' || *p == '#')
923 * The name should begin in the left margin. Make sure it is
924 * in upper case. Stop when we see white space or a comment.
927 while (*p && (isalpha((unsigned char) *p) || *p == '_'))
928 *p++ = toupper((unsigned char) *p);
931 fprintf(stderr, "%s:%d: name required\n", filename,
937 /* Skip past white space after the name */
938 while (*p == ' ' || *p == '\t')
940 /* silently ignore errors in the rc file. */
942 fprintf(stderr, "%s:%d: equals sign required after '%.*s'\n",
944 (int)(p1-name), name);
949 /* Skip pas the = sign, and any white space following it */
951 while (*p == ' ' || *p == '\t')
954 /* Get rid of trailing newline */
955 for (p1 = p; *p1 && *p1 != '\n' && *p1 != '\r'; p1++)
959 /* Figure out which option we have */
960 for (rco = rcopt; rco->tag; rco++)
961 if (strcmp(rco->tag, name) == 0) {
962 /* memleak if we ever do this more than once */
963 *rco->variable = strdup(p);
968 fprintf(stderr, "%s:%d: field name '%s' unknown\n",
975 errmsg("Read error on '%s'.\n", filename);
986 #define ETCDIR "/etc"
987 #define RCFILENAME "genisoimagerc"
988 #define OLD_RCFILENAME "mkisofsrc"
991 read_rcfile(char *appname)
996 if (read_one_rcfile(getenv("GENISOIMAGERC")))
998 if (read_one_rcfile(getenv("MKISOFSRC")))
1000 if (read_one_rcfile("." RCFILENAME))
1002 if (read_one_rcfile("." OLD_RCFILENAME))
1006 if (p && strlen(p) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
1007 strcpy(filename, p);
1008 p = filename + strlen(filename);
1009 *p++ = PATH_SEPARATOR;
1010 strcpy(p, "." RCFILENAME);
1011 if (read_one_rcfile(filename))
1013 strcpy(p, "." OLD_RCFILENAME);
1014 if (read_one_rcfile(filename))
1018 if (read_one_rcfile(ETCDIR SPATH_SEPARATOR RCFILENAME))
1022 strlen(appname) + 1 + sizeof(RCFILENAME) < sizeof(filename)) {
1023 strcpy(filename, appname);
1024 p = strrchr(filename, PATH_SEPARATOR);
1026 strcpy(p + 1, RCFILENAME);
1027 if (read_one_rcfile(filename))
1033 char *path_table_l = NULL;
1034 char *path_table_m = NULL;
1036 char *jpath_table_l = NULL;
1037 char *jpath_table_m = NULL;
1052 const char *program_name = "genisoimage";
1054 fprintf(stderr, "Usage: %s [options] -o file directory ...\n", program_name);
1055 fprintf(stderr, "\nUse %s -help\n", program_name);
1056 fprintf(stderr, "to get a list of valid options.\n");
1057 fprintf(stderr, "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
1065 const char *program_name = "genisoimage";
1069 /* const char **targets, **pp;*/
1071 fprintf(stderr, "Usage: %s [options] file...\n", program_name);
1073 fprintf(stderr, "Options:\n");
1074 for (i = 0; i < (int)OPTION_COUNT; i++) {
1075 if (ld_options[i].doc != NULL) {
1080 fprintf(stderr, " ");
1087 if (ld_options[j].shortopt != '\0' &&
1088 ld_options[j].control != NO_HELP) {
1089 fprintf(stderr, "%s-%c",
1091 ld_options[j].shortopt);
1092 len += (comma ? 2 : 0) + 2;
1093 if (ld_options[j].arg != NULL) {
1094 if (ld_options[j].opt.has_arg != optional_argument) {
1095 fprintf(stderr, " ");
1098 fprintf(stderr, "%s",
1100 len += strlen(ld_options[j].arg);
1106 while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
1110 if (ld_options[j].opt.name != NULL &&
1111 ld_options[j].control != NO_HELP) {
1112 fprintf(stderr, "%s-%s%s",
1114 ld_options[j].control == TWO_DASHES ? "-" : "",
1115 ld_options[j].opt.name);
1116 len += ((comma ? 2 : 0)
1118 + (ld_options[j].control == TWO_DASHES ? 1 : 0)
1119 + strlen(ld_options[j].opt.name));
1120 if (ld_options[j].arg != NULL) {
1121 fprintf(stderr, " %s",
1124 strlen(ld_options[j].arg);
1130 while (j < (int)OPTION_COUNT && ld_options[j].doc == NULL);
1133 fprintf(stderr, "\n");
1136 for (; len < 30; len++)
1139 fprintf(stderr, "%s\n", ld_options[i].doc);
1143 "\nReport problems to debburn-devel@lists.alioth.debian.org.\n");
1149 * Fill in date in the iso9660 format
1151 * The standards state that the timezone offset is in multiples of 15
1152 * minutes, and is what you add to GMT to get the localtime. The U.S.
1153 * is always at a negative offset, from -5h to -8h (can vary a little
1154 * with DST, I guess). The Linux iso9660 filesystem has had the sign
1155 * of this wrong for ages (genisoimage had it wrong too for the longest time).
1158 iso9660_date(char *result, time_t crtime)
1162 local = localtime(&crtime);
1163 result[0] = local->tm_year;
1164 result[1] = local->tm_mon + 1;
1165 result[2] = local->tm_mday;
1166 result[3] = local->tm_hour;
1167 result[4] = local->tm_min;
1168 result[5] = local->tm_sec;
1171 * Must recalculate proper timezone offset each time, as some files use
1172 * daylight savings time and some don't...
1174 result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */
1175 local = gmtime(&crtime);
1176 local->tm_year -= result[0];
1177 local->tm_yday -= result[6];
1178 local->tm_hour -= result[3];
1179 local->tm_min -= result[4];
1180 if (local->tm_year < 0) {
1181 local->tm_yday = -1;
1183 if (local->tm_year > 0)
1187 result[6] = -(local->tm_min + 60 *
1188 (local->tm_hour + 24 * local->tm_yday)) / 15;
1193 /* hide "./rr_moved" if all its contents are hidden */
1197 struct directory_entry *s_entry;
1199 for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) {
1200 if (strcmp(s_entry->name, ".") == 0 ||
1201 strcmp(s_entry->name, "..") == 0)
1204 if ((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
1208 /* all entries are hidden, so hide this directory */
1209 reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
1210 reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY;
1214 * get pathnames from the command line, and then from given file
1217 get_pnames(int argc, char **argv, int opt, char *pname, int pnsize, FILE *fp)
1221 /* we may of already read the first line from the pathnames file */
1231 return ((char *) 0);
1233 if (fgets(pname, pnsize, fp)) {
1234 /* Discard newline */
1235 len = strlen(pname);
1236 if (pname[len - 1] == '\n') {
1237 pname[len - 1] = '\0';
1241 return ((char *) 0);
1244 extern char *cdrecord_data;
1246 int main(int argc, char *argv[])
1248 struct directory_entry de;
1251 unsigned long mem_start;
1254 struct stat statbuf;
1255 char *merge_image = NULL;
1256 char *reloc_root = NULL;
1257 char *reloc_old_root = NULL;
1258 struct iso_directory_record *mrootp = NULL;
1259 struct output_fragment *opnt;
1261 char shortopts[OPTION_COUNT * 3 + 2];
1262 struct option longopts[OPTION_COUNT + 1];
1267 char *pathnames = 0;
1269 char pname[2*PATH_MAX + 1 + 1]; /* may be too short */
1270 char *arg; /* if '\\' present */
1271 char nodename[PATH_MAX + 1];
1272 int no_path_names = 1;
1273 int warn_violate = 0;
1274 int have_cmd_line_pathspec = 0;
1275 int rationalize_all = 0;
1276 char *mkisofs_call = 0; /* use as pointer and boolean */
1279 char *afpfile = ""; /* mapping file for TYPE/CREATOR */
1281 char *root_info = 0;
1282 #endif /* APPLE_HYB */
1285 mkisofs_call=strstr(argv[0], "mkisofs");
1286 if(mkisofs_call && '\0' == mkisofs_call[7]) /* lame cheater detected */
1287 argv[0]="genisoimage";
1290 /* This gives wildcard expansion with Non-Posix shells with EMX */
1291 _wildcard(&argc, &argv);
1293 save_args(argc, argv);
1296 #ifdef USE_LIBSCHILY
1297 errmsgno(EX_BAD, "Missing pathspec.\n");
1301 /* Get the defaults from the .genisoimagerc file */
1302 read_rcfile(argv[0]);
1307 * Copy long option initialization from GNU-ld.
1310 * Starting the short option string with '-' is for programs that
1311 * expect options and other ARGV-elements in any order and that care
1312 * about the ordering of the two. We describe each non-option
1313 * ARGV-element as if it were the argument of an option with
1324 for (i = 0; i < (int)OPTION_COUNT; i++) {
1325 if (ld_options[i].shortopt != '\0') {
1326 shortopts[is] = ld_options[i].shortopt;
1328 if (ld_options[i].opt.has_arg ==
1329 required_argument ||
1330 ld_options[i].opt.has_arg ==
1331 optional_argument) {
1332 shortopts[is] = ':';
1334 if (ld_options[i].opt.has_arg ==
1335 optional_argument) {
1336 shortopts[is] = ':';
1341 if (ld_options[i].opt.name != NULL) {
1342 longopts[il] = ld_options[i].opt;
1346 shortopts[is] = '\0';
1347 longopts[il].name = NULL;
1350 while ((c = getopt_long_only(argc, argv, shortopts,
1351 longopts, &longind)) != EOF)
1354 /* A filename that we take as input. */
1356 have_cmd_line_pathspec = 1;
1357 goto parse_input_files;
1359 case OPTION_USE_GRAFT:
1364 * This is a temporary hack until cdrecord gets the
1365 * proper hooks in it.
1367 cdrecord_data = optarg;
1373 #ifdef USE_LIBSCHILY
1374 comerrno(EX_BAD, "-i option no longer supported.\n");
1376 fprintf(stderr, "-i option no longer supported.\n");
1380 case OPTION_ISO_LEVEL:
1381 iso9660_level = atoi(optarg);
1383 switch (iso9660_level) {
1387 * Only on file section
1388 * 8.3 d or d1 characters for files
1389 * 8 d or d1 characters for directories
1394 * Only on file section
1405 * This is ISO-9660:1988 (ISO-9660 version 2)
1407 iso9660_namelen = MAX_ISONAME_V2; /* allow 207 chars */
1408 full_iso9660_filenames++; /* 31+ chars */
1409 omit_version_number++;
1410 RR_relocation_depth = 32767;
1415 omit_period++; /* trailing dot */
1416 allow_leading_dots++;
1417 relaxed_filenames++; /* all chars */
1418 allow_lowercase++; /* even lowcase */
1419 allow_multidot++; /* > 1 dots */
1424 comerrno(EX_BAD, "Illegal iso9660 Level %d, use 1..3 or 4.\n",
1435 case OPTION_JCHARSET:
1438 case OPTION_INPUT_CHARSET:
1441 case OPTION_OUTPUT_CHARSET:
1444 #ifdef JIGDO_TEMPLATE
1445 case OPTION_JTT_OUTPUT:
1446 jtemplate_out = optarg;
1448 case OPTION_JTJ_OUTPUT:
1449 jjigdo_out = optarg;
1451 case OPTION_JT_MD5_LIST:
1454 case OPTION_JT_MIN_SIZE:
1455 jte_min_size = atoi(optarg);
1456 if (jte_min_size < MIN_JIGDO_FILE_SIZE) {
1457 fprintf(stderr, "Jigdo min size %d too small; using default %d instead\n", jte_min_size, MIN_JIGDO_FILE_SIZE);
1458 jte_min_size = MIN_JIGDO_FILE_SIZE;
1461 case OPTION_JT_INCLUDE:
1462 if (jte_add_include(optarg)) {
1463 #ifdef USE_LIBSCHILY
1465 "Failed to build jigdo-include list\n");
1468 "Failed to build jigdo-include list\n");
1473 case OPTION_JT_EXCLUDE:
1474 if (jte_add_exclude(optarg)) {
1475 #ifdef USE_LIBSCHILY
1477 "Failed to build jigdo-exclude list\n");
1480 "Failed to build jigdo-exclude list\n");
1485 case OPTION_JT_PATH_MAP:
1486 if (jte_add_mapping(optarg)) {
1487 #ifdef USE_LIBSCHILY
1489 "Failed to build jigdo mapping list\n");
1492 "Failed to build jigdo mapping list\n");
1497 case OPTION_JT_COMPRESS_ALGO:
1498 if (!strcasecmp(optarg, "gzip"))
1499 jte_template_compression = JTE_TEMP_GZIP;
1500 else if (!strcasecmp(optarg, "bzip2"))
1501 jte_template_compression = JTE_TEMP_BZIP2;
1504 #ifdef USE_LIBSCHILY
1505 comerrno(EX_BAD, "Compression algorithm %s unknown\n", optarg);
1507 fprintf(stderr, "Compression algorithm %s unknown\n", optarg);
1513 case OPTION_JT_CHECKSUM_ALGO_ISO:
1514 if (parse_checksum_algo(optarg, &checksum_algo_iso))
1516 #ifdef USE_LIBSCHILY
1517 comerrno(EX_BAD, "Problem with ISO checksum choices: %s \n", optarg);
1519 fprintf(stderr, "Problem with ISO checksum choices: %s\n", optarg);
1526 case OPTION_JT_CHECKSUM_ALGO_TMPL:
1527 if (parse_checksum_algo(optarg, &checksum_algo_tmpl))
1529 #ifdef USE_LIBSCHILY
1530 comerrno(EX_BAD, "Problem with template checksum choices: %s \n", optarg);
1532 fprintf(stderr, "Problem with template checksum choices: %s\n", optarg);
1538 #endif /* JIGDO_TEMPLATE */
1543 do_sort++; /* We sort bootcat/botimage */
1545 boot_image = optarg; /* pathname of the boot image */
1547 if (boot_image == NULL) {
1548 #ifdef USE_LIBSCHILY
1550 "Required Eltorito boot image pathname missing\n");
1553 "Required Eltorito boot image pathname missing\n");
1558 current_boot_entry->boot_image = boot_image;
1560 case OPTION_ALT_BOOT:
1562 * Start new boot entry parameter list.
1566 case OPTION_BOOTALPHA:
1568 /* list of pathnames of boot images */
1569 add_boot_alpha_filename(optarg);
1571 case OPTION_HPPA_CMDLINE:
1573 add_boot_hppa_cmdline(optarg);
1575 case OPTION_HPPA_KERNEL_32:
1577 add_boot_hppa_kernel_32(optarg);
1579 case OPTION_HPPA_KERNEL_64:
1581 add_boot_hppa_kernel_64(optarg);
1583 case OPTION_HPPA_BOOTLOADER:
1585 add_boot_hppa_bootloader(optarg);
1587 case OPTION_HPPA_RAMDISK:
1589 /* list of pathnames of boot images */
1590 add_boot_hppa_ramdisk(optarg);
1592 case OPTION_BOOTMIPS:
1594 /* list of pathnames of boot images */
1595 add_boot_mips_filename(optarg);
1597 case OPTION_BOOTMIPSEL:
1599 add_boot_mipsel_filename(optarg);
1604 "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
1606 /* list of pathnames of boot images */
1607 scan_sparc_boot(optarg);
1609 case OPTION_SUNX86BOOT:
1612 "-sparc-boot and -sunx86-boot are mutual exclusive.\n");
1614 /* list of pathnames of boot images */
1615 scan_sunx86_boot(optarg);
1619 /* pathname of the boot image on disk */
1620 genboot_image = optarg;
1621 if (genboot_image == NULL) {
1622 #ifdef USE_LIBSCHILY
1624 "Required generic boot image pathname missing\n");
1627 "Required generic boot image pathname missing\n");
1632 case OPTION_SPARCLABEL:
1633 /* Sun disk label string */
1634 sparc_boot_label(optarg);
1636 case OPTION_SUNX86LABEL:
1637 /* Sun disk label string */
1638 sunx86_boot_label(optarg);
1642 /* pathname of the boot image on cd */
1643 boot_catalog = optarg;
1644 if (boot_catalog == NULL) {
1645 #ifdef USE_LIBSCHILY
1647 "Required boot catalog pathname missing\n");
1650 "Required boot catalog pathname missing\n");
1655 case OPTION_ABSTRACT:
1657 if (strlen(abstract) > 37) {
1658 #ifdef USE_LIBSCHILY
1660 "Abstract filename string too long\n");
1663 "Abstract filename string too long\n");
1670 if (strlen(appid) > 128) {
1671 #ifdef USE_LIBSCHILY
1673 "Application-id string too long\n");
1676 "Application-id string too long\n");
1683 if (strlen(biblio) > 37) {
1684 #ifdef USE_LIBSCHILY
1686 "Bibliographic filename string too long\n");
1689 "Bibliographic filename string too long\n");
1694 case OPTION_CACHE_INODES:
1697 case OPTION_NOCACHE_INODES:
1700 case OPTION_CHECK_OLDNAMES:
1703 case OPTION_CHECK_SESSION:
1706 merge_image = optarg;
1707 outfile = "/dev/null";
1709 * cdrecord_data is handled specially in multi.c
1710 * as we cannot write to all strings.
1711 * If genisoimage is called with -C xx,yy
1712 * our default is overwritten.
1714 /* cdrecord_data = "0,0";*/
1716 case OPTION_COPYRIGHT:
1718 if (strlen(copyright) > 37) {
1719 #ifdef USE_LIBSCHILY
1721 "Copyright filename string too long\n");
1724 "Copyright filename string too long\n");
1737 RR_relocation_depth = 32767;
1743 full_iso9660_filenames++;
1745 case OPTION_MAX_FILENAMES:
1746 iso9660_namelen = MAX_ISONAME_V1; /* allow 37 chars */
1747 full_iso9660_filenames++;
1748 omit_version_number++;
1753 case OPTION_ALLOW_LEADING_DOTS:
1754 allow_leading_dots++;
1757 case OPTION_LOG_FILE:
1761 merge_image = optarg;
1763 case OPTION_RELOC_ROOT:
1764 reloc_root = optarg;
1766 case OPTION_RELOC_OLD_ROOT:
1767 reloc_old_root = optarg;
1770 omit_version_number++;
1773 case OPTION_FORCE_RR:
1793 if (strlen(preparer) > 128) {
1794 #ifdef USE_LIBSCHILY
1795 comerrno(EX_BAD, "Preparer string too long\n");
1797 fprintf(stderr, "Preparer string too long\n");
1802 case OPTION_PRINT_SIZE:
1807 case OPTION_PUBLISHER:
1809 if (strlen(publisher) > 128) {
1810 #ifdef USE_LIBSCHILY
1812 "Publisher string too long\n");
1814 fprintf(stderr, "Publisher string too long\n");
1832 case OPTION_XA_RATIONALIZED:
1838 if (strcmp(optarg, "data") == 0)
1840 else if (strcmp(optarg, "xa1") == 0)
1842 else if (strcmp(optarg, "raw") == 0) {
1845 "Unsupported sector type '%s'.\n",
1850 #ifdef USE_LIBSCHILY
1851 errmsgno(EX_BAD, "Option -%c is reserved for future use.\n", c);
1853 fprintf(stderr, "Option -%c is reserved for future use.\n", c);
1858 case OPTION_NEW_DIR_MODE:
1863 new_dir_mode = strtol(optarg, &end, 8);
1864 if (!end || *end != 0 ||
1865 new_dir_mode < 0 || new_dir_mode > 07777) {
1866 #ifdef USE_LIBSCHILY
1867 comerrno(EX_BAD, "Bad mode for -new-dir-mode\n");
1869 fprintf(stderr, "Bad mode for -new-dir-mode\n");
1883 uid_to_use = strtol(optarg, &end, 0);
1884 if (!end || *end != 0) {
1885 #ifdef USE_LIBSCHILY
1886 comerrno(EX_BAD, "Bad value for -uid\n");
1888 fprintf(stderr, "Bad value for -uid\n");
1902 gid_to_use = strtol(optarg, &end, 0);
1903 if (!end || *end != 0) {
1904 #ifdef USE_LIBSCHILY
1905 comerrno(EX_BAD, "Bad value for -gid\n");
1907 fprintf(stderr, "Bad value for -gid\n");
1914 case OPTION_FILEMODE:
1917 rationalize_filemode++;
1921 filemode_to_use = strtol(optarg, &end, 8);
1922 if (!end || *end != 0 ||
1923 filemode_to_use < 0 || filemode_to_use > 07777) {
1924 #ifdef USE_LIBSCHILY
1925 comerrno(EX_BAD, "Bad mode for -file-mode\n");
1927 fprintf(stderr, "Bad mode for -file-mode\n");
1934 case OPTION_DIRMODE:
1937 rationalize_dirmode++;
1941 dirmode_to_use = strtol(optarg, &end, 8);
1942 if (!end || *end != 0 ||
1943 dirmode_to_use < 0 || dirmode_to_use > 07777) {
1944 #ifdef USE_LIBSCHILY
1945 comerrno(EX_BAD, "Bad mode for -dir-mode\n");
1947 fprintf(stderr, "Bad mode for -dir-mode\n");
1957 add_sort_list(optarg);
1959 #endif /* SORTING */
1961 case OPTION_SPLIT_OUTPUT:
1965 case OPTION_STREAM_FILE_NAME:
1966 stream_filename = optarg;
1969 case OPTION_STREAM_CD_SIZE:
1970 stream_media_size = atoi(optarg);
1975 if (strlen(system_id) > 32) {
1976 #ifdef USE_LIBSCHILY
1978 "System ID string too long\n");
1980 fprintf(stderr, "System ID string too long\n");
1985 case OPTION_TRANS_TBL:
1991 case OPTION_UCS_LEVEL:
1992 ucs_level = atoi(optarg);
1993 if (ucs_level < 1 || ucs_level > 3)
1994 comerrno(EX_BAD, "Illegal UCS Level %d, use 1..3.\n",
2009 case OPTION_USE_FILEVERSION:
2014 * Minimal (only truncation of 31+ characters)
2015 * translation of filenames.
2017 * Forces -l, -d, -N, -allow-leading-dots,
2018 * -relaxed-filenames,
2019 * -allow-lowercase, -allow-multidot
2021 * This is for HP-UX, which does not recognize ANY
2022 * extentions (Rock Ridge, Joliet), causing pain when
2023 * loading software. pfs_mount can be used to read the
2024 * extensions, but the untranslated filenames can be
2025 * read by the "native" cdfs mounter. Completely
2028 full_iso9660_filenames++; /* 31 chars */
2029 omit_period++; /* trailing dot */
2030 allow_leading_dots++;
2031 omit_version_number++;
2032 relaxed_filenames++; /* all chars */
2033 allow_lowercase++; /* even lowcase */
2034 allow_multidot++; /* > 1 dots */
2038 case OPTION_RELAXED_FILENAMES:
2039 relaxed_filenames++;
2042 case OPTION_ALLOW_LOWERCASE:
2046 case OPTION_ALLOW_MULTIDOT:
2050 case OPTION_ISO_TRANSLATE:
2056 if (strlen(volume_id) > 32) {
2057 #ifdef USE_LIBSCHILY
2059 "Volume ID string too long\n");
2062 "Volume ID string too long\n");
2069 if (strlen(volset_id) > 128) {
2070 #ifdef USE_LIBSCHILY
2072 "Volume set ID string too long\n");
2075 "Volume set ID string too long\n");
2080 case OPTION_VOLSET_SIZE:
2081 volume_set_size = atoi(optarg);
2082 if (volume_set_size <= 0) {
2083 #ifdef USE_LIBSCHILY
2085 "Illegal Volume Set Size %s\n", optarg);
2088 "Illegal Volume Set Size %s\n", optarg);
2092 if (volume_set_size > 1) {
2093 #ifdef USE_LIBSCHILY
2095 "Volume Set Size > 1 not yet supported\n");
2098 "Volume Set Size > 1 not yet supported\n");
2103 case OPTION_VOLSET_SEQ_NUM:
2104 volume_sequence_number = atoi(optarg);
2105 if (volume_sequence_number > volume_set_size) {
2106 #ifdef USE_LIBSCHILY
2108 "Volume set sequence number too big\n");
2111 "Volume set sequence number too big\n");
2121 #ifdef USE_LIBSCHILY
2123 "Transparent compression not supported with VMS\n");
2126 "Transparent compression not supported with VMS\n");
2130 transparent_compression++;
2136 * Somehow two options to do basically the same thing
2137 * got added somewhere along the way. The 'match'
2138 * code supports limited globbing, so this is the one
2139 * that got selected. Unfortunately the 'x' switch is
2140 * probably more intuitive.
2148 i_add_match(optarg);
2154 h_add_match(optarg);
2160 j_add_match(optarg);
2165 case OPTION_HIDE_TRANS_TBL:
2168 case OPTION_HIDE_RR_MOVED:
2174 case OPTION_PVERSION:
2176 printf("mkisofs 2.01 is not what you see here. This line is only a fake for too clever\n"
2177 "GUIs and other frontend applications. In fact, this program is:\n");
2178 printf("%s (%s)\n", version_string, HOST_SYSTEM);
2181 case OPTION_NOSPLIT_SL_COMPONENT:
2182 split_SL_component = 0;
2184 case OPTION_NOSPLIT_SL_FIELD:
2187 case OPTION_HARD_DISK_BOOT:
2191 current_boot_entry->hard_disk_boot = 1;
2193 case OPTION_NO_EMUL_BOOT:
2197 current_boot_entry->no_emul_boot = 1;
2199 case OPTION_NO_BOOT:
2203 current_boot_entry->not_bootable = 1;
2205 case OPTION_BOOT_LOAD_ADDR:
2211 val = strtol(optarg, &ptr, 0);
2212 if (*ptr || val < 0 || val >= 0x10000) {
2213 #ifdef USE_LIBSCHILY
2214 comerrno(EX_BAD, "Boot image load address invalid.\n");
2216 fprintf(stderr, "Boot image load address invalid.\n");
2223 current_boot_entry->load_addr = load_addr;
2225 case OPTION_BOOT_LOAD_SIZE:
2231 val = strtol(optarg, &ptr, 0);
2232 if (*ptr || val < 0 || val >= 0x10000) {
2233 #ifdef USE_LIBSCHILY
2235 "Boot image load size invalid.\n");
2238 "Boot image load size invalid.\n");
2245 current_boot_entry->load_size = load_size;
2247 case OPTION_BOOT_INFO_TABLE:
2251 current_boot_entry->boot_info_table = 1;
2254 case OPTION_HFS_TYPE:
2257 if (strlen(deftype) != 4) {
2258 #ifdef USE_LIBSCHILY
2260 "HFS default TYPE string has illegal length.\n");
2263 "HFS default TYPE string has illegal length.\n");
2268 case OPTION_HFS_CREATOR:
2269 defcreator = optarg;
2271 if (strlen(defcreator) != 4) {
2272 #ifdef USE_LIBSCHILY
2274 "HFS default CREATOR string has illegal length.\n");
2277 "HFS default CREATOR string has illegal length.\n");
2284 case OPTION_MAP_FILE:
2286 hfs_last = MAP_LAST;
2297 case OPTION_MACNAME:
2300 case OPTION_NOMACFILES:
2301 #ifdef USE_LIBSCHILY
2303 "Warning: -no-mac-files no longer used ... ignoring\n");
2306 "Warning: -no-mac-files no longer used ... ignoring\n");
2309 case OPTION_BOOT_HFS_FILE:
2310 hfs_boot_file = optarg;
2315 case OPTION_MAGIC_FILE:
2317 fprintf(stderr, "This program has been compiled without magic library support.\n"
2318 "Ignoring the -magic option.\n");
2320 magic_filename = optarg;
2321 hfs_last = MAG_LAST;
2323 case OPTION_AUTOSTART:
2328 afe_size = atoi(optarg);
2329 hfs_select |= DO_FEU;
2330 hfs_select |= DO_FEL;
2332 case OPTION_HFS_VOLID:
2333 hfs_volume_id = optarg;
2335 case OPTION_ROOT_INFO:
2338 case OPTION_ICON_POS:
2341 /* Mac/Unix types to include */
2343 hfs_select |= DO_CAP;
2346 hfs_select |= DO_NETA;
2349 hfs_select |= DO_DBL;
2353 hfs_select |= DO_ESH;
2356 hfs_select |= DO_FEU;
2357 hfs_select |= DO_FEL;
2361 hfs_select |= DO_SGI;
2364 hfs_select |= DO_MBIN;
2367 hfs_select |= DO_SGL;
2370 hfs_select |= DO_DAVE;
2373 hfs_select |= DO_SFM;
2376 hfs_select |= DO_XDBL;
2380 hfs_select |= DO_XHFS;
2381 #else /* IS_MACOS_X */
2382 #ifdef USE_LIBSCHILY
2384 "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
2385 #else /* USE_LIBSCHILY */
2387 "Warning: --osx-hfs only works on MacOS X ... ignoring\n");
2388 #endif /* USE_LIBSCHILY */
2389 #endif /* IS_MACOS_X */
2391 case OPTION_CREATE_DT:
2394 case OPTION_HFS_HIDE:
2395 hfs_add_match(optarg);
2397 case OPTION_HFS_LIST:
2398 hfs_add_list(optarg);
2400 case OPTION_HFS_INPUT_CHARSET:
2402 hfs_icharset = optarg;
2404 case OPTION_HFS_OUTPUT_CHARSET:
2405 hfs_ocharset = optarg;
2407 case OPTION_HFS_UNLOCK:
2410 case OPTION_HFS_BLESS:
2413 case OPTION_HFS_PARMS:
2414 hfs_parms = strdup(optarg);
2417 case OPTION_PREP_BOOT:
2419 if (use_prep_boot > 4 - use_chrp_boot) {
2420 #ifdef USE_LIBSCHILY
2422 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2425 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2429 /* pathname of the boot image on cd */
2430 prep_boot_image[use_prep_boot - 1] = optarg;
2431 if (prep_boot_image[use_prep_boot - 1] == NULL) {
2432 #ifdef USE_LIBSCHILY
2434 "Required PReP boot image pathname missing\n");
2437 "Required PReP boot image pathname missing\n");
2442 case OPTION_CHRP_BOOT:
2444 break; /* silently allow duplicates */
2446 if (use_prep_boot > 3) {
2447 #ifdef USE_LIBSCHILY
2449 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2452 "Maximum of 4 PRep+CHRP partition entries are allowed\n");
2457 #endif /* PREP_BOOT */
2458 #endif /* APPLE_HYB */
2459 case OPTION_ALLOW_LIMITED_SIZE:
2460 allow_limited_size++;
2467 * "--" was found, the next argument is a pathspec
2470 have_cmd_line_pathspec = 1;
2476 * XXX This is a hack until we have a decent separate name handling
2477 * XXX for UDF filenames.
2479 if (dvd_video && use_Joliet) {
2481 fprintf(stderr, "Warning: Disabling Joliet support for DVD-Video.\n");
2483 if (use_udf && !use_Joliet)
2487 if (strlen(preparer) > 128) {
2488 comerrno(EX_BAD, "Preparer string too long\n");
2492 if (strlen(publisher) > 128) {
2494 "Publisher string too long\n");
2497 if (stream_filename) {
2498 if (strlen(stream_filename) > MAX_ISONAME)
2500 "stream-file-name too long (%d), max is %d.\n",
2501 (int)strlen(stream_filename), (int)MAX_ISONAME);
2502 if (strchr(stream_filename, '/'))
2503 comerrno(EX_BAD, "Illegal character '/' in stream-file-name.\n");
2506 stream_filename = "STREAM.IMG;1";
2509 if (strlen(system_id) > 32) {
2511 "System ID string too long\n");
2516 if (use_RockRidge && (iso9660_namelen > MAX_ISONAME_V2_RR))
2517 iso9660_namelen = MAX_ISONAME_V2_RR;
2519 if (warn_violate) /* this one is enough for quiet mode, print others warnings only in more verbose modes */
2520 fprintf(stderr, "Warning: creating filesystem that does not conform to ISO-9660.\n");
2521 if (iso9660_level > 3 && verbose>0)
2522 fprintf(stderr, "Warning: Creating ISO-9660:1999 (version 2) filesystem.\n");
2523 if (iso9660_namelen > LEN_ISONAME && verbose>0)
2524 fprintf(stderr, "Warning: ISO-9660 filenames longer than %d may cause buffer overflows in the OS.\n",
2526 if (use_Joliet && !use_RockRidge && verbose>0) {
2528 "Warning: creating filesystem with Joliet extensions but without Rock Ridge\n"
2529 " extensions. It is highly recommended to add Rock Ridge.\n");
2531 if (transparent_compression && verbose>0) {
2532 fprintf(stderr, "Warning: using transparent compression. This is a nonstandard Rock Ridge\n");
2533 fprintf(stderr, " extension. The resulting filesystem can only be transparently\n");
2534 fprintf(stderr, " read on Linux. On other operating systems you need to call\n");
2535 fprintf(stderr, " mkzftree by hand to decompress the files.\n");
2537 if (transparent_compression && !use_RockRidge && verbose>0) {
2538 fprintf(stderr, "Warning: transparent decompression is a Linux Rock Ridge extension, but\n");
2539 fprintf(stderr, " creating filesystem without Rock Ridge attributes; files\n");
2540 fprintf(stderr, " will not be transparently decompressed.\n");
2542 if(follow_links && verbose>0)
2544 "Warning: -follow-links does not always work correctly; be careful.\n");
2546 init_unls(); /* Initialize UNICODE tables */
2548 /* initialize code tables from a file - if they exists */
2549 init_unls_file(icharset);
2550 init_unls_file(ocharset);
2552 init_unls_file(hfs_icharset);
2553 init_unls_file(hfs_ocharset);
2554 #endif /* APPLE_HYB */
2557 iconv_possible = !(iso9660_level >= 4 || ((ocharset &&
2558 strcmp(ocharset, icharset ? icharset : "")) &&
2559 use_RockRidge) || apple_ext || apple_hyb);
2561 setlocale(LC_CTYPE, "");
2563 if (icharset == NULL && iconv_possible) {
2564 char *charset = nl_langinfo(CODESET);
2565 /* set to detected value but only if it is not pure US-ASCII */
2566 if(charset) { /* workaround for SunOS, iconv is case-sensitive */
2568 charset = strdup(charset);
2569 for(t=charset;*t!='\0';t++)
2573 if(strcmp(charset, "ansi_x3.4-1968") != 0)
2576 if(icharset && verbose > 0)
2577 fprintf(stderr, "I: -input-charset not specified, using %s (detected in locale settings)\n",
2581 if(iconv_possible) {
2583 * don't care if initialization fails
2585 init_nls_iconv(icharset);
2586 init_nls_iconv(ocharset);
2590 if (icharset == NULL) {
2591 #if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
2592 in_nls = load_unls("cp437");
2594 in_nls = load_unls("iso8859-1");
2597 if (strcmp(icharset, "default") == 0)
2598 in_nls = load_unls_default();
2600 in_nls = load_unls(icharset);
2603 * set the output charset to the same as the input or the given output
2606 if (ocharset == NULL) {
2609 if (strcmp(ocharset, "default") == 0)
2610 out_nls = load_unls_default();
2612 out_nls = load_unls(ocharset);
2614 if (in_nls == NULL || out_nls == NULL) { /* Unknown charset specified */
2615 fprintf(stderr, "Unknown charset\nKnown charsets are:\n");
2616 list_unls(); /* List all known charset names */
2618 fprintf(stderr, "\nAdditional input charsets are available for Joliet through the iconv support."
2619 "\nRun \"iconv -l\" to display them. Iconv charsets cannot be used with HFS, Apple"
2620 "\nextension, ISO9660 version 2 or Rock Ridge.\n");
2627 if (hfs_icharset == NULL || strcmp(hfs_icharset, "mac-roman")) {
2628 hfs_inls = load_unls("cp10000");
2630 if (strcmp(hfs_icharset, "default") == 0)
2631 hfs_inls = load_unls_default();
2633 hfs_inls = load_unls(hfs_icharset);
2635 if (hfs_ocharset == NULL) {
2636 hfs_onls = hfs_inls;
2638 if (strcmp(hfs_ocharset, "default") == 0)
2639 hfs_onls = load_unls_default();
2640 else if (strcmp(hfs_ocharset, "mac-roman") == 0)
2641 hfs_onls = load_unls("cp10000");
2643 hfs_onls = load_unls(hfs_ocharset);
2646 if (hfs_inls == NULL || hfs_onls == NULL) {
2647 fprintf(stderr, "Unknown HFS charset\nKnown charsets are:\n");
2651 #endif /* APPLE_HYB */
2653 if (merge_image != NULL) {
2654 if (open_merge_image(merge_image) < 0) {
2655 /* Complain and die. */
2656 #ifdef USE_LIBSCHILY
2657 comerr("Unable to open previous session image '%s'.\n",
2661 "Unable to open previous session image '%s'.\n",
2667 /* We don't need root privilleges anymore. */
2668 #ifdef HAVE_SETREUID
2669 if (setreuid(-1, getuid()) < 0)
2672 if (seteuid(getuid()) < 0)
2674 if (setuid(getuid()) < 0)
2677 #ifdef USE_LIBSCHILY
2678 comerr("Panic cannot set back effective uid.\n");
2681 perror("Panic cannot set back effective uid.");
2687 #ifdef no_more_needed
2693 if (getrlimit(RLIMIT_DATA, &rlp) == -1)
2694 perror("Warning: getrlimit failed");
2696 rlp.rlim_cur = 33554432;
2697 if (setrlimit(RLIMIT_DATA, &rlp) == -1)
2698 perror("Warning: setrlimit failed");
2702 #endif /* no_more_needed */
2704 mem_start = (unsigned long) sbrk(0);
2708 * if the -hide-joliet option has been given, set the Joliet option
2710 if (!use_Joliet && j_ishidden())
2714 if (apple_hyb && apple_ext) {
2715 #ifdef USE_LIBSCHILY
2716 comerrno(EX_BAD, "Can't have both -apple and -hfs options");
2718 fprintf(stderr, "Can't have both -apple and -hfs options");
2723 * if -probe, -macname, any hfs selection and/or mapping file is given,
2724 * but no HFS option, then select apple_hyb
2726 if (!apple_hyb && !apple_ext) {
2727 if (*afpfile || probe || use_mac_name || hfs_select ||
2728 hfs_boot_file || magic_filename ||
2729 hfs_ishidden() || gen_pt || autoname ||
2730 afe_size || icon_pos || hfs_ct ||
2731 hfs_icharset || hfs_ocharset) {
2735 if (apple_ext && hfs_boot_file) {
2736 #ifdef USE_LIBSCHILY
2737 comerrno(EX_BAD, "Can't have -hfs-boot-file with -apple\n");
2739 fprintf(stderr, "Can't have -hfs-boot-file with -apple\n");
2743 if (apple_ext && autoname) {
2744 #ifdef USE_LIBSCHILY
2745 comerrno(EX_BAD, "Can't have -auto with -apple\n");
2747 fprintf(stderr, "Can't have -auto with -apple\n");
2751 if (apple_hyb && (use_sparcboot || use_sunx86boot)) {
2752 #ifdef USE_LIBSCHILY
2753 comerrno(EX_BAD, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
2755 fprintf(stderr, "Can't have -hfs with -sparc-boot/-sunx86-boot\n");
2760 if (do_largefiles) printf("Warning: cannot support large files with -hfs\n");
2762 maxnonlarge = (off_t)0x7FFFFFFF;
2764 if (apple_hyb && use_genboot) {
2765 #ifdef USE_LIBSCHILY
2766 comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n");
2768 fprintf(stderr, "Can't have -hfs with -generic-boot\n");
2773 if (apple_ext && use_prep_boot) {
2774 #ifdef USE_LIBSCHILY
2775 comerrno(EX_BAD, "Can't have -prep-boot with -apple\n");
2777 fprintf(stderr, "Can't have -prep-boot with -apple\n");
2781 #endif /* PREP_BOOT */
2783 if (apple_hyb || apple_ext)
2787 /* we need to search for all types of Apple/Unix files */
2790 if (apple_both && verbose && !(hfs_select || *afpfile || magic_filename)) {
2791 #ifdef USE_LIBSCHILY
2793 "Warning: no Apple/Unix files will be decoded/mapped\n");
2796 "Warning: no Apple/Unix files will be decoded/mapped\n");
2799 if (apple_both && verbose && !afe_size &&
2800 (hfs_select & (DO_FEU | DO_FEL))) {
2801 #ifdef USE_LIBSCHILY
2803 "Warning: assuming PC Exchange cluster size of 512 bytes\n");
2806 "Warning: assuming PC Exchange cluster size of 512 bytes\n");
2811 /* set up the TYPE/CREATOR mappings */
2812 hfs_init(afpfile, 0, hfs_select);
2814 if (apple_ext && !use_RockRidge) {
2816 /* use RockRidge to set the SystemUse field ... */
2823 if (apple_ext && !(use_XA || use_RockRidge)) {
2824 comerrno(EX_BAD, "Need either -XA/-xa or -R/-r for -apple to become active.\n");
2827 #endif /* APPLE_HYB */
2829 if (rationalize_all) {
2833 rationalize_filemode++;
2834 rationalize_dirmode++;
2838 fprintf(stderr, "%s (%s)\n", version_string, HOST_SYSTEM);
2840 if (cdrecord_data == NULL && !check_session && merge_image != NULL) {
2841 #ifdef USE_LIBSCHILY
2843 "Multisession usage bug: Must specify -C if -M is used.\n");
2846 "Multisession usage bug: Must specify -C if -M is used.\n");
2850 if (cdrecord_data != NULL && merge_image == NULL) {
2851 #ifdef USE_LIBSCHILY
2853 "Warning: -C specified without -M: old session data will not be merged.\n");
2856 "Warning: -C specified without -M: old session data will not be merged.\n");
2860 if (merge_image != NULL && apple_hyb) {
2861 #ifdef USE_LIBSCHILY
2863 "Warning: files from previous sessions will not be included in the HFS volume.\n");
2866 "Warning: files from previous sessions will not be included in the HFS volume.\n");
2869 #endif /* APPLE_HYB */
2872 * see if we have a list of pathnames to process
2875 /* "-" means take list from the standard input */
2876 if (strcmp(pathnames, "-")) {
2877 if ((pfp = fopen(pathnames, "r")) == NULL) {
2878 #ifdef USE_LIBSCHILY
2879 comerr("Unable to open pathname list %s.\n",
2883 "Unable to open pathname list %s.\n",
2892 /* The first step is to scan the directory tree, and take some notes */
2894 if ((arg = get_pnames(argc, argv, optind, pname,
2895 sizeof (pname), pfp)) == NULL) {
2896 if (check_session == 0 && !stream_media_size) {
2897 #ifdef USE_LIBSCHILY
2898 errmsgno(EX_BAD, "Missing pathspec.\n");
2905 * if we don't have a pathspec, then save the pathspec found
2906 * in the pathnames file (stored in pname) - we don't want
2907 * to skip this pathspec when we read the pathnames file again
2909 if (!have_cmd_line_pathspec && !stream_media_size) {
2912 if (stream_media_size) {
2913 if (use_XA || use_RockRidge || use_udf || use_Joliet)
2915 "Cannot use XA, Rock Ridge, UDF or Joliet with -stream-media-size\n");
2918 "Cannot use multi session with -stream-media-size\n");
2919 if (use_eltorito || use_sparcboot || use_sunx86boot ||
2920 use_genboot || use_prep_boot || hfs_boot_file)
2922 "Cannot use boot options with -stream-media-size\n");
2925 "Cannot use Apple hybrid options with -stream-media-size\n");
2928 if (use_RockRidge) {
2931 extension_record = generate_rr_extension_record("RRIP_1991A",
2932 "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
2933 "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.",
2934 &extension_record_size);
2936 extension_record = generate_rr_extension_record("IEEE_P1282",
2937 "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
2938 "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.",
2939 &extension_record_size);
2947 /* open log file - test that we can open OK */
2948 if ((lfp = fopen(log_file, "w")) == NULL) {
2949 #ifdef USE_LIBSCHILY
2950 comerr("Can't open logfile: '%s'.\n", log_file);
2952 fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
2958 /* redirect all stderr message to log_file */
2959 fprintf(stderr, "re-directing all messages to %s\n", log_file);
2962 /* associate stderr with the log file */
2963 if (freopen(log_file, "w", stderr) == NULL) {
2964 #ifdef USE_LIBSCHILY
2965 comerr("Can't open logfile: '%s'.\n", log_file);
2967 fprintf(stderr, "Can't open logfile: '%s'.\n", log_file);
2972 for (i = 0; i < argc; i++)
2973 fprintf(stderr, "%s ", argv[i]);
2975 fprintf(stderr, "\n%s (%s)\n",
2976 version_string, HOST_SYSTEM);
2979 /* Find name of root directory. */
2981 node = findgequal(arg);
2982 if (!use_graft_ptrs)
2985 if (use_graft_ptrs && arg != NULL)
2986 node = escstrcpy(nodename, arg);
2991 * Remove '\\' escape chars which are located
2992 * before '\\' and '=' chars
2994 node = escstrcpy(nodename, ++node);
2998 * See if boot catalog file exists in root directory, if not we will
3002 init_boot_catalog(node);
3005 * Find the device and inode number of the root directory. Record this
3006 * in the hash table so we don't scan it more than once.
3008 stat_filter(node, &statbuf);
3009 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
3011 memset(&de, 0, sizeof (de));
3015 * Isn't root NULL at this time anyway?
3016 * I think it is created by the first call to
3017 * find_or_create_directory() below.
3019 de.filedir = root; /* We need this to bootstrap */
3021 if (cdrecord_data != NULL && merge_image == NULL) {
3023 * in case we want to add a new session, but don't want to
3026 get_session_start(NULL);
3028 if (merge_image != NULL) {
3029 char sector[SECTOR_SIZE];
3032 mrootp = merge_isofs(merge_image);
3033 if (mrootp == NULL) {
3034 /* Complain and die. */
3035 #ifdef USE_LIBSCHILY
3038 comerr("Unable to find previous session PVD '%s'.\n",
3042 "Unable to find previous session PVD '%s'.\n",
3047 memcpy(de.isorec.extent, mrootp->extent, 8);
3050 * Look for RR Attributes in '.' entry of root dir.
3051 * This is the first ISO directory entry in the root dir.
3053 c = isonum_733((unsigned char *)mrootp->extent);
3055 readsecs(c, sector, 1);
3057 lseek(fileno(in_image), c*2048, SEEK_SET);
3058 read(fileno(in_image), sector, sizeof (sector));
3060 c = rr_flags((struct iso_directory_record *)sector);
3062 fprintf(stderr, "XA signatures found\n");
3064 fprintf(stderr, "AA signatures found\n");
3065 if (c & ~(RR_FLAG_XA|RR_FLAG_AA)) {
3066 if (c & RR_FLAG_SP) {
3067 fprintf(stderr, "Rock Ridge signatures found\n");
3069 fprintf(stderr, "Bad Rock Ridge signatures found (SU record missing)\n");
3074 fprintf(stderr, "NO Rock Ridge present\n");
3075 if ((c & (RR_FLAG_XA|RR_FLAG_AA)) == 0) {
3081 fprintf(stderr, "Disabling Rock Ridge / XA / AA\n");
3084 * Create an empty root directory. If we ever scan it for real,
3085 * we will fill in the contents.
3087 find_or_create_directory(NULL, "", &de, TRUE, NULL);
3090 /* may need to set window layout of the volume */
3092 set_root_info(root_info);
3093 #endif /* APPLE_HYB */
3096 merge_warn_msg="NOTE: multiple source directories have been specified and merged into the root\n"
3097 "of the filesystem. Check your program arguments. genisoimage is not tar.\n";
3100 * Scan the actual directory (and any we find below it) for files to
3101 * write out to the output image. Note - we take multiple source
3102 * directories and keep merging them onto the image.
3104 if (check_session == 0)
3105 while ((arg = get_pnames(argc, argv, optind, pname,
3106 sizeof (pname), pfp)) != NULL) {
3107 struct directory *graft_dir;
3111 char graft_point[PATH_MAX + 1];
3114 * We would like a syntax like:
3118 * where the user can specify a place to graft each component
3119 * of the tree. To do this, we may have to create directories
3120 * along the way, of course. Secondly, I would like to allow
3121 * the user to do something like:
3123 * /home/baz/RMAIL=/u3/users/baz/RMAIL
3125 * so that normal files could also be injected into the tree
3126 * at an arbitrary point.
3128 * The idea is that the last component of whatever is being
3129 * entered would take the name from the last component of
3130 * whatever the user specifies.
3132 * The default will be that the file is injected at the root of
3135 node = findgequal(arg);
3136 if (!use_graft_ptrs)
3139 * Remove '\\' escape chars which are located
3140 * before '\\' and '=' chars ---> below in escstrcpy()
3145 if (node != NULL || reloc_root) {
3151 /* insert -root prefix */
3152 if (reloc_root != NULL) {
3153 strcpy(graft_point, reloc_root);
3154 len = strlen(graft_point);
3155 if (graft_point[len] != '/') {
3156 graft_point[len++] = '/';
3157 graft_point[len] = '\0';
3165 escstrcpy(&graft_point[len], arg);
3170 * Remove unwanted "./" & "/" sequences from start...
3174 while (xpnt[0] == '.' && xpnt[1] == '/')
3176 while (*xpnt == PATH_SEPARATOR) {
3179 memmove(graft_point, xpnt, strlen(xpnt)+1);
3180 } while (xpnt > graft_point);
3183 node = escstrcpy(nodename, ++node);
3192 * If "node" points to a directory, then graft_point
3193 * needs to point to a directory too.
3196 status = stat_filter(node, &st);
3198 status = lstat_filter(node, &st);
3200 node_is_dir = S_ISDIR(st.st_mode);
3201 if (status == 0 && node_is_dir) {
3202 len = strlen(graft_point);
3204 if ((len <= (sizeof (graft_point) -1)) &&
3205 graft_point[len-1] != '/') {
3206 graft_point[len++] = '/';
3207 graft_point[len] = '\0';
3211 fprintf(stderr, "GRAFT:'%s'\n", xpnt);
3213 * Loop down deeper and deeper until we find the
3214 * correct insertion spot.
3215 * Canonicalize the filename while parsing it.
3218 struct stat* stat_template;
3221 while (xpnt[0] == '.' && xpnt[1] == '/')
3223 while (xpnt[0] == '/')
3225 if (xpnt[0] == '.' && xpnt[1] == '.' && xpnt[2] == '/') {
3226 if (graft_dir && graft_dir != root) {
3227 graft_dir = graft_dir->parent;
3231 } while ((xpnt[0] == '/') || (xpnt[0] == '.' && xpnt[1] == '/'));
3232 pnt = strchr(xpnt, PATH_SEPARATOR);
3234 if (*xpnt != '\0') {
3241 fprintf(stderr, "GRAFT Point:'%s' in '%s : %s' (%s)\n",
3243 graft_dir->whole_name,
3248 * If the node being grafted is a
3249 * directory, then we want the last
3250 * directory in this graft chain to have
3251 * the ownership and permissions of the
3252 * source node. Other directories in the
3253 * chain get default ownership and
3257 (pnt[1] == '\0' && node_is_dir) ? &st : 0;
3259 graft_dir = find_or_create_directory(graft_dir,
3260 graft_point, NULL, TRUE,
3263 *pnt = PATH_SEPARATOR;
3269 node = escstrcpy(nodename, arg);
3275 * Get information on the node
3278 status = stat_filter(node, &st);
3280 status = lstat_filter(node, &st);
3283 * This is a fatal error - the user won't be getting
3284 * what they want if we were to proceed.
3286 #ifdef USE_LIBSCHILY
3287 comerr("Invalid node - '%s'.\n", node);
3289 fprintf(stderr, "Invalid node - '%s'.\n", node);
3294 * Now see whether the user wants to add a regular
3295 * file or a directory at this point.
3297 if (S_ISDIR(st.st_mode)) {
3299 fprintf(stderr, "graft_dir: '%s : %s', node: '%s', (scan)\n",
3300 graft_dir->whole_name,
3301 graft_dir->de_name, node);
3303 if (!scan_directory_tree(graft_dir,
3308 fprintf(stderr, "scan done\n");
3311 if (short_name == NULL) {
3312 short_name = strrchr(node,
3314 if (short_name == NULL ||
3315 short_name < node) {
3322 fprintf(stderr, "graft_dir: '%s : %s', node: '%s', short_name: '%s'\n",
3323 graft_dir->whole_name,
3324 graft_dir->de_name, node,
3328 if (!insert_file_entry(graft_dir, node,
3331 if (!insert_file_entry(graft_dir, node,
3333 #endif /* APPLE_HYB */
3336 * Should we ignore this?
3348 if (pfp && pfp != stdin)
3352 * exit if we don't have any pathnames to process
3353 * - not going to happen at the moment as we have to have at least one
3354 * path on the command line
3356 if (no_path_names && !check_session && !stream_media_size) {
3357 #ifdef USE_LIBSCHILY
3358 errmsgno(EX_BAD, "No pathnames found.\n");
3363 * Now merge in any previous sessions. This is driven on the source
3364 * side, since we may need to create some additional directories.
3366 if (merge_image != NULL) {
3367 if (merge_previous_session(root, mrootp,
3368 reloc_root, reloc_old_root) < 0) {
3369 #ifdef USE_LIBSCHILY
3370 comerrno(EX_BAD, "Cannot merge previous session.\n");
3372 fprintf(stderr, "Cannot merge previous session.\n");
3376 close_merge_image();
3379 * set up parent_dir and filedir in relocated entries which
3380 * were read from previous session so that
3381 * finish_cl_pl_entries can do its job
3383 match_cl_re_entries();
3386 /* free up any HFS filename mapping memory */
3389 #endif /* APPLE_HYB */
3391 /* hide "./rr_moved" if all its contents have been hidden */
3392 if (reloc_dir && i_ishidden())
3395 /* insert the boot catalog if required */
3400 * Free up any matching memory
3402 for (n = 0; n < MAX_MAT; n++)
3407 #endif /* SORTING */
3410 * Sort the directories in the required order (by ISO9660). Also,
3411 * choose the names for the 8.3 filesystem if required, and do any
3412 * other post-scan work.
3414 goof += sort_tree(root);
3417 fprintf(stderr, "ISO9660/Rock Ridge tree sort failed.\n");
3419 fprintf(stderr, merge_warn_msg);
3423 if (use_Joliet || use_udf) {
3427 goof += joliet_sort_tree(root);
3430 fprintf(stderr, "Joliet tree sort failed. The -joliet-long switch may help you.\n");
3432 fprintf(stderr, merge_warn_msg);
3436 * Fix a couple of things in the root directory so that everything is
3437 * self consistent. Fix this up so that the path tables get done right.
3439 root->self = root->contents;
3441 /* OK, ready to write the file. Open it up, and generate the thing. */
3443 discimage = fopen("/dev/null", "wb");
3445 #ifdef USE_LIBSCHILY
3446 comerr("Unable to open /dev/null\n");
3448 fprintf(stderr, "Unable to open /dev/null\n");
3452 } else if (outfile && (strcmp (outfile, "-")) != 0) {
3453 discimage = fopen(outfile, "wb");
3455 #ifdef USE_LIBSCHILY
3456 comerr("Unable to open disc image file '%s'.\n", outfile);
3458 fprintf(stderr, "Unable to open disc image file '%s'.\n", outfile);
3462 if (jtemplate_out || jjigdo_out) {
3463 if (!jtemplate_out || !jjigdo_out || !jmd5_list) {
3464 #ifdef USE_LIBSCHILY
3465 comerr("Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
3467 fprintf(stderr, "Bad options - need to specify output names for jigdo and template file, and also the md5-list input file!\n");
3471 jtjigdo = fopen(jjigdo_out, "wb");
3472 jttemplate = fopen(jtemplate_out, "wb");
3473 if (!jtjigdo || !jttemplate) {
3474 #ifdef USE_LIBSCHILY
3475 comerr("Unable to open jigdo template image file\n");
3477 fprintf(stderr, "Unable to open jigdo template image file\n");
3481 write_jt_header(jttemplate, jtjigdo);
3483 } else if ((outfile == NULL)
3484 && isatty (fileno (stdout))) {
3485 /* FIXME: a cleaner way to override this check? */
3486 fputs (("image not written to a terminal.\n"
3487 "Use -o - to force the output.\n"),
3493 #ifdef NEED_O_BINARY
3494 setmode(fileno(stdout), O_BINARY);
3498 /* Now assign addresses on the disc for the path table. */
3500 path_blocks = ISO_BLOCKS(path_table_size);
3501 if (path_blocks & 1)
3504 jpath_blocks = ISO_BLOCKS(jpath_table_size);
3505 if (jpath_blocks & 1)
3509 * Start to set up the linked list that we use to track the contents
3514 if (apple_hyb || use_prep_boot || use_chrp_boot)
3515 #else /* PREP_BOOT */
3517 #endif /* PREP_BOOT */
3518 outputlist_insert(&hfs_desc);
3519 #endif /* APPLE_HYB */
3520 if (use_sparcboot || use_sunx86boot)
3521 outputlist_insert(&sunlabel_desc);
3523 outputlist_insert(&alphaboot_desc);
3525 outputlist_insert(&hppaboot_desc);
3526 if (use_alphaboot || use_hppaboot)
3527 outputlist_insert(&alpha_hppa_boot_desc);
3529 outputlist_insert(&mipsboot_desc);
3531 outputlist_insert(&mipselboot_desc);
3533 outputlist_insert(&genboot_desc);
3534 outputlist_insert(&startpad_desc);
3537 outputlist_insert(&voldesc_desc);
3539 /* SVD for El Torito. MUST be immediately after the PVD! */
3541 outputlist_insert(&torito_desc);
3543 /* Enhanced PVD for disc. neded if we write ISO-9660:1999 */
3544 if (iso9660_level > 3)
3545 outputlist_insert(&xvoldesc_desc);
3547 /* SVD for Joliet. */
3549 outputlist_insert(&joliet_desc);
3551 /* Finally the last volume descriptor. */
3552 outputlist_insert(&end_vol);
3556 outputlist_insert(&udf_vol_recognition_area_frag);
3560 /* Insert the version descriptor. */
3561 outputlist_insert(&version_desc);
3566 * Most of the space before sector 256 is wasted when
3567 * UDF is turned on. The waste could be reduced by
3568 * putting the ISO9660/Joliet structures before the
3569 * pad_to_sector_256; the problem is that they might
3570 * overshoot sector 256, so there would have to be some
3571 * ugly logic to detect this case and rearrange things
3572 * appropriately. I don't know if it's worth it.
3574 outputlist_insert(&udf_pad_to_sector_32_frag);
3575 outputlist_insert(&udf_main_seq_frag);
3576 outputlist_insert(&udf_main_seq_copy_frag);
3577 outputlist_insert(&udf_integ_seq_frag);
3578 outputlist_insert(&udf_pad_to_sector_256_frag);
3579 outputlist_insert(&udf_anchor_vol_desc_frag);
3580 outputlist_insert(&udf_file_set_desc_frag);
3581 outputlist_insert(&udf_dirtree_frag);
3582 outputlist_insert(&udf_file_entries_frag);
3586 /* Now start with path tables and directory tree info. */
3587 if (!stream_media_size)
3588 outputlist_insert(&pathtable_desc);
3590 outputlist_insert(&strpath_desc);
3593 outputlist_insert(&jpathtable_desc);
3596 if (!stream_media_size)
3597 outputlist_insert(&dirtree_desc);
3600 outputlist_insert(&jdirtree_desc);
3602 outputlist_insert(&dirtree_clean);
3604 if (extension_record) {
3605 outputlist_insert(&extension_desc);
3608 if (!stream_media_size) {
3609 outputlist_insert(&files_desc);
3611 outputlist_insert(&strfile_desc);
3612 outputlist_insert(&strdir_desc);
3616 * Allow room for the various headers we will be writing.
3617 * There will always be a primary and an end volume descriptor.
3619 last_extent = session_start;
3622 * Calculate the size of all of the components of the disc, and assign
3625 for (opnt = out_list; opnt; opnt = opnt->of_next) {
3626 opnt->of_start_extent = last_extent;
3627 if (opnt->of_size != NULL) {
3628 (*opnt->of_size) (last_extent);
3633 * Generate the contents of any of the sections that we want to
3634 * generate. Not all of the fragments will do anything here
3635 * - most will generate the data on the fly when we get to the write
3638 for (opnt = out_list; opnt; opnt = opnt->of_next) {
3639 if (opnt->of_generate != NULL) {
3640 (*opnt->of_generate) ();
3645 * Padding just after the ISO-9660 filesystem.
3647 * files_desc does not have an of_size function. For this
3648 * reason, we must insert us after the files content has been
3653 /* Single anchor volume descriptor pointer at end */
3654 outputlist_insert(&udf_end_anchor_vol_desc_frag);
3655 if (udf_end_anchor_vol_desc_frag.of_size != NULL) {
3656 (*udf_end_anchor_vol_desc_frag.of_size) (last_extent);
3660 * Pad with anchor volume descriptor pointer
3661 * blocks instead of zeroes.
3663 outputlist_insert(&udf_padend_avdp_frag);
3664 if (udf_padend_avdp_frag.of_size != NULL) {
3665 (*udf_padend_avdp_frag.of_size) (last_extent);
3670 if (dopad && !(use_sparcboot || use_sunx86boot)) {
3671 outputlist_insert(&endpad_desc);
3672 if (endpad_desc.of_size != NULL) {
3673 (*endpad_desc.of_size) (last_extent);
3677 if (use_sparcboot) {
3679 /* Padding before the boot partitions. */
3680 outputlist_insert(&interpad_desc);
3681 if (interpad_desc.of_size != NULL) {
3682 (*interpad_desc.of_size) (last_extent);
3685 c = make_sun_label();
3687 outputlist_insert(&sunboot_desc);
3689 outputlist_insert(&endpad_desc);
3690 if (endpad_desc.of_size != NULL) {
3691 (*endpad_desc.of_size) (last_extent);
3694 } else if (use_sunx86boot) {
3696 /* Padding before the boot partitions. */
3697 outputlist_insert(&interpad_desc);
3698 if (interpad_desc.of_size != NULL) {
3699 (*interpad_desc.of_size) (last_extent);
3702 c = make_sunx86_label();
3704 outputlist_insert(&sunboot_desc);
3706 outputlist_insert(&endpad_desc);
3707 if (endpad_desc.of_size != NULL) {
3708 (*endpad_desc.of_size) (last_extent);
3712 if (print_size > 0) {
3715 "Total extents scheduled to be written = %u\n",
3716 (last_extent - session_start));
3717 printf("%u\n", (last_extent - session_start));
3721 * Now go through the list of fragments and write the data that
3722 * corresponds to each one.
3724 for (opnt = out_list; opnt; opnt = opnt->of_next) {
3727 oext = last_extent_written;
3728 if (opnt->of_start_extent != 0 &&
3729 opnt->of_start_extent != last_extent_written) {
3731 * Consistency check.
3732 * XXX Should make sure that all entries have
3733 * XXXX of_start_extent set up correctly.
3736 "Implementation botch: %s should start at %u but starts at %u.\n",
3737 opnt->of_name, opnt->of_start_extent, last_extent_written);
3739 if (opnt->of_write != NULL) {
3741 fprintf(stderr, "Writing: %-40sStart Block %u\n",
3742 opnt->of_name, last_extent_written);
3743 (*opnt->of_write) (discimage);
3745 fprintf(stderr, "Done with: %-40sBlock(s) %u\n",
3746 opnt->of_name, last_extent_written-oext);
3749 if (last_extent != last_extent_written) {
3751 "Implementation botch: FS should end at %u but ends at %u.\n",
3752 last_extent, last_extent_written);
3764 fprintf(stderr, "Max brk space used %x\n",
3765 (unsigned int)(((unsigned long) sbrk(0)) - mem_start));
3767 fprintf(stderr, "%u extents written (%u MB)\n",
3768 last_extent, last_extent >> 9);
3778 * Find unescaped equal sign in graft pointer string.
3785 while ((p = strchr(p, '=')) != NULL) {
3786 if (p > s && p[-1] != '\\')
3794 * Find unescaped equal sign in string.
3797 escstrcpy(char *to, char *from)
3802 fprintf(stderr, "FROM: '%s'\n", from);
3804 while ((*p = *from++) != '\0') {
3806 if ((*p = *from++) == '\0')
3808 if (*p != '\\' && *p != '=') {
3816 fprintf(stderr, "ESC: '%s'\n", to);
3821 e_malloc(size_t size)
3825 if ((size > 0) && ((pt = malloc(size)) == NULL)) {
3826 #ifdef USE_LIBSCHILY
3827 comerr("Not enough memory\n");
3829 fprintf(stderr, "Not enough memory\n");
3834 * Not all code is clean yet.
3835 * Filling all allocated data with zeroes will help
3836 * to avoid core dumps.
3838 if (size > 0) /* a workaround for gcc bug gcc.gnu.org/PR25639 */
3839 memset(pt, 0, size);