mkisofs.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:46k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

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