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