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