ReactOS  0.4.14-dev-608-gd495a4f
multi.c
Go to the documentation of this file.
1 /* @(#)multi.c 1.104 16/01/06 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5  "@(#)multi.c 1.104 16/01/06 joerg";
6 #endif
7 /*
8  * File multi.c - scan existing iso9660 image and merge into
9  * iso9660 filesystem. Used for multisession support.
10  *
11  * Written by Eric Youngdale (1996).
12  * Copyright (c) 1999-2016 J. Schilling
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  */
28 
29 #include "mkisofs.h"
30 #include "rock.h"
31 #include <schily/time.h>
32 #include <schily/errno.h>
33 #include <schily/utypes.h>
34 #include <schily/schily.h>
35 #include <schily/ctype.h> /* Needed for printasc() */
36 
37 #ifdef VMS
38 
39 #include <sys/file.h>
40 #include <vms/fabdef.h>
41 #include "vms.h"
42 #endif
43 
44 #ifndef howmany
45 #define howmany(x, y) (((x)+((y)-1))/(y))
46 #endif
47 #ifndef roundup
48 #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
49 #endif
50 
51 /*
52  * Cannot debug memset() with gdb on Linux, so use fillbytes()
53  */
54 /*#define memset(s, c, n) fillbytes(s, n, c)*/
55 
56 #define TF_CREATE 1
57 #define TF_MODIFY 2
58 #define TF_ACCESS 4
59 #define TF_ATTRIBUTES 8
60 
61 LOCAL void printasc __PR((char *txt, unsigned char *p, int len));
62 LOCAL void prbytes __PR((char *txt, unsigned char *p, int len));
63 unsigned char *parse_xa __PR((unsigned char *pnt, int *lenp,
64  struct directory_entry *dpnt));
65 EXPORT int rr_flags __PR((struct iso_directory_record *idr));
66 LOCAL int parse_rrflags __PR((Uchar *pnt, int len, int cont_flag));
67 LOCAL BOOL find_rr __PR((struct iso_directory_record *idr, Uchar **pntp, int *lenp));
68 LOCAL int parse_rr __PR((unsigned char *pnt, int len,
69  struct directory_entry *dpnt));
70 LOCAL int check_rr_dates __PR((struct directory_entry *dpnt,
71  struct directory_entry *current,
72  struct stat *statbuf,
73  struct stat *lstatbuf));
75  int idr_off,
76  size_t space_left));
77 LOCAL struct directory_entry **
79 LOCAL int free_mdinfo __PR((struct directory_entry **, int len));
80 LOCAL void free_directory_entry __PR((struct directory_entry *dirp));
81 LOCAL int iso_dir_ents __PR((struct directory_entry *de));
82 LOCAL void copy_mult_extent __PR((struct directory_entry *se1,
83  struct directory_entry *se2));
85  struct directory_entry **, int));
86 
88  struct directory *));
90 
93 int su_version = -1;
94 int rr_version = -1;
95 int aa_version = -1;
96 char er_id[256];
97 
98 #ifndef USE_SCG
99 /*
100  * Don't define readsecs if mkisofs is linked with
101  * the SCSI library.
102  * readsecs() will be implemented as SCSI command in this case.
103  *
104  * Use global var in_image directly in readsecs()
105  * the SCSI equivalent will not use a FILE* for I/O.
106  *
107  * The main point of this pointless abstraction is that Solaris won't let
108  * you read 2K sectors from the cdrom driver. The fact that 99.9% of the
109  * discs out there have a 2K sectorsize doesn't seem to matter that much.
110  * Anyways, this allows the use of a scsi-generics type of interface on
111  * Solaris.
112  */
113 #ifdef PROTOTYPES
114 EXPORT int
115 readsecs(UInt32_t startsecno, void *buffer, int sectorcount)
116 #else
117 EXPORT int
118 readsecs(startsecno, buffer, sectorcount)
119  UInt32_t startsecno;
120  void *buffer;
121  int sectorcount;
122 #endif
123 {
124  int f = fileno(in_image);
125 
126  if (lseek(f, (off_t)startsecno * SECTOR_SIZE, SEEK_SET) == (off_t)-1) {
127  comerr(_("Seek error on old image\n"));
128  }
129  if (read(f, buffer, (sectorcount * SECTOR_SIZE))
130  != (sectorcount * SECTOR_SIZE)) {
131  comerr(_("Read error on old image\n"));
132  }
133  return (sectorcount * SECTOR_SIZE);
134 }
135 
136 #endif
137 
138 LOCAL void
139 printasc(txt, p, len)
140  char *txt;
141  unsigned char *p;
142  int len;
143 {
144  int i;
145 
146  error("%s ", txt);
147  for (i = 0; i < len; i++) {
148  if (isprint(p[i]))
149  error("%c", p[i]);
150  else
151  error(".");
152  }
153  error("\n");
154 }
155 
156 LOCAL void
157 prbytes(txt, p, len)
158  char *txt;
159  register Uchar *p;
160  register int len;
161 {
162  error("%s", txt);
163  while (--len >= 0)
164  error(" %02X", *p++);
165  error("\n");
166 }
167 
168 unsigned char *
169 parse_xa(pnt, lenp, dpnt)
170  unsigned char *pnt;
171  int *lenp;
172  struct directory_entry *dpnt;
173 {
174  struct iso_xa_dir_record *xadp;
175  int len = *lenp;
176 static int did_xa = 0;
177 
178 /*error("len: %d\n", len);*/
179 
180  if (len >= 14) {
181  xadp = (struct iso_xa_dir_record *)pnt;
182 
183 /* if (dpnt) prbytes("XA ", pnt, len);*/
184  if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
185  xadp->reserved[0] == '\0') {
186  len -= 14;
187  pnt += 14;
188  *lenp = len;
189  if (!did_xa) {
190  did_xa = 1;
191  errmsgno(EX_BAD, _("Found XA directory extension record.\n"));
192  }
193  } else if (pnt[2] == 0) {
194  char *cp = NULL;
195 
196  if (dpnt)
197  cp = (char *)&dpnt->isorec;
198  if (cp) {
199  prbytes("ISOREC:", (Uchar *)cp, 33+cp[32]);
200  printasc("ISOREC:", (Uchar *)cp, 33+cp[32]);
201  prbytes("XA REC:", pnt, len);
202  printasc("XA REC:", pnt, len);
203  }
204  if (no_rr == 0) {
205  errmsgno(EX_BAD, _("Disabling RR / XA / AA.\n"));
206  no_rr = 1;
207  }
208  *lenp = 0;
209  if (cp) {
210  errmsgno(EX_BAD, _("Problems with old ISO directory entry for file: '%s'.\n"), &cp[33]);
211  }
212  errmsgno(EX_BAD, _("Illegal extended directory attributes found (bad XA disk?).\n"));
213 /* errmsgno(EX_BAD, _("Disabling Rock Ridge for old session.\n"));*/
214  comerrno(EX_BAD, _("Try again using the -no-rr option.\n"));
215  }
216  }
217  if (len >= 4 && pnt[3] != 1 && pnt[3] != 2) {
218  prbytes("BAD RR ATTRIBUTES:", pnt, len);
219  printasc("BAD RR ATTRIBUTES:", pnt, len);
220  }
221  return (pnt);
222 }
223 
224 LOCAL BOOL
225 find_rr(idr, pntp, lenp)
226  struct iso_directory_record *idr;
227  Uchar **pntp;
228  int *lenp;
229 {
230  struct iso_xa_dir_record *xadp;
231  int len;
232  unsigned char *pnt;
233  BOOL ret = FALSE;
234 
235  len = idr->length[0] & 0xff;
236  len -= sizeof (struct iso_directory_record);
237  len += sizeof (idr->name);
238  len -= idr->name_len[0];
239 
240  pnt = (unsigned char *) idr;
241  pnt += sizeof (struct iso_directory_record);
242  pnt -= sizeof (idr->name);
243  pnt += idr->name_len[0];
244  if ((idr->name_len[0] & 1) == 0) {
245  pnt++;
246  len--;
247  }
248  if (len >= 14) {
249  xadp = (struct iso_xa_dir_record *)pnt;
250 
251  if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
252  xadp->reserved[0] == '\0') {
253  len -= 14;
254  pnt += 14;
255  ret = TRUE;
256  }
257  }
258  *pntp = pnt;
259  *lenp = len;
260  return (ret);
261 }
262 
263 LOCAL int
264 parse_rrflags(pnt, len, cont_flag)
265  Uchar *pnt;
266  int len;
267  int cont_flag;
268 {
269  int ncount;
270  UInt32_t cont_extent;
271  UInt32_t cont_offset;
272  UInt32_t cont_size;
273  int flag1;
274  int flag2;
275 
276  cont_extent = cont_offset = cont_size = 0;
277 
278  ncount = 0;
279  flag1 = -1;
280  flag2 = 0;
281  while (len >= 4) {
282  if (pnt[3] != 1 && pnt[3] != 2) {
284  _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
285  pnt[3], pnt[0], pnt[1], pnt[0], pnt[1]);
286  return (0); /* JS ??? Is this right ??? */
287  }
288  if (pnt[2] < 4) {
290  _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
291  pnt[2], pnt, pnt[0], pnt[1]);
292  return (0); /* JS ??? Is this right ??? */
293  }
294  ncount++;
295  if (pnt[0] == 'R' && pnt[1] == 'R')
296  flag1 = pnt[4] & 0xff;
297 
298  if (strncmp((char *)pnt, "PX", 2) == 0) /* POSIX attributes */
299  flag2 |= RR_FLAG_PX;
300  if (strncmp((char *)pnt, "PN", 2) == 0) /* POSIX device number */
301  flag2 |= RR_FLAG_PN;
302  if (strncmp((char *)pnt, "SL", 2) == 0) /* Symlink */
303  flag2 |= RR_FLAG_SL;
304  if (strncmp((char *)pnt, "NM", 2) == 0) /* Alternate Name */
305  flag2 |= RR_FLAG_NM;
306  if (strncmp((char *)pnt, "CL", 2) == 0) /* Child link */
307  flag2 |= RR_FLAG_CL;
308  if (strncmp((char *)pnt, "PL", 2) == 0) /* Parent link */
309  flag2 |= RR_FLAG_PL;
310  if (strncmp((char *)pnt, "RE", 2) == 0) /* Relocated Direcotry */
311  flag2 |= RR_FLAG_RE;
312  if (strncmp((char *)pnt, "TF", 2) == 0) /* Time stamp */
313  flag2 |= RR_FLAG_TF;
314  if (strncmp((char *)pnt, "SP", 2) == 0) { /* SUSP record */
315  flag2 |= RR_FLAG_SP;
316  if (su_version < 0)
317  su_version = pnt[3] & 0xff;
318  }
319  if (strncmp((char *)pnt, "AA", 2) == 0) { /* Apple Signature record */
320  flag2 |= RR_FLAG_AA;
321  if (aa_version < 0)
322  aa_version = pnt[3] & 0xff;
323  }
324  if (strncmp((char *)pnt, "ER", 2) == 0) {
325  flag2 |= RR_FLAG_ER; /* ER record */
326  if (rr_version < 0)
327  rr_version = pnt[7] & 0xff; /* Ext Version */
328  strlcpy(er_id, (char *)&pnt[8], (pnt[4] & 0xFF) + 1);
329  }
330 
331  if (strncmp((char *)pnt, "CE", 2) == 0) { /* Continuation Area */
332  cont_extent = get_733(pnt+4);
333  cont_offset = get_733(pnt+12);
334  cont_size = get_733(pnt+20);
335  }
336  if (strncmp((char *)pnt, "ST", 2) == 0) { /* Terminate SUSP */
337  break;
338  }
339 
340  len -= pnt[2];
341  pnt += pnt[2];
342  }
343  if (cont_extent) {
344  unsigned char sector[SECTOR_SIZE];
345 
346  readsecs(cont_extent, sector, 1);
347  flag2 |= parse_rrflags(&sector[cont_offset], cont_size, 1);
348  }
349  return (flag2);
350 }
351 
352 int
354  struct iso_directory_record *idr;
355 {
356  int len;
357  unsigned char *pnt;
358  int ret = 0;
359 
360  if (find_rr(idr, &pnt, &len))
361  ret |= RR_FLAG_XA;
362  ret |= parse_rrflags(pnt, len, 0);
363  return (ret);
364 }
365 
366 /*
367  * Parse the RR attributes so we can find the file name.
368  */
369 LOCAL int
370 parse_rr(pnt, len, dpnt)
371  unsigned char *pnt;
372  int len;
373  struct directory_entry *dpnt;
374 {
375  UInt32_t cont_extent;
376  UInt32_t cont_offset;
377  UInt32_t cont_size;
378  char name_buf[256];
379 
380  cont_extent = cont_offset = cont_size = 0;
381 
382  pnt = parse_xa(pnt, &len, dpnt /* 0 */);
383 
384  while (len >= 4) {
385  if (pnt[3] != 1 && pnt[3] != 2) {
387  _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
388  pnt[3], pnt[0], pnt[1], pnt[0], pnt[1]);
389  return (-1);
390  }
391  if (pnt[2] < 4) {
393  _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
394  pnt[2], pnt, pnt[0], pnt[1]);
395  return (-1);
396  }
397  if (strncmp((char *)pnt, "NM", 2) == 0) {
398  strncpy(name_buf, (char *)pnt + 5, pnt[2] - 5);
399  name_buf[pnt[2] - 5] = 0;
400  if (dpnt->name) {
401  size_t nlen = strlen(dpnt->name);
402 
403  /*
404  * append to name from previous NM records
405  */
406  dpnt->name = realloc(dpnt->name, nlen +
407  strlen(name_buf) + 1);
408  strcpy(dpnt->name + nlen, name_buf);
409  } else {
410  dpnt->name = e_strdup(name_buf);
411  dpnt->got_rr_name = 1;
412  }
413  /* continue searching for more NM records */
414  } else if (strncmp((char *)pnt, "CE", 2) == 0) {
415  cont_extent = get_733(pnt + 4);
416  cont_offset = get_733(pnt + 12);
417  cont_size = get_733(pnt + 20);
418  } else if (strncmp((char *)pnt, "ST", 2) == 0) {
419  break;
420  }
421 
422  len -= pnt[2];
423  pnt += pnt[2];
424  }
425  if (cont_extent) {
426  unsigned char sector[SECTOR_SIZE];
427 
428  readsecs(cont_extent, sector, 1);
429  if (parse_rr(&sector[cont_offset], cont_size, dpnt) == -1)
430  return (-1);
431  }
432 
433  /* Fall back to the iso name if no RR name found */
434  if (dpnt->name == NULL) {
435  char *cp;
436 
437  strlcpy(name_buf, dpnt->isorec.name, sizeof (name_buf));
438  cp = strchr(name_buf, ';');
439  if (cp != NULL) {
440  *cp = '\0';
441  }
442  dpnt->name = e_strdup(name_buf);
443  }
444  return (0);
445 } /* parse_rr */
446 
447 
448 /*
449  * Returns 1 if the two files are identical
450  * Returns 0 if the two files differ
451  */
452 LOCAL int
453 check_rr_dates(dpnt, current, statbuf, lstatbuf)
454  struct directory_entry *dpnt;
455  struct directory_entry *current;
456  struct stat *statbuf;
457  struct stat *lstatbuf;
458 {
459  UInt32_t cont_extent;
460  UInt32_t cont_offset;
461  UInt32_t cont_size;
462  UInt32_t offset;
463  unsigned char *pnt;
464  int len;
465  int same_file;
466  int same_file_type;
467  mode_t mode;
468  char time_buf[7];
469 
470 
471  cont_extent = cont_offset = cont_size = 0;
472  same_file = 1;
473  same_file_type = 1;
474 
475  pnt = dpnt->rr_attributes;
476  len = dpnt->rr_attr_size;
477  /*
478  * We basically need to parse the rr attributes again, and dig out the
479  * dates and file types.
480  */
481  pnt = parse_xa(pnt, &len, /* dpnt */ 0);
482  while (len >= 4) {
483  if (pnt[3] != 1 && pnt[3] != 2) {
485  _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
486  pnt[3], pnt[0], pnt[1], pnt[0], pnt[1]);
487  return (-1);
488  }
489  if (pnt[2] < 4) {
491  _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
492  pnt[2], pnt, pnt[0], pnt[1]);
493  return (-1);
494  }
495 
496  /*
497  * If we have POSIX file modes, make sure that the file type is
498  * the same. If it isn't, then we must always write the new
499  * file.
500  */
501  if (strncmp((char *)pnt, "PX", 2) == 0) {
502  mode = get_733(pnt + 4);
503  if ((lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT)) {
504  same_file_type = 0;
505  same_file = 0;
506  }
507  }
508  if (strncmp((char *)pnt, "TF", 2) == 0) {
509  offset = 5;
510  if (pnt[4] & TF_CREATE) {
511  iso9660_date((char *)time_buf,
512  lstatbuf->st_ctime);
513  if (memcmp(time_buf, pnt + offset, 7) != 0)
514  same_file = 0;
515  offset += 7;
516  }
517  if (pnt[4] & TF_MODIFY) {
518  iso9660_date((char *)time_buf,
519  lstatbuf->st_mtime);
520  if (memcmp(time_buf, pnt + offset, 7) != 0)
521  same_file = 0;
522  offset += 7;
523  }
524  }
525  if (strncmp((char *)pnt, "CE", 2) == 0) {
526  cont_extent = get_733(pnt + 4);
527  cont_offset = get_733(pnt + 12);
528  cont_size = get_733(pnt + 20);
529  }
530  if (strncmp((char *)pnt, "ST", 2) == 0) { /* Terminate SUSP */
531  break;
532  }
533 
534  len -= pnt[2];
535  pnt += pnt[2];
536  }
537  if (cont_extent) {
538  unsigned char sector[SECTOR_SIZE];
539 
540  readsecs(cont_extent, sector, 1);
541  /*
542  * Continue to scan the extension record.
543  * Note that this has not been tested yet, but it is
544  * definitely more correct that calling parse_rr()
545  * as done in Eric's old code.
546  */
547  pnt = &sector[cont_offset];
548  len = cont_size;
549  /*
550  * Clear the "pending extension record" state as
551  * we did already read it now.
552  */
553  cont_extent = cont_offset = cont_size = 0;
554  }
555 
556  /*
557  * If we have the same fundamental file type, then it is clearly safe
558  * to reuse the TRANS.TBL entry.
559  */
560  if (same_file_type) {
561  current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
562  }
563  return (same_file);
564 }
565 
566 LOCAL BOOL
567 valid_iso_directory(idr, idr_off, space_left)
568  struct iso_directory_record *idr;
569  int idr_off;
570  size_t space_left;
571 {
572  size_t idr_length = idr->length[0] & 0xFF;
573  size_t idr_ext_length = idr->ext_attr_length[0] & 0xFF;
574  size_t idr_namelength = idr->name_len[0] & 0xFF;
575  int namelimit = space_left -
576  offsetof(struct iso_directory_record, name[0]);
577  int nlimit = (idr_namelength < namelimit) ?
578  idr_namelength : namelimit;
579 
580  /*
581  * Check for sane length entries.
582  */
583  if (idr_length > space_left) {
585  _("Bad directory length %zu (> %d available) for '%.*s'.\n"),
586  idr_length, namelimit, nlimit, idr->name);
587  }
588 
589  if (idr_length == 0) {
590  if ((idr_off % SECTOR_SIZE) != 0) {
591  /*
592  * It marks a valid continuation entry.
593  */
594  return (TRUE);
595  } else {
597  _("Zero directory length for '%.*s'.\n"),
598  nlimit, idr->name);
599  }
600  }
601  if (idr_length <= offsetof(struct iso_directory_record, name[0])) {
602  comerrno(EX_BAD, _("Bad directory length %zu (< %zu minimum).\n"),
603  idr_length, 1 + offsetof(struct iso_directory_record, name[0]));
604  }
605  if ((idr_length & 1) != 0) {
606  comerrno(EX_BAD, _("Odd directory length %zu for '%.*s'.\n"),
607  idr_length, nlimit, idr->name);
608  }
609 
610  if (idr_namelength == 0) {
611  comerrno(EX_BAD, _("Zero filename length.\n"));
612  }
613 
614  if (!(idr_namelength & 1)) {
615  /*
616  * if nam_len[0] is even, there has to be a pad byte at the end
617  * to make the directory length even
618  */
619  idr_namelength++;
620  }
621  if ((offsetof(struct iso_directory_record, name[0]) +
622  idr_namelength) > idr_length) {
623  int xlimit = idr_length -
624  offsetof(struct iso_directory_record, name[0]) -
625  idr_ext_length;
626 
627  if (xlimit < 0)
628  xlimit = 0;
629  if (nlimit < xlimit)
630  xlimit = nlimit;
631  comerrno(EX_BAD, _("Bad filename length %zu (> %d) for '%.*s'.\n"),
632  idr_namelength, xlimit, xlimit, idr->name);
633  }
634  if ((offsetof(struct iso_directory_record, name[0]) +
635  idr_namelength + idr_ext_length) > idr_length) {
636  int xlimit = idr_length -
637  offsetof(struct iso_directory_record, name[0]) -
638  idr_namelength;
639 
640  comerrno(EX_BAD, _("Bad extended attribute length %zu (> %d) for '%.*s'.\n"),
641  idr_ext_length, xlimit, nlimit, idr->name);
642  }
643 
644 #ifdef __do_rr_
645  /* check for rock ridge extensions */
646 
647  if (no_rr) {
648  /*
649  * Rock Ridge extensions are not present or manually disabled.
650  */
651  return (TRUE);
652  } else {
653  int rlen = idr_length -
654  offsetof(struct iso_directory_record, name[0]) -
655  idr_namelength;
656 
657  /* Check for the minimum of Rock Ridge extensions. */
658  }
659 #endif
660  return (TRUE);
661 }
662 
663 LOCAL struct directory_entry **
665  struct iso_directory_record *mrootp;
666  int *nentp;
667 {
668  unsigned char *cpnt;
669  unsigned char *cpnt1;
670  char *p;
671  char *dirbuff;
672  int i;
673  struct iso_directory_record *idr;
674  UInt32_t len;
675  UInt32_t nbytes;
676  int nent;
677  int nmult; /* # of multi extent root entries */
678  int mx;
679  struct directory_entry **pnt;
680  UInt32_t rlen;
681  struct directory_entry **rtn;
682  int seen_rockridge;
683  unsigned char *tt_buf;
684  UInt32_t tt_extent;
685  UInt32_t tt_size;
686 
687  static int warning_given = 0;
688 
689  /*
690  * This is the number of sectors we will need to read. We need to
691  * round up to get the last fractional sector - we are asking for the
692  * data in terms of a number of sectors.
693  */
694  nbytes = roundup(get_733(mrootp->size), SECTOR_SIZE);
695 
696  /*
697  * First, allocate a buffer large enough to read in the entire
698  * directory.
699  */
700  dirbuff = (char *)e_malloc(nbytes);
701 
702  readsecs(get_733(mrootp->extent), dirbuff, nbytes / SECTOR_SIZE);
703 
704  /*
705  * Next look over the directory, and count up how many entries we have.
706  */
707  len = get_733(mrootp->size);
708  i = 0;
709  *nentp = 0;
710  nent = 0;
711  nmult = 0;
712  mx = 0;
713  while ((i + offsetof(struct iso_directory_record, name[0])) < len) {
714  idr = (struct iso_directory_record *)&dirbuff[i];
715 
716  if (!valid_iso_directory(idr, i, len - i))
717  break;
718 
719  if (idr->length[0] == 0) {
720  i = ISO_ROUND_UP(i);
721  continue;
722  }
723  nent++;
724  if ((mx & ISO_MULTIEXTENT) == 0 &&
725  (idr->flags[0] & ISO_MULTIEXTENT) != 0) {
726  nmult++; /* Need a multi extent root entry */
727  }
728  mx = idr->flags[0];
729  i += idr->length[0];
730  }
731 
732  /*
733  * Now allocate the buffer which will hold the array we are about to
734  * return. We need one entry per real directory entry and in addition
735  * one multi-extent root entry per multi-extent file.
736  */
737  rtn = (struct directory_entry **)e_malloc((nent+nmult) * sizeof (*rtn));
738 
739  /*
740  * Finally, scan the directory one last time, and pick out the relevant
741  * bits of information, and store it in the relevant bits of the
742  * structure.
743  */
744  i = 0;
745  pnt = rtn;
746  tt_extent = 0;
747  seen_rockridge = 0;
748  tt_size = 0;
749  mx = 0;
750  while ((i + offsetof(struct iso_directory_record, name[0])) < len) {
751  idr = (struct iso_directory_record *)&dirbuff[i];
752 
753  if (!valid_iso_directory(idr, i, len - i))
754  break;
755 
756  if (idr->length[0] == 0) {
757  i = ISO_ROUND_UP(i);
758  continue;
759  }
760  *pnt = (struct directory_entry *)e_malloc(sizeof (**rtn));
761  (*pnt)->next = NULL;
762 #ifdef DEBUG
763  error("IDR name: '%s' ist: %d soll: %d\n",
764  idr->name, strlen(idr->name), idr->name_len[0]);
765 #endif
766  movebytes(idr, &(*pnt)->isorec, idr->length[0] & 0xFF);
767  (*pnt)->starting_block =
768  get_733(idr->extent);
769  (*pnt)->size = get_733(idr->size);
770  if ((*pnt)->size == 0) {
771  /*
772  * Find lowest used inode number for zero sized files
773  */
774  if (((UInt32_t)(*pnt)->starting_block) <= null_inodes) {
775  null_inodes = (UInt32_t)(*pnt)->starting_block;
776  null_inodes--;
777  }
778  }
779  (*pnt)->priority = 0;
780  (*pnt)->name = NULL;
781  (*pnt)->got_rr_name = 0;
782  (*pnt)->table = NULL;
783  (*pnt)->whole_name = NULL;
784  (*pnt)->filedir = NULL;
785  (*pnt)->parent_rec = NULL;
786  /*
787  * Set this information so that we correctly cache previous
788  * session bits of information.
789  */
790  (*pnt)->inode = (*pnt)->starting_block;
791  (*pnt)->dev = PREV_SESS_DEV;
792  (*pnt)->rr_attributes = NULL;
793  (*pnt)->rr_attr_size = 0;
794  (*pnt)->total_rr_attr_size = 0;
795  (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY;
796 #ifdef APPLE_HYB
797  (*pnt)->assoc = NULL;
798  (*pnt)->hfs_ent = NULL;
799 #endif /* APPLE_HYB */
800 
801  /*
802  * Check for and parse any RR attributes for the file. All we
803  * are really looking for here is the original name of the
804  * file.
805  */
806  rlen = idr->length[0] & 0xff;
807  cpnt = (unsigned char *) idr;
808 
809  rlen -= offsetof(struct iso_directory_record, name[0]);
810  cpnt += offsetof(struct iso_directory_record, name[0]);
811 
812  rlen -= idr->name_len[0];
813  cpnt += idr->name_len[0];
814 
815  if ((idr->name_len[0] & 1) == 0) {
816  cpnt++;
817  rlen--;
818  }
819 
820  if (no_rr)
821  rlen = 0;
822  if (rlen > 0) {
823  (*pnt)->total_rr_attr_size =
824  (*pnt)->rr_attr_size = rlen;
825  (*pnt)->rr_attributes = e_malloc(rlen);
826  memcpy((*pnt)->rr_attributes, cpnt, rlen);
827  seen_rockridge = 1;
828  }
829 #ifdef DEBUG
830  error("INT name: '%s' ist: %d soll: %d\n",
831  (*pnt)->isorec.name, strlen((*pnt)->isorec.name),
832  idr->name_len[0]);
833 #endif
834 
835  if (idr->name_len[0] < sizeof ((*pnt)->isorec.name)) {
836  /*
837  * Now zero out the remainder of the name field.
838  */
839  cpnt = (unsigned char *) (*pnt)->isorec.name;
840  cpnt += idr->name_len[0];
841  memset(cpnt, 0,
842  sizeof ((*pnt)->isorec.name) - idr->name_len[0]);
843  } else {
844  /*
845  * Simple sanity work to make sure that we have no
846  * illegal data structures in our tree.
847  */
848  (*pnt)->isorec.name[MAX_ISONAME] = '\0';
849  (*pnt)->isorec.name_len[0] = MAX_ISONAME;
850  }
851  /*
852  * If the filename len from the old session is more
853  * then 31 chars, there is a high risk of hard violations
854  * of the ISO9660 standard.
855  * Run it through our name canonication machine....
856  */
857  if (idr->name_len[0] > LEN_ISONAME || check_oldnames) {
858  iso9660_check(idr, *pnt);
859  }
860 
861  if (parse_rr((*pnt)->rr_attributes, rlen, *pnt) == -1) {
863  _("Cannot parse Rock Ridge attributes for '%s'.\n"),
864  idr->name);
865  }
866  if (((*pnt)->isorec.name_len[0] == 1) &&
867  (((*pnt)->isorec.name[0] == 0) || /* "." entry */
868  ((*pnt)->isorec.name[0] == 1))) { /* ".." entry */
869 
870  if ((*pnt)->name != NULL) {
871  free((*pnt)->name);
872  }
873  if ((*pnt)->whole_name != NULL) {
874  free((*pnt)->whole_name);
875  }
876  if ((*pnt)->isorec.name[0] == 0) {
877  (*pnt)->name = e_strdup(".");
878  } else {
879  (*pnt)->name = e_strdup("..");
880  }
881  }
882 #ifdef DEBUG
883  fprintf(stderr, "got DE name: %s\n", (*pnt)->name);
884 #endif
885 
886  if (strncmp(idr->name, trans_tbl, strlen(trans_tbl)) == 0) {
887  if ((*pnt)->name != NULL) {
888  free((*pnt)->name);
889  }
890  if ((*pnt)->whole_name != NULL) {
891  free((*pnt)->whole_name);
892  }
893 /* (*pnt)->name = e_strdup("<translation table>");*/
894  (*pnt)->name = e_strdup(trans_tbl);
895  tt_extent = get_733(idr->extent);
896  tt_size = get_733(idr->size);
897  if (tt_extent == 0)
898  tt_size = 0;
899  }
900  /*
901  * The beginning of a new multi extent directory chain is when
902  * the last directory had no ISO_MULTIEXTENT flag set and the
903  * current entry did set ISO_MULTIEXTENT.
904  */
905  if ((mx & ISO_MULTIEXTENT) == 0 &&
906  (idr->flags[0] & ISO_MULTIEXTENT) != 0) {
907  struct directory_entry *s_entry;
908  struct iso_directory_record *idr2 = idr;
909  int i2 = i;
910  off_t tsize = 0;
911 
912  /*
913  * Sum up the total file size for the multi extent file
914  */
915  while ((i2 + offsetof(struct iso_directory_record, name[0])) < len) {
916  idr2 = (struct iso_directory_record *)&dirbuff[i2];
917  if (idr2->length[0] == 0) {
918  i2 = ISO_ROUND_UP(i2);
919  continue;
920  }
921 
922  tsize += get_733(idr2->size);
923  if ((idr2->flags[0] & ISO_MULTIEXTENT) == 0)
924  break;
925  i2 += idr2->length[0];
926  }
927 
928  s_entry = dup_directory_entry(*pnt); /* dup first for mxroot */
929  s_entry->de_flags |= MULTI_EXTENT;
931  s_entry->size = tsize;
932  s_entry->starting_block = (*pnt)->starting_block;
933  s_entry->mxroot = s_entry;
934  s_entry->mxpart = 0;
935  s_entry->next = *pnt; /* Next in list */
936  pnt[1] = pnt[0]; /* Move to next slot */
937  *pnt = s_entry; /* First slot is mxroot */
938  pnt++; /* Point again to cur. */
939  }
940  if ((mx & ISO_MULTIEXTENT) != 0 ||
941  (idr->flags[0] & ISO_MULTIEXTENT) != 0) {
942  (*pnt)->de_flags |= MULTI_EXTENT;
943  (*pnt)->de_flags |= INHIBIT_UDF_ENTRY;
944  (pnt[-1])->next = *pnt;
945  (*pnt)->mxroot = (pnt[-1])->mxroot;
946  (*pnt)->mxpart = (pnt[-1])->mxpart + 1;
947  }
948  pnt++;
949  mx = idr->flags[0];
950  i += idr->length[0];
951  }
952 #ifdef APPLE_HYB
953  /*
954  * If we find an associated file, check if there is a file
955  * with same ISO name and link it to this entry
956  */
957  for (pnt = rtn, i = 0; i < nent; i++, pnt++) {
958  int j;
959 
960  rlen = get_711((*pnt)->isorec.name_len);
961  if ((*pnt)->isorec.flags[0] & ISO_ASSOCIATED) {
962  for (j = 0; j < nent; j++) {
963  if (strncmp(rtn[j]->isorec.name,
964  (*pnt)->isorec.name, rlen) == 0 &&
965  (rtn[j]->isorec.flags[0] & ISO_ASSOCIATED) == 0) {
966  rtn[j]->assoc = *pnt;
967 
968  /*
969  * don't want this entry to be
970  * in the Joliet tree
971  */
972  (*pnt)->de_flags |= INHIBIT_JOLIET_ENTRY;
973  /*
974  * XXX Is it correct to exclude UDF too?
975  */
976  (*pnt)->de_flags |= INHIBIT_UDF_ENTRY;
977 
978  /*
979  * as we have associated files, then
980  * assume we are are dealing with
981  * Apple's extensions - if not already
982  * set
983  */
984  if (apple_both == 0) {
985  apple_both = apple_ext = 1;
986  }
987  break;
988  }
989  }
990  }
991  }
992 #endif /* APPLE_HYB */
993 
994  /*
995  * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it
996  * to get the filenames of the files. Also, save the table info, just
997  * in case we need to use it.
998  *
999  * The entries look something like: F ISODUMP.;1 isodump
1000  */
1001  if (tt_extent != 0 && tt_size != 0) {
1002  nbytes = roundup(tt_size, SECTOR_SIZE);
1003  tt_buf = (unsigned char *) e_malloc(nbytes);
1004  readsecs(tt_extent, tt_buf, nbytes / SECTOR_SIZE);
1005 
1006  /*
1007  * Loop through the file, examine each entry, and attempt to
1008  * attach it to the correct entry.
1009  */
1010  cpnt = tt_buf;
1011  cpnt1 = tt_buf;
1012  while (cpnt - tt_buf < tt_size) {
1013  /* Skip to a line terminator, or end of the file. */
1014  while ((cpnt1 - tt_buf < tt_size) &&
1015  (*cpnt1 != '\n') &&
1016  (*cpnt1 != '\0')) {
1017  cpnt1++;
1018  }
1019  /* Zero terminate this particular line. */
1020  if (cpnt1 - tt_buf < tt_size) {
1021  *cpnt1 = '\0';
1022  }
1023  /*
1024  * Now dig through the actual directories, and try and
1025  * find the attachment for this particular filename.
1026  */
1027  for (pnt = rtn, i = 0; i < nent; i++, pnt++) {
1028  rlen = get_711((*pnt)->isorec.name_len);
1029 
1030  /*
1031  * If this filename is so long that it would
1032  * extend past the end of the file, it cannot
1033  * be the one we want.
1034  */
1035  if (cpnt + 2 + rlen - tt_buf >= tt_size) {
1036  continue;
1037  }
1038  /*
1039  * Now actually compare the name, and make sure
1040  * that the character at the end is a ' '.
1041  */
1042  if (strncmp((char *)cpnt + 2,
1043  (*pnt)->isorec.name, rlen) == 0 &&
1044  cpnt[2 + rlen] == ' ' &&
1045  (p = strchr((char *)&cpnt[2 + rlen], '\t'))) {
1046  p++;
1047  /*
1048  * This is a keeper. Now determine the
1049  * correct table entry that we will
1050  * use on the new image.
1051  */
1052  if (strlen(p) > 0) {
1053  (*pnt)->table =
1054  e_malloc(strlen(p) + 4);
1055  sprintf((*pnt)->table,
1056  "%c\t%s\n",
1057  *cpnt, p);
1058  }
1059  if (!(*pnt)->got_rr_name) {
1060  if ((*pnt)->name != NULL) {
1061  free((*pnt)->name);
1062  }
1063  (*pnt)->name = e_strdup(p);
1064  }
1065  break;
1066  }
1067  }
1068  cpnt = cpnt1 + 1;
1069  cpnt1 = cpnt;
1070  }
1071 
1072  free(tt_buf);
1073  } else if (!seen_rockridge && !warning_given) {
1074  /*
1075  * Warn the user that iso-9660 names were used because neither
1076  * Rock Ridge (-R) nor TRANS.TBL (-T) name translations were
1077  * found.
1078  */
1079  fprintf(stderr,
1080  _("Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) \n"));
1081  fprintf(stderr,
1082  _("name translations were found on previous session.\n"));
1083  fprintf(stderr,
1084  _("ISO-9660 file names have been used instead.\n"));
1085  warning_given = 1;
1086  }
1087  if (dirbuff != NULL) {
1088  free(dirbuff);
1089  }
1090  *nentp = nent + nmult;
1091  return (rtn);
1092 } /* read_merging_directory */
1093 
1094 /*
1095  * Free any associated data related to the structures.
1096  */
1097 LOCAL int
1099  struct directory_entry **ptr;
1100  int len;
1101 {
1102  int i;
1103  struct directory_entry **p;
1104 
1105  p = ptr;
1106  for (i = 0; i < len; i++, p++) {
1107  /*
1108  * If the tree-handling code decided that it needed an entry, it
1109  * will have removed it from the list. Thus we must allow for
1110  * null pointers here.
1111  */
1112  if (*p == NULL) {
1113  continue;
1114  }
1116  }
1117 
1118  free(ptr);
1119  return (0);
1120 }
1121 
1122 LOCAL void
1124  struct directory_entry *dirp;
1125 {
1126  if (dirp->name != NULL)
1127  free(dirp->name);
1128 
1129  if (dirp->whole_name != NULL)
1130  free(dirp->whole_name);
1131 
1132  if (dirp->rr_attributes != NULL)
1133  free(dirp->rr_attributes);
1134 
1135  if (dirp->table != NULL)
1136  free(dirp->table);
1137 
1138  free(dirp);
1139 }
1140 
1141 /*
1142  * Search the list to see if we have any entries from the previous
1143  * session that match this entry. If so, copy the extent number
1144  * over so we don't bother to write it out to the new session.
1145  */
1146 int
1147 check_prev_session(ptr, len, curr_entry, statbuf, lstatbuf, odpnt)
1148  struct directory_entry **ptr;
1149  int len;
1150  struct directory_entry *curr_entry;
1151  struct stat *statbuf;
1152  struct stat *lstatbuf;
1153  struct directory_entry **odpnt;
1154 {
1155  int i;
1156  int rr;
1157  int retcode = -2; /* Default not found */
1158 
1159  for (i = 0; i < len; i++) {
1160  if (ptr[i] == NULL) { /* Used or empty entry skip */
1161  continue;
1162  }
1163 #if 0
1164  if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 &&
1165  ptr[i]->name[0] == '\0') {
1166  continue;
1167  }
1168  if (ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 &&
1169  ptr[i]->name[0] == 1) {
1170  continue;
1171  }
1172 #else
1173  if (ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0) {
1174  continue;
1175  }
1176  if (ptr[i]->name != NULL && strcmp(ptr[i]->name, "..") == 0) {
1177  continue;
1178  }
1179 #endif
1180 
1181  if (ptr[i]->name != NULL &&
1182  strcmp(ptr[i]->name, curr_entry->name) != 0) {
1183  /* Not the same name continue */
1184  continue;
1185  }
1186  /*
1187  * It's a directory so we must always merge it with the new
1188  * session. Never ever reuse directory extents. See comments
1189  * in tree.c for an explaination of why this must be the case.
1190  */
1191  if ((curr_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) {
1192  retcode = i;
1193  goto found_it;
1194  }
1195  /*
1196  * We know that the files have the same name. If they also
1197  * have the same file type (i.e. file, dir, block, etc), then
1198  * we can safely reuse the TRANS.TBL entry for this file. The
1199  * check_rr_dates() function will do this for us.
1200  *
1201  * Verify that the file type and dates are consistent. If not,
1202  * we probably have a different file, and we need to write it
1203  * out again.
1204  */
1205  retcode = i;
1206 
1207  if (ptr[i]->rr_attributes != NULL) {
1208  if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf,
1209  lstatbuf)) == -1)
1210  return (-1);
1211 
1212  if (rr == 0) { /* Different files */
1213  goto found_it;
1214  }
1215  }
1216  /*
1217  * Verify size and timestamp. If rock ridge is in use, we
1218  * need to compare dates from RR too. Directories are special,
1219  * we calculate their size later.
1220  */
1221  if (ptr[i]->size != curr_entry->size) {
1222  /* Different files */
1223  goto found_it;
1224  }
1225  if (memcmp(ptr[i]->isorec.date,
1226  curr_entry->isorec.date, 7) != 0) {
1227  /* Different files */
1228  goto found_it;
1229  }
1230  /* We found it and we can reuse the extent */
1231  memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
1232  curr_entry->starting_block = get_733(ptr[i]->isorec.extent);
1233  curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
1234 
1235  if ((curr_entry->isorec.flags[0] & ISO_MULTIEXTENT) ||
1236  (ptr[i]->isorec.flags[0] & ISO_MULTIEXTENT)) {
1237  copy_mult_extent(curr_entry, ptr[i]);
1238  }
1239  goto found_it;
1240  }
1241  return (retcode);
1242 
1243 found_it:
1244  if (ptr[i]->mxroot == ptr[i]) { /* Remove all multi ext. entries */
1245  int j = i + 1; /* First one will be removed below */
1246 
1247  while (j < len && ptr[j] && ptr[j]->mxroot == ptr[i]) {
1248  free(ptr[j]);
1249  ptr[j++] = NULL;
1250  }
1251  }
1252  if (odpnt != NULL) {
1253  *odpnt = ptr[i];
1254  } else {
1255  free(ptr[i]);
1256  }
1257  ptr[i] = NULL;
1258  return (retcode);
1259 }
1260 
1261 /*
1262  * Return the number of directory entries for a file. This is usually 1
1263  * but may be 3 or more in case of multi extent files.
1264  */
1265 LOCAL int
1267  struct directory_entry *de;
1268 {
1269  struct directory_entry *de2;
1270  int ret = 0;
1271 
1272  if (de->mxroot == NULL)
1273  return (1);
1274  de2 = de;
1275  while (de2 != NULL && de2->mxroot == de->mxroot) {
1276  ret++;
1277  de2 = de2->next;
1278  }
1279  return (ret);
1280 }
1281 
1282 /*
1283  * Copy old multi-extent directory information from the previous session.
1284  * If both the old session and the current session are created by mkisofs
1285  * then this code could be extremely simple as the information is only copied
1286  * in case that the file did not change since the last session was made.
1287  * As we don't know the other ISO formatter program, any combination of
1288  * multi-extent files and even a single extent file could be possible.
1289  * We need to handle all files the same way ad the old session was created as
1290  * we reuse the data extents from the file in the old session.
1291  */
1292 LOCAL void
1294  struct directory_entry *se1;
1295  struct directory_entry *se2;
1296 {
1297  struct directory_entry *curr_entry = se1;
1298  int len1;
1299  int len2;
1300  int mxpart = 0;
1301 
1302  len1 = iso_dir_ents(se1);
1303  len2 = iso_dir_ents(se2);
1304 
1305  if (len1 == 1) {
1306  /*
1307  * Convert single-extent to multi-extent.
1308  * If *se1 is not multi-extent, *se2 definitely is
1309  * and we need to set up a MULTI_EXTENT directory header.
1310  */
1311  se1->de_flags |= MULTI_EXTENT;
1312  se1->isorec.flags[0] |= ISO_MULTIEXTENT;
1313  se1->mxroot = curr_entry;
1314  se1->mxpart = 0;
1315  se1 = dup_directory_entry(se1);
1317  se1->de_flags |= INHIBIT_UDF_ENTRY;
1318  se1->next = curr_entry->next;
1319  curr_entry->next = se1;
1320  se1 = curr_entry;
1321  len1 = 2;
1322  }
1323 
1324  while (se2->isorec.flags[0] & ISO_MULTIEXTENT) {
1325  len1--;
1326  len2--;
1327  if (len1 <= 0) {
1328  struct directory_entry *sex = dup_directory_entry(se1);
1329 
1330  sex->mxroot = curr_entry;
1331  sex->next = se1->next;
1332  se1->next = sex;
1333  len1++;
1334  }
1335  memcpy(se1->isorec.extent, se2->isorec.extent, 8);
1336  se1->starting_block = get_733(se2->isorec.extent);
1338  se1->de_flags |= MULTI_EXTENT;
1339  se1->isorec.flags[0] |= ISO_MULTIEXTENT;
1340  se1->mxroot = curr_entry;
1341  se1->mxpart = mxpart++;
1342 
1343  se1 = se1->next;
1344  se2 = se2->next;
1345  }
1346  memcpy(se1->isorec.extent, se2->isorec.extent, 8);
1347  se1->starting_block = get_733(se2->isorec.extent);
1349  se1->isorec.flags[0] &= ~ISO_MULTIEXTENT; /* Last entry */
1350  se1->mxpart = mxpart;
1351  while (len1 > 1) { /* Drop other entries */
1352  struct directory_entry *sex;
1353 
1354  sex = se1->next;
1355  se1->next = sex->next;
1356  free(sex);
1357  len1--;
1358  }
1359 }
1360 
1361 /*
1362  * open_merge_image: Open an existing image.
1363  */
1364 int
1366  char *path;
1367 {
1368 #ifndef USE_SCG
1369  in_image = fopen(path, "rb");
1370  if (in_image == NULL) {
1371  return (-1);
1372  }
1373 #else
1374  in_image = fopen(path, "rb");
1375  if (in_image == NULL) {
1376  if (scsidev_open(path) < 0)
1377  return (-1);
1378  }
1379 #endif
1380  return (0);
1381 }
1382 
1383 /*
1384  * close_merge_image: Close an existing image.
1385  */
1386 int
1388 {
1389 #ifdef USE_SCG
1390  return (scsidev_close());
1391 #else
1392  return (fclose(in_image));
1393 #endif
1394 }
1395 
1396 /*
1397  * merge_isofs: Scan an existing image, and return a pointer
1398  * to the root directory for this image.
1399  */
1400 struct iso_directory_record *
1402  char *path;
1403 {
1404  char buffer[SECTOR_SIZE];
1405  int file_addr;
1406  int i;
1407  int sum = 0;
1408  char *p = buffer;
1409  struct iso_primary_descriptor *pri = NULL;
1410  struct iso_directory_record *rootp;
1411  struct iso_volume_descriptor *vdp;
1412 
1413  /*
1414  * Start by searching for the volume header. Ultimately, we need to
1415  * search for volume headers in multiple places because we might be
1416  * starting with a multisession image. FIXME(eric).
1417  */
1418  get_session_start(&file_addr);
1419 
1420  for (i = 0; i < 100; i++) {
1421  if (readsecs(file_addr, buffer,
1422  sizeof (buffer) / SECTOR_SIZE) != sizeof (buffer)) {
1423  comerr(_("Read error on old image %s\n"), path);
1424  }
1425  vdp = (struct iso_volume_descriptor *)buffer;
1426 
1427  if ((strncmp(vdp->id, ISO_STANDARD_ID, sizeof (vdp->id)) == 0) &&
1428  (get_711(vdp->type) == ISO_VD_PRIMARY)) {
1429  break;
1430  }
1431  file_addr += 1;
1432  }
1433 
1434  if (i == 100) {
1435  return (NULL);
1436  }
1437  for (i = 0; i < 2048-3; i++) {
1438  sum += p[i] & 0xFF;
1439  }
1440  pri = (struct iso_primary_descriptor *)vdp;
1441 
1442  /* Check the blocksize of the image to make sure it is compatible. */
1443  if (get_723(pri->logical_block_size) != SECTOR_SIZE) {
1444  errmsgno(EX_BAD,
1445  _("Previous session has incompatible sector size %u.\n"),
1446  get_723(pri->logical_block_size));
1447  return (NULL);
1448  }
1449  if (get_723(pri->volume_set_size) != 1) {
1450  errmsgno(EX_BAD,
1451  _("Previous session has volume set size %u (must be 1).\n"),
1452  get_723(pri->volume_set_size));
1453  return (NULL);
1454  }
1455  /* Get the location and size of the root directory. */
1456  rootp = (struct iso_directory_record *)
1457  e_malloc(sizeof (struct iso_directory_record));
1458 
1459  memcpy(rootp, pri->root_directory_record,
1460  sizeof (pri->root_directory_record));
1461 
1462  for (i = 0; i < 100; i++) {
1463  if (readsecs(file_addr, buffer,
1464  sizeof (buffer) / SECTOR_SIZE) != sizeof (buffer)) {
1465  comerr(_("Read error on old image %s\n"), path);
1466  }
1467  if (strncmp(buffer, "MKI ", 4) == 0) {
1468  int sum2;
1469 
1470  sum2 = p[2045] & 0xFF;
1471  sum2 *= 256;
1472  sum2 += p[2046] & 0xFF;
1473  sum2 *= 256;
1474  sum2 += p[2047] & 0xFF;
1475  if (sum == sum2) {
1476  error(_("ISO-9660 image includes checksum signature for correct inode numbers.\n"));
1477  } else {
1479  rrip112 = FALSE;
1480  }
1481  break;
1482  }
1483  file_addr += 1;
1484  }
1485 
1486  return (rootp);
1487 }
1488 
1489 LOCAL void
1490 merge_remaining_entries(this_dir, pnt, n_orig)
1491  struct directory *this_dir;
1492  struct directory_entry **pnt;
1493  int n_orig;
1494 {
1495  int i;
1496  struct directory_entry *s_entry;
1497  UInt32_t ttbl_extent = 0;
1498  unsigned int ttbl_index = 0;
1499  char whole_path[PATH_MAX];
1500 
1501  /*
1502  * Whatever is leftover in the list needs to get merged back into the
1503  * directory.
1504  */
1505  for (i = 0; i < n_orig; i++) {
1506  if (pnt[i] == NULL) {
1507  continue;
1508  }
1509  if (pnt[i]->name != NULL && pnt[i]->whole_name == NULL) {
1510  /* Set the name for this directory. */
1511  strlcpy(whole_path, this_dir->de_name,
1512  sizeof (whole_path));
1513  strcat(whole_path, SPATH_SEPARATOR);
1514  strcat(whole_path, pnt[i]->name);
1515 
1516  pnt[i]->whole_name = e_strdup(whole_path);
1517  }
1518  if (pnt[i]->name != NULL &&
1519 /* strcmp(pnt[i]->name, "<translation table>") == 0 )*/
1520  strcmp(pnt[i]->name, trans_tbl) == 0) {
1521  ttbl_extent =
1522  get_733(pnt[i]->isorec.extent);
1523  ttbl_index = i;
1524  continue;
1525  }
1526 
1527  /*
1528  * Skip directories for now - these need to be treated
1529  * differently.
1530  */
1531  if ((pnt[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) {
1532  /*
1533  * FIXME - we need to insert this directory into the
1534  * tree, so that the path tables we generate will be
1535  * correct.
1536  */
1537  if ((strcmp(pnt[i]->name, ".") == 0) ||
1538  (strcmp(pnt[i]->name, "..") == 0)) {
1539  free_directory_entry(pnt[i]);
1540  pnt[i] = NULL;
1541  continue;
1542  } else {
1543  merge_old_directory_into_tree(pnt[i], this_dir);
1544  }
1545  }
1546  pnt[i]->next = this_dir->contents;
1547  pnt[i]->filedir = this_dir;
1548  this_dir->contents = pnt[i];
1549  pnt[i] = NULL;
1550  }
1551 
1552 
1553  /*
1554  * If we don't have an entry for the translation table, then don't
1555  * bother trying to copy the starting extent over. Note that it is
1556  * possible that if we are copying the entire directory, the entry for
1557  * the translation table will have already been inserted into the
1558  * linked list and removed from the old entries list, in which case we
1559  * want to leave the extent number as it was before.
1560  */
1561  if (ttbl_extent == 0) {
1562  return;
1563  }
1564  /*
1565  * Finally, check the directory we are creating to see whether there
1566  * are any new entries in it. If there are not, we can reuse the same
1567  * translation table.
1568  */
1569  for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
1570  /*
1571  * Don't care about '.' or '..'. They are never in the table
1572  * anyways.
1573  */
1574  if (s_entry->name != NULL && strcmp(s_entry->name, ".") == 0) {
1575  continue;
1576  }
1577  if (s_entry->name != NULL && strcmp(s_entry->name, "..") == 0) {
1578  continue;
1579  }
1580 /* if (s_entry->name != NULL &&*/
1581 /* strcmp(s_entry->name, "<translation table>") == 0)*/
1582  if (s_entry->name != NULL &&
1583  strcmp(s_entry->name, trans_tbl) == 0) {
1584  continue;
1585  }
1586  if ((s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0) {
1587  return;
1588  }
1589  }
1590 
1591  /*
1592  * Locate the translation table, and re-use the same extent. It isn't
1593  * clear that there should ever be one in there already so for now we
1594  * try and muddle through the best we can.
1595  */
1596  for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
1597 /* if (strcmp(s_entry->name, "<translation table>") == 0)*/
1598  if (strcmp(s_entry->name, trans_tbl) == 0) {
1599  fprintf(stderr, "Should never get here\n");
1600  set_733(s_entry->isorec.extent, ttbl_extent);
1601  return;
1602  }
1603  }
1604 
1605  pnt[ttbl_index]->next = this_dir->contents;
1606  pnt[ttbl_index]->filedir = this_dir;
1607  this_dir->contents = pnt[ttbl_index];
1608  pnt[ttbl_index] = NULL;
1609 }
1610 
1611 
1612 /*
1613  * Here we have a case of a directory that has completely disappeared from
1614  * the face of the earth on the tree we are mastering from. Go through and
1615  * merge it into the tree, as well as everything beneath it.
1616  *
1617  * Note that if a directory has been moved for some reason, this will
1618  * incorrectly pick it up and attempt to merge it back into the old
1619  * location. FIXME(eric).
1620  */
1621 LOCAL int
1623  struct directory_entry *dpnt;
1624  struct directory *parent;
1625 {
1626  struct directory_entry **contents = NULL;
1627  int i;
1628  int n_orig;
1629  struct directory *this_dir,
1630  *next_brother;
1631  char whole_path[PATH_MAX];
1632 
1633  this_dir = (struct directory *)e_malloc(sizeof (struct directory));
1634  memset(this_dir, 0, sizeof (struct directory));
1635  this_dir->next = NULL;
1636  this_dir->subdir = NULL;
1637  this_dir->self = dpnt;
1638  this_dir->contents = NULL;
1639  this_dir->size = 0;
1640  this_dir->extent = 0;
1641  this_dir->depth = parent->depth + 1;
1642  this_dir->parent = parent;
1643  if (!parent->subdir)
1644  parent->subdir = this_dir;
1645  else {
1646  next_brother = parent->subdir;
1647  while (next_brother->next)
1648  next_brother = next_brother->next;
1649  next_brother->next = this_dir;
1650  }
1651 
1652  /* Set the name for this directory. */
1653  if (strlcpy(whole_path, parent->de_name, sizeof (whole_path)) >= sizeof (whole_path) ||
1654  strlcat(whole_path, SPATH_SEPARATOR, sizeof (whole_path)) >= sizeof (whole_path) ||
1655  strlcat(whole_path, dpnt->name, sizeof (whole_path)) >= sizeof (whole_path))
1656  comerrno(EX_BAD, _("Path name '%s%s%s' exceeds max length %zd\n"),
1657  parent->de_name,
1659  dpnt->name,
1660  sizeof (whole_path));
1661  this_dir->de_name = e_strdup(whole_path);
1662  this_dir->whole_name = e_strdup(whole_path);
1663 
1664  /*
1665  * Now fill this directory using information from the previous session.
1666  */
1667  contents = read_merging_directory(&dpnt->isorec, &n_orig);
1668  /*
1669  * Start by simply copying the '.', '..' and non-directory entries to
1670  * this directory. Technically we could let merge_remaining_entries
1671  * handle this, but it gets rather confused by the '.' and '..' entries
1672  */
1673  for (i = 0; i < n_orig; i++) {
1674  /*
1675  * We can always reuse the TRANS.TBL in this particular case.
1676  */
1677  contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
1678 
1679  if (((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) &&
1680  (i >= 2)) {
1681  continue;
1682  }
1683  /* If we have a directory, don't reuse the extent number. */
1684  if ((contents[i]->isorec.flags[0] & ISO_DIRECTORY) != 0) {
1685  memset(contents[i]->isorec.extent, 0, 8);
1686 
1687  if (strcmp(contents[i]->name, ".") == 0)
1688  this_dir->dir_flags |= DIR_HAS_DOT;
1689 
1690  if (strcmp(contents[i]->name, "..") == 0)
1691  this_dir->dir_flags |= DIR_HAS_DOTDOT;
1692  }
1693  /*
1694  * for regilar files, we do it here.
1695  * If it has CL or RE attributes, remember its extent
1696  */
1698 
1699  /*
1700  * Set the whole name for this file.
1701  */
1702  if (strlcpy(whole_path, this_dir->whole_name, sizeof (whole_path)) >= sizeof (whole_path) ||
1703  strlcat(whole_path, SPATH_SEPARATOR, sizeof (whole_path)) >= sizeof (whole_path) ||
1704  strlcat(whole_path, contents[i]->name, sizeof (whole_path)) >= sizeof (whole_path))
1705  comerrno(EX_BAD, _("Path name '%s%s%s' exceeds max length %zd\n"),
1706  this_dir->whole_name,
1708  contents[i]->name,
1709  sizeof (whole_path));
1710 
1711  contents[i]->whole_name = e_strdup(whole_path);
1712 
1713  contents[i]->next = this_dir->contents;
1714  contents[i]->filedir = this_dir;
1715  this_dir->contents = contents[i];
1716  contents[i] = NULL;
1717  }
1718 
1719  /*
1720  * and for directories, we do it here.
1721  * If it has CL or RE attributes, remember its extent
1722  */
1723  check_rr_relocation(dpnt);
1724 
1725  /*
1726  * Zero the extent number for ourselves.
1727  */
1728  memset(dpnt->isorec.extent, 0, 8);
1729 
1730  /*
1731  * Anything that is left are other subdirectories that need to be
1732  * merged.
1733  */
1734  merge_remaining_entries(this_dir, contents, n_orig);
1735  free_mdinfo(contents, n_orig);
1736 #if 0
1737  /*
1738  * This is no longer required. The post-scan sort will handle all of
1739  * this for us.
1740  */
1741  sort_n_finish(this_dir);
1742 #endif
1743 
1744  return (0);
1745 }
1746 
1747 
1749 
1750 int
1752  int *file_addr;
1753 {
1754  char *pnt;
1755 
1756 #ifdef CDRECORD_DETERMINES_FIRST_WRITABLE_ADDRESS
1757  /*
1758  * FIXME(eric). We need to coordinate with cdrecord to obtain the
1759  * parameters. For now, we assume we are writing the 2nd session, so
1760  * we start from the session that starts at 0.
1761  */
1762  if (file_addr != NULL)
1763  *file_addr = 16;
1764 
1765  /*
1766  * We need to coordinate with cdrecord to get the next writable address
1767  * from the device. Here is where we use it.
1768  */
1769  session_start = last_extent = last_extent_written = cdrecord_result();
1770 #else
1771 
1772  if (file_addr != NULL)
1773  *file_addr = 0L;
1775  if (check_session && cdrecord_data == NULL)
1776  return (0);
1777 
1778  if (cdrecord_data == NULL) {
1779  comerrno(EX_BAD,
1780  _("Special parameters for cdrecord not specified with -C\n"));
1781  }
1782  /*
1783  * Next try and find the ',' in there which delimits the two numbers.
1784  */
1785  pnt = strchr(cdrecord_data, ',');
1786  if (pnt == NULL) {
1787  comerrno(EX_BAD, _("Malformed cdrecord parameters\n"));
1788  }
1789 
1790  *pnt = '\0';
1791  if (file_addr != NULL) {
1792  *file_addr = atol(cdrecord_data);
1793  }
1794  pnt++;
1795 
1797 
1798  pnt--;
1799  *pnt = ',';
1800 
1801 #endif
1802  return (0);
1803 }
1804 
1805 /*
1806  * This function scans the directory tree, looking for files, and it makes
1807  * note of everything that is found. We also begin to construct the ISO9660
1808  * directory entries, so that we can determine how large each directory is.
1809  */
1810 int
1812  struct directory *this_dir;
1813  struct iso_directory_record *mrootp;
1814  char *reloc_root;
1815  char *reloc_old_root;
1816 {
1817  struct directory_entry **orig_contents = NULL;
1818  struct directory_entry *odpnt = NULL;
1819  int n_orig;
1820  struct directory_entry *s_entry;
1821  int status;
1822  int lstatus;
1823  struct stat statbuf,
1824  lstatbuf;
1825  int retcode;
1826 
1827  /* skip leading slash */
1828  while (reloc_old_root && reloc_old_root[0] == PATH_SEPARATOR) {
1829  reloc_old_root++;
1830  }
1831  while (reloc_root && reloc_root[0] == PATH_SEPARATOR) {
1832  reloc_root++;
1833  }
1834 
1835  /*
1836  * Parse the same directory in the image that we are merging for
1837  * multisession stuff.
1838  */
1839  orig_contents = read_merging_directory(mrootp, &n_orig);
1840  if (orig_contents == NULL) {
1841  if (reloc_old_root) {
1842  comerrno(EX_BAD,
1843  _("Reading old session failed, cannot execute -old-root.\n"));
1844  }
1845  return (0);
1846  }
1847 
1848  if (reloc_old_root && reloc_old_root[0]) {
1849  struct directory_entry **new_orig_contents = orig_contents;
1850  int new_n_orig = n_orig;
1851 
1852  /* decend until we reach the original root */
1853  while (reloc_old_root[0]) {
1854  int i;
1855  char *next;
1856  int last;
1857 
1858  for (next = reloc_old_root; *next && *next != PATH_SEPARATOR; next++);
1859  if (*next) {
1860  last = 0;
1861  *next = 0;
1862  next++;
1863  } else {
1864  last = 1;
1865  }
1866  while (*next == PATH_SEPARATOR) {
1867  next++;
1868  }
1869 
1870  for (i = 0; i < new_n_orig; i++) {
1871  struct iso_directory_record subroot;
1872 
1873  if (new_orig_contents[i]->name != NULL &&
1874  strcmp(new_orig_contents[i]->name, reloc_old_root) != 0) {
1875  /* Not the same name continue */
1876  continue;
1877  }
1878  /*
1879  * enter directory, free old one only if not the top level,
1880  * which is still needed
1881  */
1882  subroot = new_orig_contents[i]->isorec;
1883  if (new_orig_contents != orig_contents) {
1884  free_mdinfo(new_orig_contents, new_n_orig);
1885  }
1886  new_orig_contents = read_merging_directory(&subroot, &new_n_orig);
1887 
1888  if (!new_orig_contents) {
1889  comerrno(EX_BAD,
1890  _("Reading directory %s in old session failed, cannot execute -old-root.\n"),
1891  reloc_old_root);
1892  }
1893  i = -1;
1894  break;
1895  }
1896 
1897  if (i == new_n_orig) {
1898  comerrno(EX_BAD,
1899  _("-old-root (sub)directory %s not found in old session.\n"),
1900  reloc_old_root);
1901  }
1902 
1903  /* restore string, proceed to next sub directory */
1904  if (!last) {
1906  }
1907  reloc_old_root = next;
1908  }
1909 
1910  /*
1911  * preserve the old session, skipping those dirs/files that are found again
1912  * in the new root
1913  */
1914  for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
1915  status = stat_filter(s_entry->whole_name, &statbuf);
1916  lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
1917 
1918  /*
1919  * check_prev_session() will search for s_entry and remove it from
1920  * orig_contents if found
1921  */
1922  retcode = check_prev_session(orig_contents, n_orig, s_entry,
1923  &statbuf, &lstatbuf, NULL);
1924  if (retcode == -1)
1925  return (-1);
1926  /*
1927  * Skip other directory entries for multi-extent files
1928  */
1929  if (s_entry->de_flags & MULTI_EXTENT) {
1930  struct directory_entry *s_e;
1931 
1932  for (s_e = s_entry->mxroot;
1933  s_e && s_e->mxroot == s_entry->mxroot;
1934  s_e = s_e->next) {
1935  s_entry = s_e;
1936  ;
1937  }
1938  }
1939  }
1940  merge_remaining_entries(this_dir, orig_contents, n_orig);
1941 
1942  /* use new directory */
1943  free_mdinfo(orig_contents, n_orig);
1944  orig_contents = new_orig_contents;
1945  n_orig = new_n_orig;
1946 
1947  if (reloc_root && reloc_root[0]) {
1948  /* also decend into new root before searching for files */
1949  this_dir = find_or_create_directory(this_dir, reloc_root, NULL, TRUE);
1950  if (!this_dir) {
1951  return (-1);
1952  }
1953  }
1954  }
1955 
1956 
1957  /*
1958  * Now we scan the directory itself, and look at what is inside of it.
1959  */
1960  for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
1961  status = stat_filter(s_entry->whole_name, &statbuf);
1962  lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
1963 
1964  /*
1965  * We always should create an entirely new directory tree
1966  * whenever we generate a new session, unless there were
1967  * *no* changes whatsoever to any of the directories, in which
1968  * case it would be kind of pointless to generate a new
1969  * session.
1970  * I believe it is possible to rigorously prove that any change
1971  * anywhere in the filesystem will force the entire tree to be
1972  * regenerated because the modified directory will get a new
1973  * extent number. Since each subdirectory of the changed
1974  * directory has a '..' entry, all of them will need to be
1975  * rewritten too, and since the parent directory of the
1976  * modified directory will have an extent pointer to the
1977  * directory it too will need to be rewritten. Thus we will
1978  * never be able to reuse any directory information when
1979  * writing new sessions.
1980  *
1981  * We still check the previous session so we can mark off the
1982  * equivalent entry in the list we got from the original disc,
1983  * however.
1984  */
1985 
1986  /*
1987  * The check_prev_session function looks for an identical
1988  * entry in the previous session. If we see it, then we copy
1989  * the extent number to s_entry, and cross it off the list.
1990  */
1991  retcode = check_prev_session(orig_contents, n_orig, s_entry,
1992  &statbuf, &lstatbuf, &odpnt);
1993  if (retcode == -1)
1994  return (-1);
1995 
1996  if (odpnt != NULL &&
1997  (s_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) {
1998  int dflag;
1999 
2000  if (strcmp(s_entry->name, ".") != 0 &&
2001  strcmp(s_entry->name, "..") != 0) {
2002  struct directory *child;
2003 
2004  /*
2005  * XXX It seems that the tree that has been
2006  * XXX read from the previous session does not
2007  * XXX carry whole_name entries. We provide a
2008  * XXX hack in
2009  * XXX multi.c:find_or_create_directory()
2010  * XXX that should be removed when a
2011  * XXX reasonable method could be found.
2012  */
2013  child = find_or_create_directory(this_dir,
2014  s_entry->whole_name,
2015  s_entry, 1);
2016  dflag = merge_previous_session(child,
2017  &odpnt->isorec,
2018  NULL, reloc_old_root);
2019  if (dflag == -1) {
2020  return (-1);
2021  }
2022  free(odpnt);
2023  odpnt = NULL;
2024  }
2025  }
2026  if (odpnt) {
2027  free(odpnt);
2028  odpnt = NULL;
2029  }
2030  /*
2031  * Skip other directory entries for multi-extent files
2032  */
2033  if (s_entry->de_flags & MULTI_EXTENT) {
2034  struct directory_entry *s_e;
2035 
2036  for (s_e = s_entry->mxroot;
2037  s_e && s_e->mxroot == s_entry->mxroot;
2038  s_e = s_e->next) {
2039  s_entry = s_e;
2040  ;
2041  }
2042  }
2043  }
2044 
2045  if (!reloc_old_root) {
2046  /*
2047  * Whatever is left over, are things which are no longer in the tree on
2048  * disk. We need to also merge these into the tree.
2049  */
2050  merge_remaining_entries(this_dir, orig_contents, n_orig);
2051  }
2052  free_mdinfo(orig_contents, n_orig);
2053  return (1);
2054 }
2055 
2056 /*
2057  * This code deals with relocated directories which may exist
2058  * in the previous session.
2059  */
2061  unsigned int extent;
2064 };
2065 
2066 static struct dir_extent_link *cl_dirs = NULL;
2067 static struct dir_extent_link *re_dirs = NULL;
2068 
2069 LOCAL void
2071  struct directory_entry *de;
2072 {
2073  unsigned char sector[SECTOR_SIZE];
2074  unsigned char *pnt = de->rr_attributes;
2075  int len = de->rr_attr_size;
2076  UInt32_t cont_extent = 0,
2077  cont_offset = 0,
2078  cont_size = 0;
2079 
2080  pnt = parse_xa(pnt, &len, /* dpnt */ 0);
2081  while (len >= 4) {
2082  if (pnt[3] != 1 && pnt[3] != 2) {
2083  errmsgno(EX_BAD,
2084  _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
2085  pnt[3], pnt[0], pnt[1], pnt[0], pnt[1]);
2086  }
2087  if (pnt[2] < 4) {
2088  errmsgno(EX_BAD,
2089  _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
2090  pnt[2], pnt, pnt[0], pnt[1]);
2091  break;
2092  }
2093  if (strncmp((char *)pnt, "CL", 2) == 0) {
2094  struct dir_extent_link *dlink = e_malloc(sizeof (*dlink));
2095 
2096  dlink->extent = get_733(pnt + 4);
2097  dlink->de = de;
2098  dlink->next = cl_dirs;
2099  cl_dirs = dlink;
2100 
2101  } else if (strncmp((char *)pnt, "RE", 2) == 0) {
2102  struct dir_extent_link *dlink = e_malloc(sizeof (*dlink));
2103 
2104  dlink->extent = de->starting_block;
2105  dlink->de = de;
2106  dlink->next = re_dirs;
2107  re_dirs = dlink;
2108 
2109  } else if (strncmp((char *)pnt, "CE", 2) == 0) {
2110  cont_extent = get_733(pnt + 4);
2111  cont_offset = get_733(pnt + 12);
2112  cont_size = get_733(pnt + 20);
2113 
2114  } else if (strncmp((char *)pnt, "ST", 2) == 0) {
2115  len = pnt[2];
2116  }
2117  len -= pnt[2];
2118  pnt += pnt[2];
2119  if (len <= 3 && cont_extent) {
2120  /* ??? What if cont_offset+cont_size > SECTOR_SIZE */
2121  readsecs(cont_extent, sector, 1);
2122  pnt = sector + cont_offset;
2123  len = cont_size;
2124  cont_extent = cont_offset = cont_size = 0;
2125  }
2126  }
2127 
2128 }
2129 
2130 void
2132 {
2133  struct dir_extent_link *re = re_dirs;
2134 
2135  /* for each relocated directory */
2136  for (; re; re = re->next) {
2137  struct dir_extent_link *cl = cl_dirs;
2138 
2139  for (; cl; cl = cl->next) {
2140  /* find a place where it was relocated from */
2141  if (cl->extent == re->extent) {
2142  /* set link to that place */
2143  re->de->parent_rec = cl->de;
2144  re->de->filedir = cl->de->filedir;
2145 
2146  /*
2147  * see if it is in rr_moved
2148  */
2149  if (reloc_dir != NULL) {
2150  struct directory_entry *rr_moved_e = reloc_dir->contents;
2151 
2152  for (; rr_moved_e; rr_moved_e = rr_moved_e->next) {
2153  /* yes it is */
2154  if (re->de == rr_moved_e) {
2155  /* forget it */
2156  re->de = NULL;
2157  }
2158  }
2159  }
2160  break;
2161  }
2162  }
2163  }
2164 }
2165 
2166 void
2168 {
2169  struct dir_extent_link *re = re_dirs;
2170 
2171  /* for those that were relocated, but NOT to rr_moved */
2172  re = re_dirs;
2173  for (; re; re = re->next) {
2174  if (re->de != NULL) {
2175  /*
2176  * here we have hypothetical case when previous session
2177  * was not created by mkisofs and contains relocations
2178  */
2179  struct directory_entry *s_entry = re->de;
2180  struct directory_entry *s_entry1;
2181  struct directory *d_entry = reloc_dir->subdir;
2182 
2183  /* do the same as finish_cl_pl_entries */
2184  if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
2185  continue;
2186  }
2187  while (d_entry) {
2188  if (d_entry->self == s_entry)
2189  break;
2190  d_entry = d_entry->next;
2191  }
2192  if (!d_entry) {
2193  comerrno(EX_BAD, _("Unable to locate directory parent\n"));
2194  }
2195 
2196  if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) {
2197  char *rr_attr;
2198 
2199  /*
2200  * First fix the PL pointer in the directory in the
2201  * rr_reloc dir
2202  */
2203  s_entry1 = d_entry->contents->next;
2204  rr_attr = find_rr_attribute(s_entry1->rr_attributes,
2205  s_entry1->total_rr_attr_size, "PL");
2206  if (rr_attr != NULL)
2207  set_733(rr_attr + 4, s_entry->filedir->extent);
2208 
2209  /* Now fix the CL pointer */
2210  s_entry1 = s_entry->parent_rec;
2211 
2212  rr_attr = find_rr_attribute(s_entry1->rr_attributes,
2213  s_entry1->total_rr_attr_size, "CL");
2214  if (rr_attr != NULL)
2215  set_733(rr_attr + 4, d_entry->extent);
2216  }
2217  }
2218  }
2219  /* free memory */
2220  re = re_dirs;
2221  while (re) {
2222  struct dir_extent_link *next = re->next;
2223 
2224  free(re);
2225  re = next;
2226  }
2227  re = cl_dirs;
2228  while (re) {
2229  struct dir_extent_link *next = re->next;
2230 
2231  free(re);
2232  re = next;
2233  }
2234 }
#define realloc
Definition: debug_ros.c:6
unsigned int de_flags
Definition: mkisofs.h:122
char * whole_name
Definition: mkisofs.h:273
uint32_t sector
Definition: isohybrid.c:61
char id[ISODCL(2, 6)]
Definition: iso9660.h:37
unsigned char name_len[ISODCL(33, 33)]
Definition: iso9660.h:255
#define TRUE
Definition: types.h:120
LOCAL struct directory_entry ** read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
Definition: multi.c:664
EXPORT char * find_rr_attribute(unsigned char *pnt, int len, char *attr_type)
Definition: tree.c:1007
char * table
Definition: mkisofs.h:117
EXPORT void comerr(char *msg, va_alist)
Definition: comerr.c:84
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
LOCAL void prbytes(char *txt, Uchar *p, int len)
Definition: multi.c:157
BOOL rrip112
Definition: mkisofs.c:325
BOOL ignerr
Definition: multi.c:92
#define error(str)
Definition: mkdosfs.c:1605
unsigned char Uchar
Definition: utypes.h:45
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
Definition: mkisofs.h:107
#define MULTI_EXTENT
Definition: mkisofs.h:808
time_t st_ctime
Definition: stat.h:66
#define RR_FLAG_PN
Definition: rock.h:27
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
POINT last
Definition: font.c:46
LOCAL int check_rr_dates(struct directory_entry *dpnt, struct directory_entry *current, struct stat *statbuf, struct stat *lstatbuf)
Definition: multi.c:453
GLsizei const GLchar ** path
Definition: glext.h:7234
unsigned int size
Definition: mkisofs.h:279
unsigned int depth
Definition: mkisofs.h:278
unsigned int starting_block
Definition: mkisofs.h:111
LOCAL int merge_old_directory_into_tree(struct directory_entry *dpnt, struct directory *parent)
Definition: multi.c:1622
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
char * reloc_root
Definition: mkisofs.c:177
#define SPATH_SEPARATOR
Definition: mkisofs.h:787
#define free
Definition: debug_ros.c:5
__kernel_off_t off_t
Definition: linux.h:201
size_t strlcpy(char *d, const char *s, size_t bufsize)
Definition: compat.c:3
#define PREV_SESS_DEV
Definition: mkisofs.h:762
struct directory * filedir
Definition: mkisofs.h:119
GLintptr offset
Definition: glext.h:5920
char ext_attr_length[ISODCL(2, 2)]
Definition: iso9660.h:247
#define UConst
Definition: ccomdefs.h:72
#define RR_FLAG_AA
Definition: rock.h:38
#define PATH_SEPARATOR
Definition: xmllint.c:210
LOCAL int iso_dir_ents(struct directory_entry *de)
Definition: multi.c:1266
GLuint buffer
Definition: glext.h:5915
#define RR_FLAG_SL
Definition: rock.h:28
_Check_return_opt_ _CRTIMP long __cdecl lseek(_In_ int _FileHandle, _In_ long _Offset, _In_ int _Origin)
EXPORT int stat_filter(char *path, struct stat *st)
Definition: tree.c:232
EXPORT size_t strlcat(char *s1, const char *s2, size_t len)
Definition: strlcat.c:32
LOCAL int free_mdinfo(struct directory_entry **ptr, int len)
Definition: multi.c:1098
EXPORT char * e_strdup(char *s) const
Definition: mkisofs.c:3941
#define ISO_STANDARD_ID
Definition: iso9660.h:47
static HWND child
Definition: cursoricon.c:298
#define DIR_HAS_DOTDOT
Definition: mkisofs.h:798
char volume_set_size[ISODCL(121, 124)]
Definition: iso9660.h:74
unsigned int got_rr_name
Definition: mkisofs.h:137
#define RR_FLAG_ER
Definition: rock.h:42
char * name
Definition: mkisofs.h:116
struct directory * subdir
Definition: mkisofs.h:268
int check_oldnames
Definition: mkisofs.c:98
int open_merge_image(char *path)
Definition: multi.c:1365
int mxpart
Definition: mkisofs.h:113
#define sprintf(buf, format,...)
Definition: sprintf.c:55
unsigned int extent
Definition: mkisofs.h:280
LOCAL void check_rr_relocation(struct directory_entry *de)
Definition: multi.c:2070
LOCAL int parse_rrflags(Uchar *pnt, int len, int cont_flag)
Definition: multi.c:264
struct directory * parent
Definition: mkisofs.h:269
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define S_IFMT
Definition: ext2fs.h:353
#define _(X)
Definition: i386-dis.c:36
char name[MAX_ISONAME+1]
Definition: iso9660.h:256
unsigned char flags[ISODCL(26, 26)]
Definition: iso9660.h:251
unsigned int BOOL
Definition: ntddk_ex.h:94
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define DIR_HAS_DOT
Definition: mkisofs.h:797
struct iso_directory_record isorec
Definition: mkisofs.h:110
struct directory_entry * parent_rec
Definition: mkisofs.h:120
static PVOID ptr
Definition: dispmode.c:27
static struct dir_extent_link * re_dirs
Definition: multi.c:2067
UInt32_t last_extent
Definition: mkisofs.c:76
EXPORT UInt32_t get_733(void *vp)
Definition: isonum.c:219
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
char * whole_name
Definition: mkisofs.h:118
EXPORT int iso9660_date(char *result, time_t crtime)
Definition: mkisofs.c:1868
#define roundup(x, y)
Definition: multi.c:48
#define INHIBIT_ISO9660_ENTRY
Definition: mkisofs.h:802
#define INHIBIT_JOLIET_ENTRY
Definition: mkisofs.h:799
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
char reserved[ISODCL(10, 14)]
Definition: iso9660.h:330
struct directory_entry * contents
Definition: mkisofs.h:270
#define LOCAL(type)
Definition: jmorecfg.h:289
char * de_name
Definition: mkisofs.h:275
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
unsigned int total_rr_attr_size
Definition: mkisofs.h:136
#define RR_FLAG_RE
Definition: rock.h:32
char size[ISODCL(11, 18)]
Definition: iso9660.h:249
#define RR_FLAG_TF
Definition: rock.h:33
#define SEEK_SET
Definition: jmemansi.c:26
void iso9660_check(struct iso_directory_record *idr, struct directory_entry *ndr)
Definition: name.c:45
UInt32_t null_inodes
Definition: mkisofs.c:323
#define INHIBIT_UDF_ENTRY
Definition: mkisofs.h:809
GLfloat f
Definition: glext.h:7540
int check_prev_session(struct directory_entry **ptr, int len, struct directory_entry *curr_entry, struct stat *statbuf, struct stat *lstatbuf, struct directory_entry **odpnt)
Definition: multi.c:1147
GLsizeiptr size
Definition: glext.h:5919
char * reloc_old_root
Definition: mkisofs.c:178
int check_session
Definition: mkisofs.c:99
r parent
Definition: btrfs.c:2869
_Check_return_ _CRTIMP int __cdecl fileno(_In_ FILE *_File)
EXPORT UInt32_t get_711(void *vp)
Definition: isonum.c:142
if(!(yy_init))
Definition: macro.lex.yy.c:714
struct directory * reloc_dir
Definition: tree.c:111
#define TF_MODIFY
Definition: multi.c:57
#define MAX_ISONAME
Definition: iso9660.h:242
UInt32_t session_start
Definition: mkisofs.c:77
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
unsigned char * parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt)
Definition: multi.c:169
char * name
Definition: compiler.c:66
int aa_version
Definition: multi.c:95
#define PATH_MAX
Definition: types.h:280
int close_merge_image()
Definition: multi.c:1387
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
#define RR_FLAG_NM
Definition: rock.h:29
static UConst char sccsid[]
Definition: multi.c:4
char * trans_tbl
Definition: mkisofs.c:259
EXPORT int lstat_filter(char *path, struct stat *st)
Definition: tree.c:244
int rr_version
Definition: multi.c:94
int ret
#define ISO_DIRECTORY
Definition: iso9660.h:265
#define LEN_ISONAME
Definition: iso9660.h:237
UInt32_t last_extent_written
Definition: write.c:303
#define RR_FLAG_CL
Definition: rock.h:30
static const WCHAR L[]
Definition: oid.c:1250
unsigned short st_mode
Definition: stat.h:58
LOCAL void printasc(char *txt, unsigned char *p, int len)
Definition: multi.c:139
LOCAL void printasc __PR((char *txt, unsigned char *p, int len))
Definition: stat.h:55
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
LOCAL int sort_n_finish(struct directory *this_dir)
Definition: tree.c:256
GLenum GLsizei len
Definition: glext.h:6722
LOCAL BOOL valid_iso_directory(struct iso_directory_record *idr, int idr_off, size_t space_left)
Definition: multi.c:567
struct directory_entry * next
Definition: mkisofs.h:108
struct directory_entry * self
Definition: mkisofs.h:272
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
off_t size
Definition: mkisofs.h:112
GLenum mode
Definition: glext.h:6217
#define TF_CREATE
Definition: multi.c:56
void match_cl_re_entries()
Definition: multi.c:2131
#define RR_FLAG_PL
Definition: rock.h:31
LOCAL void merge_remaining_entries(struct directory *this_dir, struct directory_entry **pnt, int n_orig)
Definition: multi.c:1490
EXPORT struct directory_entry * dup_directory_entry(struct directory_entry *s_entry)
Definition: tree.c:2429
FILE * in_image
Definition: multi.c:91
EXPORT UInt32_t get_723(void *vp)
Definition: isonum.c:169
static struct dir_extent_link * cl_dirs
Definition: multi.c:2066
static unsigned __int64 next
Definition: rand_nt.c:6
#define ISO_VD_PRIMARY
Definition: iso9660.h:43
#define RR_FLAG_PX
Definition: rock.h:26
#define ISO_ROUND_UP(X)
Definition: mkisofs.h:742
__kernel_mode_t mode_t
Definition: linux.h:199
char * cdrecord_data
Definition: multi.c:1748
int rr_flags(struct iso_directory_record *idr)
Definition: multi.c:353
unsigned int rr_attr_size
Definition: mkisofs.h:135
int no_rr
Definition: mkisofs.c:237
struct directory_entry * mxroot
Definition: mkisofs.h:121
#define ISO_MULTIEXTENT
Definition: iso9660.h:271
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
char * strchr(const char *String, int ch)
Definition: utclib.c:501
EXPORT void * e_malloc(size_t size)
Definition: mkisofs.c:3921
#define isprint(c)
Definition: acclib.h:73
unsigned char length[ISODCL(1, 1)]
Definition: iso9660.h:246
EXPORT struct directory * find_or_create_directory(struct directory *parent, char *path, struct directory_entry *de, int flag)
Definition: tree.c:2508
POINT cp
Definition: magnifier.c:59
char er_id[256]
Definition: multi.c:96
Definition: name.c:38
struct iso_directory_record * merge_isofs(char *path)
Definition: multi.c:1401
LOCAL BOOL find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp)
Definition: multi.c:225
EXPORT int readsecs(UInt32_t startsecno, void *buffer, int sectorcount)
Definition: multi.c:118
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
EXPORT char * movebytes(void *fromv, void *tov, ssize_t cnt) const
Definition: movebytes.c:30
#define RR_FLAG_XA
Definition: rock.h:39
FILE * stderr
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
unsigned char * rr_attributes
Definition: mkisofs.h:134
LOCAL void copy_mult_extent(struct directory_entry *se1, struct directory_entry *se2)
Definition: multi.c:1293
#define ISO_ASSOCIATED
Definition: iso9660.h:266
#define SECTOR_SIZE
Definition: fs.h:22
int get_session_start(int *file_addr)
Definition: multi.c:1751
#define RR_FLAG_SP
Definition: rock.h:37
LOCAL void free_directory_entry(struct directory_entry *dirp)
Definition: multi.c:1123
GLfloat GLfloat p
Definition: glext.h:8902
char type[ISODCL(1, 1)]
Definition: iso9660.h:36
time_t st_mtime
Definition: stat.h:65
int merge_previous_session(struct directory *this_dir, struct iso_directory_record *mrootp, char *reloc_root, char *reloc_old_root)
Definition: multi.c:1811
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
#define SAFE_TO_REUSE_TABLE_ENTRY
Definition: mkisofs.h:796
LOCAL int parse_rr(unsigned char *pnt, int len, struct directory_entry *dpnt)
Definition: multi.c:370
void finish_cl_pl_for_prev_session()
Definition: multi.c:2167
unsigned short dir_flags
Definition: mkisofs.h:285
int su_version
Definition: multi.c:93
char logical_block_size[ISODCL(129, 132)]
Definition: iso9660.h:76
BOOL correct_inodes
Definition: mkisofs.c:324
EXPORT void set_733(void *vp, UInt32_t i)
Definition: isonum.c:125
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
char signature[ISODCL(7, 8)]
Definition: iso9660.h:328
struct task_struct * current
Definition: linux.c:32
struct directory * next
Definition: mkisofs.h:267
char root_directory_record[ISODCL(157, 190)]
Definition: iso9660.h:82
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219
char extent[ISODCL(3, 10)]
Definition: iso9660.h:248
Definition: ps.c:97
#define EX_BAD
Definition: standard.h:62