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