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

SCSI/ASPI

开发平台:

MultiPlatform

  1. /*
  2.  * Program write.c - dump memory  structures to  file for iso9660 filesystem.
  3.    Written by Eric Youngdale (1993).
  4.    Copyright 1993 Yggdrasil Computing, Incorporated
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16. static char rcsid[] ="$Id: write.c,v 1.21 1999/03/07 17:41:19 eric Exp $";
  17. #include "config.h"
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include "mkisofs.h"
  21. #include "iso9660.h"
  22. #include <time.h>
  23. #include <errno.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <fcntl.h>
  27. #ifdef HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30.  
  31. #ifdef USE_LIBSCHILY
  32. #include <standard.h>
  33. #endif
  34. #ifdef __SVR4
  35. extern char * strdup(const char *);
  36. #endif
  37. #ifdef VMS
  38. extern char * strdup(const char *);
  39. #endif
  40. /* Max number of sectors we will write at  one time */
  41. #define NSECT 16
  42. /* Counters for statistics */
  43. static int table_size       = 0;
  44. static int total_dir_size   = 0;
  45. static int rockridge_size   = 0;
  46. static struct directory ** pathlist;
  47. static int next_path_index  = 1;
  48. static int sort_goof;
  49. static int is_rr_dir        = 0;
  50. struct output_fragment * out_tail;
  51. struct output_fragment * out_list;
  52. struct iso_primary_descriptor vol_desc;
  53. static int root_gen __PR((void));
  54. static int generate_path_tables __PR((void));
  55. static int file_gen __PR((void));
  56. static int dirtree_dump __PR((void));
  57. /* Routines to actually write the disc.  We write sequentially so that
  58.    we could write a tape, or write the disc directly */
  59. #define FILL_SPACE(X)   memset(vol_desc.X, ' ', sizeof(vol_desc.X))
  60. void FDECL2(set_721, char *, pnt, unsigned int, i)
  61. {
  62.      pnt[0] = i & 0xff;
  63.      pnt[1] = (i >> 8) &  0xff;
  64. }
  65. void FDECL2(set_722, char *, pnt, unsigned int, i)
  66. {
  67.      pnt[0] = (i >> 8) &  0xff;
  68.      pnt[1] = i & 0xff;
  69. }
  70. void FDECL2(set_723, char *, pnt, unsigned int, i)
  71. {
  72.      pnt[3] = pnt[0] = i & 0xff;
  73.      pnt[2] = pnt[1] = (i >> 8) &  0xff;
  74. }
  75. void FDECL2(set_731, char *, pnt, unsigned int, i)
  76. {
  77.      pnt[0] = i & 0xff;
  78.      pnt[1] = (i >> 8) &  0xff;
  79.      pnt[2] = (i >> 16) &  0xff;
  80.      pnt[3] = (i >> 24) &  0xff;
  81. }
  82. void FDECL2(set_732, char *, pnt, unsigned int, i)
  83. {
  84.      pnt[3] = i & 0xff;
  85.      pnt[2] = (i >> 8) &  0xff;
  86.      pnt[1] = (i >> 16) &  0xff;
  87.      pnt[0] = (i >> 24) &  0xff;
  88. }
  89. int FDECL1(get_731, char *, p)
  90. {
  91.      return ((p[0] & 0xff)
  92.      | ((p[1] & 0xff) << 8)
  93.      | ((p[2] & 0xff) << 16)
  94.      | ((p[3] & 0xff) << 24));
  95. }
  96. int FDECL1(get_732, char *, p)
  97. {
  98.      return ((p[3] & 0xff)
  99.      | ((p[2] & 0xff) << 8)
  100.      | ((p[1] & 0xff) << 16)
  101.      | ((p[0] & 0xff) << 24));
  102. }
  103. int FDECL1(get_733, char *, p)
  104. {
  105.      return ((p[0] & 0xff)
  106.      | ((p[1] & 0xff) << 8)
  107.      | ((p[2] & 0xff) << 16)
  108.      | ((p[3] & 0xff) << 24));
  109. }
  110. void FDECL2(set_733, char *, pnt, unsigned int, i)
  111. {
  112.      pnt[7] = pnt[0] = i & 0xff;
  113.      pnt[6] = pnt[1] = (i >> 8) &  0xff;
  114.      pnt[5] = pnt[2] = (i >> 16) &  0xff;
  115.      pnt[4] = pnt[3] = (i >> 24) &  0xff;
  116. }
  117. void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file)
  118. {
  119. /*
  120.  * This is a hack that could be made better. XXXIs this the only place?
  121.  * It is definitely needed on Operating Systems that do not
  122.  * allow to write files that are > 2GB.
  123.  * If the system is fast enough to be able to feed 1400 KB/s
  124.  * writing speed of a DVD-R drive, use stdout.
  125.  * If the system cannot do this reliable, you need to use this
  126.  * hacky option.
  127.  */
  128. static int idx = 0;
  129. if (split_output != 0 &&
  130.     (idx == 0 || ftell(file) >= (1024 * 1024 * 1024) )) {
  131. char nbuf[512];
  132. extern char *outfile;
  133. if (idx == 0)
  134. unlink(outfile);
  135. sprintf(nbuf, "%s_%02d", outfile, idx++);
  136. file = freopen(nbuf, "wb", file);
  137. if (file == NULL) {
  138. #ifdef USE_LIBSCHILY
  139. comerr("Cannot open '%s'.n", nbuf);
  140. #else
  141. fprintf(stderr, "Cannot open '%s'.n", nbuf);
  142. exit(1);
  143. #endif
  144. }
  145. }
  146.      while(count) 
  147.      {
  148.   int got = fwrite(buffer,size,count,file);
  149.   if(got<=0) 
  150.   {
  151. #ifdef USE_LIBSCHILY
  152.        comerr("cannot fwrite %d*%dn",size,count);
  153. #else
  154.        fprintf(stderr,"cannot fwrite %d*%dn",size,count);
  155.        exit(1);
  156. #endif
  157.   }
  158.   count-=got,*(char**)&buffer+=size*got;
  159.      }
  160. }
  161. struct deferred_write
  162. {
  163.   struct deferred_write * next;
  164.   char * table;
  165.   unsigned int   extent;
  166.   unsigned int   size;
  167.   char * name;
  168. };
  169. static struct deferred_write * dw_head = NULL, * dw_tail = NULL;
  170. unsigned int last_extent_written  =0;
  171. static int path_table_index;
  172. static time_t begun;
  173. /* We recursively walk through all of the directories and assign extent
  174.    numbers to them.  We have already assigned extent numbers to everything that
  175.    goes in front of them */
  176. static int FDECL1(assign_directory_addresses, struct directory *, node)
  177. {
  178.      int dir_size;
  179.      struct directory * dpnt;
  180.      dpnt = node;
  181.      
  182.      while (dpnt)
  183.      {
  184.   /* skip if it's hidden */
  185.   if(dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
  186.      dpnt = dpnt->next;
  187.      continue;
  188.   }
  189.   /*
  190.    * If we already have an extent for this (i.e. it came from
  191.    * a multisession disc), then don't reassign a new extent.
  192.    */
  193.   dpnt->path_index = next_path_index++;
  194.   if( dpnt->extent == 0 )
  195.   {
  196.        dpnt->extent = last_extent;
  197.        dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;
  198.        
  199.        last_extent += dir_size;
  200.        
  201.        /* 
  202. * Leave room for the CE entries for this directory.  Keep them
  203. * close to the reference directory so that access will be 
  204. * quick. 
  205. */
  206.        if(dpnt->ce_bytes)
  207.        {
  208.     last_extent += ROUND_UP(dpnt->ce_bytes) >> 11;
  209.        }
  210.   }
  211.   if(dpnt->subdir) 
  212.   {
  213.        assign_directory_addresses(dpnt->subdir);
  214.   }
  215.   dpnt = dpnt->next;
  216.      }
  217.      return 0;
  218. }
  219. static void FDECL3(write_one_file, char *, filename, 
  220.    unsigned int, size, FILE *, outfile)
  221. {
  222.      char   buffer[SECTOR_SIZE * NSECT];
  223.      FILE * infile;
  224.      int   remain;
  225.      int   use;
  226.      if ((infile = fopen(filename, "rb")) == NULL) 
  227.      {
  228. #ifdef USE_LIBSCHILY
  229.   comerr("cannot open '%s'n", filename);
  230. #else
  231. #if defined(sun) || defined(_AUX_SOURCE)
  232.   fprintf(stderr, "cannot open %s: (%d)n", filename, errno);
  233. #else
  234.   fprintf(stderr, "cannot open %s: %sn", filename, strerror(errno));
  235. #endif
  236.   exit(1);
  237. #endif
  238.      }
  239.      remain = size;
  240.      while(remain > 0)
  241.      {
  242.   use =  (remain >  SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
  243.   use = ROUND_UP(use); /* Round up to nearest sector boundary */
  244.   memset(buffer, 0, use);
  245.   if (fread(buffer, 1, use, infile) == 0) 
  246.   {
  247. #ifdef USE_LIBSCHILY
  248. comerr("cannot read from %sn",filename); 
  249. #else
  250. fprintf(stderr,"cannot read from %sn",filename); 
  251. exit(1);
  252. #endif
  253.   }
  254.   xfwrite(buffer, 1, use, outfile);
  255.   last_extent_written += use/SECTOR_SIZE;
  256. #if 0
  257.   if((last_extent_written % 1000) < use/SECTOR_SIZE) 
  258.   {
  259.        fprintf(stderr,"%d..", last_extent_written);
  260.   }
  261. #else
  262.   if((last_extent_written % (gui?500:5000)) < use/SECTOR_SIZE)
  263.   {
  264.        time_t now;
  265.        time_t the_end;
  266.        double frac;
  267.        
  268.        time(&now);
  269.        frac = last_extent_written / (double)last_extent;
  270.        the_end = begun + (now - begun) / frac;
  271.        fprintf(stderr, "%6.2f%% done, estimate finish %s",
  272.        frac * 100., ctime(&the_end));
  273. fflush(stderr);
  274.   }
  275. #endif
  276.   remain -= use;
  277.      }
  278.      fclose(infile);
  279. } /* write_one_file(... */
  280. static void FDECL1(write_files, FILE *, outfile)
  281. {
  282.      struct deferred_write * dwpnt, *dwnext;
  283.      dwpnt = dw_head;
  284.      while(dwpnt)
  285.      {
  286.   if(dwpnt->table) 
  287.   {
  288.        xfwrite(dwpnt->table,  1, ROUND_UP(dwpnt->size), outfile);
  289.        last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE;
  290.        table_size += dwpnt->size;
  291. /*   fprintf(stderr,"Size %d ", dwpnt->size); */
  292.        free(dwpnt->table);
  293.        dwpnt->table = NULL;
  294.   } 
  295.   else 
  296.   {
  297. #ifdef VMS
  298.        vms_write_one_file(dwpnt->name, dwpnt->size, outfile);
  299. #else
  300.        write_one_file(dwpnt->name, dwpnt->size, outfile);
  301. #endif
  302.        free(dwpnt->name);
  303.        dwpnt->name = NULL;
  304.   }
  305.   dwnext = dwpnt;
  306.   dwpnt = dwpnt->next;
  307.   free(dwnext);
  308.   dwnext = NULL;
  309.      }
  310. } /* write_files(... */
  311. #if 0
  312. static void dump_filelist()
  313. {
  314.      struct deferred_write * dwpnt;
  315.      dwpnt = dw_head;
  316.      while(dwpnt)
  317.      {
  318.   fprintf(stderr, "File %sn",dwpnt->name);
  319.   dwpnt = dwpnt->next;
  320.      }
  321.      fprintf(stderr,"n");
  322. }
  323. #endif
  324. static int FDECL2(compare_dirs, const void *, rr, const void *, ll) 
  325. {
  326.      char * rpnt, *lpnt;
  327.      struct directory_entry ** r, **l;
  328.      
  329.      r = (struct directory_entry **) rr;
  330.      l = (struct directory_entry **) ll;
  331.      rpnt = (*r)->isorec.name;
  332.      lpnt = (*l)->isorec.name;
  333.      /*
  334.       * If the entries are the same, this is an error.
  335.       */
  336.      if( strcmp(rpnt, lpnt) == 0 )
  337.        {
  338. #ifdef USE_LIBSCHILY
  339.  errmsgno(EX_BAD, "Error: %s and %s have the same ISO9660 namen",
  340. (*r)->whole_name, (*l)->whole_name);
  341. #else
  342.  fprintf(stderr, "Error: %s and %s have the same ISO9660 namen",
  343. (*r)->whole_name, (*l)->whole_name);
  344. #endif
  345.  sort_goof++;
  346.        }
  347.      /* Check we don't have the same RR name */
  348.      if (use_RockRidge && !is_rr_dir) {
  349. /* entries *can* have the same RR name in the "rr_moved" directory
  350.    so skip checks if we're in reloc_dir */
  351. if (!(strcmp((*r)->name, (*l)->name))) {
  352. #ifdef USE_LIBSCHILY
  353.    errmsgno(EX_BAD, "Error: %s and %s have the same Rock Ridge namen",
  354. (*r)->whole_name, (*l)->whole_name);
  355. #else
  356.    fprintf (stderr, "Error: %s and %s have the same Rock Ridge namen",
  357. (*r)->whole_name, (*l)->whole_name);
  358. #endif
  359.    sort_goof++;
  360. }
  361.      }
  362.      /*
  363.       *  Put the '.' and '..' entries on the head of the sorted list.
  364.       *  For normal ASCII, this always happens to be the case, but out of
  365.       *  band characters cause this not to be the case sometimes.
  366.       *
  367.       * FIXME(eric) - these tests seem redundant, in taht the name is
  368.       * never assigned these values.  It will instead be 00 or 01,
  369.       * and thus should always be sorted correctly.   I need to figure
  370.       * out why I thought I needed this in the first place.
  371.       */
  372. #if 0
  373.      if( strcmp(rpnt, ".") == 0 ) return -1;
  374.      if( strcmp(lpnt, ".") == 0 ) return  1;
  375.      if( strcmp(rpnt, "..") == 0 ) return -1;
  376.      if( strcmp(lpnt, "..") == 0 ) return  1;
  377. #else
  378.      /*
  379.       * The code above is wrong (as explained in Eric's comment), leading to incorrect
  380.       * sort order iff the -L option ("allow leading dots") is in effect and a directory
  381.       * contains entries that start with a dot.
  382.       *
  383.       * (TF, Tue Dec 29 13:49:24 CET 1998)
  384.       */
  385.      if((*r)->isorec.name_len[0] == 1 && *rpnt == 0) return -1; /* '.' */
  386.      if((*l)->isorec.name_len[0] == 1 && *lpnt == 0) return 1;
  387.      if((*r)->isorec.name_len[0] == 1 && *rpnt == 1) return -1; /* '..' */
  388.      if((*l)->isorec.name_len[0] == 1 && *lpnt == 1) return 1;
  389. #endif
  390.      while(*rpnt && *lpnt) 
  391.      {
  392.   if(*rpnt == ';' && *lpnt != ';') return -1;
  393.   if(*rpnt != ';' && *lpnt == ';') return 1;
  394.   
  395.   if(*rpnt == ';' && *lpnt == ';') return 0;
  396.   
  397.   if(*rpnt == '.' && *lpnt != '.') return -1;
  398.   if(*rpnt != '.' && *lpnt == '.') return 1;
  399.   
  400.   if((unsigned char)*rpnt < (unsigned char)*lpnt) return -1;
  401.   if((unsigned char)*rpnt > (unsigned char)*lpnt) return 1;
  402.   rpnt++;  lpnt++;
  403.      }
  404.      if(*rpnt) return 1;
  405.      if(*lpnt) return -1;
  406.      return 0;
  407. }
  408. /* 
  409.  * Function: sort_directory
  410.  *
  411.  * Purpose: Sort the directory in the appropriate ISO9660
  412.  * order.
  413.  *
  414.  * Notes: Returns 0 if OK, returns > 0 if an error occurred.
  415.  */
  416. int FDECL2(sort_directory, struct directory_entry **, sort_dir, int, rr)
  417. {
  418.      int dcount = 0;
  419.      int xcount = 0;
  420.      int j;
  421.      int i, len;
  422.      struct directory_entry * s_entry;
  423.      struct directory_entry ** sortlist;
  424.      
  425.      /* need to keep a count of how many entries are hidden */
  426.      s_entry = *sort_dir;
  427.      while(s_entry)
  428.      {
  429.   if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
  430.     xcount++;
  431.   dcount++;
  432.   s_entry = s_entry->next;
  433.      }
  434.      if( dcount == 0 )
  435.      {
  436.           return 0;
  437.      }
  438.      /*
  439.       * OK, now we know how many there are.  Build a vector for sorting. 
  440.       */
  441.      sortlist =   (struct directory_entry **) 
  442.   e_malloc(sizeof(struct directory_entry *) * dcount);
  443.      j = dcount - 1;
  444.      dcount = 0;
  445.      s_entry = *sort_dir;
  446.      while(s_entry)
  447.      {
  448. if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
  449.  {
  450.   /* put any hidden entries at the end of the vector */
  451.   sortlist[j--] = s_entry;
  452.  }
  453. else
  454.  {
  455.   sortlist[dcount] = s_entry;
  456.   dcount++;
  457.  }
  458.  len = s_entry->isorec.name_len[0];
  459.  s_entry->isorec.name[len] = 0;
  460.  s_entry = s_entry->next;
  461.      }
  462.   
  463.      /*
  464.       * Each directory is required to contain at least . and ..
  465.       */
  466.      if( dcount < 2 )
  467.        {
  468. #ifdef USE_LIBSCHILY
  469.  errmsgno(EX_BAD, "Directory size too small (. or .. missing ???)n"); 
  470. #else
  471.  fprintf(stderr, "Directory size too small (. or .. missing ???)n"); 
  472. #endif
  473.  sort_goof = 1;
  474.  
  475.        }
  476.      else
  477.        {
  478.  /* only sort the non-hidden entries */
  479.  sort_goof = 0;
  480. is_rr_dir = rr;
  481. #ifdef __STDC__
  482.  qsort(sortlist, dcount, sizeof(struct directory_entry *), 
  483.        (int (*)(const void *, const void *))compare_dirs);
  484. #else
  485.  qsort(sortlist, dcount, sizeof(struct directory_entry *), 
  486.        compare_dirs);
  487. #endif
  488.  
  489.  /* 
  490.   * Now reassemble the linked list in the proper sorted order 
  491.   * We still need the hidden entries, as they may be used in the
  492.   * Joliet tree.
  493.   */
  494.  for(i=0; i<dcount+xcount-1; i++)
  495.    {
  496.      sortlist[i]->next = sortlist[i+1];
  497.    }
  498.  
  499.  sortlist[dcount+xcount-1]->next = NULL;
  500.  *sort_dir = sortlist[0];
  501.        }
  502.      free(sortlist);
  503.      sortlist = NULL;
  504.      return sort_goof;
  505. }
  506. static int root_gen()
  507. {
  508.      init_fstatbuf();
  509.      
  510.      root_record.length[0] = 1 + offsetof(struct iso_directory_record, name[0]);
  511.      root_record.ext_attr_length[0] = 0;
  512.      set_733((char *) root_record.extent, root->extent);
  513.      set_733((char *) root_record.size, ROUND_UP(root->size));
  514.      iso9660_date(root_record.date, root_statbuf.st_mtime);
  515.      root_record.flags[0] = 2;
  516.      root_record.file_unit_size[0] = 0;
  517.      root_record.interleave[0] = 0;
  518.      set_723(root_record.volume_sequence_number, volume_sequence_number);
  519.      root_record.name_len[0] = 1;
  520.      return 0;
  521. }
  522. static void FDECL1(assign_file_addresses, struct directory *, dpnt)
  523. {
  524.      struct directory * finddir;
  525.      struct directory_entry * s_entry;
  526.      struct file_hash *s_hash;
  527.      struct deferred_write * dwpnt;
  528.      char whole_path[1024];
  529.      while (dpnt)
  530.      {
  531.   s_entry = dpnt->contents;
  532.   for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
  533.   {
  534.        /*
  535. * If we already have an  extent for this entry,
  536. * then don't assign a new one.  It must have come
  537. * from a previous session on the disc.  Note that
  538. * we don't end up scheduling the thing for writing
  539. * either.
  540. */
  541.        if( isonum_733((unsigned char *) s_entry->isorec.extent) != 0 )
  542.        {
  543.     continue;
  544.        }
  545.        
  546.        /* 
  547. * This saves some space if there are symlinks present 
  548. */
  549.        s_hash = find_hash(s_entry->dev, s_entry->inode);
  550.        if(s_hash)
  551.        {
  552.     if(verbose > 2)
  553.     {
  554.  fprintf(stderr, "Cache hit for %s%s%sn",s_entry->filedir->de_name, 
  555.  SPATH_SEPARATOR, s_entry->name);
  556.     }
  557.     set_733((char *) s_entry->isorec.extent, s_hash->starting_block);
  558.     set_733((char *) s_entry->isorec.size, s_hash->size);
  559.     continue;
  560.        }
  561.        /*
  562. * If this is for a directory that is not a . or a .. entry, 
  563. * then look up the information for the entry.  We have already
  564. * assigned extents for directories, so we just need to
  565. * fill in the blanks here.
  566. */
  567.        if (strcmp(s_entry->name,".") != 0 && strcmp(s_entry->name,"..") != 0 &&
  568.    s_entry->isorec.flags[0] == 2)
  569.        {
  570.     finddir = dpnt->subdir;
  571.     while(1==1)
  572.     {
  573.  if(finddir->self == s_entry) break;
  574.  finddir = finddir->next;
  575.  if(!finddir) 
  576.  {
  577. #ifdef USE_LIBSCHILY
  578.       comerrno(EX_BAD,
  579. "Fatal goof - could not find dir entry for '%s'n",
  580. s_entry->name);
  581. #else
  582.       fprintf(stderr,
  583. "Fatal goof - could not find dir entry for '%s'n",
  584. s_entry->name);
  585.       exit(1);
  586. #endif
  587.  }
  588.     }
  589.     set_733((char *) s_entry->isorec.extent, finddir->extent);
  590.     s_entry->starting_block = finddir->extent;
  591.     s_entry->size = ROUND_UP(finddir->size);
  592.     total_dir_size += s_entry->size;
  593.     add_hash(s_entry);
  594.     set_733((char *) s_entry->isorec.size, ROUND_UP(finddir->size));
  595.     continue;
  596.        }
  597.        /*
  598. * If this is . or .., then look up the relevant info from the
  599. * tables.
  600. */
  601.        if(strcmp(s_entry->name,".") == 0) 
  602.        {
  603.     set_733((char *) s_entry->isorec.extent, dpnt->extent);
  604.     
  605.     /* 
  606.      * Set these so that the hash table has the
  607.      * correct information
  608.      */
  609.     s_entry->starting_block = dpnt->extent;
  610.     s_entry->size = ROUND_UP(dpnt->size);
  611.     
  612.     add_hash(s_entry);
  613.     s_entry->starting_block = dpnt->extent;
  614.     set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->size));
  615.     continue;
  616.        }
  617.        if(strcmp(s_entry->name,"..") == 0) 
  618.        {
  619.     if(dpnt == root)
  620.     { 
  621.  total_dir_size += root->size;
  622.     }
  623.     set_733((char *) s_entry->isorec.extent, dpnt->parent->extent);
  624.     
  625.     /* 
  626.      * Set these so that the hash table has the
  627.      * correct information
  628.      */
  629.     s_entry->starting_block = dpnt->parent->extent;
  630.     s_entry->size = ROUND_UP(dpnt->parent->size);
  631.     
  632.     add_hash(s_entry);
  633.     s_entry->starting_block = dpnt->parent->extent;
  634.     set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->parent->size));
  635.     continue;
  636.        }
  637.        /* 
  638. * Some ordinary non-directory file.  Just schedule the
  639. * file to be written.  This is all quite
  640. * straightforward, just make a list and assign extents
  641. * as we go.  Once we get through writing all of the
  642. * directories, we should be ready write out these
  643. * files
  644. */
  645.        if(s_entry->size) 
  646.        {
  647.     dwpnt = (struct deferred_write *) 
  648.  e_malloc(sizeof(struct deferred_write));
  649.     if(dw_tail)
  650.     {
  651.  dw_tail->next = dwpnt;
  652.  dw_tail = dwpnt;
  653.     } 
  654.     else 
  655.     {
  656.  dw_head = dwpnt;
  657.  dw_tail = dwpnt;
  658.     }
  659.     if(s_entry->inode  ==  TABLE_INODE) 
  660.     {
  661.  dwpnt->table = s_entry->table;
  662.  dwpnt->name = NULL;
  663.  sprintf(whole_path,"%s%s%s",
  664.  s_entry->filedir->whole_name,
  665.  SPATH_SEPARATOR, trans_tbl);
  666.     } 
  667.     else 
  668.     {
  669.  dwpnt->table = NULL;
  670.  strcpy(whole_path, s_entry->whole_name);
  671.  dwpnt->name = strdup(whole_path);
  672.     }
  673.     dwpnt->next = NULL;
  674.     dwpnt->size = s_entry->size;
  675.     dwpnt->extent = last_extent;
  676.     set_733((char *) s_entry->isorec.extent, last_extent);
  677.     s_entry->starting_block = last_extent;
  678.     add_hash(s_entry);
  679.     last_extent += ROUND_UP(s_entry->size) >> 11;
  680.     if(verbose > 2)
  681.     {
  682.  fprintf(stderr,"%d %d %sn", s_entry->starting_block,
  683.  last_extent-1, whole_path);
  684.     }
  685. #ifdef DBG_ISO
  686.     if((ROUND_UP(s_entry->size) >> 11) > 500)
  687.     {
  688.  fprintf(stderr,"Warning: large file %sn", whole_path);
  689.  fprintf(stderr,"Starting block is %dn", s_entry->starting_block);
  690.  fprintf(stderr,"Reported file size is %d extentsn", s_entry->size);
  691.  
  692.     }
  693. #endif
  694. #ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */
  695.     if(last_extent > (800000000 >> 11)) 
  696.     { 
  697.  /*
  698.   * More than 800Mb? Punt 
  699.   */
  700.  fprintf(stderr,"Extent overflow processing file %sn", whole_path);
  701.  fprintf(stderr,"Starting block is %dn", s_entry->starting_block);
  702.  fprintf(stderr,"Reported file size is %d extentsn", s_entry->size);
  703.  exit(1);
  704.     }
  705. #endif
  706.     continue;
  707.        }
  708.        /*
  709. * This is for zero-length files.  If we leave the extent 0,
  710. * then we get screwed, because many readers simply drop files
  711. * that have an extent of zero.  Thus we leave the size 0,
  712. * and just assign the extent number.
  713. */
  714.        set_733((char *) s_entry->isorec.extent, last_extent);
  715.   }
  716.   if(dpnt->subdir) 
  717.   {
  718.        assign_file_addresses(dpnt->subdir);
  719.   }
  720.   dpnt = dpnt->next;
  721.      }
  722. } /* assign_file_addresses(... */
  723. static void FDECL1(free_one_directory, struct directory *, dpnt)
  724. {
  725.      struct directory_entry * s_entry;
  726.      struct directory_entry * s_entry_d;
  727.      
  728.      s_entry = dpnt->contents;
  729.      while(s_entry) 
  730.      {
  731.  s_entry_d = s_entry;
  732.  s_entry = s_entry->next;
  733.  
  734.  if (s_entry_d->rr_attributes) {
  735.      free(s_entry_d->rr_attributes);
  736.      s_entry_d->rr_attributes = NULL;
  737.  }
  738.  if( s_entry_d->name != NULL )
  739.  {
  740.      free (s_entry_d->name);
  741.      s_entry_d->name = NULL;
  742.  }
  743.  if( s_entry_d->whole_name != NULL )
  744.  {
  745.      free (s_entry_d->whole_name);
  746.      s_entry_d->whole_name = NULL;
  747.  }
  748.  free (s_entry_d);
  749.  s_entry_d = NULL;
  750.      }
  751.      dpnt->contents = NULL;
  752. } /* free_one_directory(... */
  753. static void FDECL1(free_directories, struct directory *, dpnt)
  754. {
  755.   while (dpnt)
  756.     {
  757.       free_one_directory(dpnt);
  758.       if(dpnt->subdir) free_directories(dpnt->subdir);
  759.       dpnt = dpnt->next;
  760.     }
  761. }
  762. void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile)
  763. {
  764.      unsigned int   ce_address = 0;
  765.      char * ce_buffer;
  766.      unsigned int   ce_index = 0;
  767.      unsigned int   ce_size;
  768.      unsigned int   dir_index;
  769.      char * directory_buffer;
  770.      int   new_reclen;
  771.      struct directory_entry * s_entry;
  772.      struct directory_entry * s_entry_d;
  773.      unsigned int   total_size;
  774.      
  775.      total_size = (dpnt->size + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
  776.      directory_buffer = (char *) e_malloc(total_size);
  777.      memset(directory_buffer, 0, total_size);
  778.      dir_index = 0;
  779.      
  780.      ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
  781.      ce_buffer = NULL;
  782.      
  783.      if(ce_size > 0) 
  784.      {
  785.   ce_buffer = (char *) e_malloc(ce_size);
  786.   memset(ce_buffer, 0, ce_size);
  787.   
  788.   ce_index = 0;
  789.   
  790.   /*
  791.    * Absolute byte address of CE entries for this directory 
  792.    */
  793.   ce_address = last_extent_written + (total_size >> 11);
  794.   ce_address = ce_address << 11;
  795.      }
  796.      
  797.      s_entry = dpnt->contents;
  798.      while(s_entry) 
  799.      {
  800.   /* skip if it's hidden */
  801.   if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
  802.     s_entry = s_entry->next;
  803.     continue;
  804.   }
  805.   /* 
  806.    * We do not allow directory entries to cross sector boundaries.  
  807.    * Simply pad, and then start the next entry at the next sector 
  808.    */
  809.   new_reclen = s_entry->isorec.length[0];
  810.   if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE )
  811.   {
  812.        dir_index = (dir_index + (SECTOR_SIZE - 1)) & 
  813.     ~(SECTOR_SIZE - 1);
  814.   }
  815.   memcpy(directory_buffer + dir_index, &s_entry->isorec, 
  816.  offsetof(struct iso_directory_record, name[0]) +
  817.  s_entry->isorec.name_len[0]);
  818.   dir_index += offsetof(struct iso_directory_record, name[0]) +
  819.        s_entry->isorec.name_len[0];
  820.   /*
  821.    * Add the Rock Ridge attributes, if present 
  822.    */
  823.   if(s_entry->rr_attr_size)
  824.   {
  825.        if(dir_index & 1)
  826.        {
  827.     directory_buffer[dir_index++] = 0;
  828.        }
  829.        /* 
  830. * If the RR attributes were too long, then write the
  831. * CE records, as required.
  832. */
  833.        if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) 
  834.        {
  835.     unsigned char * pnt;
  836.     int len, nbytes;
  837.     
  838.     /* 
  839.      * Go through the entire record and fix up the CE entries
  840.      * so that the extent and offset are correct 
  841.      */
  842.     
  843.     pnt = s_entry->rr_attributes;
  844.     len = s_entry->total_rr_attr_size;
  845.     while(len > 3)
  846.     {
  847. #ifdef DEBUG
  848.  if (ce_size <= 0)
  849.  {
  850.       fprintf(stderr,"Warning: ce_index(%d) && ce_address(%d) not initializedn",
  851.       ce_index, ce_address);
  852.  }
  853. #endif
  854.  
  855.  if(pnt[0] == 'C' && pnt[1] == 'E') 
  856.  {
  857.       nbytes = get_733( (char *) pnt+20);
  858.       
  859.       if((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
  860.  SECTOR_SIZE) 
  861.       {
  862.    ce_index = ROUND_UP(ce_index);
  863.       }
  864.       
  865.       set_733( (char *) pnt+4, 
  866.        (ce_address + ce_index) >> 11);
  867.       set_733( (char *) pnt+12, 
  868.        (ce_address + ce_index) & (SECTOR_SIZE - 1));
  869.       
  870.       
  871.       /* 
  872.        * Now store the block in the ce buffer 
  873.        */
  874.       memcpy(ce_buffer + ce_index, 
  875.      pnt + pnt[2], nbytes);
  876.       ce_index += nbytes;
  877.       if(ce_index & 1) 
  878.       {
  879.    ce_index++;
  880.       }
  881.  }
  882.  len -= pnt[2];
  883.  pnt += pnt[2];
  884.     }
  885.     
  886.        }
  887.        rockridge_size += s_entry->total_rr_attr_size;
  888.        memcpy(directory_buffer + dir_index, s_entry->rr_attributes, 
  889.       s_entry->rr_attr_size);
  890.        dir_index += s_entry->rr_attr_size;
  891.   }
  892.   if(dir_index & 1)
  893.   {
  894.        directory_buffer[dir_index++] = 0;
  895.   }
  896.   
  897.   s_entry_d = s_entry;
  898.   s_entry = s_entry->next;
  899.   
  900.   /*
  901.    * Joliet doesn't use the Rock Ridge attributes, so we free it here.
  902.    */
  903.   if (s_entry_d->rr_attributes) 
  904.     {
  905.       free(s_entry_d->rr_attributes);
  906.       s_entry_d->rr_attributes = NULL;
  907.     }
  908.      }
  909.      if(dpnt->size != dir_index)
  910.      {
  911. #ifdef USE_LIBSCHILY
  912.   errmsgno(EX_BAD,"Unexpected directory length %d expected: %d '%s'n",dpnt->size,
  913.     dir_index, dpnt->de_name);
  914. #else
  915.   fprintf(stderr,"Unexpected directory length %d expected: %d '%s'n",dpnt->size,
  916.     dir_index, dpnt->de_name);
  917. #endif
  918.      }
  919.      xfwrite(directory_buffer, 1, total_size, outfile);
  920.      last_extent_written += total_size >> 11;
  921.      free(directory_buffer);
  922.      directory_buffer = NULL;
  923.      if(ce_size > 0)
  924.      {
  925.   if(ce_index != dpnt->ce_bytes)
  926.   {
  927. #ifdef USE_LIBSCHILY
  928.        errmsgno(EX_BAD,"Continuation entry record length mismatch %d expected: %d.n",
  929.        ce_index, dpnt->ce_bytes);
  930. #else
  931.        fprintf(stderr,"Continuation entry record length mismatch %d expected: %d.n",
  932.        ce_index, dpnt->ce_bytes);
  933. #endif
  934.   }
  935.   xfwrite(ce_buffer, 1, ce_size, outfile);
  936.   last_extent_written += ce_size >> 11;
  937.   free(ce_buffer);
  938.   ce_buffer = NULL;
  939.      }
  940.      
  941. } /* generate_one_directory(... */
  942. static 
  943. void FDECL1(build_pathlist, struct directory *, node)
  944. {
  945.      struct directory * dpnt;
  946.      
  947.      dpnt = node;
  948.      
  949.      while (dpnt)
  950.      {
  951. /* skip if it's hidden */
  952. if( (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0 )
  953.   pathlist[dpnt->path_index] = dpnt;
  954. if(dpnt->subdir) build_pathlist(dpnt->subdir);
  955. dpnt = dpnt->next;
  956.      }
  957. } /* build_pathlist(... */
  958. static int FDECL2(compare_paths, void const *, r, void const *, l) 
  959. {
  960.   struct directory const *ll = *(struct directory * const *)l;
  961.   struct directory const *rr = *(struct directory * const *)r;
  962.   if (rr->parent->path_index < ll->parent->path_index)
  963.   {
  964.        return -1;
  965.   }
  966.   if (rr->parent->path_index > ll->parent->path_index) 
  967.   {
  968.        return 1;
  969.   }
  970.   return strcmp(rr->self->isorec.name, ll->self->isorec.name);
  971.   
  972. } /* compare_paths(... */
  973. static int generate_path_tables()
  974. {
  975.   struct directory_entry * de = NULL;
  976.   struct directory  * dpnt;
  977.   int    fix;
  978.   int    i;
  979.   int    j;
  980.   int    namelen;
  981.   char  * npnt;
  982.   char  * npnt1;
  983.   int    tablesize;
  984.   /*
  985.    * First allocate memory for the tables and initialize the memory 
  986.    */
  987.   tablesize = path_blocks << 11;
  988.   path_table_m = (char *) e_malloc(tablesize);
  989.   path_table_l = (char *) e_malloc(tablesize);
  990.   memset(path_table_l, 0, tablesize);
  991.   memset(path_table_m, 0, tablesize);
  992.   /*
  993.    * Now start filling in the path tables.  Start with root directory 
  994.    */
  995.   if( next_path_index > 0xffff )
  996.   {
  997. #ifdef USE_LIBSCHILY
  998.       comerrno(EX_BAD, "Unable to generate sane path tables - too many directories (%d)n",
  999.       next_path_index);
  1000. #else
  1001.       fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)n",
  1002.       next_path_index);
  1003.       exit(1);
  1004. #endif
  1005.   }
  1006.   path_table_index = 0;
  1007.   pathlist = (struct directory **) e_malloc(sizeof(struct directory *) 
  1008.     * next_path_index);
  1009.   memset(pathlist, 0, sizeof(struct directory *) * next_path_index);
  1010.   build_pathlist(root);
  1011.   do
  1012.   {
  1013.        fix = 0;
  1014. #ifdef __STDC__
  1015.        qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), 
  1016.      (int (*)(const void *, const void *))compare_paths);
  1017. #else
  1018.        qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), 
  1019.      compare_paths);
  1020. #endif
  1021.        for(j=1; j<next_path_index; j++)
  1022.        {
  1023.     if(pathlist[j]->path_index != j)
  1024.     {
  1025.  pathlist[j]->path_index = j;
  1026.  fix++;
  1027.     }
  1028.        }
  1029.   } while(fix);
  1030.   for(j=1; j<next_path_index; j++)
  1031.   {
  1032.        dpnt = pathlist[j];
  1033.        if(!dpnt)
  1034.        {
  1035. #ifdef USE_LIBSCHILY
  1036.     comerrno(EX_BAD, "Entry %d not in path tablesn", j);
  1037. #else
  1038.     fprintf(stderr,"Entry %d not in path tablesn", j);
  1039.     exit(1);
  1040. #endif
  1041.        }
  1042.        npnt = dpnt->de_name;
  1043.        
  1044.        /* 
  1045. * So the root comes out OK 
  1046. */
  1047.        if( (*npnt == 0) || (dpnt == root) ) 
  1048.        {
  1049.     npnt = ".";  
  1050.        }
  1051.        npnt1 = strrchr(npnt, PATH_SEPARATOR);
  1052.        if(npnt1) 
  1053.        { 
  1054.     npnt = npnt1 + 1;
  1055.        }
  1056.        
  1057.        de = dpnt->self;
  1058.        if(!de) 
  1059.        {
  1060. #ifdef USE_LIBSCHILY
  1061.     comerrno(EX_BAD, "Fatal ISO9660 goof - directory has amnesian"); 
  1062. #else
  1063.     fprintf(stderr,"Fatal ISO9660 goof - directory has amnesian"); 
  1064.     exit(1);
  1065. #endif
  1066.        }
  1067.        
  1068.        
  1069.        namelen = de->isorec.name_len[0];
  1070.        
  1071.        path_table_l[path_table_index] = namelen;
  1072.        path_table_m[path_table_index] = namelen;
  1073.        path_table_index += 2;
  1074.        
  1075.        set_731(path_table_l + path_table_index, dpnt->extent); 
  1076.        set_732(path_table_m + path_table_index, dpnt->extent); 
  1077.        path_table_index += 4;
  1078.        
  1079.        set_721(path_table_l + path_table_index, 
  1080.        dpnt->parent->path_index); 
  1081.        set_722(path_table_m + path_table_index, 
  1082.        dpnt->parent->path_index); 
  1083.        path_table_index += 2;
  1084.        
  1085.        for(i =0; i<namelen; i++)
  1086.        {
  1087.     path_table_l[path_table_index] = de->isorec.name[i];
  1088.     path_table_m[path_table_index] = de->isorec.name[i];
  1089.     path_table_index++;
  1090.        }
  1091.        if(path_table_index & 1) 
  1092.        {
  1093.     path_table_index++;  /* For odd lengths we pad */
  1094.        }
  1095.   }
  1096.   
  1097.   free(pathlist);
  1098.   pathlist = NULL;
  1099.   if(path_table_index != path_table_size)
  1100.   {
  1101. #ifdef USE_LIBSCHILY
  1102.        errmsgno(EX_BAD,"Path table lengths do not match %d expected: %dn",
  1103.        path_table_index,
  1104.        path_table_size);
  1105. #else
  1106.        fprintf(stderr,"Path table lengths do not match %d expected: %dn",
  1107.        path_table_index,
  1108.        path_table_size);
  1109. #endif
  1110.   }
  1111.   return 0;
  1112. } /* generate_path_tables(... */
  1113. void
  1114. FDECL3(memcpy_max, char *, to, char *, from, int, max)
  1115. {
  1116.   int n = strlen(from);
  1117.   if (n > max)
  1118.   {
  1119.        n = max;
  1120.   }
  1121.   memcpy(to, from, n);
  1122. } /* memcpy_max(... */
  1123. void FDECL1(outputlist_insert, struct output_fragment *, frag)
  1124. {
  1125.   if( out_tail == NULL )
  1126.     {
  1127.       out_list = out_tail = frag;
  1128.     }
  1129.   else
  1130.     {
  1131.       out_tail->of_next = frag;
  1132.       out_tail = frag;
  1133.     }
  1134. }
  1135. static int FDECL1(file_write, FILE *, outfile)
  1136. {
  1137.   int should_write;
  1138.   /*
  1139.    * OK, all done with that crap.  Now write out the directories.
  1140.    * This is where the fur starts to fly, because we need to keep track of
  1141.    * each file as we find it and keep track of where we put it. 
  1142.    */
  1143.   should_write = last_extent - session_start;
  1144.   if( verbose > 2 )
  1145.     {
  1146. #ifdef DBG_ISO
  1147.       fprintf(stderr,"Total directory extents being written = %dn", last_extent);
  1148. #endif
  1149.       
  1150.       fprintf(stderr,"Total extents scheduled to be written = %dn", 
  1151.       last_extent - session_start);
  1152.     }
  1153.   /* 
  1154.    * Now write all of the files that we need. 
  1155.    */
  1156.   write_files(outfile);
  1157.   
  1158.   /*
  1159.    * The rest is just fluff.
  1160.    */
  1161.   if( verbose == 0 )
  1162.     {
  1163.       return 0;
  1164.     }
  1165.   fprintf(stderr,"Total extents actually written = %dn", 
  1166.   last_extent_written - session_start);
  1167.   /* 
  1168.    * Hard links throw us off here 
  1169.    */
  1170.   if(should_write != last_extent - session_start)
  1171.     {
  1172.       fprintf(stderr,"Number of extents written not what was predicted.  Please fix.n");
  1173.       fprintf(stderr,"Predicted = %d, written = %dn", should_write, last_extent);
  1174.     }
  1175.   fprintf(stderr,"Total translation table size: %dn", table_size);
  1176.   fprintf(stderr,"Total rockridge attributes bytes: %dn", rockridge_size);
  1177.   fprintf(stderr,"Total directory bytes: %dn", total_dir_size);
  1178.   fprintf(stderr,"Path table size(bytes): %dn", path_table_size);
  1179. #ifdef DEBUG
  1180.   fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %dn",
  1181.   next_extent, last_extent, last_extent_written);
  1182. #endif
  1183.   return 0;
  1184. } /* iso_write(... */
  1185. /*
  1186.  * Function to write the PVD for the disc.
  1187.  */
  1188. static int FDECL1(pvd_write, FILE *, outfile)
  1189. {
  1190.   char iso_time[17];
  1191.   int should_write;
  1192.   struct tm local;
  1193.   struct tm gmt;
  1194.   time(&begun);
  1195.   local = *localtime(&begun);
  1196.   gmt   = *gmtime(&begun);
  1197.   /*
  1198.    * There was a comment here about breaking in the year 2000.  That's
  1199.    * not true, in 2000 tm_year == 100, so 1900+tm_year == 2000.
  1200.    */
  1201.   sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local.tm_year,
  1202.   local.tm_mon+1, local.tm_mday,
  1203.   local.tm_hour, local.tm_min, local.tm_sec);
  1204.   local.tm_min -= gmt.tm_min;
  1205.   local.tm_hour -= gmt.tm_hour;
  1206.   local.tm_yday -= gmt.tm_yday;
  1207.   iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15;
  1208.   /*
  1209.    * Next we write out the primary descriptor for the disc 
  1210.    */
  1211.   memset(&vol_desc, 0, sizeof(vol_desc));
  1212.   vol_desc.type[0] = ISO_VD_PRIMARY;
  1213.   memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
  1214.   vol_desc.version[0] = 1;
  1215.   
  1216.   memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id));
  1217.   memcpy_max(vol_desc.system_id, system_id, strlen(system_id));
  1218.   
  1219.   memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
  1220.   memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id));
  1221.   
  1222.   should_write = last_extent - session_start;
  1223.   set_733((char *) vol_desc.volume_space_size, should_write);
  1224.   set_723(vol_desc.volume_set_size, volume_set_size);
  1225.   set_723(vol_desc.volume_sequence_number, volume_sequence_number);
  1226.   set_723(vol_desc.logical_block_size, 2048);
  1227.   
  1228.   /*
  1229.    * The path tables are used by DOS based machines to cache directory
  1230.    * locations 
  1231.    */
  1232.   set_733((char *) vol_desc.path_table_size, path_table_size);
  1233.   set_731(vol_desc.type_l_path_table, path_table[0]);
  1234.   set_731(vol_desc.opt_type_l_path_table, path_table[1]);
  1235.   set_732(vol_desc.type_m_path_table, path_table[2]);
  1236.   set_732(vol_desc.opt_type_m_path_table, path_table[3]);
  1237.   /*
  1238.    * Now we copy the actual root directory record 
  1239.    */
  1240.   memcpy(vol_desc.root_directory_record, &root_record, 
  1241.  offsetof(struct iso_directory_record, name[0]) + 1);
  1242.   /*
  1243.    * The rest is just fluff.  It looks nice to fill in many of these fields,
  1244.    * though.
  1245.    */
  1246.   FILL_SPACE(volume_set_id);
  1247.   if(volset_id)  memcpy_max(vol_desc.volume_set_id,  volset_id, strlen(volset_id));
  1248.   FILL_SPACE(publisher_id);
  1249.   if(publisher)  memcpy_max(vol_desc.publisher_id,  publisher, strlen(publisher));
  1250.   FILL_SPACE(preparer_id);
  1251.   if(preparer)  memcpy_max(vol_desc.preparer_id,  preparer, strlen(preparer));
  1252.   FILL_SPACE(application_id);
  1253.   if(appid) memcpy_max(vol_desc.application_id, appid, strlen(appid));
  1254.   FILL_SPACE(copyright_file_id);
  1255.   if(copyright) memcpy_max(vol_desc.copyright_file_id, copyright, 
  1256.        strlen(copyright));
  1257.   FILL_SPACE(abstract_file_id);
  1258.   if(abstract) memcpy_max(vol_desc.abstract_file_id, abstract, 
  1259.   strlen(abstract));
  1260.   FILL_SPACE(bibliographic_file_id);
  1261.   if(biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio, 
  1262.        strlen(biblio));
  1263.   FILL_SPACE(creation_date);
  1264.   FILL_SPACE(modification_date);
  1265.   FILL_SPACE(expiration_date);
  1266.   FILL_SPACE(effective_date);
  1267.   vol_desc.file_structure_version[0] = 1;
  1268.   FILL_SPACE(application_data);
  1269.   memcpy(vol_desc.creation_date,  iso_time, 17);
  1270.   memcpy(vol_desc.modification_date,  iso_time, 17);
  1271.   memcpy(vol_desc.expiration_date, "0000000000000000", 17);
  1272.   memcpy(vol_desc.effective_date,  iso_time,  17);
  1273.   /*
  1274.    * if not a bootable cd do it the old way 
  1275.    */
  1276.   xfwrite(&vol_desc, 1, 2048, outfile);
  1277.   last_extent_written++;
  1278.   return 0;
  1279. }
  1280. /*
  1281.  * Function to write the EVD for the disc.
  1282.  */
  1283. static int FDECL1(evd_write, FILE *, outfile)
  1284. {
  1285.   struct iso_primary_descriptor evol_desc;
  1286.   /*
  1287.    * Now write the end volume descriptor.  Much simpler than the other one 
  1288.    */
  1289.   memset(&evol_desc, 0, sizeof(evol_desc));
  1290.   evol_desc.type[0] = (unsigned char)ISO_VD_END;
  1291.   memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
  1292.   evol_desc.version[0] = 1;
  1293.   xfwrite(&evol_desc, 1, 2048, outfile);
  1294.   last_extent_written += 1;
  1295.   return 0;
  1296. }
  1297. /*
  1298.  * Function to write the EVD for the disc.
  1299.  */
  1300. static int FDECL1(pathtab_write, FILE *, outfile)
  1301. {
  1302.   /*
  1303.    * Next we write the path tables 
  1304.    */
  1305.   xfwrite(path_table_l, 1, path_blocks << 11, outfile);
  1306.   xfwrite(path_table_m, 1, path_blocks << 11, outfile);
  1307.   last_extent_written += 2*path_blocks;
  1308.   free(path_table_l);
  1309.   free(path_table_m);
  1310.   path_table_l = NULL;
  1311.   path_table_m = NULL;
  1312.   return 0;
  1313. }
  1314. static int FDECL1(exten_write, FILE *, outfile)
  1315. {
  1316.   xfwrite(extension_record, 1, SECTOR_SIZE, outfile);
  1317.   last_extent_written++;
  1318.   return 0;
  1319. }
  1320. /*
  1321.  * Functions to describe padding block at the start of the disc.
  1322.  */
  1323. int FDECL1(oneblock_size, int, starting_extent)
  1324. {
  1325.   last_extent++;
  1326.   return 0;
  1327. }
  1328. /*
  1329.  * Functions to describe padding block at the start of the disc.
  1330.  */
  1331. static int FDECL1(pathtab_size, int, starting_extent)
  1332. {
  1333.   path_table[0] = starting_extent;
  1334.   path_table[1] = 0;
  1335.   path_table[2] = path_table[0] + path_blocks;
  1336.   path_table[3] = 0;
  1337.   last_extent += 2*path_blocks;
  1338.   return 0;
  1339. }
  1340. static int FDECL1(padblock_size, int, starting_extent)
  1341. {
  1342.   last_extent= session_start + 16;
  1343.   return 0;
  1344. }
  1345. static int file_gen()
  1346. {
  1347.   assign_file_addresses(root);
  1348.   return 0;
  1349. }
  1350. static int dirtree_dump()
  1351. {
  1352.   if (verbose > 2)
  1353.   {
  1354.       dump_tree(root);
  1355.   }
  1356.   return 0;
  1357. }
  1358. static int FDECL1(dirtree_fixup, int, starting_extent)
  1359. {
  1360.   if (use_RockRidge && reloc_dir)
  1361.   finish_cl_pl_entries();
  1362.   if (use_RockRidge )
  1363.   update_nlink_field(root);
  1364.   return 0;
  1365. }
  1366. static int FDECL1(dirtree_size, int, starting_extent)
  1367. {
  1368.   assign_directory_addresses(root);
  1369.   return 0;
  1370. }
  1371. static int FDECL1(ext_size, int, starting_extent)
  1372. {
  1373.   extern int extension_record_size;
  1374.   struct directory_entry * s_entry;
  1375.   extension_record_extent = starting_extent;
  1376.   s_entry = root->contents;
  1377.   set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
  1378.   extension_record_extent);
  1379.   set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
  1380.   extension_record_size);
  1381.   last_extent++;
  1382.   return 0;
  1383. }
  1384. static int FDECL1(dirtree_write, FILE *, outfile)
  1385. {
  1386.   generate_iso9660_directories(root, outfile);
  1387.   return 0;
  1388. }
  1389. static int FDECL1(dirtree_cleanup, FILE *, outfile)
  1390. {
  1391.   free_directories(root);
  1392.   return 0;
  1393. }
  1394. static int FDECL1(padblock_write, FILE *, outfile)
  1395. {
  1396.   char buffer[2048];
  1397.   int i;
  1398.   int npad;
  1399.   memset(buffer, 0, sizeof(buffer));
  1400.   npad = session_start + 16 - last_extent_written;
  1401.   for(i=0; i<npad; i++)
  1402.     {
  1403.       xfwrite(buffer, 1, sizeof(buffer), outfile);
  1404.     }
  1405.   last_extent_written += npad;
  1406.   return 0;
  1407. }
  1408. struct output_fragment padblock_desc  = {NULL, padblock_size, NULL,     padblock_write};
  1409. struct output_fragment voldesc_desc   = {NULL, oneblock_size, root_gen, pvd_write};
  1410. struct output_fragment end_vol       = {NULL, oneblock_size, NULL,     evd_write};
  1411. struct output_fragment pathtable_desc = {NULL, pathtab_size,  generate_path_tables,     pathtab_write};
  1412. struct output_fragment dirtree_desc   = {NULL, dirtree_size,  NULL,     dirtree_write};
  1413. struct output_fragment dirtree_clean  = {NULL, dirtree_fixup, dirtree_dump,     dirtree_cleanup};
  1414. struct output_fragment extension_desc = {NULL, ext_size,      NULL,     exten_write};
  1415. struct output_fragment files_desc     = {NULL, NULL,          file_gen, file_write};