[MKISOFS]
[reactos.git] / reactos / sdk / tools / mkisofs / schilytools / mkisofs / mkisofs.c
1 /* @(#)mkisofs.c 1.284 16/10/23 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)mkisofs.c 1.284 16/10/23 joerg";
6 #endif
7 /*
8 * Program mkisofs.c - generate iso9660 filesystem based upon directory
9 * tree on hard disk.
10 *
11 * Written by Eric Youngdale (1993).
12 *
13 * Copyright 1993 Yggdrasil Computing, Incorporated
14 * Copyright (c) 1997-2016 J. Schilling
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2, or (at your option)
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30
31 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 22/2/2000 */
32 /* MAC UDF images by HELIOS Software GmbH support@helios.de */
33 /* HFS+ by HELIOS Software GmbH support@helios.de */
34
35 #ifdef USE_FIND
36 #include <schily/walk.h>
37 #include <schily/find.h>
38 #endif
39 #include "mkisofs.h"
40 #include "rock.h"
41 #include <schily/errno.h>
42 #include <schily/time.h>
43 #include <schily/fcntl.h>
44 #include <schily/ctype.h>
45 #include "match.h"
46 #include <schily/schily.h>
47 #include <schily/nlsdefs.h>
48 #include <schily/checkerr.h>
49 #ifdef UDF
50 #include "udf.h"
51 #endif
52
53 #include <schily/io.h> /* for setmode() prototype */
54 #include <schily/getargs.h>
55
56 #ifdef VMS
57 #include "vms.h"
58 #endif
59
60 #ifdef no_more_needed
61 #include <schily/resource.h>
62 #endif /* no_more_needed */
63
64 #include "../cdrecord/version.h"
65
66 struct directory *root = NULL;
67 int path_ind;
68
69 char version_string[] = VERSION;
70
71 char *outfile;
72 FILE *discimage;
73 UInt32_t next_extent = 0;
74 UInt32_t last_extent = 0;
75 UInt32_t session_start = 0;
76 unsigned int path_table_size = 0;
77 unsigned int path_table[4] = {0, };
78 unsigned int path_blocks = 0;
79
80
81 unsigned int jpath_table_size = 0;
82 unsigned int jpath_table[4] = {0, };
83 unsigned int jpath_blocks = 0;
84
85 struct iso_directory_record root_record;
86 struct iso_directory_record jroot_record;
87
88 char *extension_record = NULL;
89 UInt32_t extension_record_extent = 0;
90 int extension_record_size = 0;
91 BOOL archive_isreg;
92 dev_t archive_dev;
93 ino_t archive_ino;
94
95 /* These variables are associated with command line options */
96 int check_oldnames = 0;
97 int check_session = 0;
98 int use_eltorito = 0;
99 int hard_disk_boot = 0;
100 int not_bootable = 0;
101 int no_emul_boot = 0;
102 int load_addr = 0;
103 int load_size = 0;
104 int boot_info_table = 0;
105 int use_sparcboot = 0;
106 int use_sunx86boot = 0;
107 int use_genboot = 0;
108 int use_RockRidge = 0;
109 int use_XA = 0;
110 int osecsize = 0; /* Output-sector size, 0 means default secsize 2048 */
111 int use_Joliet = 0;
112 int jlen = JMAX; /* maximum Joliet file name length */
113 /*
114 * Verbose levels currently used:
115 *
116 * 1+ Boot information
117 * 1+ Rcfile information
118 * 1+ Name mapping information
119 * 1+ Progress information
120 * 2+ Version informaton
121 * 2+ Output Extent (of_write) information
122 * 2+ PReP boot information
123 * 3+ HFS warnings
124 * 3+ Dump dirtree
125 */
126 int verbose = 1;
127 int debug = 0;
128 int gui = 0;
129 BOOL legacy = FALSE; /* Implement legacy support for historic CLI */
130 int all_files = 1; /* New default is to include all files */
131 BOOL Hflag = FALSE; /* Follow links on cmdline (-H) */
132 BOOL follow_links = FALSE; /* Follow all links (-L) */
133 #if defined(IS_CYGWIN) || defined(__MINGW32__) || defined(_MSC_VER)
134 /*
135 * Do not cache inodes on Cygwin by default
136 * See below in main(), cache for 64bit ino_t
137 */
138 int cache_inodes = 0;
139 #else
140 int cache_inodes = 1; /* Cache inodes if OS has unique inodes */
141 #endif
142 int rationalize = 0; /* Need to call stat_fix() */
143 int rationalize_uid = 0;
144 int rationalize_gid = 0;
145 int rationalize_filemode = 0;
146 int rationalize_dirmode = 0;
147 uid_t uid_to_use = 0; /* when rationalizing uid */
148 gid_t gid_to_use = 0; /* when rationalizing gid */
149 int filemode_to_use = 0; /* if non-zero, when rationalizing file mode */
150 int dirmode_to_use = 0; /* if non-zero, when rationalizing dir mode */
151 int new_dir_mode = 0555; /* neither -new-dir-mode nor -dir-mode used */
152 int generate_tables = 0;
153 int dopad = 1; /* Now default to do padding */
154 int print_size = 0;
155 int split_output = 0;
156 char *icharset = NULL; /* input charset to convert to UNICODE */
157 char *ocharset = NULL; /* output charset to convert from UNICODE */
158 char *preparer = PREPARER_DEFAULT;
159 char *publisher = PUBLISHER_DEFAULT;
160 char *appid = APPID_DEFAULT;
161 char *copyright = COPYRIGHT_DEFAULT;
162 char *biblio = BIBLIO_DEFAULT;
163 char *abstract = ABSTRACT_DEFAULT;
164 char *volset_id = VOLSET_ID_DEFAULT;
165 char *volume_id = VOLUME_ID_DEFAULT;
166 char *system_id = SYSTEM_ID_DEFAULT;
167 char *boot_catalog;
168 char *boot_image = BOOT_IMAGE_DEFAULT;
169 char *genboot_image = BOOT_IMAGE_DEFAULT;
170 int ucs_level = 3; /* We now have Unicode tables so use level 3 */
171 int volume_set_size = 1;
172 int volume_sequence_number = 1;
173 /* -------------------------------------------------------------------------- */
174 char *merge_image; /* CLI Parameter for -M option */
175 char *check_image; /* CLI Parameter for -check-session option */
176 char *reloc_root = NULL; /* CLI Parameter for -root option */
177 char *reloc_old_root = NULL; /* CLI Parameter for -oldroot option */
178 extern char *cdrecord_data; /* CLI Parameter for -C option */
179 int disable_deep_reloc; /* CLI Parameter for -D option */
180 char *dirmode_str; /* CLI Parameter for -dir-mode option */
181 char *filemode_str; /* CLI Parameter for -file-mode option */
182 char *gid_str; /* CLI Parameter for -gid option */
183 int help; /* CLI Parameter for -help option */
184 int joliet_long; /* CLI Parameter for -joliet-long option */
185 char *jcharset; /* CLI Parameter for -jcharset option */
186 int max_filenames; /* CLI Parameter for -max-iso9660-filenames option */
187 char *log_file; /* CLI Parameter for -log-file option */
188 char *new_dirmode_str; /* CLI Parameter for -new-dir-mode option */
189 char *pathnames; /* CLI Parameter for -help option */
190 int rationalize_rr; /* CLI Parameter for -path-list option */
191 char *sectype; /* CLI Parameter for -s option */
192 char *uid_str; /* CLI Parameter for -uid option */
193 int untranslated_filenames; /* CLI Parameter for -U option */
194 int pversion; /* CLI Parameter for -version option */
195 int rationalize_xa; /* CLI Parameter for -xa option */
196 ldate modification_date; /* CLI Parameter for -modification-date */
197 #ifdef APPLE_HYB
198 char *afpfile = ""; /* CLI Parameter for -map option */
199 char *root_info; /* CLI Parameter for -root-info option */
200 #endif
201 BOOL nodesc = FALSE; /* Whether not to descend directories */
202 #ifdef USE_FIND
203 BOOL dofind = FALSE; /* -find option found */
204 int find_ac = 0; /* ac past -find option */
205 char *const *find_av = NULL; /* av past -find option */
206 int find_pac = 0; /* ac for first find primary */
207 char *const *find_pav = NULL; /* av for first find primary */
208 findn_t *find_node; /* syntaxtree from find_parse() */
209 void *plusp; /* residual for -exec ...{} + */
210 int find_patlen; /* len for -find pattern state */
211
212 LOCAL int walkflags = WALK_CHDIR | WALK_PHYS | WALK_NOEXIT;
213 LOCAL int maxdepth = -1;
214 LOCAL int mindepth = -1;
215 EXPORT struct WALK walkstate;
216 #else
217 LOCAL int walkflags = 0;
218 #endif
219
220 extern time_t begun;
221 extern struct timeval tv_begun;
222
223 LOCAL BOOL data_change_warn;
224
225 struct eltorito_boot_entry_info *first_boot_entry = NULL;
226 struct eltorito_boot_entry_info *last_boot_entry = NULL;
227 struct eltorito_boot_entry_info *current_boot_entry = NULL;
228
229 int use_graft_ptrs; /* Use graft points */
230 int jhide_trans_tbl; /* Hide TRANS.TBL from Joliet tree */
231 int hide_rr_moved; /* Name RR_MOVED .rr_moved in Rock Ridge tree */
232 int omit_period = 0; /* Violates iso9660, but these are a pain */
233 int transparent_compression = 0; /* So far only works with linux */
234 int omit_version_number = 0; /* May violate iso9660, but noone uses vers */
235 int no_rr = 0; /* Do not use RR attributes from old session */
236 int force_rr = 0; /* Force to use RR attributes from old session */
237 Uint RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
238 int do_largefiles = 0; /* Whether to allow multi-extent files */
239 off_t maxnonlarge = (off_t)0xFFFFFFFF;
240 int iso9660_level = 1;
241 int iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */
242 int full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */
243 int nolimitpathtables = 0; /* Don't limit size of pathtable. Violates iso9660 */
244 int relaxed_filenames = 0; /* For Amiga. Disc will not work with DOS */
245 int allow_lowercase = 0; /* Allow lower case letters */
246 int allow_multidot = 0; /* Allow more than on dot in filename */
247 int iso_translate = 1; /* 1 == enables '#', '-' and '~' removal */
248 int allow_leading_dots = 0; /* DOS cannot read names with leading dots */
249 #ifdef VMS
250 int use_fileversion = 1; /* Use file version # from filesystem */
251 #else
252 int use_fileversion = 0; /* Use file version # from filesystem */
253 #endif
254 int split_SL_component = 1; /* circumvent a bug in the SunOS driver */
255 int split_SL_field = 1; /* circumvent a bug in the SunOS */
256 char *trans_tbl; /* default name for translation table */
257 int stream_media_size = 0; /* # of blocks on the media */
258 char *stream_filename; /* Default stream file name */
259
260 #ifdef APPLE_HYB
261 int donotwrite_macpart = 0; /* Do not write "hfs" hybrid with UDF */
262 int apple_hyb = 0; /* -hfs HFS hybrid flag */
263 int no_apple_hyb = 0; /* -no-hfs HFS hybrid flag */
264 int apple_ext = 0; /* create HFS extensions flag */
265 int apple_both = 0; /* common flag (for above) */
266 int hfs_extra = 0; /* extra HFS blocks added to end of ISO vol */
267 int use_mac_name = 0; /* use Mac name for ISO/Joliet/RR flag */
268 hce_mem *hce; /* libhfs/mkisofs extras */
269 char *hfs_boot_file = 0; /* name of HFS boot file */
270 int gen_pt = 0; /* generate HFS partition table */
271 char *autoname = 0; /* AutoStart filename */
272 char *magic_file = 0; /* name of magic file */
273 int probe = 0; /* search files for HFS/Unix type */
274 int nomacfiles = 0; /* don't look for Mac/Unix files */
275 int hfs_select = 0; /* Mac/Unix types to select */
276 int create_dt = 1; /* create the Desktp files */
277 int afe_size = 0; /* Apple File Exchange block size */
278 int hfs_last = MAG_LAST; /* process magic file after map file */
279 char *deftype; /* default Apple TYPE */
280 char *defcreator; /* default Apple CREATOR */
281 char *hfs_volume_id = NULL; /* HFS volume ID */
282 int icon_pos = 0; /* Keep icon position */
283 char *hfs_icharset = NULL; /* input HFS charset name */
284 char *hfs_ocharset = NULL; /* output HFS charset name */
285 int hfs_lock = 1; /* lock HFS volume (read-only) */
286 char *hfs_bless = NULL; /* name of folder to 'bless' (System Folder) */
287 char *hfs_parms = NULL; /* low level HFS parameters */
288
289 #ifdef PREP_BOOT
290 char *prep_boot_image[4];
291 int use_prep_boot = 0;
292 int use_chrp_boot = 0;
293 #endif /* PREP_BOOT */
294 #else /* APPLE_HYB */
295 int donotwrite_macpart = 1; /* Do not write "hfs" hybrid with UDF */
296 #endif /* APPLE_HYB */
297
298 #ifdef UDF
299 int rationalize_udf = 0; /* -udf (rationalized UDF) */
300 int use_udf = 0; /* -udf or -UDF */
301 int create_udfsymlinks = 1; /* include symlinks in UDF */
302 #endif
303
304 #ifdef DVD_AUD_VID
305 int dvd_audio = 0;
306 int dvd_hybrid = 0;
307 int dvd_video = 0;
308 int dvd_aud_vid_flag = DVD_SPEC_NONE;
309 #endif
310
311 #ifdef SORTING
312 int do_sort = 0; /* sort file data */
313 #endif /* SORTING */
314
315 /*
316 * inode numbers for zero sized files start from this number and count
317 * backwards. This is done to allow unique inode numbers even on multi-session
318 * disks.
319 */
320 UInt32_t null_inodes = NULL_INO_MAX;
321 BOOL correct_inodes = TRUE; /* TRUE: add a "correct inodes" fingerprint */
322 BOOL rrip112 = TRUE; /* TRUE: create Rock Ridge V 1.12 */
323 BOOL long_rr_time = FALSE; /* TRUE: use long (17 Byte) time format */
324
325 siconvt_t *in_nls = NULL; /* input UNICODE conversion table */
326 siconvt_t *out_nls = NULL; /* output UNICODE conversion table */
327 #ifdef APPLE_HYB
328 siconvt_t *hfs_inls = NULL; /* input HFS UNICODE conversion table */
329 siconvt_t *hfs_onls = NULL; /* output HFS UNICODE conversion table */
330 #endif /* APPLE_HYB */
331
332 struct rcopts {
333 char *tag;
334 char **variable;
335 };
336
337 struct rcopts rcopt[] = {
338 {"PREP", &preparer},
339 {"PUBL", &publisher},
340 {"APPI", &appid},
341 {"COPY", &copyright},
342 {"BIBL", &biblio},
343 {"ABST", &abstract},
344 {"VOLS", &volset_id},
345 {"VOLI", &volume_id},
346 {"SYSI", &system_id},
347 #ifdef APPLE_HYB
348 {"HFS_TYPE", &deftype},
349 {"HFS_CREATOR", &defcreator},
350 #endif /* APPLE_HYB */
351 {NULL, NULL}
352 };
353
354 #ifdef USE_FIND
355 LOCAL int getfind __PR((char *arg, long *valp,
356 int *pac, char *const **pav));
357 #endif
358
359 LOCAL int getH __PR((const char *arg, void *valp, int *pac, char *const **pav, const char *opt));
360 LOCAL int getL __PR((const char *arg, void *valp, int *pac, char *const **pav, const char *opt));
361 LOCAL int getP __PR((const char *arg, void *valp, int *pac, char *const **pav, const char *opt));
362 LOCAL int dolegacy __PR((const char *arg, void *valp, int *pac, char *const **pav, const char *opt));
363
364 LOCAL int get_boot_image __PR((char *opt_arg));
365 LOCAL int get_hd_boot __PR((char *opt_arg));
366 LOCAL int get_ne_boot __PR((char *opt_arg));
367 LOCAL int get_no_boot __PR((char *opt_arg));
368 LOCAL int get_boot_addr __PR((char *opt_arg));
369 LOCAL int get_boot_size __PR((char *opt_arg));
370 LOCAL int get_boot_platid __PR((char *opt_arg));
371 LOCAL int get_boot_table __PR((char *opt_arg));
372 #ifdef APPLE_HYB
373 #ifdef PREP_BOOT
374 LOCAL int get_prep_boot __PR((char *opt_arg));
375 LOCAL int get_chrp_boot __PR((char *opt_arg));
376 #endif
377 LOCAL int get_bsize __PR((char *opt_arg));
378
379 LOCAL int hfs_cap __PR((void));
380 LOCAL int hfs_neta __PR((void));
381 LOCAL int hfs_dbl __PR((void));
382 LOCAL int hfs_esh __PR((void));
383 LOCAL int hfs_fe __PR((void));
384 LOCAL int hfs_sgi __PR((void));
385 LOCAL int hfs_mbin __PR((void));
386 LOCAL int hfs_sgl __PR((void));
387 LOCAL int hfs_dave __PR((void));
388 LOCAL int hfs_sfm __PR((void));
389 LOCAL int hfs_xdbl __PR((void));
390 LOCAL int hfs_xhfs __PR((void));
391 LOCAL int hfs_nohfs __PR((void));
392 #endif /* APPLE_HYB */
393
394 LOCAL void ldate_error __PR((char *arg));
395 LOCAL char *strntoi __PR((char *p, int n, int *ip));
396 LOCAL int mosize __PR((int y, int m));
397 LOCAL char *parse_date __PR((char *arg, struct tm *tp));
398 LOCAL int get_ldate __PR((char *opt_arg, void *valp));
399
400 LOCAL int
401 get_boot_image(opt_arg)
402 char *opt_arg;
403 {
404 do_sort++; /* We sort bootcat/botimage */
405 use_eltorito++;
406 boot_image = opt_arg; /* pathname of the boot image */
407 /* on disk */
408 if (boot_image == NULL || *boot_image == '\0') {
409 comerrno(EX_BAD,
410 _("Required Eltorito boot image pathname missing\n"));
411 }
412 get_boot_entry();
413 current_boot_entry->boot_image = boot_image;
414 return (1);
415 }
416
417 LOCAL int
418 get_hd_boot(opt_arg)
419 char *opt_arg;
420 {
421 use_eltorito++;
422 hard_disk_boot++;
423 get_boot_entry();
424 current_boot_entry->hard_disk_boot = 1;
425 return (1);
426 }
427
428 LOCAL int
429 get_ne_boot(opt_arg)
430 char *opt_arg;
431 {
432 use_eltorito++;
433 no_emul_boot++;
434 get_boot_entry();
435 current_boot_entry->no_emul_boot = 1;
436 return (1);
437 }
438
439 LOCAL int
440 get_no_boot(opt_arg)
441 char *opt_arg;
442 {
443 use_eltorito++;
444 not_bootable++;
445 get_boot_entry();
446 current_boot_entry->not_bootable = 1;
447 return (1);
448 }
449
450 LOCAL int
451 get_boot_addr(opt_arg)
452 char *opt_arg;
453 {
454 long val;
455 char *ptr;
456
457 use_eltorito++;
458 val = strtol(opt_arg, &ptr, 0);
459 if (*ptr || val < 0 || val >= 0x10000) {
460 comerrno(EX_BAD, _("Boot image load address invalid.\n"));
461 }
462 load_addr = val;
463 get_boot_entry();
464 current_boot_entry->load_addr = load_addr;
465 return (1);
466 }
467
468 LOCAL int
469 get_boot_size(opt_arg)
470 char *opt_arg;
471 {
472 long val;
473 char *ptr;
474
475 use_eltorito++;
476 val = strtol(opt_arg, &ptr, 0);
477 if (*ptr || val < 0 || val >= 0x10000) {
478 comerrno(EX_BAD,
479 _("Boot image load size invalid.\n"));
480 }
481 load_size = val;
482 get_boot_entry();
483 current_boot_entry->load_size = load_size;
484 return (1);
485 }
486
487 LOCAL int
488 get_boot_platid(opt_arg)
489 char *opt_arg;
490 {
491 long val;
492 char *ptr;
493
494 use_eltorito++;
495 if (streql(opt_arg, "x86")) {
496 val = EL_TORITO_ARCH_x86;
497 } else if (streql(opt_arg, "PPC")) {
498 val = EL_TORITO_ARCH_PPC;
499 } else if (streql(opt_arg, "Mac")) {
500 val = EL_TORITO_ARCH_MAC;
501 } else if (streql(opt_arg, "efi")) {
502 val = EL_TORITO_ARCH_EFI;
503 } else {
504 val = strtol(opt_arg, &ptr, 0);
505 if (*ptr || val < 0 || val >= 0x100) {
506 comerrno(EX_BAD, _("Bad boot system ID.\n"));
507 }
508 }
509
510 /*
511 * If there is already a boot entry and the boot file name has been set
512 * for this boot entry and the new platform id differs from the
513 * previous value, we start a new boot section.
514 */
515 if (current_boot_entry &&
516 current_boot_entry->boot_image != NULL &&
517 current_boot_entry->boot_platform != val) {
518 new_boot_entry();
519 }
520 get_boot_entry();
521 current_boot_entry->type |= ELTORITO_BOOT_ID;
522 current_boot_entry->boot_platform = val;
523 return (1);
524 }
525
526 LOCAL int
527 get_boot_table(opt_arg)
528 char *opt_arg;
529 {
530 use_eltorito++;
531 boot_info_table++;
532 get_boot_entry();
533 current_boot_entry->boot_info_table = 1;
534 return (1);
535 }
536
537 #ifdef APPLE_HYB
538 #ifdef PREP_BOOT
539 LOCAL int
540 get_prep_boot(opt_arg)
541 char *opt_arg;
542 {
543 use_prep_boot++;
544 if (use_prep_boot > 4 - use_chrp_boot) {
545 comerrno(EX_BAD,
546 _("Maximum of 4 PRep+CHRP partition entries are allowed\n"));
547 }
548 /* pathname of the boot image on cd */
549 prep_boot_image[use_prep_boot - 1] = opt_arg;
550 if (prep_boot_image[use_prep_boot - 1] == NULL) {
551 comerrno(EX_BAD,
552 _("Required PReP boot image pathname missing\n"));
553 }
554 return (1);
555 }
556
557 LOCAL int
558 get_chrp_boot(opt_arg)
559 char *opt_arg;
560 {
561 if (use_chrp_boot)
562 return (1); /* silently allow duplicates */
563 use_chrp_boot = 1;
564 if (use_prep_boot > 3) {
565 comerrno(EX_BAD,
566 _("Maximum of 4 PRep+CHRP partition entries are allowed\n"));
567 }
568 return (1);
569 }
570 #endif /* PREP_BOOT */
571
572
573 LOCAL int
574 get_bsize(opt_arg)
575 char *opt_arg;
576 {
577 afe_size = atoi(opt_arg);
578 hfs_select |= DO_FEU;
579 hfs_select |= DO_FEL;
580 return (1);
581 }
582
583 LOCAL int
584 hfs_cap()
585 {
586 hfs_select |= DO_CAP;
587 return (1);
588 }
589
590 LOCAL int
591 hfs_neta()
592 {
593 hfs_select |= DO_NETA;
594 return (1);
595 }
596
597 LOCAL int
598 hfs_dbl()
599 {
600 hfs_select |= DO_DBL;
601 return (1);
602 }
603
604 LOCAL int
605 hfs_esh()
606 {
607 hfs_select |= DO_ESH;
608 return (1);
609 }
610
611 LOCAL int
612 hfs_fe()
613 {
614 hfs_select |= DO_FEU;
615 hfs_select |= DO_FEL;
616 return (1);
617 }
618
619 LOCAL int
620 hfs_sgi()
621 {
622 hfs_select |= DO_SGI;
623 return (1);
624 }
625
626 LOCAL int
627 hfs_mbin()
628 {
629 hfs_select |= DO_MBIN;
630 return (1);
631 }
632
633 LOCAL int
634 hfs_sgl()
635 {
636 hfs_select |= DO_SGL;
637 return (1);
638 }
639
640 LOCAL int
641 hfs_dave()
642 {
643 hfs_select |= DO_DAVE;
644 return (1);
645 }
646
647
648 LOCAL int
649 hfs_sfm()
650 {
651 hfs_select |= DO_SFM;
652 return (1);
653 }
654
655 LOCAL int
656 hfs_xdbl()
657 {
658 hfs_select |= DO_XDBL;
659 return (1);
660 }
661
662 LOCAL int
663 hfs_xhfs()
664 {
665 #ifdef IS_MACOS_X
666 hfs_select |= DO_XHFS;
667 #else
668 errmsgno(EX_BAD,
669 _("Warning: --osx-hfs only works on MacOS X ... ignoring\n"));
670 #endif
671 return (1);
672 }
673
674 LOCAL int
675 hfs_nohfs()
676 {
677 no_apple_hyb = 1;
678 return (1);
679 }
680
681 #endif /* APPLE_HYB */
682
683 LOCAL void
684 ldate_error(arg)
685 char *arg;
686 {
687 comerrno(EX_BAD, _("Ilegal date specification '%s'.\n"), arg);
688 }
689
690 LOCAL char *
691 strntoi(p, n, ip)
692 char *p;
693 int n;
694 int *ip;
695 {
696 int i = 0;
697 int digits = 0;
698 int c;
699
700 while (*p) {
701 if (digits >= n)
702 break;
703 c = *p;
704 if (c < '0' || c > '9')
705 break;
706 p++;
707 digits++;
708 i *= 10;
709 i += c - '0';
710 }
711 *ip = i;
712
713 return (p);
714 }
715
716 #define dysize(A) (((A)%4)? 365 : (((A)%100) == 0 && ((A)%400)) ? 365 : 366)
717
718 static int dmsize[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
719
720 LOCAL int
721 mosize(y, m)
722 int y;
723 int m;
724 {
725
726 if (m == 1 && dysize(y) == 366)
727 return (29);
728 return (dmsize[m]);
729 }
730
731 LOCAL char *
732 parse_date(arg, tp)
733 char *arg;
734 struct tm *tp;
735 {
736 char *oarg = arg;
737 char *p;
738
739 tp->tm_mon = tp->tm_hour = tp->tm_min = tp->tm_sec = 0;
740 tp->tm_mday = 1;
741 tp->tm_isdst = -1;
742
743 p = strchr(arg, '/');
744 if (p == NULL)
745 p = strchr(arg, '-');
746 if (p) {
747 if ((p - arg) != 2 && (p - arg) != 4)
748 ldate_error(oarg);
749 p = strntoi(arg, 4, &tp->tm_year);
750 if ((p - arg) != 2 && (p - arg) != 4)
751 ldate_error(oarg);
752 if ((p - arg) == 2) {
753 if (tp->tm_year < 69)
754 tp->tm_year += 100;
755 } else {
756 tp->tm_year -= 1900;
757 }
758 if (*p == '/' || *p == '-')
759 p++;
760 } else if (strlen(arg) < 4) {
761 ldate_error(oarg);
762 } else {
763 p = strntoi(arg, 4, &tp->tm_year);
764 if ((p - arg) != 4)
765 ldate_error(oarg);
766 tp->tm_year -= 1900;
767 }
768 if (*p == '\0' || strchr(".+-", *p))
769 return (p);
770 arg = p;
771 p = strntoi(arg, 2, &tp->tm_mon);
772 if ((p - arg) != 2)
773 ldate_error(oarg);
774 tp->tm_mon -= 1;
775 if (tp->tm_mon < 0 || tp->tm_mon >= 12)
776 ldate_error(oarg);
777 if (*p == '/' || *p == '-')
778 p++;
779 if (*p == '\0' || strchr(".+-", *p))
780 return (p);
781 arg = p;
782 p = strntoi(arg, 2, &tp->tm_mday);
783 if ((p - arg) != 2)
784 ldate_error(oarg);
785 if (tp->tm_mday < 1 || tp->tm_mday > mosize(tp->tm_year+1900, tp->tm_mon))
786 ldate_error(oarg);
787 if (*p == ' ')
788 p++;
789 if (*p == '\0' || strchr(".+-", *p))
790 return (p);
791 arg = p;
792 p = strntoi(arg, 2, &tp->tm_hour);
793 if ((p - arg) != 2)
794 ldate_error(oarg);
795 if (tp->tm_hour > 23)
796 ldate_error(oarg);
797 if (*p == ':')
798 p++;
799 if (*p == '\0' || strchr(".+-", *p))
800 return (p);
801 arg = p;
802 p = strntoi(arg, 2, &tp->tm_min);
803 if ((p - arg) != 2)
804 ldate_error(oarg);
805 if (tp->tm_min > 59)
806 ldate_error(oarg);
807 if (*p == ':')
808 p++;
809 if (*p == '\0' || strchr(".+-", *p))
810 return (p);
811 arg = p;
812 p = strntoi(arg, 2, &tp->tm_sec);
813 if ((p - arg) != 2)
814 ldate_error(oarg);
815 if (tp->tm_sec > 61)
816 ldate_error(oarg);
817 return (p);
818 }
819
820 /*
821 * Parse a date spec similar to:
822 * YYYY[MM[DD[HH[MM[SS]]]]][.hh][+-GHGM]
823 */
824 LOCAL int
825 get_ldate(opt_arg, valp)
826 char *opt_arg;
827 void *valp;
828 {
829 time_t t;
830 int usec = 0;
831 int gmtoff = -100;
832 struct tm tm;
833 char *p;
834 char *arg;
835
836 p = parse_date(opt_arg, &tm);
837 if (*p == '.') {
838 p++;
839 arg = p;
840 p = strntoi(arg, 2, &usec);
841 if ((p - arg) != 2)
842 ldate_error(opt_arg);
843 if (usec > 99)
844 ldate_error(opt_arg);
845 usec *= 10000;
846 }
847 if (*p == ' ')
848 p++;
849 if (*p == '+' || *p == '-') {
850 int i;
851 char *s = p++;
852
853 arg = p;
854 p = strntoi(arg, 2, &gmtoff);
855 if ((p - arg) != 2)
856 ldate_error(opt_arg);
857 arg = p;
858 p = strntoi(arg, 2, &i);
859 if ((p - arg) != 2)
860 ldate_error(opt_arg);
861 if (i > 59)
862 ldate_error(opt_arg);
863 gmtoff *= 60;
864 gmtoff += i;
865 if (gmtoff % 15)
866 ldate_error(opt_arg);
867 if (*s == '-')
868 gmtoff *= -1;
869 gmtoff /= 15;
870 if (gmtoff < -48 || gmtoff > 52)
871 ldate_error(opt_arg);
872 }
873 if (*p != '\0')
874 ldate_error(opt_arg);
875
876 seterrno(0);
877 t = mktime(&tm);
878 if (t == -1 && geterrno() != 0)
879 comerr(_("Date '%s' is out of range.\n"), opt_arg);
880
881 ((ldate *)valp)->l_sec = t;
882 ((ldate *)valp)->l_usec = usec;
883 ((ldate *)valp)->l_gmtoff = gmtoff;
884
885 return (1);
886 }
887
888 #ifdef USE_FIND
889 /* ARGSUSED */
890 LOCAL int
891 getfind(arg, valp, pac, pav)
892 char *arg;
893 long *valp; /* Not used until we introduce a ptr to opt struct */
894 int *pac;
895 char *const **pav;
896 {
897 dofind = TRUE;
898 find_ac = *pac;
899 find_av = *pav;
900 find_ac--, find_av++;
901 return (NOARGS);
902 }
903 #endif
904
905 /* ARGSUSED */
906 LOCAL int
907 getH(arg, valp, pac, pav, opt) /* Follow symlinks encountered on cmdline */
908 const char *arg;
909 void *valp;
910 int *pac;
911 char *const **pav;
912 const char *opt;
913 {
914 /*error("getH\n");*/
915 if (opt[0] == '-' && opt[1] == 'H' && opt[2] == '\0') {
916 #ifdef APPLE_HYB
917 if (legacy) {
918 errmsgno(EX_BAD, _("The option '-H' is deprecated since 2002.\n"));
919 errmsgno(EX_BAD, _("The option '-H' was disabled in 2006.\n"));
920 errmsgno(EX_BAD, _("Use '-map' instead of '-H' as documented instead of using the legacy mode.\n"));
921 afpfile = (char *)arg;
922 return (1);
923 }
924 #endif
925 return (BADFLAG); /* POSIX -H is not yet active */
926 }
927 follow_links = FALSE;
928 Hflag = TRUE;
929 #ifdef USE_FIND
930 *(int *)valp |= WALK_ARGFOLLOW;
931 #endif
932 return (1);
933 }
934
935 /* ARGSUSED */
936 LOCAL int
937 getL(arg, valp, pac, pav, opt) /* Follow all symlinks */
938 const char *arg;
939 void *valp;
940 int *pac;
941 char *const **pav;
942 const char *opt;
943 {
944 /*error("getL\n");*/
945 if (opt[0] == '-' && opt[1] == 'L' && opt[2] == '\0') {
946 if (legacy) {
947 errmsgno(EX_BAD, _("The option '-L' is deprecated since 2002.\n"));
948 errmsgno(EX_BAD, _("The option '-L' was disabled in 2006.\n"));
949 errmsgno(EX_BAD,
950 _("Use '-allow-leading-dots' instead of '-L' as documented instead of using the legacy mode.\n"));
951 allow_leading_dots = TRUE;
952 return (1);
953 }
954 return (BADFLAG); /* POSIX -L is not yet active */
955 }
956 follow_links = TRUE;
957 Hflag = FALSE;
958 #ifdef USE_FIND
959 *(int *)valp |= WALK_ALLFOLLOW;
960 #endif
961 return (1);
962 }
963
964 /* ARGSUSED */
965 LOCAL int
966 getP(arg, valp, pac, pav, opt) /* Do not follow symlinks */
967 const char *arg;
968 void *valp;
969 int *pac;
970 char *const **pav;
971 const char *opt;
972 {
973 /*error("getP\n");*/
974 if (opt[0] == '-' && opt[1] == 'P' && opt[2] == '\0') {
975 if (legacy) {
976 errmsgno(EX_BAD, _("The option '-P' is deprecated since 2002.\n"));
977 errmsgno(EX_BAD, _("The option '-P' was disabled in 2006.\n"));
978 errmsgno(EX_BAD, _("Use '-publisher' instead of '-P' as documented instead of using the legacy mode.\n"));
979 publisher = (char *)arg;
980 return (1);
981 }
982 return (BADFLAG); /* POSIX -P is not yet active */
983 }
984 follow_links = FALSE;
985 Hflag = FALSE;
986 #ifdef USE_FIND
987 *(int *)valp &= ~(WALK_ARGFOLLOW | WALK_ALLFOLLOW);
988 #endif
989 return (1);
990 }
991
992 LOCAL struct ga_flags *gl_flags;
993 /* ARGSUSED */
994 LOCAL int
995 dolegacy(arg, valp, pac, pav, opt) /* Follow symlinks encountered on cmdline */
996 const char *arg;
997 void *valp;
998 int *pac;
999 char *const **pav;
1000 const char *opt;
1001 {
1002 legacy = TRUE;
1003 #ifdef APPLE_HYB
1004 gl_flags[2].ga_format = "H&"; /* Apple Hybrid "-map" */
1005 #endif
1006 #ifdef OPT_L_HAS_ARG /* never ;-) */
1007 gl_flags[4].ga_format = "L&"; /* -allow-leading-dots */
1008 #endif
1009 gl_flags[6].ga_format = "P&"; /* -publisher */
1010 return (1);
1011 }
1012
1013 struct mki_option {
1014 /*
1015 * The long option information.
1016 */
1017 struct ga_flags opt;
1018 /*
1019 * The documentation string. If this is NULL or empty, this is a
1020 * synonym for the previous option.
1021 *
1022 * If the string starts with a '-', the (long) option is a
1023 * double dash option.
1024 *
1025 * If the next character in the string is a ^A (\1), then the following
1026 * characters are the argument name for the option. The arg string ends
1027 * before a \1 or a \2 is seen. A \1 is skipped.
1028 *
1029 * The rest of the string is the real documentation string. If it
1030 * starts with \2, then the option is hidden from the online help.
1031 */
1032 const char *doc;
1033 };
1034
1035
1036 LOCAL int save_pname = 0;
1037
1038 LOCAL const struct mki_option mki_options[] =
1039 {
1040 #ifdef USE_FIND
1041 {{"find~", NULL, (getpargfun)getfind },
1042 __("\1file... [find expr.]\1Option separator: Use find command line to the right")},
1043 #endif
1044 /*
1045 * The options -H/-L/-P did have different meaning in old releases of
1046 * mkisofs. In October 2002, mkisofs introduced a warning that the
1047 * short options -H/-L/-P should not be used with the old meaning
1048 * anymore. The long options should be used instead. The options
1049 * -H/-L/-P previously have been associated with the following long
1050 * options:
1051 *
1052 * -H -map 2000..2002
1053 * -L -allow-leading-dots 1995..2002
1054 * -P -publisher 1993..2002
1055 *
1056 * Since December 2006, the short options -H/-L/-P have been disabled
1057 * for their old meaning.
1058 *
1059 * Warning: for the -legacy mode, the entries for -H/-L/-P need to stay
1060 * at their current index in mki_options[] or dolegacy() needs to be
1061 * changed to fit the modification.
1062 */
1063 {{"posix-H~", &walkflags, getH },
1064 __("Follow symbolic links encountered on command line")},
1065 {{"H~", &walkflags, getH },
1066 #ifdef LATER
1067 NULL},
1068 #else
1069 __("\2")},
1070 #endif
1071 {{"posix-L~", &walkflags, getL },
1072 __("Follow all symbolic links")},
1073 {{"L~", &walkflags, getL },
1074 #ifdef LATER
1075 NULL},
1076 #else
1077 __("\2")},
1078 #endif
1079 {{"posix-P~", &walkflags, getP },
1080 __("Do not follow symbolic links (default)")},
1081 {{"P~", &walkflags, getP },
1082 #ifdef LATER
1083 NULL},
1084 #else
1085 __("\2")},
1086 #endif
1087
1088 {{"abstract*", &abstract },
1089 __("\1FILE\1Set Abstract filename")},
1090 {{"A*,appid*", &appid },
1091 __("\1ID\1Set Application ID")},
1092 {{"biblio*", &biblio },
1093 __("\1FILE\1Set Bibliographic filename")},
1094 /*
1095 * If this includes UWIN, we need to modify the condition.
1096 */
1097 #if !defined(__MINGW32__) && !defined(_MSC_VER)
1098 {{"cache-inodes", &cache_inodes },
1099 __("Cache inodes (needed to detect hard links)")},
1100 #endif
1101 {{"no-cache-inodes%0", &cache_inodes },
1102 __("Do not cache inodes (if filesystem has no unique inodes)")},
1103 {{"rrip110%0", &rrip112 },
1104 __("Create old Rock Ridge V 1.10")},
1105 {{"rrip112", &rrip112 },
1106 __("Create new Rock Ridge V 1.12 (default)")},
1107 {{"check-oldnames", &check_oldnames },
1108 __("Check all imported ISO9660 names from old session")},
1109 {{"check-session*", &check_image },
1110 __("\1FILE\1Check all ISO9660 names from previous session")},
1111 {{"copyright*", &copyright },
1112 __("\1FILE\1Set Copyright filename")},
1113 {{"debug+", &debug },
1114 __("Set debug flag")},
1115 {{"ignore-error", &ignerr },
1116 __("Ignore errors")},
1117 {{"b& ,eltorito-boot&", NULL, (getpargfun)get_boot_image },
1118 __("\1FILE\1Set El Torito boot image name")},
1119 {{"eltorito-alt-boot~", NULL, (getpargfun)new_boot_entry },
1120 __("Start specifying alternative El Torito boot parameters")},
1121 {{"eltorito-platform&", NULL, (getpargfun)get_boot_platid },
1122 __("\1ID\1Set El Torito platform id for the next boot entry")},
1123 {{"B&,sparc-boot&", NULL, (getpargfun)scan_sparc_boot },
1124 __("\1FILES\1Set sparc boot image names")},
1125 {{"sunx86-boot&", NULL, (getpargfun)scan_sunx86_boot },
1126 __("\1FILES\1Set sunx86 boot image names")},
1127 {{"G*,generic-boot*", &genboot_image },
1128 __("\1FILE\1Set generic boot image name")},
1129 {{"sparc-label&", NULL, (getpargfun)sparc_boot_label },
1130 __("\1label text\1Set sparc boot disk label")},
1131 {{"sunx86-label&", NULL, (getpargfun)sunx86_boot_label },
1132 __("\1label text\1Set sunx86 boot disk label")},
1133 {{"c* ,eltorito-catalog*", &boot_catalog },
1134 __("\1FILE\1Set El Torito boot catalog name")},
1135 {{"C*,cdrecord-params*", &cdrecord_data },
1136 __("\1PARAMS\1Magic paramters from cdrecord")},
1137 {{"d,omit-period", &omit_period },
1138 __("Omit trailing periods from filenames (violates ISO9660)")},
1139 {{"data-change-warn", &data_change_warn },
1140 __("Treat data/size changes as warning only")},
1141 {{"dir-mode*", &dirmode_str },
1142 __("\1mode\1Make the mode of all directories this mode.")},
1143 {{"D,disable-deep-relocation", &disable_deep_reloc },
1144 __("Disable deep directory relocation (violates ISO9660)")},
1145 {{"file-mode*", &filemode_str },
1146 __("\1mode\1Make the mode of all plain files this mode.")},
1147 {{"errctl&", NULL, (getpargfun)errconfig },
1148 __("\1name\1Read error control defs from file or inline.")},
1149 {{"f,follow-links", &follow_links },
1150 __("Follow symbolic links")},
1151 {{"gid*", &gid_str },
1152 __("\1gid\1Make the group owner of all files this gid.")},
1153 {{"graft-points", &use_graft_ptrs },
1154 __("Allow to use graft points for filenames")},
1155 {{"root*", &reloc_root },
1156 __("\1DIR\1Set root directory for all new files and directories")},
1157 {{"old-root*", &reloc_old_root },
1158 __("\1DIR\1Set root directory in previous session that is searched for files")},
1159 {{"help", &help },
1160 __("Print option help")},
1161 {{"hide& ", NULL, (getpargfun)i_add_match },
1162 __("\1GLOBFILE\1Hide ISO9660/RR file")},
1163 {{"hide-list&", NULL, (getpargfun)i_add_list },
1164 __("\1FILE\1File with list of ISO9660/RR files to hide")},
1165 {{"hidden& ", NULL, (getpargfun)h_add_match },
1166 __("\1GLOBFILE\1Set hidden attribute on ISO9660 file")},
1167 {{"hidden-list&", NULL, (getpargfun)h_add_list },
1168 __("\1FILE\1File with list of ISO9660 files with hidden attribute")},
1169 {{"hide-joliet& ", NULL, (getpargfun)j_add_match },
1170 __("\1GLOBFILE\1Hide Joliet file")},
1171 {{"hide-joliet-list&", NULL, (getpargfun)j_add_list },
1172 __("\1FILE\1File with list of Joliet files to hide")},
1173 #ifdef UDF
1174 {{"hide-udf& ", NULL, (getpargfun)u_add_match },
1175 __("\1GLOBFILE\1Hide UDF file")},
1176 {{"hide-udf-list&", NULL, (getpargfun)u_add_list },
1177 __("\1FILE\1File with list of UDF files to hide")},
1178 #endif
1179 {{"hide-joliet-trans-tbl", &jhide_trans_tbl},
1180 __("Hide TRANS.TBL from Joliet tree")},
1181 {{"hide-rr-moved", &hide_rr_moved },
1182 __("Rename RR_MOVED to .rr_moved in Rock Ridge tree")},
1183 {{"gui", &gui},
1184 __("Switch behaviour for GUI")},
1185 {{"input-charset*", &icharset },
1186 __("\1CHARSET\1Local input charset for file name conversion")},
1187 {{"output-charset*", &ocharset },
1188 __("\1CHARSET\1Output charset for file name conversion")},
1189 {{"iso-level#", &iso9660_level },
1190 __("\1LEVEL\1Set ISO9660 conformance level (1..3) or 4 for ISO9660 version 2")},
1191 {{"J,joliet", &use_Joliet },
1192 __("Generate Joliet directory information")},
1193 {{"joliet-long", &joliet_long },
1194 __("Allow Joliet file names to be 103 Unicode characters")},
1195 {{"jcharset*", &jcharset },
1196 __("\1CHARSET\1Local charset for Joliet directory information")},
1197 {{"l,full-iso9660-filenames", &full_iso9660_filenames },
1198 __("Allow full 31 character filenames for ISO9660 names")},
1199 {{"max-iso9660-filenames", &max_filenames },
1200 __("Allow 37 character filenames for ISO9660 names (violates ISO9660)")},
1201
1202 {{"allow-leading-dots", &allow_leading_dots },
1203 __("Allow ISO9660 filenames to start with '.' (violates ISO9660)")},
1204 {{"ldots", &allow_leading_dots },
1205 __("Allow ISO9660 filenames to start with '.' (violates ISO9660)")},
1206
1207 {{"log-file*", &log_file },
1208 __("\1LOG_FILE\1Re-direct messages to LOG_FILE")},
1209 {{"long-rr-time%1", &long_rr_time },
1210 __("Use long Rock Ridge time format")},
1211 {{"m& ,exclude& ", NULL, (getpargfun)add_match },
1212 __("\1GLOBFILE\1Exclude file name")},
1213 {{"exclude-list&", NULL, (getpargfun)add_list},
1214 __("\1FILE\1File with list of file names to exclude")},
1215 {{"modification-date&", &modification_date, (getpargfun)get_ldate },
1216 __("\1DATE\1Set the modification date field of the PVD")},
1217 {{"nobak%0", &all_files },
1218 __("Do not include backup files")},
1219 {{"no-bak%0", &all_files},
1220 __("Do not include backup files")},
1221 {{"pad", &dopad },
1222 __("Pad output to a multiple of 32k (default)")},
1223 {{"no-pad%0", &dopad },
1224 __("Do not pad output to a multiple of 32k")},
1225 {{"no-limit-pathtables", &nolimitpathtables },
1226 __("Allow more than 65535 parent directories (violates ISO9660)")},
1227 {{"no-long-rr-time%0", &long_rr_time },
1228 __("Use short Rock Ridge time format")},
1229 {{"M*,prev-session*", &merge_image },
1230 __("\1FILE\1Set path to previous session to merge")},
1231 {{"dev*", &merge_image },
1232 __("\1SCSIdev\1Set path to previous session to merge")},
1233 {{"N,omit-version-number", &omit_version_number },
1234 __("Omit version number from ISO9660 filename (violates ISO9660)")},
1235 {{"new-dir-mode*", &new_dirmode_str },
1236 __("\1mode\1Mode used when creating new directories.")},
1237 {{"force-rr", &force_rr },
1238 __("Inhibit automatic Rock Ridge detection for previous session")},
1239 {{"no-rr", &no_rr },
1240 __("Inhibit reading of Rock Ridge attributes from previous session")},
1241 {{"no-split-symlink-components%0", &split_SL_component },
1242 __("Inhibit splitting symlink components")},
1243 {{"no-split-symlink-fields%0", &split_SL_field },
1244 __("Inhibit splitting symlink fields")},
1245 {{"o* ,output* ", &outfile },
1246 __("\1FILE\1Set output file name")},
1247 {{"path-list*", &pathnames },
1248 __("\1FILE\1File with list of pathnames to process")},
1249 {{"p* ,preparer*", &preparer },
1250 __("\1PREP\1Set Volume preparer")},
1251 {{"print-size", &print_size },
1252 __("Print estimated filesystem size and exit")},
1253 {{"publisher*", &publisher },
1254 __("\1PUB\1Set Volume publisher")},
1255 {{"quiet%0", &verbose },
1256 __("Run quietly")},
1257 {{"r,rational-rock", &rationalize_rr },
1258 __("Generate rationalized Rock Ridge directory information")},
1259 {{"R,rock", &use_RockRidge },
1260 __("Generate Rock Ridge directory information")},
1261 {{"s* ,sectype*", &sectype },
1262 __("\1TYPE\1Set output sector type to e.g. data/xa1/raw")},
1263 {{"short-rr-time%0", &long_rr_time },
1264 __("Use short Rock Ridge time format")},
1265
1266 #ifdef SORTING
1267 { {"sort&", NULL, (getpargfun)add_sort_list },
1268 __("\1FILE\1Sort file content locations according to rules in FILE")},
1269 #endif /* SORTING */
1270
1271 {{"split-output", &split_output },
1272 __("Split output into files of approx. 1GB size")},
1273 {{"stream-file-name*", &stream_filename },
1274 __("\1FILE_NAME\1Set the stream file ISO9660 name (incl. version)")},
1275 {{"stream-media-size#", &stream_media_size },
1276 __("\1#\1Set the size of your CD media in sectors")},
1277 {{"sysid*", &system_id },
1278 __("\1ID\1Set System ID")},
1279 {{"T,translation-table", &generate_tables },
1280 __("Generate translation tables for systems that don't understand long filenames")},
1281 {{"table-name*", &trans_tbl },
1282 __("\1TABLE_NAME\1Translation table file name")},
1283 {{"ucs-level#", &ucs_level },
1284 __("\1LEVEL\1Set Joliet UCS level (1..3)")},
1285
1286 #ifdef UDF
1287 {{"udf", &rationalize_udf },
1288 __("Generate rationalized UDF file system")},
1289 {{"UDF", &use_udf },
1290 __("Generate UDF file system")},
1291 {{"udf-symlinks", &create_udfsymlinks },
1292 __("Create symbolic links on UDF image (default)")},
1293 {{"no-udf-symlinks%0", &create_udfsymlinks },
1294 __("Do not reate symbolic links on UDF image")},
1295 #endif
1296
1297 #ifdef DVD_AUD_VID
1298 {{"dvd-audio", &dvd_audio },
1299 "Generate DVD-Audio compliant UDF file system"},
1300 {{"dvd-hybrid", &dvd_hybrid },
1301 "Generate a hybrid (DVD-Audio and DVD-Video) compliant UDF file system"},
1302 {{"dvd-video", &dvd_video },
1303 __("Generate DVD-Video compliant UDF file system")},
1304 #endif
1305
1306 {{"uid*", &uid_str },
1307 __("\1uid\1Make the owner of all files this uid.")},
1308 {{"U,untranslated-filenames", &untranslated_filenames },
1309 /* CSTYLED */
1310 __("Allow Untranslated filenames (for HPUX & AIX - violates ISO9660). Forces -l, -d, -N, -allow-leading-dots, -relaxed-filenames, -allow-lowercase, -allow-multidot")},
1311 {{"relaxed-filenames", &relaxed_filenames },
1312 __("Allow 7 bit ASCII except lower case characters (violates ISO9660)")},
1313 {{"no-iso-translate%0", &iso_translate },
1314 __("Do not translate illegal ISO characters '~', '-' and '#' (violates ISO9660)")},
1315 {{"allow-lowercase", &allow_lowercase },
1316 __("Allow lower case characters in addition to the current character set (violates ISO9660)")},
1317 {{"allow-multidot", &allow_multidot },
1318 __("Allow more than one dot in filenames (e.g. .tar.gz) (violates ISO9660)")},
1319 {{"use-fileversion", &use_fileversion },
1320 __("\1LEVEL\1Use file version # from filesystem")},
1321 {{"v+,verbose+", &verbose },
1322 __("Verbose")},
1323 {{"version", &pversion },
1324 __("Print the current version")},
1325 {{"V*,volid*", &volume_id },
1326 __("\1ID\1Set Volume ID")},
1327 {{"volset* ", &volset_id },
1328 __("\1ID\1Set Volume set ID")},
1329 {{"volset-size#", &volume_set_size },
1330 __("\1#\1Set Volume set size")},
1331 {{"volset-seqno#", &volume_sequence_number },
1332 __("\1#\1Set Volume set sequence number")},
1333 {{"x& ,old-exclude&", NULL, (getpargfun)add_match },
1334 __("\1FILE\1Exclude file name(depreciated)")},
1335 {{"hard-disk-boot~", NULL, (getpargfun)get_hd_boot },
1336 __("Boot image is a hard disk image")},
1337 {{"no-emul-boot~", NULL, (getpargfun)get_ne_boot },
1338 __("Boot image is 'no emulation' image")},
1339 {{"no-boot~", NULL, (getpargfun)get_no_boot },
1340 __("Boot image is not bootable")},
1341 {{"boot-load-seg&", NULL, (getpargfun)get_boot_addr },
1342 __("\1#\1Set load segment for boot image")},
1343 {{"boot-load-size&", NULL, (getpargfun)get_boot_size },
1344 __("\1#\1Set numbers of load sectors")},
1345 {{"boot-info-table~", NULL, (getpargfun)get_boot_table },
1346 __("Patch boot image with info table")},
1347 {{"XA", &use_XA },
1348 __("Generate XA directory attributes")},
1349 {{"xa", &rationalize_xa },
1350 __("Generate rationalized XA directory attributes")},
1351 {{"z,transparent-compression", &transparent_compression },
1352 __("Enable transparent compression of files")},
1353
1354 #ifdef APPLE_HYB
1355 {{"hfs-type*", &deftype },
1356 __("\1TYPE\1Set HFS default TYPE")},
1357 {{"hfs-creator", &defcreator },
1358 __("\1CREATOR\1Set HFS default CREATOR")},
1359 {{"g,apple", &apple_ext },
1360 __("Add Apple ISO9660 extensions")},
1361 {{"h,hfs", &apple_hyb },
1362 __("Create ISO9660/HFS hybrid")},
1363 {{"map*", &afpfile },
1364 __("\1MAPPING_FILE\1Map file extensions to HFS TYPE/CREATOR")},
1365 {{"magic*", &magic_file },
1366 __("\1FILE\1Magic file for HFS TYPE/CREATOR")},
1367 {{"probe", &probe },
1368 __("Probe all files for Apple/Unix file types")},
1369 {{"mac-name", &use_mac_name },
1370 __("Use Macintosh name for ISO9660/Joliet/RockRidge file name")},
1371 {{"no-mac-files", &nomacfiles },
1372 __("Do not look for Unix/Mac files (depreciated)")},
1373 {{"boot-hfs-file*", &hfs_boot_file },
1374 __("\1FILE\1Set HFS boot image name")},
1375 {{"part", &gen_pt },
1376 __("Generate HFS partition table")},
1377 {{"cluster-size&", NULL, (getpargfun)get_bsize },
1378 __("\1SIZE\1Cluster size for PC Exchange Macintosh files")},
1379 {{"auto*", &autoname },
1380 __("\1FILE\1Set HFS AutoStart file name")},
1381 {{"no-desktop%0", &create_dt },
1382 __("Do not create the HFS (empty) Desktop files")},
1383 {{"hide-hfs& ", NULL, (getpargfun)hfs_add_match },
1384 __("\1GLOBFILE\1Hide HFS file")},
1385 {{"hide-hfs-list&", NULL, (getpargfun)hfs_add_list },
1386 __("\1FILE\1List of HFS files to hide")},
1387 {{"hfs-volid*", &hfs_volume_id },
1388 __("\1HFS_VOLID\1Volume name for the HFS partition")},
1389 {{"icon-position", &icon_pos },
1390 __("Keep HFS icon position")},
1391 {{"root-info*", &root_info },
1392 __("\1FILE\1finderinfo for root folder")},
1393 {{"input-hfs-charset*", &hfs_icharset },
1394 __("\1CHARSET\1Local input charset for HFS file name conversion")},
1395 {{"output-hfs-charset*", &hfs_ocharset },
1396 __("\1CHARSET\1Output charset for HFS file name conversion")},
1397 {{"hfs-unlock%0", &hfs_lock },
1398 __("Leave HFS Volume unlocked")},
1399 {{"hfs-bless*", &hfs_bless },
1400 __("\1FOLDER_NAME\1Name of Folder to be blessed")},
1401 {{"hfs-parms*", &hfs_parms },
1402 __("\1PARAMETERS\1Comma separated list of HFS parameters")},
1403 #ifdef PREP_BOOT
1404 {{"prep-boot&", NULL, (getpargfun)get_prep_boot },
1405 __("\1FILE\1PReP boot image file -- up to 4 are allowed")},
1406 {{"chrp-boot&", NULL, (getpargfun)get_chrp_boot },
1407 __("Add CHRP boot header")},
1408 #endif /* PREP_BOOT */
1409 {{"cap~", NULL, (getpargfun)hfs_cap },
1410 __("-Look for AUFS CAP Macintosh files")},
1411 {{"netatalk~", NULL, (getpargfun)hfs_neta},
1412 __("-Look for NETATALK Macintosh files")},
1413 {{"double~", NULL, (getpargfun)hfs_dbl },
1414 __("-Look for AppleDouble Macintosh files")},
1415 {{"ethershare~", NULL, (getpargfun)hfs_esh },
1416 __("-Look for Helios EtherShare Macintosh files")},
1417 {{"exchange~", NULL, (getpargfun)hfs_fe },
1418 __("-Look for PC Exchange Macintosh files")},
1419 {{"sgi~", NULL, (getpargfun)hfs_sgi },
1420 __("-Look for SGI Macintosh files")},
1421 {{"macbin~", NULL, (getpargfun)hfs_mbin },
1422 __("-Look for MacBinary Macintosh files")},
1423 {{"single~", NULL, (getpargfun)hfs_sgl },
1424 __("-Look for AppleSingle Macintosh files")},
1425 {{"ushare~", NULL, (getpargfun)hfs_esh },
1426 __("-Look for IPT UShare Macintosh files")},
1427 {{"xinet~", NULL, (getpargfun)hfs_sgi },
1428 __("-Look for XINET Macintosh files")},
1429 {{"dave~", NULL, (getpargfun)hfs_dave },
1430 __("-Look for DAVE Macintosh files")},
1431 {{"sfm~", NULL, (getpargfun)hfs_sfm },
1432 __("-Look for SFM Macintosh files")},
1433 {{"osx-double~", NULL, (getpargfun)hfs_xdbl },
1434 __("-Look for MacOS X AppleDouble Macintosh files")},
1435 {{"osx-hfs~", NULL, (getpargfun)hfs_xhfs },
1436 __("-Look for MacOS X HFS Macintosh files")},
1437 {{"no-hfs~", NULL, (getpargfun)hfs_nohfs },
1438 __("Do not create ISO9660/HFS hybrid")},
1439 #endif /* APPLE_HYB */
1440 {{"legacy~", NULL, dolegacy },
1441 __("\2")},
1442 };
1443
1444 #define OPTION_COUNT (sizeof mki_options / sizeof (mki_options[0]))
1445
1446 LOCAL void read_rcfile __PR((char *appname));
1447 LOCAL void susage __PR((int excode));
1448 LOCAL void usage __PR((int excode));
1449 EXPORT int iso9660_date __PR((char *result, time_t crtime));
1450 LOCAL void hide_reloc_dir __PR((void));
1451 LOCAL char *get_pnames __PR((int argc, char *const *argv, int opt,
1452 char *pname, int pnsize, FILE *fp));
1453 EXPORT int main __PR((int argc, char *argv[]));
1454 LOCAL void list_locales __PR((void));
1455 EXPORT char *findgequal __PR((char *s));
1456 LOCAL char *escstrcpy __PR((char *to, size_t tolen, char *from));
1457 struct directory *get_graft __PR((char *arg, char *graft_point, size_t glen,
1458 char *nodename, size_t nlen,
1459 char **short_namep, BOOL do_insert));
1460 EXPORT void *e_malloc __PR((size_t size));
1461 EXPORT char *e_strdup __PR((const char *s));
1462 LOCAL void ovstrcpy __PR((char *p2, char *p1));
1463 LOCAL void checkarch __PR((char *name));
1464
1465 LOCAL void
1466 read_rcfile(appname)
1467 char *appname;
1468 {
1469 FILE *rcfile = (FILE *)NULL;
1470 struct rcopts *rco;
1471 char *pnt,
1472 *pnt1;
1473 char linebuffer[256];
1474 static char rcfn[] = ".mkisofsrc";
1475 char filename[1000];
1476 int linum;
1477
1478 strlcpy(filename, rcfn, sizeof (filename));
1479 if (access(filename, R_OK) == 0)
1480 rcfile = fopen(filename, "r");
1481 if (!rcfile && errno != ENOENT)
1482 errmsg(_("Cannot open '%s'.\n"), filename);
1483
1484 if (!rcfile) {
1485 pnt = getenv("MKISOFSRC");
1486 if (pnt && strlen(pnt) <= sizeof (filename)) {
1487 strlcpy(filename, pnt, sizeof (filename));
1488 if (access(filename, R_OK) == 0)
1489 rcfile = fopen(filename, "r");
1490 if (!rcfile && errno != ENOENT)
1491 errmsg(_("Cannot open '%s'.\n"), filename);
1492 }
1493 }
1494 if (!rcfile) {
1495 pnt = getenv("HOME");
1496 if (pnt && strlen(pnt) + strlen(rcfn) + 2 <=
1497 sizeof (filename)) {
1498 strlcpy(filename, pnt, sizeof (filename));
1499 if (strlen(rcfn) + 2 <=
1500 (sizeof (filename) - strlen(filename))) {
1501 strcat(filename, "/");
1502 strcat(filename, rcfn);
1503 }
1504 if (access(filename, R_OK) == 0)
1505 rcfile = fopen(filename, "r");
1506 if (!rcfile && errno != ENOENT)
1507 errmsg(_("Cannot open '%s'.\n"), filename);
1508 }
1509 }
1510 if (!rcfile && strlen(appname) + sizeof (rcfn) + 2 <=
1511 sizeof (filename)) {
1512 strlcpy(filename, appname, sizeof (filename));
1513 pnt = strrchr(filename, '/');
1514 if (pnt) {
1515 strlcpy(pnt + 1, rcfn,
1516 sizeof (filename) - (pnt + 1 - filename));
1517 if (access(filename, R_OK) == 0)
1518 rcfile = fopen(filename, "r");
1519 if (!rcfile && errno != ENOENT)
1520 errmsg(_("Cannot open '%s'.\n"), filename);
1521 }
1522 }
1523 if (!rcfile)
1524 return;
1525 if (verbose > 0) {
1526 fprintf(stderr, _("Using \"%s\"\n"), filename);
1527 }
1528 /* OK, we got it. Now read in the lines and parse them */
1529 linum = 0;
1530 while (fgets(linebuffer, sizeof (linebuffer), rcfile)) {
1531 char *name;
1532 char *name_end;
1533
1534 ++linum;
1535 /* skip any leading white space */
1536 pnt = linebuffer;
1537 while (*pnt == ' ' || *pnt == '\t')
1538 ++pnt;
1539 /*
1540 * If we are looking at a # character, this line is a comment.
1541 */
1542 if (*pnt == '#')
1543 continue;
1544 /*
1545 * The name should begin in the left margin. Make sure it is
1546 * in upper case. Stop when we see white space or a comment.
1547 */
1548 name = pnt;
1549 while (*pnt && (isalpha((unsigned char) *pnt) || *pnt == '_')) {
1550 if (islower((unsigned char) *pnt))
1551 *pnt = toupper((unsigned char) *pnt);
1552 pnt++;
1553 }
1554 if (name == pnt) {
1555 fprintf(stderr, _("%s:%d: name required\n"), filename,
1556 linum);
1557 continue;
1558 }
1559 name_end = pnt;
1560 /* Skip past white space after the name */
1561 while (*pnt == ' ' || *pnt == '\t')
1562 pnt++;
1563 /* silently ignore errors in the rc file. */
1564 if (*pnt != '=') {
1565 fprintf(stderr, _("%s:%d: equals sign required after '%.*s'\n"),
1566 filename, linum,
1567 /* XXX Should not be > int */
1568 (int)(name_end-name), name);
1569 continue;
1570 }
1571 /* Skip pas the = sign, and any white space following it */
1572 pnt++; /* Skip past '=' sign */
1573 while (*pnt == ' ' || *pnt == '\t')
1574 pnt++;
1575
1576 /* now it is safe to NUL terminate the name */
1577
1578 *name_end = 0;
1579
1580 /* Now get rid of trailing newline */
1581
1582 pnt1 = pnt;
1583 while (*pnt1) {
1584 if (*pnt1 == '\n') {
1585 *pnt1 = 0;
1586 break;
1587 }
1588 pnt1++;
1589 }
1590 /* OK, now figure out which option we have */
1591 for (rco = rcopt; rco->tag; rco++) {
1592 if (strcmp(rco->tag, name) == 0) {
1593 *rco->variable = e_strdup(pnt);
1594 break;
1595 }
1596 }
1597 if (rco->tag == NULL) {
1598 fprintf(stderr, _("%s:%d: field name \"%s\" unknown\n"),
1599 filename, linum,
1600 name);
1601 }
1602 }
1603 if (ferror(rcfile))
1604 errmsg(_("Read error on '%s'.\n"), filename);
1605 fclose(rcfile);
1606 }
1607
1608 char *path_table_l = NULL;
1609 char *path_table_m = NULL;
1610
1611 char *jpath_table_l = NULL;
1612 char *jpath_table_m = NULL;
1613
1614 int goof = 0;
1615
1616 #ifndef TRUE
1617 #define TRUE 1
1618 #endif
1619
1620 #ifndef FALSE
1621 #define FALSE 0
1622 #endif
1623
1624 LOCAL void
1625 susage(excode)
1626 int excode;
1627 {
1628 const char *program_name = "mkisofs";
1629
1630 #ifdef USE_FIND
1631 fprintf(stderr, _("Usage: %s [options] [-find] file... [find expression]\n"), program_name);
1632 #else
1633 fprintf(stderr, _("Usage: %s [options] file...\n"), program_name);
1634 #endif
1635 fprintf(stderr, _("\nUse %s -help\n"), program_name);
1636 fprintf(stderr, _("to get a list all of valid options.\n"));
1637 #ifdef USE_FIND
1638 fprintf(stderr, _("\nUse %s -find -help\n"), program_name);
1639 fprintf(stderr, _("to get a list of all valid -find options.\n"));
1640 #endif
1641 error(_("\nMost important Options:\n"));
1642 error(_(" -posix-H Follow sylinks encountered on command line\n"));
1643 error(_(" -posix-L Follow all symlinks\n"));
1644 error(_(" -posix-P Do not follow symlinks (default)\n"));
1645 error(_(" -o FILE, -output FILE Set output file name\n"));
1646 error(_(" -R, -rock Generate Rock Ridge directory information\n"));
1647 error(_(" -r, -rational-rock Generate rationalized Rock Ridge directory info\n"));
1648 error(_(" -J, -joliet Generate Joliet directory information\n"));
1649 error(_(" -print-size Print estimated filesystem size and exit\n"));
1650 #ifdef UDF
1651 error(_(" -UDF Generate UDF file system\n"));
1652 #endif
1653 #ifdef DVD_AUD_VID
1654 error(_(" -dvd-audio Generate DVD-Audio compliant UDF file system\n"));
1655 error(_(" -dvd-video Generate DVD-Video compliant UDF file system\n"));
1656 error(_(" -dvd-hybrid Generate a hybrid (DVD-Audio/DVD-Video) compliant UDF file system\n"));
1657 #endif
1658 error(_(" -iso-level LEVEL Set ISO9660 level (1..3) or 4 for ISO9660 v 2\n"));
1659 error(_(" -V ID, -volid ID Set Volume ID\n"));
1660 error(_(" -graft-points Allow to use graft points for filenames\n"));
1661 error(_(" -M FILE, -prev-session FILE Set path to previous session to merge\n"));
1662
1663 exit(excode);
1664 }
1665
1666 const char *optend __PR((const char *fmt));
1667 const char *
1668 optend(fmt)
1669 const char *fmt;
1670 {
1671 int c;
1672
1673 for (; *fmt != '\0'; fmt++) {
1674 c = *fmt;
1675 if (c == '\\') {
1676 if (*++fmt == '\0')
1677 break;
1678 continue;
1679 }
1680 if (c == ',' || c == '%' || c == '*' || c == '?' ||
1681 c == '#' || c == '&' || c == '~' || c == '+')
1682 break;
1683
1684 }
1685 return (fmt);
1686 }
1687
1688 int printopts __PR((FILE *f, const char *fmt, const char *arg, int twod));
1689 int
1690 printopts(f, fmt, arg, twod)
1691 FILE *f;
1692 const char *fmt;
1693 const char *arg;
1694 int twod;
1695 {
1696 const char *p;
1697 int len = 0;
1698 int optlen;
1699 int arglen = 0;
1700
1701 if (arg) {
1702 if (*arg == '-' || *arg == '\\')
1703 arg++;
1704
1705 if (*arg == '\1') {
1706 p = ++arg;
1707 while (*p != '\0' && *p != '\1' && *p != '\2')
1708 p++;
1709 arglen = p - arg;
1710 if (arglen == 0)
1711 arg = NULL;
1712 } else {
1713 arg = NULL;
1714 }
1715 }
1716 for (p = optend(fmt); p > fmt; p = optend(fmt)) {
1717 optlen = p - fmt;
1718 len += fprintf(f, "%s%.*s%s%.*s",
1719 *fmt == '+' ? "" :
1720 (optlen > 1 && twod) ? "--" : "-",
1721 (int)(p - fmt), fmt,
1722 arg != NULL ? " " : "",
1723 arglen, arg != NULL ? arg : "");
1724 fmt = p;
1725 while (*fmt != '\0' && *fmt != ',')
1726 fmt++;
1727 if (*fmt == ',') {
1728 fmt++;
1729 len += fprintf(f, ", ");
1730 }
1731 }
1732 return (len);
1733 }
1734
1735 const char *docstr __PR((const char *str, int *no_help));
1736 const char *
1737 docstr(str, no_help)
1738 const char *str;
1739 int *no_help;
1740 {
1741 if (no_help)
1742 *no_help = 0;
1743 if (str == NULL)
1744 return (str);
1745
1746 if (*str == '-' || *str == '\\')
1747 str++;
1748
1749 if (*str == '\1') {
1750 str++;
1751 while (*str != '\0' && *str != '\1' && *str != '\2')
1752 str++;
1753 }
1754 if (*str == '\1') {
1755 str++;
1756 } else if (*str == '\2') {
1757 str++;
1758 if (no_help)
1759 *no_help = 1;
1760 }
1761
1762 if (*str == '\0')
1763 return (NULL);
1764 return (str);
1765 }
1766
1767 LOCAL void
1768 usage(excode)
1769 int excode;
1770 {
1771 const char *program_name = "mkisofs";
1772
1773 int i;
1774
1775 #ifdef USE_FIND
1776 fprintf(stderr, _("Usage: %s [options] [-find] file... [find expression]\n"), program_name);
1777 #else
1778 fprintf(stderr, _("Usage: %s [options] file...\n"), program_name);
1779 #endif
1780
1781 fprintf(stderr, _("Options:\n"));
1782 for (i = 0; i < (int)OPTION_COUNT; i++) {
1783 if (docstr(mki_options[i].doc, NULL) != NULL) {
1784 int len;
1785 int j;
1786
1787 fprintf(stderr, " ");
1788 len = 2;
1789 j = i;
1790 do {
1791 int twodash;
1792 int no_help;
1793 const char *doc;
1794
1795 doc = mki_options[j].doc;
1796 twodash = (doc != NULL && *doc == '-');
1797 doc = docstr(doc, &no_help);
1798
1799 if (!no_help) {
1800 /*
1801 * If more options for one doc, then
1802 * print a comma as separator.
1803 */
1804 if (j > i)
1805 len += fprintf(stderr, ", ");
1806 len += printopts(stderr,
1807 mki_options[j].opt.ga_format,
1808 mki_options[j].doc,
1809 twodash);
1810 }
1811 ++j;
1812 }
1813 while (j < (int)OPTION_COUNT &&
1814 docstr(mki_options[j].doc, NULL) == NULL);
1815
1816 if (len >= 30) {
1817 fprintf(stderr, "\n");
1818 len = 0;
1819 }
1820 for (; len < 30; len++)
1821 fputc(' ', stderr);
1822
1823 fprintf(stderr, "%s\n",
1824 docstr(mki_options[i].doc, NULL));
1825 }
1826 }
1827 exit(excode);
1828 }
1829
1830
1831 /*
1832 * Fill in date in the iso9660 format
1833 * This takes 7 bytes and supports year 1900 .. 2155 with 1 second granularity
1834 *
1835 * The standards state that the timezone offset is in multiples of 15
1836 * minutes, and is what you add to GMT to get the localtime. The U.S.
1837 * is always at a negative offset, from -5h to -8h (can vary a little
1838 * with DST, I guess). The Linux iso9660 filesystem has had the sign
1839 * of this wrong for ages (mkisofs had it wrong too until February 1997).
1840 */
1841 EXPORT int
1842 iso9660_date(result, crtime)
1843 char *result;
1844 time_t crtime;
1845 {
1846 struct tm local;
1847 struct tm gmt;
1848
1849 local = *localtime(&crtime);
1850 gmt = *gmtime(&crtime);
1851
1852 result[0] = local.tm_year;
1853 result[1] = local.tm_mon + 1;
1854 result[2] = local.tm_mday;
1855 result[3] = local.tm_hour;
1856 result[4] = local.tm_min;
1857 result[5] = local.tm_sec;
1858
1859 local.tm_min -= gmt.tm_min;
1860 local.tm_hour -= gmt.tm_hour;
1861 local.tm_yday -= gmt.tm_yday;
1862 local.tm_year -= gmt.tm_year;
1863 if (local.tm_year) /* Hit new-year limit */
1864 local.tm_yday = local.tm_year; /* yday = +-1 */
1865
1866 result[6] = (local.tm_min + 60 *
1867 (local.tm_hour + 24 * local.tm_yday)) / 15;
1868
1869 return (0);
1870 }
1871
1872 /*
1873 * Fill in date in the iso9660 long format
1874 * This takes 17 bytes and supports year 0 .. 9999 with 10ms granularity
1875 * If iso9660_ldate() is called with gmtoff set to -100, the gmtoffset for
1876 * the related time is computed via localtime(). For the modification
1877 * date in the PVD, the date and the GMT offset may be defined via the
1878 * -modification-date command line option.
1879 */
1880 EXPORT int
1881 iso9660_ldate(result, crtime, nsec, gmtoff)
1882 char *result;
1883 time_t crtime;
1884 int nsec;
1885 int gmtoff;
1886 {
1887 struct tm local;
1888 struct tm gmt;
1889
1890 local = *localtime(&crtime);
1891 gmt = *gmtime(&crtime);
1892
1893 /*
1894 * There was a comment here about breaking in the year 2000.
1895 * That's not true, in 2000 tm_year == 100, so 1900+tm_year == 2000.
1896 */
1897 sprintf(result, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%2.2d",
1898 1900 + local.tm_year,
1899 local.tm_mon + 1, local.tm_mday,
1900 local.tm_hour, local.tm_min, local.tm_sec,
1901 nsec / 10000000);
1902
1903 if (gmtoff == -100) {
1904 local.tm_min -= gmt.tm_min;
1905 local.tm_hour -= gmt.tm_hour;
1906 local.tm_yday -= gmt.tm_yday;
1907 local.tm_year -= gmt.tm_year;
1908 if (local.tm_year) /* Hit new-year limit */
1909 local.tm_yday = local.tm_year; /* yday = +-1 */
1910
1911 result[16] = (local.tm_min + 60 *
1912 (local.tm_hour + 24 * local.tm_yday)) / 15;
1913 } else {
1914 result[16] = gmtoff;
1915 }
1916 return (0);
1917 }
1918
1919 /* hide "./rr_moved" if all its contents are hidden */
1920 LOCAL void
1921 hide_reloc_dir()
1922 {
1923 struct directory_entry *s_entry;
1924
1925 for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) {
1926 if (strcmp(s_entry->name, ".") == 0 ||
1927 strcmp(s_entry->name, "..") == 0)
1928 continue;
1929
1930 if ((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
1931 return;
1932 }
1933
1934 /* all entries are hidden, so hide this directory */
1935 reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
1936 reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY;
1937 }
1938
1939 /*
1940 * get pathnames from the command line, and then from given file
1941 */
1942 LOCAL char *
1943 get_pnames(argc, argv, opt, pname, pnsize, fp)
1944 int argc;
1945 char * const *argv;
1946 int opt;
1947 char *pname;
1948 int pnsize;
1949 FILE *fp;
1950 {
1951 int len;
1952
1953 /* we may of already read the first line from the pathnames file */
1954 if (save_pname) {
1955 save_pname = 0;
1956 return (pname);
1957 }
1958
1959 #ifdef USE_FIND
1960 if (dofind && opt < (find_pav - argv))
1961 return (argv[opt]);
1962 else if (!dofind && opt < argc)
1963 return (argv[opt]);
1964 #else
1965 if (opt < argc)
1966 return (argv[opt]);
1967 #endif
1968
1969 if (fp == NULL)
1970 return ((char *)0);
1971
1972 if (fgets(pname, pnsize, fp)) {
1973 /* Discard newline */
1974 len = strlen(pname);
1975 if (pname[len - 1] == '\n') {
1976 pname[len - 1] = '\0';
1977 }
1978 return (pname);
1979 }
1980 return ((char *)0);
1981 }
1982
1983 EXPORT int
1984 main(argc, argv)
1985 int argc;
1986 char *argv[];
1987 {
1988 int cac = argc;
1989 char * const *cav = argv;
1990
1991 struct directory_entry de;
1992
1993 #ifdef HAVE_SBRK
1994 unsigned long mem_start;
1995 #endif
1996 struct stat statbuf;
1997 struct iso_directory_record *mrootp = NULL;
1998 struct output_fragment *opnt;
1999 struct ga_flags flags[OPTION_COUNT + 1];
2000 int c;
2001 int n;
2002 char *node = NULL;
2003 FILE *pfp = NULL;
2004 char pname[2*PATH_MAX + 1 + 1]; /* may be too short */
2005 char *arg; /* if '\\' present */
2006 char nodename[PATH_MAX + 1];
2007 int no_path_names = 1;
2008 int warn_violate = 0;
2009 int have_cmd_line_pathspec = 0;
2010 int rationalize_all = 0;
2011 int argind = 0;
2012 #ifdef APPLE_HYB
2013 int hfs_ct = 0;
2014 #endif /* APPLE_HYB */
2015
2016
2017 #ifdef __EMX__
2018 /* This gives wildcard expansion with Non-Posix shells with EMX */
2019 _wildcard(&argc, &argv);
2020 #endif
2021 save_args(argc, argv);
2022
2023 #if defined(USE_NLS)
2024 setlocale(LC_ALL, "");
2025 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
2026 #define TEXT_DOMAIN "mkisofs" /* Use this only if it weren't */
2027 #endif
2028 arg = searchfileinpath("share/locale", F_OK,
2029 SIP_ANY_FILE|SIP_NO_PATH, NULL);
2030 if (arg)
2031 (void) bindtextdomain(TEXT_DOMAIN, arg);
2032 else
2033 #ifdef PROTOTYPES
2034 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
2035 #else
2036 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
2037 #endif
2038 (void) textdomain(TEXT_DOMAIN);
2039 #endif
2040
2041
2042 if (argc < 2) {
2043 errmsgno(EX_BAD, _("Missing pathspec.\n"));
2044 susage(1);
2045 }
2046 /* Get the defaults from the .mkisofsrc file */
2047 read_rcfile(argv[0]);
2048
2049 {
2050 int i;
2051
2052 for (i = 0; i < (int)OPTION_COUNT; i++) {
2053 flags[i] = mki_options[i].opt;
2054 }
2055 flags[i].ga_format = NULL;
2056 gl_flags = flags;
2057 }
2058 time(&begun);
2059 gettimeofday(&tv_begun, NULL);
2060 modification_date.l_sec = tv_begun.tv_sec;
2061 modification_date.l_usec = tv_begun.tv_usec;
2062 modification_date.l_gmtoff = -100;
2063
2064 #if defined(IS_CYGWIN)
2065 /*
2066 * If we have 64 bit inode numbers, Cygwin should be able to work
2067 * correctly on NTFS.
2068 */
2069 if (sizeof (ino_t) >= 8)
2070 cache_inodes = 1;
2071 #endif
2072 cac--;
2073 cav++;
2074 c = getvargs(&cac, &cav, GA_NO_PROPS, flags);
2075 if (c < 0) {
2076 if (c == BADFLAG && strchr(cav[0], '=')) {
2077 argind = argc - cac;
2078 goto args_ok;
2079 }
2080 error(_("Bad Option '%s' (error %d %s).\n"),
2081 cav[0], c, getargerror(c));
2082 susage(EX_BAD);
2083 }
2084 args_ok:
2085 if (argind == 0)
2086 argind = argc - cac;
2087 path_ind = argind;
2088 if (cac > 0)
2089 have_cmd_line_pathspec = 1;
2090 if (help)
2091 usage(0);
2092 if (pversion) {
2093 printf(_("mkisofs %s (%s-%s-%s)\n\n\
2094 Copyright (C) 1993-1997 %s\n\
2095 Copyright (C) 1997-2016 %s\n"),
2096 version_string,
2097 HOST_CPU, HOST_VENDOR, HOST_OS,
2098 _("Eric Youngdale"),
2099 _("Joerg Schilling"));
2100 #ifdef APPLE_HYB
2101 printf(_("Copyright (C) 1997-2001 James Pearson\n"));
2102 #endif
2103 #ifdef UDF
2104 printf(_("Copyright (C) 2006 HELIOS Software GmbH\n"));
2105 #endif
2106 #ifdef OPTION_SILO_BOOT
2107 printf(_("Warning: this is unofficial (modified) version of mkisofs that incorporates\n"));
2108 printf(_(" support for a non Sparc compliant boot method called SILO.\n"));
2109 printf(_(" The official method to create Sparc boot CDs is to use -sparc-boot\n"));
2110 printf(_(" In case of problems first test with an official version of mkisofs.\n"));
2111 #endif
2112 exit(0);
2113 }
2114 #ifdef USE_FIND
2115 if (dofind) {
2116 finda_t fa;
2117
2118 cac = find_ac;
2119 cav = find_av;
2120 find_firstprim(&cac, &cav);
2121 find_pac = cac;
2122 find_pav = cav;
2123 argind = argc - find_ac;
2124
2125 if (cac > 0) {
2126 find_argsinit(&fa);
2127 fa.walkflags = walkflags;
2128 fa.Argc = cac;
2129 fa.Argv = (char **)cav;
2130 find_node = find_parse(&fa);
2131 if (fa.primtype == FIND_ERRARG)
2132 comexit(fa.error);
2133 if (fa.primtype != FIND_ENDARGS)
2134 comerrno(EX_BAD, _("Incomplete expression.\n"));
2135 plusp = fa.plusp;
2136 find_patlen = fa.patlen;
2137 walkflags = fa.walkflags;
2138 maxdepth = fa.maxdepth;
2139 mindepth = fa.mindepth;
2140
2141 if (find_node &&
2142 !(check_image || print_size) &&
2143 (outfile == NULL ||
2144 (outfile[0] == '-' && outfile[1] == '\0'))) {
2145 if (find_pname(find_node, "-exec") ||
2146 find_pname(find_node, "-exec+") ||
2147 find_pname(find_node, "-ok"))
2148 comerrno(EX_BAD,
2149 _("Cannot -exec with '-o -'.\n"));
2150 }
2151 }
2152
2153 if (find_ac <= 0 || find_ac == find_pac) {
2154 errmsgno(EX_BAD, _("Missing pathspec for -find.\n"));
2155 susage(EX_BAD);
2156 }
2157 }
2158 #endif
2159 #ifdef DVD_AUD_VID
2160
2161 dvd_aud_vid_flag = (dvd_audio ? DVD_SPEC_AUDIO : 0)
2162 | (dvd_hybrid ? DVD_SPEC_HYBRD : 0)
2163 | (dvd_video ? DVD_SPEC_VIDEO : 0);
2164
2165 #endif
2166
2167 if (abstract) {
2168 if (strlen(abstract) > 37) {
2169 comerrno(EX_BAD,
2170 _("Abstract filename string too long (cur. %lld max. 37 chars).\n"),
2171 (Llong)strlen(abstract));
2172 }
2173 }
2174 if (appid) {
2175 if (strlen(appid) > 128) {
2176 comerrno(EX_BAD,
2177 _("Application-id string too long (cur. %lld max. 128 chars).\n"),
2178 (Llong)strlen(appid));
2179 }
2180 }
2181 if (biblio) {
2182 if (strlen(biblio) > 37) {
2183 comerrno(EX_BAD,
2184 _("Bibliographic filename string too long (cur. %lld max. 37 chars).\n"),
2185 (Llong)strlen(biblio));
2186 }
2187 }
2188 if (!cache_inodes) {
2189 correct_inodes = FALSE;
2190 if (use_RockRidge) {
2191 errmsgno(EX_BAD,
2192 _("Warning: Cannot write inode/link information with -no-cache-inodes.\n"));
2193 } else {
2194 errmsgno(EX_BAD,
2195 _("Warning: Cannot add inode hints with -no-cache-inodes.\n"));
2196 }
2197 }
2198 if (!correct_inodes)
2199 rrip112 = FALSE;
2200 if (check_image) {
2201 check_session++;
2202 check_oldnames++;
2203 merge_image = check_image;
2204 outfile = DEV_NULL;
2205 /*
2206 * cdrecord_data is handled specially in multi.c
2207 * as we cannot write to all strings.
2208 * If mkisofs is called with -C xx,yy
2209 * our default is overwritten.
2210 */
2211 /* cdrecord_data = "0,0";*/
2212 }
2213 if (copyright) {
2214 if (strlen(copyright) > 37) {
2215 comerrno(EX_BAD,
2216 _("Copyright filename string too long (cur. %lld max. 37 chars).\n"),
2217 (Llong)strlen(copyright));
2218 }
2219 }
2220 if (genboot_image)
2221 use_genboot++;
2222 if (boot_catalog)
2223 use_eltorito++;
2224 else
2225 boot_catalog = BOOT_CATALOG_DEFAULT;
2226 if (omit_period && iso9660_level < 4)
2227 warn_violate++;
2228 if (data_change_warn)
2229 errconfig("WARN|GROW|SHRINK *");
2230 if (dirmode_str) {
2231 char *end = 0;
2232
2233 rationalize++;
2234 use_RockRidge++;
2235 rationalize_dirmode++;
2236
2237 /*
2238 * If -new-dir-mode was specified, new_dir_mode is set
2239 * up later with a value that matches the -new-dir-mode arg.
2240 */
2241 new_dir_mode = dirmode_to_use = strtol(dirmode_str, &end, 8);
2242 if (!end || *end != 0 ||
2243 dirmode_to_use < 0 || dirmode_to_use > 07777) {
2244 comerrno(EX_BAD, _("Bad mode for -dir-mode\n"));
2245 }
2246 }
2247 if (disable_deep_reloc)
2248 RR_relocation_depth = 0xFFFFFFFF;
2249 if (filemode_str) {
2250 char *end = 0;
2251
2252 rationalize++;
2253 use_RockRidge++;
2254 rationalize_filemode++;
2255
2256 filemode_to_use = strtol(filemode_str, &end, 8);
2257 if (!end || *end != 0 ||
2258 filemode_to_use < 0 || filemode_to_use > 07777) {
2259 comerrno(EX_BAD, _("Bad mode for -file-mode\n"));
2260 }
2261 }
2262 #ifdef __warn_follow__
2263 if (follow_links) {
2264 errmsgno(EX_BAD,
2265 _("Warning: -follow-links does not always work correctly; be careful.\n"));
2266 }
2267 #endif
2268 if (gid_str) {
2269 char *end = 0;
2270
2271 rationalize++;
2272 use_RockRidge++;
2273 rationalize_gid++;
2274
2275 gid_to_use = strtol(gid_str, &end, 0);
2276 if (!end || *end != 0) {
2277 comerrno(EX_BAD, _("Bad value for -gid\n"));
2278 }
2279 }
2280 switch (iso9660_level) {
2281
2282 case 1:
2283 /*
2284 * Only on file section
2285 * 8.3 d or d1 characters for files
2286 * 8 d or d1 characters for directories
2287 */
2288 break;
2289 case 2:
2290 /*
2291 * Only on file section
2292 */
2293 break;
2294 case 3:
2295 /*
2296 * No restrictions
2297 */
2298 do_largefiles++;
2299 break;
2300 case 4:
2301 /*
2302 * This is ISO-9660:1988 (ISO-9660 version 2)
2303 */
2304 do_largefiles++;
2305 iso9660_namelen = MAX_ISONAME_V2; /* allow 207 chars */
2306 full_iso9660_filenames++; /* 31+ chars */
2307 omit_version_number++;
2308 RR_relocation_depth = 0xFFFFFFFF;
2309
2310 /*
2311 * From -U ...
2312 */
2313 omit_period++; /* trailing dot */
2314 allow_leading_dots++;
2315 relaxed_filenames++; /* all chars */
2316 allow_lowercase++; /* even lowcase */
2317 allow_multidot++; /* > 1 dots */
2318 break;
2319
2320 default:
2321 comerrno(EX_BAD, _("Illegal iso9660 Level %d, use 1..3 or 4.\n"),
2322 iso9660_level);
2323 }
2324
2325 if (joliet_long) {
2326 use_Joliet++;
2327 jlen = JLONGMAX;
2328 }
2329 if (jcharset) {
2330 use_Joliet++;
2331 icharset = jcharset;
2332 }
2333 if (max_filenames && iso9660_level < 4) {
2334 iso9660_namelen = MAX_ISONAME_V1; /* allow 37 chars */
2335 full_iso9660_filenames++;
2336 omit_version_number++;
2337 warn_violate++;
2338 }
2339 if (allow_leading_dots && iso9660_level < 4)
2340 warn_violate++;
2341 if (omit_version_number && iso9660_level < 4)
2342 warn_violate++;
2343 if (new_dirmode_str) {
2344 char *end = 0;
2345
2346 rationalize++;
2347
2348 new_dir_mode = strtol(new_dirmode_str, &end, 8);
2349 if (!end || *end != 0 ||
2350 new_dir_mode < 0 || new_dir_mode > 07777) {
2351 comerrno(EX_BAD, _("Bad mode for -new-dir-mode\n"));
2352 }
2353 }
2354 if (sectype) {
2355 if (strcmp(sectype, "data") == 0)
2356 osecsize = 2048;
2357 else if (strcmp(sectype, "xa1") == 0)
2358 osecsize = 2056;
2359 else if (strcmp(sectype, "raw") == 0) {
2360 osecsize = 2352;
2361 comerrno(EX_BAD,
2362 _("Unsupported sector type '%s'.\n"),
2363 sectype);
2364 }
2365 }
2366 if (preparer) {
2367 if (strlen(preparer) > 128) {
2368 comerrno(EX_BAD, _("Preparer string too long (cur. %lld max. 128 chars).\n"),
2369 (Llong)strlen(preparer));
2370 }
2371 }
2372 if (publisher) {
2373 if (strlen(publisher) > 128) {
2374 comerrno(EX_BAD,
2375 _("Publisher string too long (cur. %lld max. 128 chars).\n"),
2376 (Llong)strlen(publisher));
2377 }
2378 }
2379 if (rationalize_rr) {
2380 rationalize_all++;
2381 use_RockRidge++;
2382 }
2383 if (stream_filename) {
2384 if (strlen(stream_filename) > MAX_ISONAME)
2385 comerrno(EX_BAD,
2386 _("stream-file-name too long (%llu), max is %d.\n"),
2387 (Ullong)strlen(stream_filename), MAX_ISONAME);
2388 if (strchr(stream_filename, '/'))
2389 comerrno(EX_BAD, _("Illegal character '/' in stream-file-name.\n"));
2390 iso9660_level = 4;
2391 } else {
2392 stream_filename = omit_version_number ? "STREAM.IMG" : "STREAM.IMG;1";
2393 }
2394 if (system_id) {
2395 if (strlen(system_id) > 32) {
2396 comerrno(EX_BAD,
2397 _("System ID string too long\n"));
2398 }
2399 }
2400 if (trans_tbl)
2401 generate_tables++;
2402 else
2403 trans_tbl = "TRANS.TBL";
2404 if (ucs_level < 1 || ucs_level > 3)
2405 comerrno(EX_BAD, _("Illegal UCS Level %d, use 1..3.\n"),
2406 ucs_level);
2407 #ifdef DVD_AUD_VID
2408 if (dvd_aud_vid_flag) {
2409 if (!use_udf)
2410 rationalize_udf++;
2411 }
2412 #endif
2413 #ifdef UDF
2414 if (rationalize_udf) {
2415 rationalize_all++;
2416 use_udf++;
2417 }
2418 #endif
2419 if (uid_str) {
2420 char *end = 0;
2421
2422 rationalize++;
2423 use_RockRidge++;
2424 rationalize_uid++;
2425
2426 uid_to_use = strtol(uid_str, &end, 0);
2427 if (!end || *end != 0) {
2428 comerrno(EX_BAD, _("Bad value for -uid\n"));
2429 }
2430 }
2431 if (untranslated_filenames && iso9660_level < 4) {
2432 /*
2433 * Minimal (only truncation of 31+ characters)
2434 * translation of filenames.
2435 *
2436 * Forces -l, -d, -N, -allow-leading-dots,
2437 * -relaxed-filenames,
2438 * -allow-lowercase, -allow-multidot
2439 *
2440 * This is for HP-UX, which does not recognize ANY
2441 * extentions (Rock Ridge, Joliet), causing pain when
2442 * loading software. pfs_mount can be used to read the
2443 * extensions, but the untranslated filenames can be
2444 * read by the "native" cdfs mounter. Completely
2445 * violates iso9660.
2446 */
2447 full_iso9660_filenames++; /* 31 chars */
2448 omit_period++; /* trailing dot */
2449 allow_leading_dots++;
2450 omit_version_number++;
2451 relaxed_filenames++; /* all chars */
2452 allow_lowercase++; /* even lowcase */
2453 allow_multidot++; /* > 1 dots */
2454 warn_violate++;
2455 }
2456 if (relaxed_filenames && iso9660_level < 4)
2457 warn_violate++;
2458 if (iso_translate == 0 && iso9660_level < 4)
2459 warn_violate++;
2460 if (allow_lowercase && iso9660_level < 4)
2461 warn_violate++;
2462 if (allow_multidot && iso9660_level < 4)
2463 warn_violate++;
2464 if (volume_id) {
2465 if (strlen(volume_id) > 32) {
2466 comerrno(EX_BAD,
2467 _("Volume ID string too long (cur. %lld max. 32 chars).\n"),
2468 (Llong)strlen(volume_id));
2469 }
2470 }
2471 if (volset_id) {
2472 if (strlen(volset_id) > 128) {
2473 comerrno(EX_BAD,
2474 _("Volume set ID string too long (cur. %lld max. 128 chars).\n"),
2475 (Llong)strlen(volset_id));
2476 }
2477 }
2478 if (volume_set_size) {
2479 if (volume_set_size <= 0) {
2480 comerrno(EX_BAD,
2481 _("Illegal Volume Set Size %d\n"), volume_set_size);
2482 }
2483 if (volume_set_size > 1) {
2484 comerrno(EX_BAD,
2485 _("Volume Set Size > 1 not yet supported\n"));
2486 }
2487 }
2488 if (volume_sequence_number) {
2489 if (volume_sequence_number > volume_set_size) {
2490 comerrno(EX_BAD,
2491 _("Volume set sequence number too big\n"));
2492 }
2493 }
2494 if (rationalize_xa) {
2495 rationalize_all++;
2496 use_XA++;
2497 }
2498 if (transparent_compression) {
2499 #ifdef VMS
2500 comerrno(EX_BAD,
2501 _("Transparent compression not supported with VMS\n"));
2502 #endif
2503 }
2504 #ifdef APPLE_HYB
2505 if (deftype) {
2506 hfs_ct++;
2507 if (strlen(deftype) != 4) {
2508 comerrno(EX_BAD,
2509 _("HFS default TYPE string has illegal length.\n"));
2510 }
2511 } else {
2512 deftype = APPLE_TYPE_DEFAULT;
2513 }
2514 if (defcreator) {
2515 hfs_ct++;
2516 if (strlen(defcreator) != 4) {
2517 comerrno(EX_BAD,
2518 _("HFS default CREATOR string has illegal length.\n"));
2519 }
2520 } else {
2521 defcreator = APPLE_CREATOR_DEFAULT;
2522 }
2523 if (afpfile && *afpfile != '\0')
2524 hfs_last = MAP_LAST;
2525 if (magic_file)
2526 hfs_last = MAG_LAST;
2527 if (nomacfiles) {
2528 errmsgno(EX_BAD,
2529 _("Warning: -no-mac-files no longer used ... ignoring\n"));
2530 }
2531 if (hfs_boot_file)
2532 gen_pt = 1;
2533 if (root_info)
2534 icon_pos = 1;
2535 if (hfs_icharset)
2536 use_mac_name = 1;
2537 if (hfs_parms)
2538 hfs_parms = e_strdup(hfs_parms);
2539
2540 if (apple_hyb && apple_ext) {
2541 comerrno(EX_BAD, _("Can't have both -apple and -hfs options\n"));
2542 }
2543 /*
2544 * if -probe, -macname, any hfs selection and/or mapping file is given,
2545 * but no HFS option, then select apple_hyb
2546 */
2547 if (!apple_hyb && !apple_ext) {
2548 if (*afpfile || probe || use_mac_name || hfs_select ||
2549 hfs_boot_file || magic_file ||
2550 hfs_ishidden() || gen_pt || autoname ||
2551 afe_size || icon_pos || hfs_ct ||
2552 hfs_icharset || hfs_ocharset) {
2553 apple_hyb = 1;
2554 #ifdef UDF
2555 if ((DO_XHFS & hfs_select) && use_udf) {
2556 donotwrite_macpart = 1;
2557 if (!no_apple_hyb) {
2558 error(
2559 _("Warning: no HFS hybrid will be created with -udf and --osx-hfs\n"));
2560 }
2561 }
2562 #endif
2563 }
2564 }
2565 #ifdef UDF
2566 if (!use_udf && create_udfsymlinks)
2567 create_udfsymlinks = 0;
2568 #if 0
2569 if (use_RockRidge && use_udf && create_udfsymlinks) {
2570 error(_("Warning: cannot create UDF symlinks with activated Rock Ridge\n"));
2571 create_udfsymlinks = 0;
2572 }
2573 #endif
2574 #endif
2575 if (no_apple_hyb) {
2576 donotwrite_macpart = 1;
2577 }
2578 if (apple_hyb && !donotwrite_macpart && do_largefiles > 0) {
2579 do_largefiles = 0;
2580 maxnonlarge = (off_t)0x7FFFFFFF;
2581 error(_("Warning: cannot support large files with -hfs\n"));
2582 }
2583 #ifdef UDF
2584 if (apple_hyb && use_udf && !donotwrite_macpart) {
2585 comerrno(EX_BAD, _("Can't have -hfs with -udf\n"));
2586 }
2587 #endif
2588 if (apple_ext && hfs_boot_file) {
2589 comerrno(EX_BAD, _("Can't have -hfs-boot-file with -apple\n"));
2590 }
2591 if (apple_ext && autoname) {
2592 comerrno(EX_BAD, _("Can't have -auto with -apple\n"));
2593 }
2594 if (apple_hyb && (use_sparcboot || use_sunx86boot)) {
2595 comerrno(EX_BAD, _("Can't have -hfs with -sparc-boot/-sunx86-boot\n"));
2596 }
2597 if (apple_hyb && use_genboot) {
2598 comerrno(EX_BAD, _("Can't have -hfs with -generic-boot\n"));
2599 }
2600 #ifdef PREP_BOOT
2601 if (apple_ext && use_prep_boot) {
2602 comerrno(EX_BAD, _("Can't have -prep-boot with -apple\n"));
2603 }
2604 #endif /* PREP_BOOT */
2605
2606 if (apple_hyb || apple_ext)
2607 apple_both = 1;
2608
2609 if (probe)
2610 /* we need to search for all types of Apple/Unix files */
2611 hfs_select = ~0;
2612
2613 if (apple_both && verbose && !(hfs_select || *afpfile || magic_file)) {
2614 errmsgno(EX_BAD,
2615 _("Warning: no Apple/Unix files will be decoded/mapped\n"));
2616 }
2617 if (apple_both && verbose && !afe_size &&
2618 (hfs_select & (DO_FEU | DO_FEL))) {
2619 errmsgno(EX_BAD,
2620 _("Warning: assuming PC Exchange cluster size of 512 bytes\n"));
2621 afe_size = 512;
2622 }
2623 if (apple_both) {
2624 /* set up the TYPE/CREATOR mappings */
2625 hfs_init(afpfile, 0, hfs_select);
2626 }
2627 if (apple_ext && !use_RockRidge) {
2628 #ifdef nonono
2629 /* use RockRidge to set the SystemUse field ... */
2630 use_RockRidge++;
2631 rationalize_all++;
2632 #else
2633 /* EMPTY */
2634 #endif
2635 }
2636 if (apple_ext && !(use_XA || use_RockRidge)) {
2637 comerrno(EX_BAD, _("Need either -XA/-xa or -R/-r for -apple to become active.\n"));
2638 }
2639 #endif /* APPLE_HYB */
2640
2641 /*
2642 * if the -hide-joliet option has been given, set the Joliet option
2643 */
2644 if (!use_Joliet && j_ishidden())
2645 use_Joliet++;
2646 #ifdef UDF
2647 /*
2648 * if the -hide-udf option has been given, set the UDF option
2649 */
2650 if (!use_udf && u_ishidden())
2651 use_udf++;
2652 #endif
2653
2654 if (rationalize_all) {
2655 rationalize++;
2656 rationalize_uid++;
2657 rationalize_gid++;
2658 rationalize_filemode++;
2659 rationalize_dirmode++;
2660 }
2661
2662 /*
2663 * XXX This is a hack until we have a decent separate name handling
2664 * XXX for UDF filenames.
2665 */
2666 #ifdef DVD_AUD_VID
2667 if (dvd_aud_vid_flag && use_Joliet) {
2668 use_Joliet = 0;
2669 error(_("Warning: Disabling Joliet support for DVD-Video/DVD-Audio.\n"));
2670 }
2671 #endif
2672 #ifdef UDF
2673 if (use_udf && !use_Joliet)
2674 jlen = 255;
2675 #endif
2676
2677 if (use_RockRidge && (iso9660_namelen > MAX_ISONAME_V2_RR))
2678 iso9660_namelen = MAX_ISONAME_V2_RR;
2679
2680 if (warn_violate)
2681 error(_("Warning: creating filesystem that does not conform to ISO-9660.\n"));
2682 if (iso9660_level > 3)
2683 error(_("Warning: Creating ISO-9660:1999 (version 2) filesystem.\n"));
2684 if (iso9660_namelen > LEN_ISONAME)
2685 error(_("Warning: ISO-9660 filenames longer than %d may cause buffer overflows in the OS.\n"),
2686 LEN_ISONAME);
2687 if (use_Joliet && !use_RockRidge) {
2688 error(_("Warning: creating filesystem with (nonstandard) Joliet extensions\n"));
2689 error(_(" but without (standard) Rock Ridge extensions.\n"));
2690 error(_(" It is highly recommended to add Rock Ridge\n"));
2691 }
2692 if (transparent_compression) {
2693 error(_("Warning: using transparent compression. This is a nonstandard Rock Ridge\n"));
2694 error(_(" extension. The resulting filesystem can only be transparently\n"));
2695 error(_(" read on Linux. On other operating systems you need to call\n"));
2696 error(_(" mkzftree by hand to decompress the files.\n"));
2697 }
2698 if (transparent_compression && !use_RockRidge) {
2699 error(_("Warning: transparent decompression is a Linux Rock Ridge extension, but\n"));
2700 error(_(" creating filesystem without Rock Ridge attributes; files\n"));
2701 error(_(" will not be transparently decompressed.\n"));
2702 }
2703
2704 #if defined(USE_NLS) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
2705 /*
2706 * If the locale has not been set up, nl_langinfo() returns the
2707 * name of the default codeset. This should be either "646",
2708 * "ISO-646", "ASCII", or something similar. Unfortunately, the
2709 * POSIX standard does not include a list of valid locale names,
2710 * so ne need to find all values in use.
2711 *
2712 * Observed:
2713 * Solaris "646"
2714 * Linux "ANSI_X3.4-1968" strange value from Linux...
2715 */
2716 if (icharset == NULL) {
2717 char *codeset = nl_langinfo(CODESET);
2718 Uchar *p;
2719
2720 if (codeset != NULL)
2721 codeset = e_strdup(codeset);
2722 if (codeset == NULL) /* Should not happen */
2723 goto setcharset;
2724 if (*codeset == '\0') /* Invalid locale */
2725 goto setcharset;
2726
2727 for (p = (Uchar *)codeset; *p != '\0'; p++) {
2728 if (islower(*p))
2729 *p = toupper(*p);
2730 }
2731 p = (Uchar *)strstr(codeset, "ISO");
2732 if (p != NULL) {
2733 if (*p == '_' || *p == '-')
2734 p++;
2735 codeset = (char *)p;
2736 }
2737 if (strcmp("646", codeset) != 0 &&
2738 strcmp("ASCII", codeset) != 0 &&
2739 strcmp("US-ASCII", codeset) != 0 &&
2740 strcmp("US_ASCII", codeset) != 0 &&
2741 strcmp("USASCII", codeset) != 0 &&
2742 strcmp("ANSI_X3.4-1968", codeset) != 0)
2743 icharset = nl_langinfo(CODESET);
2744
2745 if (codeset != NULL)
2746 free(codeset);
2747
2748 if (verbose > 0 && icharset != NULL) {
2749 error(_("Setting input-charset to '%s' from locale.\n"),
2750 icharset);
2751 }
2752 }
2753 setcharset:
2754 /*
2755 * Allow to switch off locale with -input-charset "".
2756 */
2757 if (icharset != NULL && *icharset == '\0')
2758 icharset = NULL;
2759 #endif
2760 if (icharset == NULL) {
2761 #if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
2762 icharset = "cp437";
2763 #else
2764 icharset = "default";
2765 #endif
2766 }
2767 in_nls = sic_open(icharset);
2768
2769 /*
2770 * set the output charset to the same as the input or the given output
2771 * charset
2772 */
2773 if (ocharset == NULL) {
2774 ocharset = in_nls ? in_nls->sic_name : NULL;
2775 }
2776 out_nls = sic_open(ocharset);
2777
2778 if (in_nls == NULL || out_nls == NULL) { /* Unknown charset specified */
2779 fprintf(stderr, _("Unknown charset '%s'.\nKnown charsets are:\n"),
2780 in_nls == NULL ? icharset : (ocharset ? ocharset : "NULL"));
2781 list_locales();
2782 exit(EX_BAD);
2783 }
2784 #ifdef USE_ICONV
2785 /*
2786 * XXX If we ever allow this, we neeed to fix the call to conv_charset()
2787 * XXX in name.c::iso9660_file_length().
2788 */
2789 if ((in_nls->sic_cd2uni != NULL || out_nls->sic_cd2uni != NULL) &&
2790 (in_nls->sic_name != out_nls->sic_name)) {
2791 errmsgno(EX_BAD,
2792 _("Iconv based locales may change file name length.\n"));
2793 comerrno(EX_BAD,
2794 _("Cannot yet have different -input-charset/-output-charset.\n"));
2795 }
2796 #endif
2797
2798 #ifdef APPLE_HYB
2799 if (hfs_icharset == NULL || strcmp(hfs_icharset, "mac-roman") == 0) {
2800 hfs_icharset = "cp10000";
2801 }
2802 hfs_inls = sic_open(hfs_icharset);
2803
2804 if (hfs_ocharset == NULL) {
2805 hfs_ocharset = hfs_inls ? hfs_inls->sic_name : NULL;
2806 }
2807 if (hfs_ocharset == NULL || strcmp(hfs_ocharset, "mac-roman") == 0) {
2808 hfs_ocharset = "cp10000";
2809 }
2810 hfs_onls = sic_open(hfs_ocharset);
2811