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(§or[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(§or[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