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