ReactOS 0.4.16-dev-303-g11d5cb8
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
4static 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
61LOCAL void printasc __PR((char *txt, unsigned char *p, int len));
62LOCAL void prbytes __PR((char *txt, unsigned char *p, int len));
63unsigned char *parse_xa __PR((unsigned char *pnt, int *lenp,
64 struct directory_entry *dpnt));
66LOCAL int parse_rrflags __PR((Uchar *pnt, int len, int cont_flag));
67LOCAL BOOL find_rr __PR((struct iso_directory_record *idr, Uchar **pntp, int *lenp));
68LOCAL int parse_rr __PR((unsigned char *pnt, int len,
69 struct directory_entry *dpnt));
72 struct stat *statbuf,
73 struct stat *lstatbuf));
75 int idr_off,
76 size_t space_left));
77LOCAL struct directory_entry **
83 struct directory_entry *se2));
85 struct directory_entry **, int));
86
88 struct directory *));
90
93int su_version = -1;
94int rr_version = -1;
95int aa_version = -1;
96char 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
114EXPORT int
115readsecs(UInt32_t startsecno, void *buffer, int sectorcount)
116#else
117EXPORT int
118readsecs(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
138LOCAL void
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
156LOCAL void
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
168unsigned char *
169parse_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;
176static 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
225find_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
263LOCAL int
264parse_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
352int
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 */
369LOCAL int
370parse_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 */
452LOCAL int
453check_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) {
562 }
563 return (same_file);
564}
565
567valid_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 -
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 -
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 -
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 -
655 idr_namelength;
656
657 /* Check for the minimum of Rock Ridge extensions. */
658 }
659#endif
660 return (TRUE);
661}
662
663LOCAL 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 */
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 */
1080 _("Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) \n"));
1082 _("name translations were found on previous session.\n"));
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 */
1097LOCAL 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
1122LOCAL 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 */
1146int
1147check_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
1243found_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 */
1265LOCAL 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 */
1292LOCAL 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);
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 */
1364int
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 */
1386int
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 */
1400struct 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) {
1445 _("Previous session has incompatible sector size %u.\n"),
1447 return (NULL);
1448 }
1449 if (get_723(pri->volume_set_size) != 1) {
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,
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
1489LOCAL void
1490merge_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 */
1621LOCAL 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
1750int
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;
1776 return (0);
1777
1778 if (cdrecord_data == NULL) {
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 */
1810int
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 */
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) {
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) {
1890 _("Reading directory %s in old session failed, cannot execute -old-root.\n"),
1892 }
1893 i = -1;
1894 break;
1895 }
1896
1897 if (i == new_n_orig) {
1899 _("-old-root (sub)directory %s not found in old session.\n"),
1901 }
1902
1903 /* restore string, proceed to next sub directory */
1904 if (!last) {
1906 }
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 */
2014 s_entry->whole_name,
2015 s_entry, 1);
2017 &odpnt->isorec,
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
2068
2069LOCAL 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) {
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) {
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
2130void
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
2166void
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}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define isprint(c)
Definition: acclib.h:73
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define fileno
Definition: acwin.h:102
#define read
Definition: acwin.h:96
#define PATH_MAX
Definition: types.h:280
size_t strlcpy(char *d, const char *s, size_t bufsize)
Definition: compat.c:3
#define SECTOR_SIZE
Definition: fs.h:22
#define UConst
Definition: ccomdefs.h:72
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219
EXPORT void comerr(char *msg, va_alist)
Definition: comerr.c:84
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
r parent
Definition: btrfs.c:3010
__kernel_mode_t mode_t
Definition: linux.h:199
__kernel_off_t off_t
Definition: linux.h:201
#define S_IFMT
Definition: ext2fs.h:358
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLfloat f
Definition: glext.h:7540
GLenum mode
Definition: glext.h:6217
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
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
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
#define _(X)
Definition: i386-dis.c:35
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
#define MAX_ISONAME
Definition: iso9660.h:242
#define ISO_ASSOCIATED
Definition: iso9660.h:266
#define LEN_ISONAME
Definition: iso9660.h:237
#define ISO_DIRECTORY
Definition: iso9660.h:265
#define ISO_STANDARD_ID
Definition: iso9660.h:47
#define ISO_VD_PRIMARY
Definition: iso9660.h:43
#define ISO_MULTIEXTENT
Definition: iso9660.h:271
uint32_t sector
Definition: isohybrid.c:61
EXPORT UInt32_t get_711(void *vp)
Definition: isonum.c:142
EXPORT UInt32_t get_733(void *vp)
Definition: isonum.c:219
EXPORT void set_733(void *vp, UInt32_t i)
Definition: isonum.c:125
EXPORT UInt32_t get_723(void *vp)
Definition: isonum.c:169
#define SEEK_SET
Definition: jmemansi.c:26
#define LOCAL(type)
Definition: jmorecfg.h:289
NTSTATUS rtn
#define lseek
Definition: syshdrs.h:47
if(dx< 0)
Definition: linetemp.h:194
POINT cp
Definition: magnifier.c:59
#define error(str)
Definition: mkdosfs.c:1605
EXPORT int iso9660_date(char *result, time_t crtime)
Definition: mkisofs.c:1868
int check_session
Definition: mkisofs.c:99
BOOL correct_inodes
Definition: mkisofs.c:324
UInt32_t session_start
Definition: mkisofs.c:77
int no_rr
Definition: mkisofs.c:237
char * reloc_root
Definition: mkisofs.c:177
char * reloc_old_root
Definition: mkisofs.c:178
UInt32_t null_inodes
Definition: mkisofs.c:323
char * trans_tbl
Definition: mkisofs.c:259
EXPORT void * e_malloc(size_t size)
Definition: mkisofs.c:3921
EXPORT char * e_strdup(char *s) const
Definition: mkisofs.c:3941
UInt32_t last_extent
Definition: mkisofs.c:76
int check_oldnames
Definition: mkisofs.c:98
BOOL rrip112
Definition: mkisofs.c:325
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SAFE_TO_REUSE_TABLE_ENTRY
Definition: mkisofs.h:796
#define INHIBIT_JOLIET_ENTRY
Definition: mkisofs.h:799
#define PREV_SESS_DEV
Definition: mkisofs.h:762
struct directory * reloc_dir
Definition: tree.c:111
#define INHIBIT_UDF_ENTRY
Definition: mkisofs.h:809
#define DIR_HAS_DOT
Definition: mkisofs.h:797
UInt32_t last_extent_written
Definition: write.c:303
#define DIR_HAS_DOTDOT
Definition: mkisofs.h:798
#define MULTI_EXTENT
Definition: mkisofs.h:808
#define ISO_ROUND_UP(X)
Definition: mkisofs.h:742
#define INHIBIT_ISO9660_ENTRY
Definition: mkisofs.h:802
#define SPATH_SEPARATOR
Definition: mkisofs.h:787
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static UINT UINT last
Definition: font.c:45
static const char * contents
Definition: parser.c:511
static HWND child
Definition: cursoricon.c:298
EXPORT char * movebytes(void *fromv, void *tov, ssize_t cnt) const
Definition: movebytes.c:30
LOCAL void copy_mult_extent(struct directory_entry *se1, struct directory_entry *se2)
Definition: multi.c:1293
int get_session_start(int *file_addr)
Definition: multi.c:1751
FILE * in_image
Definition: multi.c:91
BOOL ignerr
Definition: multi.c:92
LOCAL void prbytes(char *txt, Uchar *p, int len)
Definition: multi.c:157
LOCAL void check_rr_relocation(struct directory_entry *de)
Definition: multi.c:2070
LOCAL void merge_remaining_entries(struct directory *this_dir, struct directory_entry **pnt, int n_orig)
Definition: multi.c:1490
struct iso_directory_record * merge_isofs(char *path)
Definition: multi.c:1401
char * cdrecord_data
Definition: multi.c:1748
int aa_version
Definition: multi.c:95
int rr_flags(struct iso_directory_record *idr)
Definition: multi.c:353
LOCAL int parse_rrflags(Uchar *pnt, int len, int cont_flag)
Definition: multi.c:264
static UConst char sccsid[]
Definition: multi.c:4
int merge_previous_session(struct directory *this_dir, struct iso_directory_record *mrootp, char *reloc_root, char *reloc_old_root)
Definition: multi.c:1811
LOCAL int free_mdinfo(struct directory_entry **ptr, int len)
Definition: multi.c:1098
LOCAL struct directory_entry ** read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
Definition: multi.c:664
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
LOCAL void free_directory_entry(struct directory_entry *dirp)
Definition: multi.c:1123
LOCAL int parse_rr(unsigned char *pnt, int len, struct directory_entry *dpnt)
Definition: multi.c:370
int open_merge_image(char *path)
Definition: multi.c:1365
static struct dir_extent_link * re_dirs
Definition: multi.c:2067
LOCAL int check_rr_dates(struct directory_entry *dpnt, struct directory_entry *current, struct stat *statbuf, struct stat *lstatbuf)
Definition: multi.c:453
char er_id[256]
Definition: multi.c:96
LOCAL int iso_dir_ents(struct directory_entry *de)
Definition: multi.c:1266
LOCAL int merge_old_directory_into_tree(struct directory_entry *dpnt, struct directory *parent)
Definition: multi.c:1622
unsigned char * parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt)
Definition: multi.c:169
#define TF_CREATE
Definition: multi.c:56
int close_merge_image()
Definition: multi.c:1387
LOCAL BOOL valid_iso_directory(struct iso_directory_record *idr, int idr_off, size_t space_left)
Definition: multi.c:567
void finish_cl_pl_for_prev_session()
Definition: multi.c:2167
#define TF_MODIFY
Definition: multi.c:57
static struct dir_extent_link * cl_dirs
Definition: multi.c:2066
int su_version
Definition: multi.c:93
LOCAL void printasc(char *txt, unsigned char *p, int len)
Definition: multi.c:139
#define roundup(x, y)
Definition: multi.c:48
LOCAL BOOL find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp)
Definition: multi.c:225
int rr_version
Definition: multi.c:94
void match_cl_re_entries()
Definition: multi.c:2131
EXPORT int readsecs(UInt32_t startsecno, void *buffer, int sectorcount)
Definition: multi.c:118
#define L(x)
Definition: ntvdm.h:50
#define __PR(a)
Definition: prototyp.h:106
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
static unsigned __int64 next
Definition: rand_nt.c:6
#define RR_FLAG_AA
Definition: rock.h:38
#define RR_FLAG_PL
Definition: rock.h:31
#define RR_FLAG_ER
Definition: rock.h:42
#define RR_FLAG_PN
Definition: rock.h:27
#define RR_FLAG_SL
Definition: rock.h:28
#define RR_FLAG_RE
Definition: rock.h:32
#define RR_FLAG_PX
Definition: rock.h:26
#define RR_FLAG_XA
Definition: rock.h:39
#define RR_FLAG_SP
Definition: rock.h:37
#define RR_FLAG_CL
Definition: rock.h:30
#define RR_FLAG_TF
Definition: rock.h:33
#define RR_FLAG_NM
Definition: rock.h:29
#define offsetof(TYPE, MEMBER)
#define memset(x, y, z)
Definition: compat.h:39
void iso9660_check(struct iso_directory_record *idr, struct directory_entry *ndr)
Definition: name.c:45
EXPORT int stat_filter(char *path, struct stat *st)
Definition: tree.c:232
EXPORT struct directory_entry * dup_directory_entry(struct directory_entry *s_entry)
Definition: tree.c:2429
EXPORT int lstat_filter(char *path, struct stat *st)
Definition: tree.c:244
EXPORT struct directory * find_or_create_directory(struct directory *parent, char *path, struct directory_entry *de, int flag)
Definition: tree.c:2508
LOCAL int sort_n_finish(struct directory *this_dir)
Definition: tree.c:256
EXPORT char * find_rr_attribute(unsigned char *pnt, int len, char *attr_type)
Definition: tree.c:1007
#define EX_BAD
Definition: standard.h:62
EXPORT size_t strlcat(char *s1, const char *s2, size_t len)
Definition: strlcat.c:32
char * name
Definition: compiler.c:66
Definition: mkisofs.h:107
char * whole_name
Definition: mkisofs.h:118
unsigned int got_rr_name
Definition: mkisofs.h:137
struct directory_entry * mxroot
Definition: mkisofs.h:121
unsigned int starting_block
Definition: mkisofs.h:111
unsigned int rr_attr_size
Definition: mkisofs.h:135
char * table
Definition: mkisofs.h:117
unsigned char * rr_attributes
Definition: mkisofs.h:134
off_t size
Definition: mkisofs.h:112
int mxpart
Definition: mkisofs.h:113
struct directory_entry * next
Definition: mkisofs.h:108
char * name
Definition: mkisofs.h:116
unsigned int de_flags
Definition: mkisofs.h:122
struct iso_directory_record isorec
Definition: mkisofs.h:110
struct directory_entry * parent_rec
Definition: mkisofs.h:120
struct directory * filedir
Definition: mkisofs.h:119
unsigned int total_rr_attr_size
Definition: mkisofs.h:136
struct directory * parent
Definition: mkisofs.h:269
char * de_name
Definition: mkisofs.h:275
unsigned short dir_flags
Definition: mkisofs.h:285
char * whole_name
Definition: mkisofs.h:273
unsigned int extent
Definition: mkisofs.h:280
unsigned int size
Definition: mkisofs.h:279
struct directory * subdir
Definition: mkisofs.h:268
unsigned int depth
Definition: mkisofs.h:278
struct directory * next
Definition: mkisofs.h:267
struct directory_entry * self
Definition: mkisofs.h:272
struct directory_entry * contents
Definition: mkisofs.h:270
unsigned char name_len[ISODCL(33, 33)]
Definition: iso9660.h:255
char extent[ISODCL(3, 10)]
Definition: iso9660.h:248
char ext_attr_length[ISODCL(2, 2)]
Definition: iso9660.h:247
char name[MAX_ISONAME+1]
Definition: iso9660.h:256
unsigned char flags[ISODCL(26, 26)]
Definition: iso9660.h:251
char size[ISODCL(11, 18)]
Definition: iso9660.h:249
unsigned char length[ISODCL(1, 1)]
Definition: iso9660.h:246
char volume_set_size[ISODCL(121, 124)]
Definition: iso9660.h:74
char root_directory_record[ISODCL(157, 190)]
Definition: iso9660.h:82
char logical_block_size[ISODCL(129, 132)]
Definition: iso9660.h:76
char type[ISODCL(1, 1)]
Definition: iso9660.h:36
char id[ISODCL(2, 6)]
Definition: iso9660.h:37
char reserved[ISODCL(10, 14)]
Definition: iso9660.h:330
char signature[ISODCL(7, 8)]
Definition: iso9660.h:328
Definition: name.c:39
Definition: stat.h:55
time_t st_ctime
Definition: stat.h:66
unsigned short st_mode
Definition: stat.h:58
time_t st_mtime
Definition: stat.h:65
Definition: ps.c:97
unsigned char Uchar
Definition: utypes.h:45
int ret
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define PATH_SEPARATOR
Definition: xmllint.c:205