home *** CD-ROM | disk | FTP | other *** search
/ Dream 49 / Amiga_Dream_49.iso / beos / utils / mkisofs-1.000 / mkisofs-1.11-beos / multi.c < prev    next >
C/C++ Source or Header  |  1998-01-25  |  24KB  |  989 lines

  1. /*
  2.  * File multi.c - scan existing iso9660 image and merge into 
  3.  * iso9660 filesystem.  Used for multisession support.
  4.  *
  5.  * Written by Eric Youngdale (1996).
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2, or (at your option)
  10.  * any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  20.  */
  21.  
  22. static char rcsid[] ="$Id: multi.c,v 1.1 1998/01/25 20:38:07 chrish Exp chrish $";
  23.  
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <time.h>
  27. #include <errno.h>
  28. #include <sys/stat.h>
  29.  
  30. #include "config.h"
  31.  
  32. #ifndef VMS
  33.  
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37.  
  38. #else
  39. #include <sys/file.h>
  40. #include <vms/fabdef.h>
  41. #include "vms.h"
  42. extern char * strdup(const char *);
  43. #endif
  44.  
  45. #include "mkisofs.h"
  46. #include "iso9660.h"
  47.  
  48. #define TF_CREATE 1
  49. #define TF_MODIFY 2
  50. #define TF_ACCESS 4
  51. #define TF_ATTRIBUTES 8
  52.  
  53. static int  DECL(get_session_start, (int *));
  54. static int  DECL(merge_old_directory_into_tree, (struct directory_entry *,
  55.                          struct directory *));
  56.  
  57. static int
  58. isonum_711 (unsigned char * p)
  59. {
  60.     return (*p & 0xff);
  61. }
  62.  
  63. int
  64. isonum_721 (unsigned char * p)
  65. {
  66.     return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
  67. }
  68.  
  69. static int
  70. isonum_723 (unsigned char * p)
  71. {
  72. #if 0
  73.     if (p[0] != p[3] || p[1] != p[2]) {
  74.         fprintf (stderr, "invalid format 7.2.3 number\n");
  75.         exit (1);
  76.     }
  77. #endif
  78.     return (isonum_721 (p));
  79. }
  80.  
  81. int
  82. isonum_731 (unsigned char * p)
  83. {
  84.     return ((p[0] & 0xff)
  85.         | ((p[1] & 0xff) << 8)
  86.         | ((p[2] & 0xff) << 16)
  87.         | ((p[3] & 0xff) << 24));
  88. }
  89.  
  90. int
  91. isonum_733 (unsigned char * p)
  92. {
  93.     return (isonum_731 (p));
  94. }
  95.  
  96. FILE * in_image = NULL;
  97.  
  98. #ifndef    USE_SCG
  99. /*
  100.  * Don't define readsecs if mkisofs is linked with
  101.  * the SCSI library.
  102.  * readsecs() will be implemented as SCSI command in this case.
  103.  *
  104.  * Use global var in_image directly in readsecs()
  105.  * the SCSI equivalent will not use a FILE* for I/O.
  106.  *
  107.  * The main point of this pointless abstraction is that Solaris won't let
  108.  * you read 2K sectors from the cdrom driver.  The fact that 99.9% of the
  109.  * discs out there have a 2K sectorsize doesn't seem to matter that much.
  110.  * Anyways, this allows the use of a scsi-generics type of interface on
  111.  * Solaris.
  112.  */
  113. static int
  114. readsecs(int startsecno, void *buffer, int sectorcount)
  115. {
  116.     int    f = fileno(in_image);
  117.  
  118.     if (lseek(f, (off_t)startsecno * SECTOR_SIZE, 0) == (off_t)-1) {
  119.         fprintf(stderr," Seek error on old image\n");
  120.         exit(10);
  121.     }
  122.     return (read(f, buffer, sectorcount * SECTOR_SIZE));
  123. }
  124. #endif
  125.  
  126. /*
  127.  * Parse the RR attributes so we can find the file name.
  128.  */
  129. static int 
  130. FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt)
  131. {
  132.     int cont_extent, cont_offset, cont_size;
  133.     char name_buf[256];
  134.  
  135.     cont_extent = cont_offset = cont_size = 0;
  136.  
  137.     while(len >= 4){
  138.         if(pnt[3] != 1) {
  139.           printf("**BAD RRVERSION");
  140.           return -1;
  141.         };
  142.         if(strncmp((char *) pnt, "NM", 2) == 0) {
  143.           strncpy(name_buf, (char *) pnt+5, pnt[2] - 5);
  144.           name_buf[pnt[2] - 5] = 0;
  145.           dpnt->name = strdup(name_buf);
  146.           return 0;
  147.         }
  148.  
  149.         if(strncmp((char *) pnt, "CE", 2) == 0) {
  150.             cont_extent = isonum_733(pnt+4);
  151.             cont_offset = isonum_733(pnt+12);
  152.             cont_size = isonum_733(pnt+20);
  153.         };
  154.  
  155.         len -= pnt[2];
  156.         pnt += pnt[2];
  157.         if(len <= 3 && cont_extent) {
  158.           unsigned char sector[SECTOR_SIZE];
  159.           readsecs(cont_extent, sector, 1);
  160.           parse_rr(§or[cont_offset], cont_size, dpnt);
  161.         };
  162.     };
  163.     return 0;
  164. }
  165.  
  166.  
  167. static int 
  168. FDECL4(check_rr_dates, struct directory_entry *, dpnt, 
  169.        struct directory_entry *, current, 
  170.        struct stat *, statbuf, 
  171.        struct stat *,lstatbuf)
  172. {
  173.     int cont_extent, cont_offset, cont_size;
  174.     int offset;
  175.     unsigned char * pnt;
  176.     int len;
  177.     int same_file;
  178.     int same_file_type;
  179.     mode_t mode;
  180.     char time_buf[7];
  181.     
  182.     
  183.     cont_extent = cont_offset = cont_size = 0;
  184.     same_file = 1;
  185.     same_file_type = 1;
  186.  
  187.     pnt = dpnt->rr_attributes;
  188.     len = dpnt->rr_attr_size;
  189.     /*
  190.      * We basically need to parse the rr attributes again, and
  191.      * dig out the dates and file types.
  192.      */
  193.     while(len >= 4){
  194.         if(pnt[3] != 1) {
  195.           printf("**BAD RRVERSION");
  196.           return -1;
  197.         };
  198.  
  199.         /*
  200.          * If we have POSIX file modes, make sure that the file type
  201.          * is the same.  If it isn't, then we must always
  202.          * write the new file.
  203.          */
  204.         if(strncmp((char *) pnt, "PX", 2) == 0) {
  205.           mode = isonum_733(pnt + 4);
  206.           if( (lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT) )
  207.             {
  208.               same_file_type = 0;
  209.               same_file = 0;
  210.             }
  211.         }
  212.  
  213.         if(strncmp((char *) pnt, "TF", 2) == 0) {
  214.           offset = 5;
  215.           if( pnt[4] & TF_CREATE )
  216.             {
  217.               iso9660_date((char *) time_buf, lstatbuf->st_ctime);
  218.               if(memcmp(time_buf, pnt+offset, 7) == 0) 
  219.             same_file = 0;
  220.               offset += 7;
  221.             }
  222.           if( pnt[4] & TF_MODIFY )
  223.             {
  224.               iso9660_date((char *) time_buf, lstatbuf->st_mtime);
  225.               if(memcmp(time_buf, pnt+offset, 7) == 0) 
  226.             same_file = 0;
  227.               offset += 7;
  228.             }
  229.         }
  230.  
  231.         if(strncmp((char *) pnt, "CE", 2) == 0) {
  232.             cont_extent = isonum_733(pnt+4);
  233.             cont_offset = isonum_733(pnt+12);
  234.             cont_size = isonum_733(pnt+20);
  235.         };
  236.  
  237.         len -= pnt[2];
  238.         pnt += pnt[2];
  239.         if(len <= 3 && cont_extent) {
  240.           unsigned char sector[SECTOR_SIZE];
  241.  
  242.           readsecs(cont_extent, sector, 1);
  243.           parse_rr(§or[cont_offset], cont_size, dpnt);
  244.         };
  245.     };
  246.  
  247.     /*
  248.      * If we have the same fundamental file type, then it is clearly
  249.      * safe to reuse the TRANS.TBL entry.
  250.      */
  251.     if( same_file_type )
  252.       {
  253.         current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
  254.       }
  255.  
  256.     return same_file;
  257. }
  258.  
  259. struct directory_entry **
  260. FDECL2(read_merging_directory, struct iso_directory_record *, mrootp,
  261.        int *, nent)
  262. {
  263.   unsigned char            * cpnt;
  264.   unsigned char            * cpnt1;
  265.   char                * dirbuff;
  266.   int                  i;
  267.   struct iso_directory_record    * idr;
  268.   int                  len;
  269.   struct directory_entry    **pnt;
  270.   int                  rlen;
  271.   struct directory_entry    **rtn;
  272.   int                  seen_rockridge;
  273.   unsigned char            * tt_buf;
  274.   int                  tt_extent;
  275.   int                  tt_size;
  276.  
  277.   /*
  278.    * First, allocate a buffer large enough to read in the entire
  279.    * directory.
  280.    */
  281.   dirbuff = (char *) e_malloc(isonum_733((unsigned char *)mrootp->size));
  282.  
  283.   readsecs(isonum_733((unsigned char *)mrootp->extent), dirbuff,
  284.        isonum_733((unsigned char *)mrootp->size)/SECTOR_SIZE);
  285.  
  286.   /*
  287.    * Next look over the directory, and count up how many entries we
  288.    * have.
  289.    */
  290.   len = isonum_733((unsigned char *)mrootp->size);
  291.   i = 0;
  292.   *nent = 0;
  293.   while(i < len )
  294.     {
  295.       idr = (struct iso_directory_record *) &dirbuff[i];
  296.       if(idr->length[0] == 0) 
  297.     {
  298.       i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
  299.       continue;
  300.     }
  301.       (*nent)++;
  302.       i += idr->length[0];
  303.     }
  304.  
  305.   /*
  306.    * Now allocate the buffer which will hold the array we are
  307.    * about to return.
  308.    */
  309.   rtn = (struct directory_entry **) e_malloc(*nent * sizeof(*rtn));
  310.  
  311.   /*
  312.    * Finally, scan the directory one last time, and pick out the
  313.    * relevant bits of information, and store it in the relevant
  314.    * bits of the structure.
  315.    */
  316.   i = 0;
  317.   pnt = rtn;
  318.   tt_extent = 0;
  319.   seen_rockridge = 0;
  320.   tt_size = 0;
  321.   while(i < len )
  322.     {
  323.       idr = (struct iso_directory_record *) &dirbuff[i];
  324.       if(idr->length[0] == 0) 
  325.     {
  326.       i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
  327.       continue;
  328.     }
  329.       *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn));
  330.       (*pnt)->next = NULL;
  331.       (*pnt)->isorec = *idr;
  332.       (*pnt)->starting_block = isonum_733((unsigned char *)idr->extent);
  333.       (*pnt)->size = isonum_733((unsigned char *)idr->size);
  334.       (*pnt)->priority = 0;
  335.       (*pnt)->name = NULL;
  336.       (*pnt)->table = NULL;
  337.       (*pnt)->whole_name = NULL;
  338.       (*pnt)->filedir = NULL;
  339.       (*pnt)->parent_rec = NULL;
  340.       /*
  341.        * Set this information so that we correctly cache previous
  342.        * session bits of information.
  343.        */
  344.       (*pnt)->inode = (*pnt)->starting_block;
  345.       (*pnt)->dev = PREV_SESS_DEV;
  346.       (*pnt)->rr_attributes = NULL;
  347.       (*pnt)->rr_attr_size = 0;
  348.       (*pnt)->total_rr_attr_size = 0;
  349.       (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY;
  350.  
  351.       /*
  352.        * Check for and parse any RR attributes for the file.
  353.        * All we are really looking for here is the original name
  354.        * of the file.
  355.        */
  356.       rlen = idr->length[0] & 0xff;
  357.       cpnt = (unsigned char *) idr;
  358.       
  359.       rlen -= sizeof(struct iso_directory_record);
  360.       cpnt += sizeof(struct iso_directory_record);
  361.       
  362.       rlen += sizeof(idr->name);
  363.       cpnt -= sizeof(idr->name);
  364.       
  365.       rlen -= idr->name_len[0];
  366.       cpnt += idr->name_len[0];
  367.       
  368.       if((idr->name_len[0] & 1) == 0){
  369.     cpnt++;
  370.     rlen--;
  371.       };
  372.  
  373.       if( rlen != 0 )
  374.     {
  375.       (*pnt)->total_rr_attr_size =  (*pnt)->rr_attr_size = rlen;
  376.       (*pnt)->rr_attributes = e_malloc(rlen);
  377.       memcpy((*pnt)->rr_attributes,  cpnt, rlen);
  378.       seen_rockridge = 1;
  379.     }
  380.  
  381.       /*
  382.        * Now zero out the remainder of the name field.
  383.        */
  384.       cpnt = (unsigned char *) &(*pnt)->isorec.name;
  385.       cpnt += idr->name_len[0];
  386.       memset(cpnt, 0, sizeof((*pnt)->isorec.name) - idr->name_len[0]);
  387.  
  388.       parse_rr((*pnt)->rr_attributes, rlen, *pnt);
  389.       
  390.       if(    ((*pnt)->isorec.name_len[0] == 1)
  391.       && (    ((*pnt)->isorec.name[0] == 0)
  392.            || ((*pnt)->isorec.name[0] == 1)) )
  393.     {
  394.       if( (*pnt)->name != NULL )
  395.         {
  396.           free((*pnt)->name);
  397.         }
  398.       if( (*pnt)->isorec.name[0] == 0 )
  399.         {
  400.           (*pnt)->name = strdup(".");
  401.         }
  402.       else
  403.         {
  404.           (*pnt)->name = strdup("..");
  405.         }
  406.     }
  407.  
  408.       if( strncmp(idr->name, "TRANS.TBL", 9) == 0)
  409.     {
  410.       if( (*pnt)->name != NULL )
  411.         {
  412.           free((*pnt)->name);
  413.         }
  414.       (*pnt)->name = strdup("<translation table>");
  415.       tt_extent = isonum_733((unsigned char *)idr->extent);
  416.       tt_size = isonum_733((unsigned char *)idr->size);
  417.     }
  418.       
  419.       pnt++;
  420.       i += idr->length[0];
  421.     }
  422.  
  423.   /*
  424.    * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it
  425.    * to get the filenames of the files.  Also, save the table info, just
  426.    * in case we need to use it.
  427.    */
  428.   if( tt_extent != 0 && tt_size != 0 )
  429.     {
  430.       tt_buf = (unsigned char *) e_malloc(tt_size);
  431.       readsecs(tt_extent, tt_buf, tt_size/SECTOR_SIZE);
  432.  
  433.       /*
  434.        * Loop through the file, examine each entry, and attempt to
  435.        * attach it to the correct entry.
  436.        */
  437.       cpnt = tt_buf;
  438.       cpnt1 = tt_buf;
  439.       while( cpnt - tt_buf < tt_size )
  440.     {
  441.       while(*cpnt1 != '\n' && *cpnt1 != '\0')  cpnt1++;
  442.       *cpnt1 = '\0';
  443.  
  444.       for(pnt = rtn, i = 0; i <*nent; i++, pnt++)
  445.         {
  446.           rlen = isonum_711((*pnt)->isorec.name_len);
  447.           if( strncmp((char *) cpnt + 2, (*pnt)->isorec.name,
  448.               rlen) == 0 
  449.           && cpnt[2+rlen] == ' ')
  450.         {
  451.           (*pnt)->table = strdup((char *) cpnt);
  452.           if( (*pnt)->name == NULL )
  453.             {
  454.               (*pnt)->name = strdup((char *) cpnt+37);
  455.             }
  456.           break;
  457.         }
  458.         }
  459.       cpnt = cpnt1 + 1;
  460.       cpnt1 = cpnt;
  461.     }
  462.       
  463.       free(tt_buf);
  464.     }
  465.   else if( !seen_rockridge )
  466.     {
  467.       /*
  468.        * This is a fatal error right now because we must have some mechanism
  469.        * for taking the 8.3 names back to the original unix names.
  470.        * In principle we could do this the hard way, and try and translate
  471.        * the unix names that we have seen forwards, but this would be
  472.        * a real pain in the butt.
  473.        */
  474.       fprintf(stderr,"Previous session must have either Rock Ridge (-R) or\n");
  475.       fprintf(stderr,"TRANS.TBL (-T) for mkisofs to be able to correctly\n");
  476.       fprintf(stderr,"generate additional sessions.\n");
  477.       exit(3);
  478.     }
  479.  
  480.   if( dirbuff != NULL )
  481.     {
  482.       free(dirbuff);
  483.     }
  484.   
  485.   return rtn;
  486. }
  487.  
  488. /*
  489.  * Free any associated data related to the structures.
  490.  */
  491. int 
  492. FDECL2(free_mdinfo, struct directory_entry **  , ptr, int, len )
  493. {
  494.   int        i;
  495.   struct directory_entry **p;
  496.  
  497.   p = ptr;
  498.   for(i=0; i<len; i++, p++)
  499.     {
  500.       /*
  501.        * If the tree-handling code decided that it needed an entry,
  502.        * it will have removed it from the list.  Thus we must allow
  503.        * for null pointers here.
  504.        */
  505.       if( *p == NULL )
  506.     {
  507.       continue;
  508.     }
  509.  
  510.       if( (*p)->name != NULL )
  511.     {
  512.       free((*p)->name);
  513.     }
  514.  
  515.       if( (*p)->rr_attributes != NULL )
  516.     {
  517.       free((*p)->rr_attributes);
  518.     }
  519.  
  520.       if( (*p)->table != NULL )
  521.     {
  522.       free((*p)->table);
  523.     }
  524.  
  525.       free(*p);
  526.  
  527.     }
  528.  
  529.   free(ptr);
  530.   return 0;
  531. }
  532.  
  533. /*
  534.  * Search the list to see if we have any entries from the previous
  535.  * session that match this entry.  If so, copy the extent number
  536.  * over so we don't bother to write it out to the new session.
  537.  */
  538.  
  539. int
  540. FDECL6(check_prev_session, struct directory_entry **  , ptr, int, len,
  541.        struct directory_entry *, curr_entry,
  542.        struct stat *, statbuf, struct stat *, lstatbuf,
  543.        struct directory_entry **, odpnt)
  544. {
  545.   int        i;
  546.  
  547.   for( i=0; i < len; i++ )
  548.     {
  549.       if( ptr[i] == NULL )
  550.     {
  551.       continue;
  552.     }
  553.  
  554. #if 0
  555.       if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1
  556.       && ptr[i]->name[0] == '\0' )
  557.     {
  558.       continue;
  559.     }
  560.       if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1
  561.       && ptr[i]->name[0] == 1)
  562.     {
  563.       continue;
  564.     }
  565. #else
  566.       if( ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0 )
  567.     {
  568.       continue;
  569.     }
  570.       if( ptr[i]->name != NULL  && strcmp(ptr[i]->name, "..") == 0 )
  571.     {
  572.       continue;
  573.     }
  574. #endif
  575.  
  576.       if(    ptr[i]->name != NULL
  577.       && strcmp(ptr[i]->name, curr_entry->name) != 0 )
  578.     {
  579.       continue;
  580.     }
  581.  
  582.       /*
  583.        * We know that the files have the same name.  If they also have
  584.        * the same file type (i.e. file, dir, block, etc), then we
  585.        * can safely reuse the TRANS.TBL entry for this file.
  586.        * The check_rr_dates function will do this for us.
  587.        *
  588.        * Verify that the file type and dates are consistent.
  589.        * If not, we probably have a different file, and we need
  590.        * to write it out again.
  591.        */
  592.       if(    (ptr[i]->rr_attributes != NULL)
  593.       && (check_rr_dates(ptr[i], curr_entry, statbuf, lstatbuf)) )
  594.     {
  595.       goto found_it;
  596.     }
  597.  
  598.  
  599.       /*
  600.        * Verify size and timestamp.  If rock ridge is in use, we need
  601.        * to compare dates from RR too.  Directories are special, we
  602.        * calculate their size later.
  603.        */
  604.       if(     (curr_entry->isorec.flags[0] & 2) == 0
  605.       &&  ptr[i]->size != curr_entry->size )
  606.     {
  607.       goto found_it;
  608.     }
  609.  
  610.       if( memcmp(ptr[i]->isorec.date, curr_entry->isorec.date,7) != 0 )
  611.     {
  612.       goto found_it;
  613.     }
  614.  
  615.       /*
  616.        * Never ever reuse directory extents.  See comments in
  617.        * tree.c for an explaination of why this must be the case.
  618.        */
  619.       if( (curr_entry->isorec.flags[0] & 2) != 0 )
  620.     {
  621.       goto found_it;
  622.     }
  623.  
  624.       memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
  625.       curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
  626.       goto found_it;
  627.     }
  628.   return 0;
  629.  
  630. found_it:
  631.   if( odpnt != NULL )
  632.     {
  633.       *odpnt = ptr[i];
  634.     }
  635.   else
  636.     {
  637.       free(ptr[i]);
  638.     }
  639.   ptr[i] = NULL;
  640.   return 0;
  641. }
  642.  
  643. /*
  644.  * merge_isofs:  Scan an existing image, and return a pointer
  645.  * to the root directory for this image.
  646.  */
  647. struct iso_directory_record * FDECL1(merge_isofs, char *, path)
  648. {
  649.   char                  buffer[SECTOR_SIZE];
  650.   int                  file_addr;
  651.   int                  i;
  652.   struct iso_primary_descriptor * pri = NULL;
  653.   struct iso_directory_record   * rootp;
  654.   struct iso_volume_descriptor  * vdp;
  655.  
  656.   /*
  657.    * Start by opening up the image and searching for the volume header.
  658.    * Ultimately, we need to search for volume headers in multiple places
  659.    * because we might be starting with a multisession image.
  660.    * FIXME(eric).
  661.    */
  662.  
  663.   in_image = fopen(path, "rb");
  664.   if( in_image == NULL )
  665.     {
  666.       return NULL;
  667.     }
  668.  
  669.   get_session_start(&file_addr);
  670.  
  671.   for(i = 0; i< 100; i++)
  672.     {
  673.       if (readsecs(file_addr/SECTOR_SIZE, &buffer,
  674.            sizeof(buffer)/SECTOR_SIZE) != sizeof(buffer))
  675.     {
  676.       fprintf(stderr," Read error on old image %s\n", path);
  677.       exit(10);
  678.     }
  679.  
  680.       vdp = (struct iso_volume_descriptor *)buffer;
  681.  
  682.       if(    (strncmp(vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0)
  683.       && (isonum_711((unsigned char *)vdp->type) == ISO_VD_PRIMARY) )
  684.     {
  685.       break;
  686.     }
  687.       file_addr += SECTOR_SIZE;
  688.     }
  689.  
  690.   if( i == 100 )
  691.     {
  692.       return NULL;
  693.     }
  694.  
  695.   pri = (struct iso_primary_descriptor *)vdp;
  696.  
  697.   /*
  698.    * Check the blocksize of the image to make sure it is compatible.
  699.    */
  700.   if(    (isonum_723 ((unsigned char *)pri->logical_block_size) != SECTOR_SIZE)
  701.       || (isonum_723 ((unsigned char *)pri->volume_set_size) != 1) )
  702.     {
  703.       return NULL;
  704.     }
  705.  
  706.   /*
  707.    * Get the location and size of the root directory.
  708.    */
  709.   rootp = (struct iso_directory_record *) 
  710.     malloc(sizeof(struct iso_directory_record));
  711.  
  712.   memcpy(rootp, pri->root_directory_record, sizeof(*rootp));
  713.  
  714.   return rootp;
  715. }
  716.  
  717. void FDECL3(merge_remaining_entries, struct directory *, this_dir,
  718.         struct directory_entry **, pnt,
  719.         int, n_orig)
  720. {
  721.   int i;
  722.   struct directory_entry * s_entry;
  723.   unsigned int ttbl_extent = 0;
  724.   unsigned int ttbl_index  = 0;
  725.  
  726.   /*
  727.    * Whatever is leftover in the list needs to get merged back
  728.    * into the directory.
  729.    */
  730.   for( i=0; i < n_orig; i++ )
  731.     {
  732.       if( pnt[i] == NULL )
  733.     {
  734.       continue;
  735.     }
  736.       
  737.       if( pnt[i]->name != NULL
  738.       && strcmp(pnt[i]->name, "<translation table>") == 0 )
  739.     {
  740.       ttbl_extent = isonum_733((unsigned char *)pnt[i]->isorec.extent);
  741.       ttbl_index = i;
  742.       continue;
  743.     }
  744.       /*
  745.        * Skip directories for now - these need to be treated
  746.        * differently.
  747.        */
  748.       if( (pnt[i]->isorec.flags[0] & 2) != 0 )
  749.     {
  750.       /*
  751.        * FIXME - we need to insert this directory into the
  752.        * tree, so that the path tables we generate will
  753.        * be correct.
  754.        */
  755.       if(    (strcmp(pnt[i]->name, ".") == 0)
  756.           || (strcmp(pnt[i]->name, "..") == 0) )
  757.         {
  758.           free(pnt[i]);
  759.           pnt[i] = NULL;
  760.           continue;
  761.         }
  762.       else
  763.         {
  764.           merge_old_directory_into_tree(pnt[i], this_dir);
  765.         }
  766.     }
  767.       pnt[i]->next = this_dir->contents;
  768.       pnt[i]->filedir = this_dir;
  769.       this_dir->contents = pnt[i];
  770.       pnt[i] = NULL;
  771.     }
  772.   
  773.  
  774.   /*
  775.    * If we don't have an entry for the translation table, then
  776.    * don't bother trying to copy the starting extent over.
  777.    * Note that it is possible that if we are copying the entire
  778.    * directory, the entry for the translation table will have already
  779.    * been inserted into the linked list and removed from the old
  780.    * entries list, in which case we want to leave the extent number
  781.    * as it was before.
  782.    */
  783.   if( ttbl_extent == 0 )
  784.     {
  785.       return;
  786.     }
  787.  
  788.   /*
  789.    * Finally, check the directory we are creating to see whether
  790.    * there are any new entries in it.  If there are not, we can
  791.    * reuse the same translation table.
  792.    */
  793.   for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  794.     {
  795.       /*
  796.        * Don't care about '.' or '..'.  They are never in the table
  797.        * anyways.
  798.        */
  799.       if( s_entry->name != NULL && strcmp(s_entry->name, ".") == 0 )
  800.     {
  801.       continue;
  802.     }
  803.       if( s_entry->name != NULL && strcmp(s_entry->name, "..") == 0 )
  804.     {
  805.       continue;
  806.     }
  807.       if( strcmp(s_entry->name, "<translation table>") == 0)
  808.     {
  809.       continue;
  810.     }
  811.       if( (s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0 )
  812.     {
  813.       return;
  814.     }
  815.     }
  816.  
  817.   /*
  818.    * Locate the translation table, and re-use the same extent.
  819.    * It isn't clear that there should ever be one in there already
  820.    * so for now we try and muddle through the best we can.
  821.    */
  822.   for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  823.     {
  824.       if( strcmp(s_entry->name, "<translation table>") == 0)
  825.     {
  826.       fprintf(stderr,"Should never get here\n");
  827.       set_733(s_entry->isorec.extent, ttbl_extent);
  828.       return;
  829.     }
  830.     }
  831.  
  832.   pnt[ttbl_index]->next = this_dir->contents;
  833.   pnt[ttbl_index]->filedir = this_dir;
  834.   this_dir->contents = pnt[ttbl_index];
  835.   pnt[ttbl_index] = NULL;
  836. }
  837.  
  838.  
  839. /*
  840.  * Here we have a case of a directory that has completely disappeared from
  841.  * the face of the earth on the tree we are mastering from.  Go through and
  842.  * merge it into the tree, as well as everything beneath it.
  843.  *
  844.  * Note that if a directory has been moved for some reason, this will
  845.  * incorrectly pick it up and attempt to merge it back into the old
  846.  * location.  FIXME(eric).
  847.  */
  848. static int
  849. FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt, 
  850.        struct directory *, parent)
  851. {
  852.   struct directory_entry    **contents = NULL;
  853.   int                  i;
  854.   int                  n_orig;
  855.   struct directory        * this_dir, *next_brother;
  856.   char                  whole_path[1024];
  857.  
  858.   this_dir = (struct directory *) e_malloc(sizeof(struct directory));
  859.   this_dir->next = NULL;
  860.   this_dir->subdir = NULL;
  861.   this_dir->self = dpnt;
  862.   this_dir->contents = NULL;
  863.   this_dir->size = 0;
  864.   this_dir->extent = 0;
  865.   this_dir->depth = parent->depth + 1;
  866.   this_dir->parent = parent;
  867.   if(!parent->subdir)
  868.     parent->subdir = this_dir;
  869.   else {
  870.     next_brother = parent->subdir;
  871.     while(next_brother->next) next_brother = next_brother->next;
  872.     next_brother->next = this_dir;
  873.   }
  874.  
  875.   /*
  876.    * Set the name for this directory.
  877.    */
  878.   strcpy(whole_path, parent->de_name);
  879.   strcat(whole_path, SPATH_SEPARATOR);
  880.   strcat(whole_path, dpnt->name);
  881.   this_dir->de_name = strdup(whole_path);
  882.  
  883.   /*
  884.    * Now fill this directory using information from the previous
  885.    * session.
  886.    */
  887.   contents = read_merging_directory(&dpnt->isorec, &n_orig);
  888.   /*
  889.    * Start by simply copying the '.', '..' and non-directory
  890.    * entries to this directory.  Technically we could let
  891.    * merge_remaining_entries handle this, but it gets rather confused
  892.    * by the '.' and '..' entries.
  893.    */
  894.   for(i=0; i < n_orig; i ++ )
  895.     {
  896.       /*
  897.        * We can always reuse the TRANS.TBL in this particular case.
  898.        */
  899.       contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;    
  900.  
  901.       if(    ((contents[i]->isorec.flags[0] & 2) != 0)
  902.       && (i >= 2) )
  903.     {
  904.       continue;
  905.     }
  906.  
  907.       /*
  908.        * If we have a directory, don't reuse the extent number.
  909.        */
  910.       if( (contents[i]->isorec.flags[0] & 2) != 0 )
  911.     {
  912.       memset(contents[i]->isorec.extent, 0, 8);
  913.     }
  914.  
  915.       contents[i]->next = this_dir->contents;
  916.       contents[i]->filedir = this_dir;
  917.       this_dir->contents = contents[i];
  918.       contents[i] = NULL;
  919.     }
  920.  
  921.   /*
  922.    * Zero the extent number for ourselves.
  923.    */
  924.   memset(dpnt->isorec.extent, 0, 8);
  925.  
  926.   /*
  927.    * Anything that is left are other subdirectories that need to be merged.
  928.    */
  929.   merge_remaining_entries(this_dir, contents, n_orig);
  930.   free_mdinfo(contents, n_orig);
  931.   sort_n_finish(this_dir);
  932.  
  933.   return 0;
  934. }
  935.  
  936.  
  937. char * cdwrite_data = NULL;
  938.  
  939. static int
  940. FDECL1(get_session_start, int *, file_addr) 
  941. {
  942.   char * pnt;
  943.  
  944. #ifdef CDWRITE_DETERMINES_FIRST_WRITABLE_ADDRESS
  945.   /*
  946.    * FIXME(eric).  We need to coordinate with cdwrite to obtain
  947.    * the parameters.  For now, we assume we are writing the 2nd session,
  948.    * so we start from the session that starts at 0.
  949.    */
  950.  
  951.   *file_addr = (16 << 11);
  952.  
  953.   /*
  954.    * We need to coordinate with cdwrite to get the next writable address
  955.    * from the device.  Here is where we use it.
  956.    */
  957.   session_start = last_extent = last_extent_written = cdwrite_result();
  958.  
  959. #else
  960.  
  961.   if( cdwrite_data == NULL )
  962.     {
  963.       fprintf(stderr,"Special parameters for cdwrite not specified with -C\n");
  964.       exit(1);
  965.     }
  966.  
  967.   /*
  968.    * Next try and find the ',' in there which delimits the two numbers.
  969.    */
  970.   pnt = strchr(cdwrite_data, ',');
  971.   if( pnt == NULL )
  972.     {
  973.       fprintf(stderr, "Malformed cdwrite parameters\n");
  974.       exit(1);
  975.     }
  976.  
  977.   *pnt = '\0';
  978.   *file_addr = atol(cdwrite_data) * SECTOR_SIZE;
  979.   pnt++;
  980.  
  981.   session_start = last_extent = last_extent_written = atol(pnt);
  982.  
  983.   pnt--;
  984.   *pnt = ',';
  985.  
  986. #endif
  987.   return 0;
  988. }
  989.