/[debburn]/nonameyet/branches/cleanup/mkisofs/mkisofs.c
ViewVC logotype

Contents of /nonameyet/branches/cleanup/mkisofs/mkisofs.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5