/[debburn]/nonameyet/trunk/mkisofs/mkisofs.c
ViewVC logotype

Contents of /nonameyet/trunk/mkisofs/mkisofs.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5