1 /* 2 * Program mkisofs.c - generate iso9660 filesystem based upon directory 3 * tree on hard disk. 4 5 Written by Eric Youngdale (1993). 6 7 Copyright 1993 Yggdrasil Computing, Incorporated 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 22 23 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 12/3/99 */ 24 25 #include <errno.h> 26 #include "config.h" 27 #include "mkisofs.h" 28 #include "match.h" 29 #include "apple_proto.h" 30 31 #ifdef linux 32 #include <getopt.h> 33 #else 34 #include "getopt.h" 35 #endif 36 37 #include "iso9660.h" 38 #include <ctype.h> 39 40 #ifndef VMS 41 #include <time.h> 42 #else 43 #include <sys/time.h> 44 #include "vms.h" 45 #endif 46 47 #include <stdlib.h> 48 #include <sys/stat.h> 49 50 #ifndef VMS 51 #ifdef HAVE_UNISTD_H 52 #include <unistd.h> 53 #endif 54 #endif 55 #include <fctldefs.h> 56 57 #if defined(__NetBSD__) || defined(__OpenBSD__) 58 #include <sys/time.h> 59 #include <sys/resource.h> 60 #endif 61 62 struct directory * root = NULL; 63 64 #ifdef APPLE_HYB 65 static char version_string[] = "mkhybrid 1.12b5.1"; 66 #else 67 static char version_string[] = "mkisofs 1.12b5"; 68 #endif /* APPLE_HYB */ 69 70 char * outfile; 71 FILE * discimage; 72 unsigned int next_extent = 0; 73 unsigned int last_extent = 0; 74 unsigned int session_start = 0; 75 unsigned int path_table_size = 0; 76 unsigned int path_table[4] = {0,}; 77 unsigned int path_blocks = 0; 78 79 80 unsigned int jpath_table_size = 0; 81 unsigned int jpath_table[4] = {0,}; 82 unsigned int jpath_blocks = 0; 83 84 struct iso_directory_record root_record; 85 struct iso_directory_record jroot_record; 86 87 char * extension_record = NULL; 88 int extension_record_extent = 0; 89 int extension_record_size = 0; 90 91 /* These variables are associated with command line options */ 92 int use_eltorito = 0; 93 int use_RockRidge = 0; 94 int use_Joliet = 0; 95 int verbose = 0; 96 int all_files = 0; 97 int follow_links = 0; 98 int rationalize = 0; 99 int generate_tables = 0; 100 int print_size = 0; 101 int split_output = 0; 102 char * preparer = PREPARER_DEFAULT; 103 char * publisher = PUBLISHER_DEFAULT; 104 char * appid = APPID_DEFAULT; 105 char * copyright = COPYRIGHT_DEFAULT; 106 char * biblio = BIBLIO_DEFAULT; 107 char * abstract = ABSTRACT_DEFAULT; 108 char * volset_id = VOLSET_ID_DEFAULT; 109 char * volume_id = VOLUME_ID_DEFAULT; 110 char * system_id = SYSTEM_ID_DEFAULT; 111 char * boot_catalog = BOOT_CATALOG_DEFAULT; 112 char * boot_image = BOOT_IMAGE_DEFAULT; 113 int volume_set_size = 1; 114 int volume_sequence_number = 1; 115 116 int omit_period = 0; /* Violates iso9660, but these are a pain */ 117 int transparent_compression = 0; /* So far only works with linux */ 118 int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/ 119 int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ 120 int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with 121 DOS */ 122 int allow_leading_dots = 0; /* DOS cannot read names with leading dots */ 123 int split_SL_component = 1; /* circumvent a bug in the SunOS driver */ 124 int split_SL_field = 1; /* circumvent a bug in the SunOS */ 125 126 #ifdef APPLE_HYB 127 int apple_hyb = 0; /* create HFS hybrid flag */ 128 int apple_ext = 0; /* create HFS extensions flag */ 129 int apple_both = 0; /* common flag (for above) */ 130 int hfs_extra = 0; /* extra HFS blocks added to end of ISO vol */ 131 int mac_name = 0; /* use Mac name for ISO/Joliet/RR flag */ 132 hce_mem *hce; /* libhfs/mkisofs extras */ 133 char *hfs_boot_file = 0; /* name of HFS boot file */ 134 int gen_pt = 0; /* generate HFS partition table */ 135 char *autoname = 0; /* AutoStart filename */ 136 char *magic_file = 0; /* name of magic file */ 137 int probe = 0; /* search files for HFS/Unix type */ 138 int nomacfiles = 0; /* don't look for Mac/Unix files */ 139 int hfs_select = 0; /* Mac/Unix types to select */ 140 int create_dt = 1; /* create the Desktp files */ 141 int bsize = 0; /* Apple File Exchange block size */ 142 int hfs_last = MAG_LAST; /* process magic file after map file */ 143 char *deftype = DEFTYPE; /* default Apple TYPE */ 144 char *defcreator = DEFCREATOR; /* default Apple CREATOR */ 145 char *trans_tbl = "TRANS.TBL"; /* default name for translation table */ 146 char *hfs_volume_id = NULL; /* HFS volume ID */ 147 char *hfs_bless = NULL; /* name of folder to 'bless' (System Folder) */ 148 149 #endif /* APPLE_HYB */ 150 151 struct rcopts{ 152 char * tag; 153 char ** variable; 154 }; 155 156 struct rcopts rcopt[] = { 157 {"PREP", &preparer}, 158 {"PUBL", &publisher}, 159 {"APPI", &appid}, 160 {"COPY", ©right}, 161 {"BIBL", &biblio}, 162 {"ABST", &abstract}, 163 {"VOLS", &volset_id}, 164 {"VOLI", &volume_id}, 165 {"SYSI", &system_id}, 166 #ifdef APPLE_HYB 167 {"TYPE", &deftype}, 168 {"CREATOR", &defcreator}, 169 #endif /* APPLE_HYB */ 170 {NULL, NULL} 171 }; 172 173 /* 174 * In case it isn't obvious, the option handling code was ripped off from GNU-ld. 175 */ 176 struct ld_option 177 { 178 /* The long option information. */ 179 struct option opt; 180 /* The short option with the same meaning ('\0' if none). */ 181 char shortopt; 182 /* The name of the argument (NULL if none). */ 183 const char *arg; 184 /* The documentation string. If this is NULL, this is a synonym for 185 the previous option. */ 186 const char *doc; 187 enum 188 { 189 /* Use one dash before long option name. */ 190 ONE_DASH, 191 /* Use two dashes before long option name. */ 192 TWO_DASHES, 193 /* Don't mention this option in --help output. */ 194 NO_HELP 195 } control; 196 }; 197 198 /* Codes used for the long options with no short synonyms. 150 isn't 199 special; it's just an arbitrary non-ASCII char value. */ 200 #define OPTION_HELP 150 201 #define OPTION_QUIET 151 202 #define OPTION_NOSPLIT_SL_COMPONENT 152 203 #define OPTION_NOSPLIT_SL_FIELD 153 204 #define OPTION_PRINT_SIZE 154 205 #define OPTION_SPLIT_OUTPUT 155 206 #define OPTION_ABSTRACT 156 207 #define OPTION_BIBLIO 157 208 #define OPTION_COPYRIGHT 158 209 #define OPTION_SYSID 159 210 #define OPTION_VOLSET 160 211 #define OPTION_VOLSET_SIZE 161 212 #define OPTION_VOLSET_SEQ_NUM 162 213 #define OPTION_I_HIDE 163 214 #define OPTION_J_HIDE 164 215 #define OPTION_LOG_FILE 165 216 #ifdef APPLE_HYB 217 #define OPTION_CAP 200 218 #define OPTION_NETA 201 219 #define OPTION_DBL 202 220 #define OPTION_ESH 203 221 #define OPTION_FE 204 222 #define OPTION_SGI 205 223 #define OPTION_MBIN 206 224 #define OPTION_SGL 207 225 /* aliases */ 226 #define OPTION_USH 208 227 #define OPTION_XIN 209 228 229 #define OPTION_PROBE 220 230 #define OPTION_MACNAME 221 231 #define OPTION_NOMACFILES 222 232 #define OPTION_BOOT_HFS_FILE 223 233 #define OPTION_MAGIC_FILE 224 234 235 #define OPTION_TRANS_TBL 225 236 237 #define OPTION_GEN_PT 226 238 239 #define OPTION_CREATE_DT 227 240 #define OPTION_HFS_HIDE 228 241 242 #define OPTION_AUTOSTART 229 243 #define OPTION_BSIZE 230 244 #define OPTION_HFS_VOLID 231 245 246 #define OPTION_H_LIST 240 247 #define OPTION_P_LIST 241 248 #define OPTION_I_LIST 242 249 #define OPTION_J_LIST 243 250 #define OPTION_X_LIST 244 251 252 #define OPTION_HFS_BLESS 245 253 #endif /* APPLE_HYB */ 254 255 static const struct ld_option ld_options[] = 256 { 257 { {"all-files", no_argument, NULL, 'a'}, 258 'a', NULL, "Process all files (don't skip backup files)", ONE_DASH }, 259 { {"abstract", required_argument, NULL, OPTION_ABSTRACT}, 260 '\0', "FILE", "Set Abstract filename" , ONE_DASH }, 261 { {"appid", required_argument, NULL, 'A'}, 262 'A', "ID", "Set Application ID" , ONE_DASH }, 263 { {"biblio", required_argument, NULL, OPTION_BIBLIO}, 264 '\0', "FILE", "Set Bibliographic filename" , ONE_DASH }, 265 { {"copyright", required_argument, NULL, OPTION_COPYRIGHT}, 266 '\0', "FILE", "Set Copyright filename" , ONE_DASH }, 267 { {"eltorito-boot", required_argument, NULL, 'b'}, 268 'b', "FILE", "Set El Torito boot image name" , ONE_DASH }, 269 { {"eltorito-catalog", required_argument, NULL, 'c'}, 270 'c', "FILE", "Set El Torito boot catalog name" , ONE_DASH }, 271 { {"cdwrite-params", required_argument, NULL, 'C'}, 272 'C', "PARAMS", "Magic paramters from cdrecord" , ONE_DASH }, 273 { {"omit-period", no_argument, NULL, 'd'}, 274 'd', NULL, "Omit trailing periods from filenames", ONE_DASH }, 275 { {"disable-deep-relocation", no_argument, NULL, 'D'}, 276 'D', NULL, "Disable deep directory relocation", ONE_DASH }, 277 { {"follow-links", no_argument, NULL, 'f'}, 278 'f', NULL, "Follow symbolic links", ONE_DASH }, 279 { {"help", no_argument, NULL, OPTION_HELP}, 280 '\0', NULL, "Print option help", ONE_DASH }, 281 { {"hide", required_argument, NULL, OPTION_I_HIDE}, 282 '\0', "GLOBFILE", "Hide ISO9660/RR file" , ONE_DASH }, 283 #ifdef APPLE_HYB 284 /* NON-HFS change */ 285 { {"hide-list", required_argument, NULL, OPTION_I_LIST}, 286 '\0', "FILE", "list of ISO9660/RR files to hide" , ONE_DASH }, 287 #endif /* APPLE_HYB */ 288 { {"hide-joliet", required_argument, NULL, OPTION_J_HIDE}, 289 '\0', "GLOBFILE", "Hide Joliet file" , ONE_DASH }, 290 #ifdef APPLE_HYB 291 /* NON-HFS change */ 292 { {"hide-joliet-list", required_argument, NULL, OPTION_J_LIST}, 293 '\0', "FILE", "List of Joliet files to hide" , ONE_DASH }, 294 #endif /* APPLE_HYB */ 295 { {NULL, required_argument, NULL, 'i'}, 296 'i', "ADD_FILES", "No longer supported" , TWO_DASHES }, 297 { {"joliet", no_argument, NULL, 'J'}, 298 'J', NULL, "Generate Joliet directory information", ONE_DASH }, 299 { {"full-iso9660-filenames", no_argument, NULL, 'l'}, 300 'l', NULL, "Allow full 32 character filenames for iso9660 names", ONE_DASH }, 301 { {"allow-leading-dots", no_argument, NULL, 'L'}, 302 'L', NULL, "Allow iso9660 filenames to start with '.'", ONE_DASH }, 303 { {"log-file", required_argument, NULL, OPTION_LOG_FILE}, 304 '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH }, 305 { {"exclude", required_argument, NULL, 'm'}, 306 'm', "GLOBFILE", "Exclude file name" , ONE_DASH }, 307 #ifdef APPLE_HYB 308 { {"exclude-list", required_argument, NULL, OPTION_X_LIST}, 309 'm', "FILE", "List of file names to exclude" , ONE_DASH }, 310 #endif /* APPLE_HYB */ 311 { {"prev-session", required_argument, NULL, 'M'}, 312 'M', "FILE", "Set path to previous session to merge" , ONE_DASH }, 313 { {"omit-version-number", no_argument, NULL, 'N'}, 314 'N', NULL, "Omit version number from iso9660 filename", ONE_DASH }, 315 { {"no-split-symlink-components", no_argument, NULL, 0}, 316 0, NULL, "Inhibit splitting symlink components" , ONE_DASH }, 317 { {"no-split-symlink-fields", no_argument, NULL, 0}, 318 0, NULL, "Inhibit splitting symlink fields" , ONE_DASH }, 319 { {"output", required_argument, NULL, 'o'}, 320 'o', "FILE", "Set output file name" , ONE_DASH }, 321 #ifdef APPLE_HYB 322 { {"path-list", required_argument, NULL, OPTION_P_LIST}, 323 '\0', "FILE", "list of pathnames to process" , ONE_DASH }, 324 #endif /* APPLE_HYB */ 325 { {"preparer", required_argument, NULL, 'p'}, 326 'p', "PREP", "Set Volume preparer" , ONE_DASH }, 327 { {"print-size", no_argument, NULL, OPTION_PRINT_SIZE}, 328 '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH }, 329 { {"publisher", required_argument, NULL, 'P'}, 330 'P', "PUB", "Set Volume publisher" , ONE_DASH }, 331 { {"quiet", no_argument, NULL, OPTION_QUIET}, 332 '\0', NULL, "Run quietly", ONE_DASH }, 333 { {"rational-rock", no_argument, NULL, 'r'}, 334 'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH }, 335 { {"rock", no_argument, NULL, 'R'}, 336 'R', NULL, "Generate Rock Ridge directory information", ONE_DASH }, 337 { {"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT}, 338 '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH }, 339 { {"sysid", required_argument, NULL, OPTION_SYSID}, 340 '\0', "ID", "Set System ID" , ONE_DASH }, 341 { {"translation-table", no_argument, NULL, 'T'}, 342 'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH }, 343 { {"verbose", no_argument, NULL, 'v'}, 344 'v', NULL, "Verbose", ONE_DASH }, 345 { {"volid", required_argument, NULL, 'V'}, 346 'V', "ID", "Set Volume ID" , ONE_DASH }, 347 { {"volset", required_argument, NULL, OPTION_VOLSET}, 348 '\0', "ID", "Set Volume set ID" , ONE_DASH }, 349 { {"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE}, 350 '\0', "#", "Set Volume set size" , ONE_DASH }, 351 { {"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM}, 352 '\0', "#", "Set Volume set sequence number" , ONE_DASH }, 353 { {"old-exclude", required_argument, NULL, 'x'}, 354 'x', "FILE", "Exclude file name(depreciated)" , ONE_DASH }, 355 #ifdef ERIC_neverdef 356 { {"transparent-compression", no_argument, NULL, 'z'}, 357 'z', NULL, "Enable transparent compression of files", ONE_DASH }, 358 #endif 359 #ifdef APPLE_HYB 360 { {"apple", no_argument, NULL, 'g'}, 361 'g', NULL, "Add Apple ISO9660 extensions", ONE_DASH }, 362 { {"hfs", no_argument, NULL, 'h'}, 363 'h', NULL, "Create ISO9660/HFS hybrid", ONE_DASH }, 364 { {"map", required_argument, NULL, 'H'}, 365 'H', "MAPPING_FILE", "Map file extensions to HFS TYPE/CREATOR", ONE_DASH}, 366 { {"magic", required_argument, NULL, OPTION_MAGIC_FILE}, 367 '\0', "FILE", "Magic file for HFS TYPE/CREATOR", ONE_DASH}, 368 { {"probe", no_argument, NULL, OPTION_PROBE}, 369 '\0', NULL, "Probe all files for Unix/HFS file type", ONE_DASH }, 370 { {"mac-name", no_argument, NULL, OPTION_MACNAME}, 371 '\0', NULL, "Use Macintosh name for ISO9660/Joliet/RockRidge file name", 372 ONE_DASH }, 373 { {"no-mac-files", no_argument, NULL, OPTION_NOMACFILES}, 374 '\0', NULL, "Do not look for Unix/Mac files", ONE_DASH }, 375 { {"boot-hfs-file", required_argument, NULL, OPTION_BOOT_HFS_FILE}, 376 '\0', "FILE", "Set HFS boot image name", ONE_DASH}, 377 { {"part", no_argument, NULL, OPTION_GEN_PT}, 378 '\0', NULL, "Generate HFS partition table", ONE_DASH }, 379 { {"cluster-size", required_argument, NULL, OPTION_BSIZE}, 380 '\0', "SIZE", "Cluster size for PC Exchange Macintosh files", ONE_DASH}, 381 { {"auto", required_argument, NULL, OPTION_AUTOSTART}, 382 '\0', "FILE", "Set HFS AutoStart file name", ONE_DASH}, 383 { {"no-desktop", no_argument, NULL, OPTION_CREATE_DT}, 384 '\0', NULL, "Do not create the HFS (empty) Desktop files", ONE_DASH }, 385 { {"hide-hfs", required_argument, NULL, OPTION_HFS_HIDE}, 386 '\0', "GLOBFILE", "Hide HFS file" , ONE_DASH }, 387 { {"hide-hfs-list", required_argument, NULL, OPTION_H_LIST}, 388 '\0', "GLOBFILE", "List of HFS files to hide" , ONE_DASH }, 389 { {"table-name", required_argument, NULL, OPTION_TRANS_TBL}, 390 '\0', "TABLE_NAME", "translation table file name", ONE_DASH }, 391 { {"hfs-volid", required_argument, NULL, OPTION_HFS_VOLID}, 392 '\0', "HFS_VOLID", "Volume name for the HFS partition", ONE_DASH }, 393 {{"hfs-bless", required_argument, NULL, OPTION_HFS_BLESS}, 394 '\0', "FOLDER_NAME", "Name of Folder to be blessed", ONE_DASH}, 395 { {"cap", no_argument, NULL, OPTION_CAP}, 396 '\0', NULL, "Look for AUFS CAP Macintosh files", TWO_DASHES }, 397 { {"netatalk", no_argument, NULL, OPTION_NETA}, 398 '\0', NULL, "Look for NETATALK Macintosh files", TWO_DASHES }, 399 { {"double", no_argument, NULL, OPTION_DBL}, 400 '\0', NULL, "Look for AppleDouble Macintosh files", TWO_DASHES }, 401 { {"ethershare", no_argument, NULL, OPTION_ESH}, 402 '\0', NULL, "Look for Helios EtherShare Macintosh files", TWO_DASHES }, 403 { {"exchange", no_argument, NULL, OPTION_FE}, 404 '\0', NULL, "Look for PC Exchange Macintosh files", TWO_DASHES }, 405 { {"sgi", no_argument, NULL, OPTION_SGI}, 406 '\0', NULL, "Look for SGI Macintosh files", TWO_DASHES }, 407 { {"macbin", no_argument, NULL, OPTION_MBIN}, 408 '\0', NULL, "Look for MacBinary Macintosh files", TWO_DASHES }, 409 { {"single", no_argument, NULL, OPTION_SGL}, 410 '\0', NULL, "Look for AppleSingle Macintosh files", TWO_DASHES }, 411 { {"ushare", no_argument, NULL, OPTION_USH}, 412 '\0', NULL, "Look for IPT UShare Macintosh files", TWO_DASHES }, 413 { {"xinet", no_argument, NULL, OPTION_XIN}, 414 '\0', NULL, "Look for XINET Macintosh files", TWO_DASHES }, 415 #endif /* APPLE_HYB */ 416 }; 417 418 #define OPTION_COUNT (sizeof ld_options / sizeof ld_options[0]) 419 420 #if defined(ultrix) || defined(_AUX_SOURCE) 421 char *strdup(s) 422 char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;} 423 #endif 424 425 void read_rcfile __PR((char * appname)); 426 void usage __PR((void)); 427 static void hide_reloc_dir __PR((void)); 428 429 void FDECL1(read_rcfile, char *, appname) 430 { 431 FILE * rcfile; 432 struct rcopts * rco; 433 char * pnt, *pnt1; 434 char linebuffer[256]; 435 static char rcfn[] = ".mkisofsrc"; 436 char filename[1000]; 437 int linum; 438 439 strcpy(filename, rcfn); 440 rcfile = fopen(filename, "r"); 441 if (!rcfile && errno != ENOENT) 442 perror(filename); 443 444 if (!rcfile) 445 { 446 pnt = getenv("MKISOFSRC"); 447 if (pnt && strlen(pnt) <= sizeof(filename)) 448 { 449 strcpy(filename, pnt); 450 rcfile = fopen(filename, "r"); 451 if (!rcfile && errno != ENOENT) 452 perror(filename); 453 } 454 } 455 456 if (!rcfile) 457 { 458 pnt = getenv("HOME"); 459 if (pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename)) 460 { 461 strcpy(filename, pnt); 462 strcat(filename, "/"); 463 strcat(filename, rcfn); 464 rcfile = fopen(filename, "r"); 465 if (!rcfile && errno != ENOENT) 466 perror(filename); 467 } 468 } 469 if (!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename)) 470 { 471 strcpy(filename, appname); 472 pnt = strrchr(filename, '/'); 473 if (pnt) 474 { 475 strcpy(pnt + 1, rcfn); 476 rcfile = fopen(filename, "r"); 477 if (!rcfile && errno != ENOENT) 478 perror(filename); 479 } 480 } 481 if (!rcfile) 482 return; 483 if ( verbose > 0 ) 484 { 485 fprintf(stderr, "Using \"%s\"\n", filename); 486 } 487 488 /* OK, we got it. Now read in the lines and parse them */ 489 linum = 0; 490 while (fgets(linebuffer, sizeof(linebuffer), rcfile)) 491 { 492 char *name; 493 char *name_end; 494 ++linum; 495 /* skip any leading white space */ 496 pnt = linebuffer; 497 while (*pnt == ' ' || *pnt == '\t') 498 ++pnt; 499 /* If we are looking at a # character, this line is a comment. */ 500 if (*pnt == '#') 501 continue; 502 /* The name should begin in the left margin. Make sure it is in 503 upper case. Stop when we see white space or a comment. */ 504 name = pnt; 505 while (*pnt && isalpha((unsigned char)*pnt)) 506 { 507 if(islower((unsigned char)*pnt)) 508 *pnt = toupper((unsigned char)*pnt); 509 pnt++; 510 } 511 if (name == pnt) 512 { 513 fprintf(stderr, "%s:%d: name required\n", filename, linum); 514 continue; 515 } 516 name_end = pnt; 517 /* Skip past white space after the name */ 518 while (*pnt == ' ' || *pnt == '\t') 519 pnt++; 520 /* silently ignore errors in the rc file. */ 521 if (*pnt != '=') 522 { 523 fprintf(stderr, "%s:%d: equals sign required\n", filename, linum); 524 continue; 525 } 526 /* Skip pas the = sign, and any white space following it */ 527 pnt++; /* Skip past '=' sign */ 528 while (*pnt == ' ' || *pnt == '\t') 529 pnt++; 530 531 /* now it is safe to NUL terminate the name */ 532 533 *name_end = 0; 534 535 /* Now get rid of trailing newline */ 536 537 pnt1 = pnt; 538 while (*pnt1) 539 { 540 if (*pnt1 == '\n') 541 { 542 *pnt1 = 0; 543 break; 544 } 545 pnt1++; 546 }; 547 /* OK, now figure out which option we have */ 548 for(rco = rcopt; rco->tag; rco++) { 549 if(strcmp(rco->tag, name) == 0) 550 { 551 *rco->variable = strdup(pnt); 552 break; 553 }; 554 } 555 if (rco->tag == NULL) 556 { 557 fprintf(stderr, "%s:%d: field name \"%s\" unknown\n", filename, linum, 558 name); 559 } 560 } 561 if (ferror(rcfile)) 562 perror(filename); 563 fclose(rcfile); 564 } 565 566 char * path_table_l = NULL; 567 char * path_table_m = NULL; 568 569 char * jpath_table_l = NULL; 570 char * jpath_table_m = NULL; 571 572 int goof = 0; 573 574 #ifndef TRUE 575 #define TRUE 1 576 #endif 577 578 #ifndef FALSE 579 #define FALSE 0 580 #endif 581 582 void usage(){ 583 #ifdef APPLE_HYB 584 const char * program_name = "mkhybrid"; 585 #else 586 const char * program_name = "mkisofs"; 587 #endif /* APPLE_HYB */ 588 589 #if 0 590 fprintf(stderr,"Usage:\n"); 591 fprintf(stderr, 592 "mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \ 593 [-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer]" 594 "[-P publisher] [ -A app_id ] [-z] \n \ 595 [-b boot_image_name] [-c boot_catalog-name] \ 596 [-x path -x path ...] path\n"); 597 #endif 598 599 int i; 600 /* const char **targets, **pp;*/ 601 602 fprintf (stderr, "Usage: %s [options] file...\n", program_name); 603 604 fprintf (stderr, "Options:\n"); 605 for (i = 0; i < OPTION_COUNT; i++) 606 { 607 if (ld_options[i].doc != NULL) 608 { 609 int comma; 610 int len; 611 int j; 612 613 fprintf (stderr, " "); 614 615 comma = FALSE; 616 len = 2; 617 618 j = i; 619 do 620 { 621 if (ld_options[j].shortopt != '\0' 622 && ld_options[j].control != NO_HELP) 623 { 624 fprintf (stderr, "%s-%c", comma ? ", " : "", ld_options[j].shortopt); 625 len += (comma ? 2 : 0) + 2; 626 if (ld_options[j].arg != NULL) 627 { 628 if (ld_options[j].opt.has_arg != optional_argument) 629 { 630 fprintf (stderr, " "); 631 ++len; 632 } 633 fprintf (stderr, "%s", ld_options[j].arg); 634 len += strlen (ld_options[j].arg); 635 } 636 comma = TRUE; 637 } 638 ++j; 639 } 640 while (j < OPTION_COUNT && ld_options[j].doc == NULL); 641 642 j = i; 643 do 644 { 645 if (ld_options[j].opt.name != NULL 646 && ld_options[j].control != NO_HELP) 647 { 648 fprintf (stderr, "%s-%s%s", 649 comma ? ", " : "", 650 ld_options[j].control == TWO_DASHES ? "-" : "", 651 ld_options[j].opt.name); 652 len += ((comma ? 2 : 0) 653 + 1 654 + (ld_options[j].control == TWO_DASHES ? 1 : 0) 655 + strlen (ld_options[j].opt.name)); 656 if (ld_options[j].arg != NULL) 657 { 658 fprintf (stderr, " %s", ld_options[j].arg); 659 len += 1 + strlen (ld_options[j].arg); 660 } 661 comma = TRUE; 662 } 663 ++j; 664 } 665 while (j < OPTION_COUNT && ld_options[j].doc == NULL); 666 667 if (len >= 30) 668 { 669 fprintf (stderr, "\n"); 670 len = 0; 671 } 672 673 for (; len < 30; len++) 674 fputc (' ', stderr); 675 676 fprintf (stderr, "%s\n", ld_options[i].doc); 677 } 678 } 679 exit(1); 680 } 681 682 683 /* 684 * Fill in date in the iso9660 format 685 * 686 * The standards state that the timezone offset is in multiples of 15 687 * minutes, and is what you add to GMT to get the localtime. The U.S. 688 * is always at a negative offset, from -5h to -8h (can vary a little 689 * with DST, I guess). The Linux iso9660 filesystem has had the sign 690 * of this wrong for ages (mkisofs had it wrong too for the longest time). 691 */ 692 int FDECL2(iso9660_date,char *, result, time_t, crtime){ 693 struct tm *local; 694 local = localtime(&crtime); 695 result[0] = local->tm_year; 696 result[1] = local->tm_mon + 1; 697 result[2] = local->tm_mday; 698 result[3] = local->tm_hour; 699 result[4] = local->tm_min; 700 result[5] = local->tm_sec; 701 702 /* 703 * Must recalculate proper timezone offset each time, 704 * as some files use daylight savings time and some don't... 705 */ 706 result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */ 707 local = gmtime(&crtime); 708 local->tm_year -= result[0]; 709 local->tm_yday -= result[6]; 710 local->tm_hour -= result[3]; 711 local->tm_min -= result[4]; 712 if (local->tm_year < 0) 713 { 714 local->tm_yday = -1; 715 } 716 else 717 { 718 if (local->tm_year > 0) local->tm_yday = 1; 719 } 720 721 result[6] = -(local->tm_min + 60*(local->tm_hour + 24*local->tm_yday)) / 15; 722 723 return 0; 724 } 725 726 /* hide "./rr_moved" if all its contents are hidden */ 727 static void 728 hide_reloc_dir() 729 { 730 struct directory_entry * s_entry; 731 732 for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) { 733 if(strcmp(s_entry->name,".")==0 || strcmp(s_entry->name,"..")==0) 734 continue; 735 736 if((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0) 737 return; 738 } 739 740 /* all entries are hidden, so hide this directory */ 741 reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY; 742 reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY; 743 } 744 745 /* get pathnames from the command line, and then from given file */ 746 static char * 747 FDECL5(get_pnames, int, argc, char **, argv, int, opt, char *, pname, FILE *, fp) 748 { 749 if (opt < argc) 750 return (argv[opt]); 751 752 if (fp == NULL) 753 return ((char *)0); 754 755 if (fscanf(fp, "%s", pname) != EOF) 756 return (pname); 757 758 return ((char *)0); 759 } 760 761 extern char * cdwrite_data; 762 763 int FDECL2(main, int, argc, char **, argv){ 764 struct directory_entry de; 765 #ifdef HAVE_SBRK 766 unsigned long mem_start; 767 #endif 768 struct stat statbuf; 769 char * scan_tree; 770 char * merge_image = NULL; 771 struct iso_directory_record * mrootp = NULL; 772 struct output_fragment * opnt; 773 int longind; 774 char shortopts[OPTION_COUNT * 3 + 2]; 775 struct option longopts[OPTION_COUNT + 1]; 776 int c; 777 char *log_file = 0; 778 #ifdef APPLE_HYB 779 char *afpfile = ""; /* mapping file for TYPE/CREATOR */ 780 char *pathnames = 0; 781 FILE *pfp = NULL; 782 char pname[1024], *arg; 783 int no_path_names = 0; 784 #endif /* APPLE_HYB */ 785 786 if (argc < 2) 787 usage(); 788 789 /* Get the defaults from the .mkisofsrc file */ 790 read_rcfile(argv[0]); 791 792 outfile = NULL; 793 794 /* 795 * Copy long option initialization from GNU-ld. 796 */ 797 /* Starting the short option string with '-' is for programs that 798 expect options and other ARGV-elements in any order and that care about 799 the ordering of the two. We describe each non-option ARGV-element 800 as if it were the argument of an option with character code 1. */ 801 { 802 int i, is, il; 803 shortopts[0] = '-'; 804 is = 1; 805 il = 0; 806 for (i = 0; i < OPTION_COUNT; i++) 807 { 808 if (ld_options[i].shortopt != '\0') 809 { 810 shortopts[is] = ld_options[i].shortopt; 811 ++is; 812 if (ld_options[i].opt.has_arg == required_argument 813 || ld_options[i].opt.has_arg == optional_argument) 814 { 815 shortopts[is] = ':'; 816 ++is; 817 if (ld_options[i].opt.has_arg == optional_argument) 818 { 819 shortopts[is] = ':'; 820 ++is; 821 } 822 } 823 } 824 if (ld_options[i].opt.name != NULL) 825 { 826 longopts[il] = ld_options[i].opt; 827 ++il; 828 } 829 } 830 shortopts[is] = '\0'; 831 longopts[il].name = NULL; 832 } 833 834 while ((c = getopt_long_only (argc, argv, shortopts, longopts, &longind)) != EOF) 835 switch (c) 836 { 837 case 1: 838 /* 839 * A filename that we take as input. 840 */ 841 optind--; 842 goto parse_input_files; 843 case 'C': 844 /* 845 * This is a temporary hack until cdwrite gets the proper hooks in 846 * it. 847 */ 848 cdwrite_data = optarg; 849 break; 850 case 'i': 851 fprintf(stderr, "-i option no longer supported.\n"); 852 exit(1); 853 break; 854 case 'J': 855 use_Joliet++; 856 break; 857 case 'a': 858 all_files++; 859 break; 860 case 'b': 861 use_eltorito++; 862 boot_image = optarg; /* pathname of the boot image on cd */ 863 if (boot_image == NULL) { 864 fprintf(stderr,"Required boot image pathname missing\n"); 865 exit(1); 866 } 867 break; 868 case 'c': 869 use_eltorito++; 870 boot_catalog = optarg; /* pathname of the boot image on cd */ 871 if (boot_catalog == NULL) { 872 fprintf(stderr,"Required boot catalog pathname missing\n"); 873 exit(1); 874 } 875 break; 876 case OPTION_ABSTRACT: 877 abstract = optarg; 878 if(strlen(abstract) > 37) { 879 fprintf(stderr,"Abstract filename string too long\n"); 880 exit(1); 881 }; 882 break; 883 case 'A': 884 appid = optarg; 885 if(strlen(appid) > 128) { 886 fprintf(stderr,"Application-id string too long\n"); 887 exit(1); 888 }; 889 break; 890 case OPTION_BIBLIO: 891 biblio = optarg; 892 if(strlen(biblio) > 37) { 893 fprintf(stderr,"Bibliographic filename string too long\n"); 894 exit(1); 895 }; 896 break; 897 case OPTION_COPYRIGHT: 898 copyright = optarg; 899 if(strlen(copyright) > 37) { 900 fprintf(stderr,"Copyright filename string too long\n"); 901 exit(1); 902 }; 903 break; 904 case 'd': 905 omit_period++; 906 break; 907 case 'D': 908 RR_relocation_depth = 32767; 909 break; 910 case 'f': 911 follow_links++; 912 break; 913 case 'l': 914 full_iso9660_filenames++; 915 break; 916 case 'L': 917 allow_leading_dots++; 918 break; 919 case OPTION_LOG_FILE: 920 log_file = optarg; 921 break; 922 case 'M': 923 merge_image = optarg; 924 break; 925 case 'N': 926 omit_version_number++; 927 break; 928 case 'o': 929 outfile = optarg; 930 break; 931 case 'p': 932 preparer = optarg; 933 if(strlen(preparer) > 128) { 934 fprintf(stderr,"Preparer string too long\n"); 935 exit(1); 936 }; 937 break; 938 case OPTION_PRINT_SIZE: 939 print_size++; 940 break; 941 case 'P': 942 publisher = optarg; 943 if(strlen(publisher) > 128) { 944 fprintf(stderr,"Publisher string too long\n"); 945 exit(1); 946 }; 947 break; 948 case OPTION_QUIET: 949 verbose = 0; 950 break; 951 case 'R': 952 use_RockRidge++; 953 break; 954 case 'r': 955 rationalize++; 956 use_RockRidge++; 957 break; 958 case OPTION_SPLIT_OUTPUT: 959 split_output++; 960 break; 961 case OPTION_SYSID: 962 system_id = optarg; 963 if(strlen(system_id) > 32) { 964 fprintf(stderr,"System ID string too long\n"); 965 exit(1); 966 }; 967 break; 968 #ifdef APPLE_HYB 969 case OPTION_TRANS_TBL: 970 trans_tbl = optarg; 971 /* fall through */ 972 #endif /* APPLE_HYB */ 973 case 'T': 974 generate_tables++; 975 break; 976 case 'V': 977 volume_id = optarg; 978 if(strlen(volume_id) > 32) { 979 fprintf(stderr,"Volume ID string too long\n"); 980 exit(1); 981 }; 982 break; 983 case OPTION_VOLSET: 984 volset_id = optarg; 985 if(strlen(volset_id) > 128) { 986 fprintf(stderr,"Volume set ID string too long\n"); 987 exit(1); 988 }; 989 break; 990 case OPTION_VOLSET_SIZE: 991 volume_set_size = atoi(optarg); 992 break; 993 case OPTION_VOLSET_SEQ_NUM: 994 volume_sequence_number = atoi(optarg); 995 if (volume_sequence_number > volume_set_size) { 996 fprintf(stderr,"Volume set sequence number too big\n"); 997 exit(1); 998 } 999 break; 1000 case 'v': 1001 verbose++; 1002 break; 1003 case 'z': 1004 #ifdef VMS 1005 fprintf(stderr,"Transparent compression not supported with VMS\n"); 1006 exit(1); 1007 #else 1008 transparent_compression++; 1009 #endif 1010 break; 1011 case 'x': 1012 case 'm': 1013 /* 1014 * Somehow two options to do basically the same thing got added somewhere along 1015 * the way. The 'match' code supports limited globbing, so this is the one 1016 * that got selected. Unfortunately the 'x' switch is probably more intuitive. 1017 */ 1018 add_match(optarg); 1019 break; 1020 case OPTION_I_HIDE: 1021 i_add_match(optarg); 1022 break; 1023 case OPTION_J_HIDE: 1024 j_add_match(optarg); 1025 break; 1026 case OPTION_HELP: 1027 usage (); 1028 exit (0); 1029 break; 1030 case OPTION_NOSPLIT_SL_COMPONENT: 1031 split_SL_component = 0; 1032 break; 1033 case OPTION_NOSPLIT_SL_FIELD: 1034 split_SL_field = 0; 1035 break; 1036 #ifdef APPLE_HYB 1037 case 'H': 1038 afpfile = optarg; 1039 hfs_last = MAP_LAST; 1040 break; 1041 case 'h': 1042 apple_hyb = 1; 1043 break; 1044 case 'g': 1045 apple_ext = 1; 1046 break; 1047 case OPTION_PROBE: 1048 probe = 1; 1049 break; 1050 case OPTION_MACNAME: 1051 mac_name = 1; 1052 break; 1053 case OPTION_NOMACFILES: 1054 nomacfiles = 1; 1055 break; 1056 case OPTION_BOOT_HFS_FILE: 1057 hfs_boot_file = optarg; 1058 /* fall through */ 1059 case OPTION_GEN_PT: 1060 gen_pt = 1; 1061 break; 1062 case OPTION_MAGIC_FILE: 1063 magic_file = optarg; 1064 hfs_last = MAG_LAST; 1065 break; 1066 case OPTION_AUTOSTART: 1067 autoname = optarg; 1068 /* gen_pt = 1; */ 1069 break; 1070 case OPTION_BSIZE: 1071 bsize = atoi(optarg); 1072 break; 1073 case OPTION_HFS_VOLID: 1074 hfs_volume_id = optarg; 1075 break; 1076 case OPTION_HFS_BLESS: 1077 hfs_bless = optarg; 1078 break; 1079 /* Mac/Unix types to include */ 1080 case OPTION_CAP: 1081 hfs_select |= DO_CAP; 1082 break; 1083 case OPTION_NETA: 1084 hfs_select |= DO_NETA; 1085 break; 1086 case OPTION_DBL: 1087 hfs_select |= DO_DBL; 1088 break; 1089 case OPTION_ESH: 1090 case OPTION_USH: 1091 hfs_select |= DO_ESH; 1092 break; 1093 case OPTION_FE: 1094 hfs_select |= DO_FEU; 1095 hfs_select |= DO_FEL; 1096 break; 1097 case OPTION_SGI: 1098 case OPTION_XIN: 1099 hfs_select |= DO_SGI; 1100 break; 1101 case OPTION_MBIN: 1102 hfs_select |= DO_MBIN; 1103 break; 1104 case OPTION_SGL: 1105 hfs_select |= DO_SGL; 1106 break; 1107 case OPTION_CREATE_DT: 1108 create_dt = 0; 1109 break; 1110 case OPTION_HFS_HIDE: 1111 hfs_add_match(optarg); 1112 break; 1113 case OPTION_H_LIST: 1114 hfs_add_list(optarg); 1115 break; 1116 /* NON-HFS change 1117 The next options will probably appear in mkisofs in the future */ 1118 case OPTION_P_LIST: 1119 pathnames = optarg; 1120 break; 1121 case OPTION_X_LIST: 1122 add_list(optarg); 1123 break; 1124 case OPTION_I_LIST: 1125 i_add_list(optarg); 1126 break; 1127 case OPTION_J_LIST: 1128 j_add_list(optarg); 1129 break; 1130 #endif /* APPLE_HYB */ 1131 default: 1132 usage(); 1133 exit(1); 1134 } 1135 1136 parse_input_files: 1137 1138 #if defined(__NetBSD__) || defined(__OpenBSD__) 1139 { 1140 struct rlimit rlp; 1141 if (getrlimit(RLIMIT_DATA,&rlp) == -1) 1142 perror("Warning: getrlimit"); 1143 else { 1144 rlp.rlim_cur=33554432; 1145 if (setrlimit(RLIMIT_DATA,&rlp) == -1) 1146 perror("Warning: setrlimit"); 1147 } 1148 } 1149 #endif 1150 #ifdef HAVE_SBRK 1151 mem_start = (unsigned long) sbrk(0); 1152 #endif 1153 1154 /* if the -hide-joliet option has been given, set the Joliet option */ 1155 if (!use_Joliet && j_ishidden()) 1156 use_Joliet++; 1157 1158 #ifdef APPLE_HYB 1159 if (apple_hyb && apple_ext) { 1160 fprintf(stderr,"can't have both -apple and -hfs options"); 1161 exit (1); 1162 } 1163 1164 /* if -probe, -macname, any hfs selection and/or mapping file is given, 1165 but no HFS option, then select apple_hyb */ 1166 if (!apple_hyb && !apple_ext) { 1167 if (*afpfile || probe || mac_name || nomacfiles || hfs_select || hfs_boot_file || magic_file || hfs_ishidden() || gen_pt || autoname || bsize) 1168 apple_hyb = 1; 1169 } 1170 1171 if (apple_ext && hfs_boot_file) { 1172 fprintf(stderr,"can't have -hfs-boot-file with -apple\n"); 1173 exit (1); 1174 } 1175 1176 if (hfs_select) 1177 /* if we have selected certain types of Mac/Unix files, then turn off 1178 probe and nomacfiles */ 1179 probe = nomacfiles = 0; 1180 1181 if (apple_hyb || apple_ext) 1182 apple_both = 1; 1183 1184 if (apple_both) { 1185 /* set up the TYPE/CREATOR mappings */ 1186 hfs_init(afpfile, 0, probe, nomacfiles, hfs_select); 1187 } 1188 1189 if (apple_ext && !use_RockRidge) { 1190 /* use RockRidge to set the SystemUse field ... */ 1191 use_RockRidge++; 1192 rationalize++; 1193 } 1194 1195 #endif /* APPLE_HYB */ 1196 1197 if(verbose > 1) fprintf(stderr,"%s\n", version_string); 1198 1199 if(cdwrite_data == NULL && merge_image != NULL) 1200 { 1201 fprintf(stderr,"Multisession usage bug: Must specify -C if -M is used.\n"); 1202 exit(0); 1203 } 1204 1205 if(cdwrite_data != NULL && merge_image == NULL) 1206 { 1207 fprintf(stderr,"Warning: -C specified without -M: old session data will not be merged.\n"); 1208 } 1209 1210 /* The first step is to scan the directory tree, and take some notes */ 1211 1212 scan_tree = argv[optind]; 1213 1214 1215 if(!scan_tree){ 1216 usage(); 1217 exit(1); 1218 }; 1219 1220 #ifndef VMS 1221 if(scan_tree[strlen(scan_tree)-1] != '/') { 1222 scan_tree = (char *) e_malloc(strlen(argv[optind])+2); 1223 strcpy(scan_tree, argv[optind]); 1224 strcat(scan_tree, "/"); 1225 }; 1226 #endif 1227 1228 if(use_RockRidge){ 1229 #if 1 1230 extension_record = generate_rr_extension_record("RRIP_1991A", 1231 "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", 1232 "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size); 1233 #else 1234 extension_record = generate_rr_extension_record("IEEE_P1282", 1235 "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", 1236 "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size); 1237 #endif 1238 } 1239 1240 if (log_file) { 1241 FILE *lfp; 1242 int i; 1243 1244 /* open log file - test that we can open OK */ 1245 if ((lfp = fopen(log_file, "w")) == NULL) { 1246 fprintf(stderr,"can't open logfile: %s\n", log_file); 1247 exit (1); 1248 } 1249 fclose(lfp); 1250 1251 /* redirect all stderr message to log_file */ 1252 fprintf(stderr, "re-directing all messages to %s\n", log_file); 1253 fflush(stderr); 1254 1255 /* associate stderr with the log file */ 1256 if (freopen(log_file, "w", stderr) == NULL) { 1257 fprintf(stderr,"can't open logfile: %s\n", log_file); 1258 exit (1); 1259 } 1260 if(verbose > 1) { 1261 for (i=0;i<argc;i++) 1262 fprintf(stderr,"%s ", argv[i]); 1263 1264 fprintf(stderr,"\n%s\n", version_string); 1265 } 1266 } 1267 1268 /* 1269 * See if boot catalog file exists in root directory, if not 1270 * we will create it. 1271 */ 1272 if (use_eltorito) 1273 init_boot_catalog(argv[optind]); 1274 1275 /* 1276 * Find the device and inode number of the root directory. 1277 * Record this in the hash table so we don't scan it more than 1278 * once. 1279 */ 1280 stat_filter(argv[optind], &statbuf); 1281 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); 1282 1283 memset(&de, 0, sizeof(de)); 1284 1285 de.filedir = root; /* We need this to bootstrap */ 1286 1287 if (cdwrite_data != NULL && merge_image == NULL) { 1288 /* in case we want to add a new session, but don't want to merge old one */ 1289 get_session_start(NULL); 1290 } 1291 1292 if( merge_image != NULL ) 1293 { 1294 mrootp = merge_isofs(merge_image); 1295 if( mrootp == NULL ) 1296 { 1297 /* 1298 * Complain and die. 1299 */ 1300 fprintf(stderr,"Unable to open previous session image %s\n", 1301 merge_image); 1302 exit(1); 1303 } 1304 1305 memcpy(&de.isorec.extent, mrootp->extent, 8); 1306 } 1307 1308 /* 1309 * Create an empty root directory. If we ever scan it for real, we will fill in the 1310 * contents. 1311 */ 1312 find_or_create_directory(NULL, "", &de, TRUE); 1313 1314 #ifdef APPLE_HYB 1315 /* NON-HFS change: see if we have a list of pathnames to process */ 1316 if (pathnames) { 1317 /* "-" means take list from the standard input */ 1318 if (strcmp(pathnames, "-")) { 1319 if ((pfp = fopen(pathnames, "r")) == NULL) { 1320 fprintf(stderr, "unable to open pathname list %s\n",pathnames); 1321 exit (1); 1322 } 1323 } 1324 else 1325 pfp = stdin; 1326 } 1327 #endif /* APPLE_HYB */ 1328 1329 /* 1330 * Scan the actual directory (and any we find below it) 1331 * for files to write out to the output image. Note - we 1332 * take multiple source directories and keep merging them 1333 * onto the image. 1334 */ 1335 #if APPLE_HYB 1336 /* NON-HFS change */ 1337 while((arg = get_pnames(argc, argv, optind, pname, pfp)) != NULL) 1338 #else 1339 while(optind < argc) 1340 #endif /* APPLE_HYB */ 1341 { 1342 char * node; 1343 struct directory * graft_dir; 1344 struct stat st; 1345 char * short_name; 1346 int status; 1347 char graft_point[1024]; 1348 1349 /* 1350 * We would like a syntax like: 1351 * 1352 * /tmp=/usr/tmp/xxx 1353 * 1354 * where the user can specify a place to graft each 1355 * component of the tree. To do this, we may have to create 1356 * directories along the way, of course. 1357 * Secondly, I would like to allow the user to do something 1358 * like: 1359 * 1360 * /home/baz/RMAIL=/u3/users/baz/RMAIL 1361 * 1362 * so that normal files could also be injected into the tree 1363 * at an arbitrary point. 1364 * 1365 * The idea is that the last component of whatever is being 1366 * entered would take the name from the last component of 1367 * whatever the user specifies. 1368 * 1369 * The default will be that the file is injected at the 1370 * root of the image tree. 1371 */ 1372 #ifdef APPLE_HYB 1373 /* NON-HFS change */ 1374 node = strchr(arg, '='); 1375 #else 1376 node = strchr(argv[optind], '='); 1377 #endif /* APPLE_HYB */ 1378 short_name = NULL; 1379 1380 if( node != NULL ) 1381 { 1382 char * pnt; 1383 char * xpnt; 1384 1385 *node = '\0'; 1386 #ifdef APPLE_HYB 1387 /* NON-HFS change */ 1388 strcpy(graft_point, arg); 1389 #else 1390 strcpy(graft_point, argv[optind]); 1391 #endif /* APPLE_HYB */ 1392 *node = '='; 1393 node++; 1394 1395 graft_dir = root; 1396 xpnt = graft_point; 1397 if( *xpnt == PATH_SEPARATOR ) 1398 { 1399 xpnt++; 1400 } 1401 1402 /* 1403 * Loop down deeper and deeper until we 1404 * find the correct insertion spot. 1405 */ 1406 while(1==1) 1407 { 1408 pnt = strchr(xpnt, PATH_SEPARATOR); 1409 if( pnt == NULL ) 1410 { 1411 if( *xpnt != '\0' ) 1412 { 1413 short_name = xpnt; 1414 } 1415 break; 1416 } 1417 *pnt = '\0'; 1418 graft_dir = find_or_create_directory(graft_dir, 1419 graft_point, 1420 NULL, TRUE); 1421 *pnt = PATH_SEPARATOR; 1422 xpnt = pnt + 1; 1423 } 1424 } 1425 else 1426 { 1427 graft_dir = root; 1428 #ifdef APPLE_HYB 1429 /* NON-HFS change */ 1430 node = arg; 1431 #else 1432 node = argv[optind]; 1433 #endif /* APPLE_HYB */ 1434 } 1435 1436 /* 1437 * Now see whether the user wants to add a regular file, 1438 * or a directory at this point. 1439 */ 1440 status = stat_filter(node, &st); 1441 if( status != 0 ) 1442 { 1443 /* 1444 * This is a fatal error - the user won't be getting what 1445 * they want if we were to proceed. 1446 */ 1447 fprintf(stderr, "Invalid node - %s\n", node); 1448 exit(1); 1449 } 1450 else 1451 { 1452 if( S_ISDIR(st.st_mode) ) 1453 { 1454 if (!scan_directory_tree(graft_dir, node, &de)) 1455 { 1456 exit(1); 1457 } 1458 } 1459 else 1460 { 1461 if( short_name == NULL ) 1462 { 1463 short_name = strrchr(node, PATH_SEPARATOR); 1464 if( short_name == NULL || short_name < node ) 1465 { 1466 short_name = node; 1467 } 1468 else 1469 { 1470 short_name++; 1471 } 1472 } 1473 #ifdef APPLE_HYB 1474 if( !insert_file_entry(graft_dir, node, short_name, 0) ) 1475 #else 1476 if( !insert_file_entry(graft_dir, node, short_name) ) 1477 #endif /* APPLE_HYB */ 1478 { 1479 exit(1); 1480 } 1481 } 1482 } 1483 1484 optind++; 1485 #ifdef APPLE_HYB 1486 /* NON-HFS change */ 1487 no_path_names = 0; 1488 #endif /* APPLE_HYB */ 1489 } 1490 1491 #ifdef APPLE_HYB 1492 /* NON-HFS change */ 1493 if (pfp && pfp != stdin) 1494 fclose(pfp); 1495 1496 /* exit if we don't have any pathnames to process - not going to happen 1497 at the moment as we have to have at least one path on the command line */ 1498 if(no_path_names){ 1499 usage(); 1500 exit(1); 1501 }; 1502 #endif /* APPLE_HYB */ 1503 1504 /* 1505 * Now merge in any previous sessions. This is driven on the source 1506 * side, since we may need to create some additional directories. 1507 */ 1508 if( merge_image != NULL ) 1509 { 1510 merge_previous_session(root, mrootp); 1511 } 1512 #ifdef APPLE_HYB 1513 /* free up any HFS filename mapping memory */ 1514 if (apple_both) 1515 clean_hfs(); 1516 #endif /* APPLE_HYB */ 1517 1518 /* hide "./rr_moved" if all its contents have been hidden */ 1519 if (reloc_dir && i_ishidden()) 1520 hide_reloc_dir(); 1521 1522 /* 1523 * Sort the directories in the required order (by ISO9660). Also, 1524 * choose the names for the 8.3 filesystem if required, and do 1525 * any other post-scan work. 1526 */ 1527 goof += sort_tree(root); 1528 1529 if( use_Joliet ) 1530 { 1531 goof += joliet_sort_tree(root); 1532 } 1533 1534 if (goof) 1535 { 1536 fprintf(stderr, "Joliet tree sort failed.\n"); 1537 exit(1); 1538 } 1539 1540 /* 1541 * Fix a couple of things in the root directory so that everything 1542 * is self consistent. 1543 */ 1544 root->self = root->contents; /* Fix this up so that the path 1545 tables get done right */ 1546 1547 /* 1548 * OK, ready to write the file. Open it up, and generate the thing. 1549 */ 1550 if (print_size){ 1551 discimage = fopen("/dev/null", "wb"); 1552 if (!discimage){ 1553 fprintf(stderr,"Unable to open /dev/null\n"); 1554 exit(1); 1555 } 1556 } else if (outfile){ 1557 discimage = fopen(outfile, "wb"); 1558 if (!discimage){ 1559 fprintf(stderr,"Unable to open disc image file\n"); 1560 exit(1); 1561 1562 }; 1563 } else { 1564 discimage = stdout; 1565 1566 #if defined(__CYGWIN32__) 1567 setmode(fileno(stdout), O_BINARY); 1568 #endif 1569 } 1570 1571 /* Now assign addresses on the disc for the path table. */ 1572 1573 path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11; 1574 if (path_blocks & 1) path_blocks++; 1575 1576 jpath_blocks = (jpath_table_size + (SECTOR_SIZE - 1)) >> 11; 1577 if (jpath_blocks & 1) jpath_blocks++; 1578 1579 /* 1580 * Start to set up the linked list that we use to track the 1581 * contents of the disc. 1582 */ 1583 outputlist_insert(&padblock_desc); 1584 1585 /* 1586 * PVD for disc. 1587 */ 1588 outputlist_insert(&voldesc_desc); 1589 1590 /* 1591 * SVD for El Torito. MUST be immediately after the PVD! 1592 */ 1593 if( use_eltorito) 1594 { 1595 outputlist_insert(&torito_desc); 1596 } 1597 1598 /* 1599 * SVD for Joliet. 1600 */ 1601 if( use_Joliet) 1602 { 1603 outputlist_insert(&joliet_desc); 1604 } 1605 1606 /* 1607 * Finally the last volume desctiptor. 1608 */ 1609 outputlist_insert(&end_vol); 1610 1611 1612 outputlist_insert(&pathtable_desc); 1613 if( use_Joliet) 1614 { 1615 outputlist_insert(&jpathtable_desc); 1616 } 1617 1618 outputlist_insert(&dirtree_desc); 1619 if( use_Joliet) 1620 { 1621 outputlist_insert(&jdirtree_desc); 1622 } 1623 1624 outputlist_insert(&dirtree_clean); 1625 1626 if(extension_record) 1627 { 1628 outputlist_insert(&extension_desc); 1629 } 1630 1631 outputlist_insert(&files_desc); 1632 1633 /* 1634 * Allow room for the various headers we will be writing. There 1635 * will always be a primary and an end volume descriptor. 1636 */ 1637 last_extent = session_start; 1638 1639 /* 1640 * Calculate the size of all of the components of the disc, and assign 1641 * extent numbers. 1642 */ 1643 for(opnt = out_list; opnt; opnt = opnt->of_next ) 1644 { 1645 if( opnt->of_size != NULL ) 1646 { 1647 (*opnt->of_size)(last_extent); 1648 } 1649 } 1650 1651 /* 1652 * Generate the contents of any of the sections that we want to generate. 1653 * Not all of the fragments will do anything here - most will generate the 1654 * data on the fly when we get to the write pass. 1655 */ 1656 for(opnt = out_list; opnt; opnt = opnt->of_next ) 1657 { 1658 if( opnt->of_generate != NULL ) 1659 { 1660 (*opnt->of_generate)(); 1661 } 1662 } 1663 1664 if( in_image != NULL ) 1665 { 1666 fclose(in_image); 1667 } 1668 1669 /* 1670 * Now go through the list of fragments and write the data that corresponds to 1671 * each one. 1672 */ 1673 for(opnt = out_list; opnt; opnt = opnt->of_next ) 1674 { 1675 if( opnt->of_write != NULL ) 1676 { 1677 (*opnt->of_write)(discimage); 1678 } 1679 } 1680 1681 if( verbose > 0 ) 1682 { 1683 #ifdef HAVE_SBRK 1684 fprintf(stderr,"Max brk space used %x\n", 1685 (unsigned int)(((unsigned long)sbrk(0)) - mem_start)); 1686 #endif 1687 fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); 1688 } 1689 #ifdef APPLE_HYB 1690 last_extent += hfs_extra; 1691 #endif /* APPLE_HYB */ 1692 1693 #ifdef VMS 1694 return 1; 1695 #else 1696 return 0; 1697 #endif 1698 } 1699 1700 void * 1701 FDECL1(e_malloc, size_t, size) 1702 { 1703 void* pt = 0; 1704 if( (size > 0) && ((pt=malloc(size))==NULL) ) { 1705 fprintf(stderr, "Not enough memory\n"); 1706 exit (1); 1707 } 1708 return pt; 1709 } 1710