Guest User

mkisofs.c

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