ReactOS 0.4.15-dev-8093-g3285f69
tree.c
Go to the documentation of this file.
1/* @(#)tree.c 1.137 16/12/13 joerg */
2#include <schily/mconfig.h>
3#ifndef lint
4static UConst char sccsid[] =
5 "@(#)tree.c 1.137 16/12/13 joerg";
6#endif
7/*
8 * File tree.c - scan directory tree and build memory structures for iso9660
9 * filesystem
10 *
11 * Written by Eric Youngdale (1993).
12 *
13 * Copyright 1993 Yggdrasil Computing, Incorporated
14 * Copyright (c) 1999,2000-2016 J. Schilling
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2, or (at your option)
19 * any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 */
30/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
31
32/* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */
33
34/* DUPLICATES_ONCE Alex Kopylov cdrtools@bootcd.ru 19.06.2004 */
35
36#include "mkisofs.h"
37#include "rock.h"
38#include "match.h"
39#include <schily/time.h>
40#include <schily/errno.h>
41#include <schily/fcntl.h>
42#include <schily/device.h>
43#include <schily/schily.h>
44
45#ifdef UDF
46#include "udf.h"
47#endif
48
49#ifdef VMS
50#include <sys/file.h>
51#include <vms/fabdef.h>
52#include "vms.h"
53#endif
54
56
57LOCAL char *filetype __PR((int t));
58LOCAL char *rstr __PR((char *s1, char *s2));
59LOCAL void stat_fix __PR((struct stat *st));
60EXPORT int stat_filter __PR((char *path, struct stat *st));
61EXPORT int lstat_filter __PR((char *path, struct stat *st));
62LOCAL int sort_n_finish __PR((struct directory *this_dir));
65 struct stat *this_stat,
66 struct stat *parent_stat));
67EXPORT char *find_rr_attribute __PR((unsigned char *pnt, int len,
68 char *attr_type));
70LOCAL void dir_nesting_warn __PR((struct directory *this_dir,
71 char *path, int contflag));
73 char *path,
74 struct directory_entry *de));
76 dup_relocated_dir __PR((struct directory *this_dir,
77 struct directory_entry *s_entry,
78 char *whole_path,
79 char *short_name,
80 struct stat *statp));
81EXPORT int insert_file_entry __PR((struct directory *this_dir,
82 char *whole_path,
83 char *short_name,
84 struct stat *statp, int have_rsrc));
88 FILE *outfile));
89
91 struct directory *this));
92
93EXPORT struct directory *
95 char *path,
96 struct directory_entry *de,
97 int flag));
99 struct directory *child));
101EXPORT void dump_tree __PR((struct directory *node));
102EXPORT struct directory_entry *
104 char *filename));
105EXPORT void init_fstatbuf __PR((void));
106
107extern int verbose;
108struct stat fstatbuf; /* We use this for the artificial */
109 /* entries we create */
110struct stat root_statbuf; /* Stat buffer for root directory */
112
113LOCAL char *
115 int t;
116{
117 static char unkn[32];
118
119 if (S_ISFIFO(t)) /* 1 */
120 return ("fifo");
121 if (S_ISCHR(t)) /* 2 */
122 return ("chr");
123 if (S_ISMPC(t)) /* 3 */
124 return ("multiplexed chr");
125 if (S_ISDIR(t)) /* 4 */
126 return ("dir");
127 if (S_ISNAM(t)) /* 5 */
128 return ("named file");
129 if (S_ISBLK(t)) /* 6 */
130 return ("blk");
131 if (S_ISMPB(t)) /* 7 */
132 return ("multiplexed blk");
133 if (S_ISREG(t)) /* 8 */
134 return ("regular file");
135 if (S_ISCTG(t)) /* 9 */
136 return ("contiguous file");
137 if (S_ISLNK(t)) /* 10 */
138 return ("symlink");
139 if (S_ISSHAD(t)) /* 11 */
140 return ("Solaris shadow inode");
141 if (S_ISSOCK(t)) /* 12 */
142 return ("socket");
143 if (S_ISDOOR(t)) /* 13 */
144 return ("door");
145 if (S_ISWHT(t)) /* 14 */
146 return ("whiteout");
147 if (S_ISEVC(t)) /* 15 */
148 return ("event count");
149
150 /*
151 * Needs to be last in case somebody makes this
152 * a supported file type.
153 */
154 if ((t & S_IFMT) == 0) /* 0 (unallocated) */
155 return ("unallocated");
156
157 sprintf(unkn, "octal '%o'", t & S_IFMT);
158 return (unkn);
159}
160
161/*
162 * Check if s1 ends in strings s2
163 */
164LOCAL char *
166 char *s1;
167 char *s2;
168{
169 int l1;
170 int l2;
171
172 l1 = strlen(s1);
173 l2 = strlen(s2);
174 if (l2 > l1)
175 return ((char *)NULL);
176
177 if (strcmp(&s1[l1 - l2], s2) == 0)
178 return (&s1[l1 - l2]);
179 return ((char *)NULL);
180}
181
182LOCAL void
184 struct stat *st;
185{
186 int adjust_modes = 0;
187
188 if (S_ISREG(st->st_mode))
189 adjust_modes = rationalize_filemode;
190 else if (S_ISDIR(st->st_mode))
191 adjust_modes = rationalize_dirmode;
192 else
193 adjust_modes = (rationalize_filemode || rationalize_dirmode);
194
195 /*
196 * If rationalizing, override the uid and gid, since the
197 * originals will only be useful on the author's system.
198 */
199 if (rationalize_uid)
200 st->st_uid = uid_to_use;
201 if (rationalize_gid)
202 st->st_gid = gid_to_use;
203
204 if (adjust_modes) {
205
206 if (S_ISREG(st->st_mode) && (filemode_to_use != 0)) {
208 } else if (S_ISDIR(st->st_mode) && (dirmode_to_use != 0)) {
210 } else {
211 /*
212 * Make sure the file modes make sense. Turn
213 * on all read bits. Turn on all exec/search
214 * bits if any exec/search bit is set. Turn
215 * off all write bits, and all special mode
216 * bits (on a r/o fs lock bits are useless,
217 * and with uid+gid 0 don't want set-id bits,
218 * either).
219 */
220
221 st->st_mode |= 0444;
222#if !defined(_WIN32) && !defined(__DJGPP__) /* make all file "executable" */
223 if (st->st_mode & 0111)
224#endif
225 st->st_mode |= 0111;
226 st->st_mode &= ~07222;
227 }
228 }
229}
230
231EXPORT int
233 char *path;
234 struct stat *st;
235{
236 int result = stat(path, st);
237
238 if (result >= 0 && rationalize)
239 stat_fix(st);
240 return (result);
241}
242
243EXPORT int
245 char *path;
246 struct stat *st;
247{
248 int result = lstat(path, st);
249
250 if (result >= 0 && rationalize)
251 stat_fix(st);
252 return (result);
253}
254
255LOCAL int
257 struct directory *this_dir;
258{
259 struct directory_entry *s_entry;
260 struct directory_entry *s_entry1;
261 struct directory_entry *table;
262 int count;
263 int d1;
264 int d2;
265 int d3;
266 register int new_reclen;
267 char *c;
268 int status = 0;
269 int tablesize = 0;
270 char newname[MAX_ISONAME+1];
271 char rootname[MAX_ISONAME+1];
272 char extname[MAX_ISONAME+1];
273
274 /*
275 * Here we can take the opportunity to toss duplicate entries from the
276 * directory.
277 */
278 /* ignore if it's hidden */
279 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) {
280 return (0);
281 }
282 table = NULL;
283
285
286 /*
287 * If we had artificially created this directory, then we might be
288 * missing the required '.' entries. Create these now if we need
289 * them.
290 */
291 if ((this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) !=
293 attach_dot_entries(this_dir, NULL, NULL);
294 }
296 s_entry = this_dir->contents;
297 while (s_entry) {
298#ifdef USE_LARGEFILES
299 /*
300 * Skip all but the last extent from a multi extent file,
301 * we like them all have the same name.
302 */
303 if ((s_entry->de_flags & MULTI_EXTENT) &&
304 (s_entry->isorec.flags[0] & ISO_MULTIEXTENT)) {
305 s_entry = s_entry->next;
306 continue;
307 }
308#endif
309 /* ignore if it's hidden */
310 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
311 s_entry = s_entry->next;
312 continue;
313 }
314 /*
315 * First assume no conflict, and handle this case
316 */
317 if (!(s_entry1 = find_file_hash(s_entry->isorec.name))) {
318 add_file_hash(s_entry);
319 s_entry = s_entry->next;
320 continue;
321 }
322#ifdef APPLE_HYB
323 /*
324 * if the pair are associated, then skip (as they have the
325 * same name!)
326 */
327 if (apple_both && s_entry1->assoc &&
328 s_entry1->assoc == s_entry) {
329 s_entry = s_entry->next;
330 continue;
331 }
332#endif /* APPLE_HYB */
333
334 if (s_entry1 == s_entry) {
336 _("Fatal goof, file '%s' already in hash table.\n"),
337 s_entry->isorec.name);
338 }
339 /*
340 * OK, handle the conflicts. Try substitute names until we
341 * come up with a winner
342 */
343 strlcpy(rootname, s_entry->isorec.name, sizeof (rootname));
344 /*
345 * Strip off the non-significant part of the name so that we
346 * are left with a sensible root filename. If we don't find
347 * a '.', then try a ';'.
348 */
349 c = strchr(rootname, '.');
350 /*
351 * In case we ever allow more than on dot, only modify the
352 * section past the last dot if the file name starts with a
353 * dot.
354 */
355 if (c != NULL && c == rootname && c != strrchr(rootname, '.')) {
356 c = strrchr(rootname, '.');
357 }
358 extname[0] = '\0'; /* In case we have no ext. */
359 if (c) {
360 strlcpy(extname, c, sizeof (extname));
361 *c = 0; /* Cut off complete ext. */
362 } else {
363 /*
364 * Could not find any '.'.
365 */
366 c = strchr(rootname, ';');
367 if (c) {
368 *c = 0; /* Cut off version number */
369 }
370 }
371 c = strchr(extname, ';');
372 if (c) {
373 *c = 0; /* Cut off version number */
374 }
375 d1 = strlen(rootname);
377 d2 = strlen(extname);
378 /*
379 * 31/37 chars minus the 3 characters we are
380 * appending below to create unique filenames.
381 */
382 if ((d1 + d2) > (iso9660_namelen - 3))
383 rootname[iso9660_namelen - 3 - d2] = 0;
384 } else {
385 if (d1 > 5)
386 rootname[5] = 0;
387 }
388 new_reclen = strlen(rootname);
389 sprintf(newname, "%s000%s%s",
390 rootname,
391 extname,
392 ((s_entry->isorec.flags[0] & ISO_DIRECTORY) ||
393 omit_version_number ? "" : ";1"));
394
395 for (d1 = 0; d1 < 36; d1++) {
396 for (d2 = 0; d2 < 36; d2++) {
397 for (d3 = 0; d3 < 36; d3++) {
398 newname[new_reclen + 0] =
399 (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10);
400 newname[new_reclen + 1] =
401 (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10);
402 newname[new_reclen + 2] =
403 (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10);
404 if (debug)
405 error(_("NEW name '%s'\n"), newname);
406
407#ifdef VMS
408 /* Sigh. VAXCRTL seems to be broken here */
409 {
410 int ijk = 0;
411
412 while (newname[ijk]) {
413 if (newname[ijk] == ' ')
414 newname[ijk] = '0';
415 ijk++;
416 }
417 }
418#endif
419
420 if (!find_file_hash(newname))
421 goto got_valid_name;
422 }
423 }
424 }
425
426 /*
427 * If we fell off the bottom here, we were in real trouble.
428 */
430 _("Unable to generate unique name for file %s\n"),
431 s_entry->name);
432
433got_valid_name:
434 /*
435 * OK, now we have a good replacement name. Now decide which
436 * one of these two beasts should get the name changed
437 */
438 if (s_entry->priority < s_entry1->priority) {
439 if (verbose > 0) {
440 fprintf(stderr, _("Using %s for %s%s%s (%s)\n"),
441 newname,
442 this_dir->whole_name, SPATH_SEPARATOR,
443 s_entry->name, s_entry1->name);
444 }
445
446 s_entry->isorec.name_len[0] = strlen(newname);
447 new_reclen = offsetof(struct iso_directory_record,
448 name[0]) +
449 strlen(newname);
450 if (use_XA || use_RockRidge) {
451 if (new_reclen & 1)
452 new_reclen++; /* Pad to an even byte */
453 new_reclen += s_entry->rr_attr_size;
454 }
455 if (new_reclen & 1)
456 new_reclen++; /* Pad to an even byte */
457 s_entry->isorec.length[0] = new_reclen;
458 strcpy(s_entry->isorec.name, newname);
459#ifdef USE_LARGEFILES
460 if (s_entry->de_flags & MULTI_EXTENT) {
461 struct directory_entry *s_e;
462
463 /*
464 * Copy over the new name to all other entries
465 */
466 for (s_e = s_entry->mxroot;
467 s_e && s_e->mxroot == s_entry->mxroot;
468 s_e = s_e->next) {
469 s_e->isorec.length[0] = new_reclen;
470 s_e->isorec.name_len[0] = s_entry->isorec.name_len[0];
471 strcpy(s_e->isorec.name, newname);
472 }
473 }
474#endif
475#ifdef APPLE_HYB
476 /*
477 * Has resource fork - needs new name
478 */
479 if (apple_both && s_entry->assoc) {
480 struct directory_entry *s_entry2 =
481 s_entry->assoc;
482
483 /*
484 * resource fork name *should* be the same as
485 * the data fork
486 */
487 s_entry2->isorec.name_len[0] =
488 s_entry->isorec.name_len[0];
489 strcpy(s_entry2->isorec.name,
490 s_entry->isorec.name);
491 s_entry2->isorec.length[0] = new_reclen;
492 }
493#endif /* APPLE_HYB */
494 } else {
495 delete_file_hash(s_entry1);
496 if (verbose > 0) {
497 fprintf(stderr, _("Using %s for %s%s%s (%s)\n"),
498 newname,
499 this_dir->whole_name, SPATH_SEPARATOR,
500 s_entry1->name, s_entry->name);
501 }
502 s_entry1->isorec.name_len[0] = strlen(newname);
503 new_reclen = offsetof(struct iso_directory_record,
504 name[0]) +
505 strlen(newname);
506 if (use_XA || use_RockRidge) {
507 if (new_reclen & 1)
508 new_reclen++; /* Pad to an even byte */
509 new_reclen += s_entry1->rr_attr_size;
510 }
511 if (new_reclen & 1)
512 new_reclen++; /* Pad to an even byte */
513 s_entry1->isorec.length[0] = new_reclen;
514 strcpy(s_entry1->isorec.name, newname);
515#ifdef USE_LARGEFILES
516 if (s_entry1->de_flags & MULTI_EXTENT) {
517 struct directory_entry *s_e;
518
519 /*
520 * Copy over the new name to all other entries
521 */
522 for (s_e = s_entry1->mxroot;
523 s_e && s_e->mxroot == s_entry1->mxroot;
524 s_e = s_e->next) {
525 s_e->isorec.length[0] = new_reclen;
526 s_e->isorec.name_len[0] = s_entry1->isorec.name_len[0];
527 strcpy(s_e->isorec.name, newname);
528 }
529 }
530#endif
531 add_file_hash(s_entry1);
532#ifdef APPLE_HYB
533 /*
534 * Has resource fork - needs new name
535 */
536 if (apple_both && s_entry1->assoc) {
537 struct directory_entry *s_entry2 =
538 s_entry1->assoc;
539
540 /*
541 * resource fork name *should* be the same as
542 * the data fork
543 */
544 s_entry2->isorec.name_len[0] =
545 s_entry1->isorec.name_len[0];
546 strcpy(s_entry2->isorec.name,
547 s_entry1->isorec.name);
548 s_entry2->isorec.length[0] = new_reclen;
549 }
550#endif /* APPLE_HYB */
551 }
552 add_file_hash(s_entry);
553 s_entry = s_entry->next;
554 }
555
556 if (generate_tables &&
558 (reloc_dir != this_dir) &&
559 (this_dir->extent == 0)) {
560 /*
561 * First we need to figure out how big this table is
562 */
563 for (s_entry = this_dir->contents; s_entry;
564 s_entry = s_entry->next) {
565 if (strcmp(s_entry->name, ".") == 0 ||
566 strcmp(s_entry->name, "..") == 0)
567 continue;
568#ifdef APPLE_HYB
569 /*
570 * Skip table entry for the resource fork
571 */
572 if (apple_both &&
573 (s_entry->isorec.flags[0] & ISO_ASSOCIATED))
574 continue;
575#endif /* APPLE_HYB */
576 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
577 continue;
578 if (s_entry->table) {
579 /*
580 * Max namelen, a space before and a space
581 * after the iso filename.
582 */
583 tablesize += MAX_ISONAME + 2 +
584 strlen(s_entry->table);
585 }
586 }
587 }
588 if (tablesize > 0) {
589 table = (struct directory_entry *)
590 e_malloc(sizeof (struct directory_entry));
591 memset(table, 0, sizeof (struct directory_entry));
592 table->table = NULL;
593 table->next = this_dir->contents;
594 this_dir->contents = table;
595
596 table->filedir = root;
597 table->isorec.flags[0] = ISO_FILE;
598 table->priority = 32768;
599 iso9660_date(table->isorec.date, fstatbuf.st_mtime);
600 table->inode = TABLE_INODE;
601 table->dev = UNCACHED_DEVICE;
602 set_723(table->isorec.volume_sequence_number,
604 set_733((char *)table->isorec.size, tablesize);
605 table->size = tablesize;
606 table->filedir = this_dir;
607 if (jhide_trans_tbl)
608 table->de_flags |= INHIBIT_JOLIET_ENTRY;
609 /*
610 * Always hide transtable from UDF tree.
611 */
612 table->de_flags |= INHIBIT_UDF_ENTRY;
613/* table->name = e_strdup("<translation table>");*/
615 /*
616 * We use sprintf() to create the strings, for this reason
617 * we need to add one byte for the null character at the
618 * end of the string even though we don't use it.
619 */
620 table->table = (char *)e_malloc(ISO_ROUND_UP(tablesize)+1);
621 memset(table->table, 0, ISO_ROUND_UP(tablesize)+1);
623
624 if (use_XA || use_RockRidge) {
625 fstatbuf.st_mode = 0444 | S_IFREG;
626 fstatbuf.st_nlink = 1;
629 &fstatbuf, &fstatbuf, 0);
630 }
631 }
632 /*
633 * We have now chosen the 8.3 names and we should now know the length
634 * of every entry in the directory.
635 */
636 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) {
637 /* skip if it's hidden */
638 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
639 continue;
640 }
641 new_reclen = strlen(s_entry->isorec.name);
642
643 /*
644 * First update the path table sizes for directories.
645 */
646 if (s_entry->isorec.flags[0] & ISO_DIRECTORY) {
647 if (strcmp(s_entry->name, ".") != 0 &&
648 strcmp(s_entry->name, "..") != 0) {
649 path_table_size += new_reclen +
651 name[0]);
652 if (new_reclen & 1)
654 } else {
655 new_reclen = 1;
656 if (this_dir == root && strlen(s_entry->name)
657 == 1) {
658 path_table_size += new_reclen +
660 name[0]);
661 }
662 }
663 }
664 if (path_table_size & 1)
665 path_table_size++; /* For odd lengths we pad */
666 s_entry->isorec.name_len[0] = new_reclen;
667
668 new_reclen += offsetof(struct iso_directory_record, name[0]);
669
670 if (new_reclen & 1)
671 new_reclen++;
672
673 new_reclen += s_entry->rr_attr_size;
674
675 if (new_reclen & 1)
676 new_reclen++;
677
678 if (new_reclen > 0xff) {
680 _("Fatal error - RR overflow (reclen %d) for file %s\n"),
681 new_reclen,
682 s_entry->name);
683 }
684 s_entry->isorec.length[0] = new_reclen;
685 }
686
687 status = sort_directory(&this_dir->contents, (reloc_dir == this_dir));
688 if (status > 0) {
689 errmsgno(EX_BAD, _("Unable to sort directory %s\n"),
690 this_dir->whole_name);
692 _("If there was more than one directory type argument to mkisofs\n"));
694 _("use -graft-points to create different target directory names.\n"));
695 }
696 /*
697 * If we are filling out a TRANS.TBL, generate the entries that will
698 * go in the thing.
699 */
700 if (table) {
701 count = 0;
702 for (s_entry = this_dir->contents; s_entry;
703 s_entry = s_entry->next) {
704 if (s_entry == table)
705 continue;
706 if (!s_entry->table)
707 continue;
708 if (strcmp(s_entry->name, ".") == 0 ||
709 strcmp(s_entry->name, "..") == 0)
710 continue;
711#ifdef APPLE_HYB
712 /*
713 * Skip table entry for the resource fork
714 */
715 if (apple_both &&
716 (s_entry->isorec.flags[0] & ISO_ASSOCIATED))
717 continue;
718#endif /* APPLE_HYB */
719 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
720 continue;
721 /*
722 * Warning: we cannot use the return value of sprintf
723 * because old BSD based sprintf() implementations
724 * will return a pointer to the result instead of a
725 * count.
726 * Old mkiofs introduced a space after the iso
727 * filename to make parsing TRANS.TBL easier.
728 */
729 sprintf(table->table + count, "%c %-*s%s",
730 s_entry->table[0],
731 MAX_ISONAME + 1,
732 s_entry->isorec.name, s_entry->table + 1);
733 count += strlen(table->table + count);
734 free(s_entry->table);
735 /*
736 * for a memory file, set s_entry->table to the
737 * correct data - which is stored in
738 * s_entry->whole_name
739 */
740 if (s_entry->de_flags & MEMORY_FILE) {
741 s_entry->table = s_entry->whole_name;
742 s_entry->whole_name = NULL;
743 } else {
744 s_entry->table = NULL;
745 }
746 }
747
748 if (count != tablesize) {
750 _("Translation table size mismatch %d %d\n"),
751 count, tablesize);
752 }
753 }
754 /*
755 * Now go through the directory and figure out how large this one will
756 * be. Do not split a directory entry across a sector boundary
757 */
758 s_entry = this_dir->contents;
759 this_dir->ce_bytes = 0;
760 while (s_entry) {
761 /* skip if it's hidden */
762 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
763 s_entry = s_entry->next;
764 continue;
765 }
766 new_reclen = s_entry->isorec.length[0];
767 if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen
768 >= SECTOR_SIZE)
769
770 this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) &
771 ~(SECTOR_SIZE - 1);
772 this_dir->size += new_reclen;
773
774 /*
775 * See if continuation entries were used on disc
776 */
777 if (use_RockRidge &&
778 s_entry->rr_attr_size != s_entry->total_rr_attr_size) {
779 unsigned char *pnt;
780 int len;
781 int nbytes;
782
783 pnt = s_entry->rr_attributes;
784 len = s_entry->total_rr_attr_size;
785 pnt = parse_xa(pnt, &len, 0);
786/* pnt = parse_xa(pnt, &len, s_entry);*/
787
788 /*
789 * We make sure that each continuation entry record is
790 * not split across sectors, but each file could in
791 * theory have more than one CE, so we scan through
792 * and figure out what we need.
793 */
794 while (len > 3) {
795 if (pnt[0] == 'C' && pnt[1] == 'E') {
796 nbytes = get_733((char *)pnt + 20);
797
798 if ((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
800 this_dir->ce_bytes =
801 ISO_ROUND_UP(this_dir->ce_bytes);
802 /*
803 * Now store the block in the
804 * ce buffer
805 */
806 this_dir->ce_bytes += nbytes;
807 if (this_dir->ce_bytes & 1)
808 this_dir->ce_bytes++;
809 }
810 len -= pnt[2];
811 pnt += pnt[2];
812 }
813 }
814 s_entry = s_entry->next;
815 }
816 return (status);
817}
818
819LOCAL void
821{
822 time_t current_time;
823 struct directory_entry *s_entry;
824
825 /*
826 * Create an entry for our internal tree
827 */
828 time(&current_time);
829 reloc_dir = (struct directory *)
830 e_malloc(sizeof (struct directory));
831 memset(reloc_dir, 0, sizeof (struct directory));
832 reloc_dir->parent = root;
833 reloc_dir->next = root->subdir;
834 root->subdir = reloc_dir;
835 reloc_dir->depth = 1;
836 if (hide_rr_moved) {
837 reloc_dir->whole_name = e_strdup("./.rr_moved");
838 reloc_dir->de_name = e_strdup(".rr_moved");
839 } else {
840 reloc_dir->whole_name = e_strdup("./rr_moved");
841 reloc_dir->de_name = e_strdup("rr_moved");
842 }
843 reloc_dir->de_path = reloc_dir->de_name;
844 reloc_dir->extent = 0;
845
846
847 /*
848 * Now create an actual directory entry
849 */
850 s_entry = (struct directory_entry *)
851 e_malloc(sizeof (struct directory_entry));
852 memset(s_entry, 0, sizeof (struct directory_entry));
853 s_entry->next = root->contents;
854 reloc_dir->self = s_entry;
855
856 /*
857 * The rr_moved entry will not appear in the Joliet nor the UDF tree.
858 */
859 reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
860 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
861
862 reloc_dir->dir_flags |= INHIBIT_UDF_ENTRY;
863 s_entry->de_flags |= INHIBIT_UDF_ENTRY;
864
865 root->contents = s_entry;
866 root->contents->name = e_strdup(reloc_dir->de_name);
867 root->contents->filedir = root;
868 root->contents->isorec.flags[0] = ISO_DIRECTORY;
869 root->contents->priority = 32768;
870 iso9660_date(root->contents->isorec.date, current_time);
871 root->contents->inode = UNCACHED_INODE;
872 root->contents->dev = UNCACHED_DEVICE;
873 set_723(root->contents->isorec.volume_sequence_number,
875 iso9660_file_length(reloc_dir->de_name, root->contents, 1);
876
878
879 if (use_XA || use_RockRidge) {
880 fstatbuf.st_mode = 0555 | S_IFDIR;
881 fstatbuf.st_nlink = 2;
883 hide_rr_moved ? ".rr_moved" : "rr_moved",
884 s_entry, &fstatbuf, &fstatbuf, NEED_RE);
885 };
886
887 /*
888 * Now create the . and .. entries in rr_moved
889 * Now create an actual directory entry
890 */
891 if (root_statbuf.st_nlink == 0)
894}
895
896/*
897 * Function: attach_dot_entries
898 *
899 * Purpose: Create . and .. entries for a new directory.
900 *
901 * Notes: Only used for artificial directories that
902 * we are creating.
903 */
904EXPORT void
905attach_dot_entries(dirnode, this_stat, parent_stat)
906 struct directory *dirnode;
907 struct stat *this_stat;
908 struct stat *parent_stat;
909{
910 struct directory_entry *s_entry;
911 struct directory_entry *orig_contents;
912 int deep_flag = 0;
913
915 fstatbuf.st_mode = new_dir_mode | S_IFDIR;
916 fstatbuf.st_nlink = 2;
917 if (parent_stat == NULL)
918 parent_stat = &fstatbuf;
919 if (this_stat == NULL)
920 this_stat = &fstatbuf;
921
922 orig_contents = dirnode->contents;
923
924 if ((dirnode->dir_flags & DIR_HAS_DOTDOT) == 0) {
925 if (dirnode->parent &&
926 dirnode->parent == reloc_dir) {
927 deep_flag = NEED_PL;
928 }
929 s_entry = (struct directory_entry *)
930 e_malloc(sizeof (struct directory_entry));
931 memcpy(s_entry, dirnode->self,
932 sizeof (struct directory_entry));
933#ifdef APPLE_HYB
934 if (dirnode->self->hfs_ent) {
935 s_entry->hfs_ent = (hfsdirent *)
936 e_malloc(sizeof (hfsdirent));
937 memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent,
938 sizeof (hfsdirent));
939 }
940#endif
941 s_entry->name = e_strdup("..");
942 s_entry->whole_name = NULL;
943 s_entry->isorec.name_len[0] = 1;
944 s_entry->isorec.flags[0] = ISO_DIRECTORY;
945 iso9660_file_length("..", s_entry, 1);
946 iso9660_date(s_entry->isorec.date, parent_stat->st_mtime);
947 set_723(s_entry->isorec.volume_sequence_number,
949 set_733(s_entry->isorec.size, SECTOR_SIZE);
950 memset(s_entry->isorec.extent, 0, 8);
951 s_entry->filedir = dirnode->parent;
952
953 dirnode->contents = s_entry;
954 dirnode->contents->next = orig_contents;
955 orig_contents = s_entry;
956
957 if (use_XA || use_RockRidge) {
959 "..", s_entry,
960 parent_stat,
961 parent_stat, deep_flag);
962 }
963 dirnode->dir_flags |= DIR_HAS_DOTDOT;
964 }
965 deep_flag = 0;
966 if ((dirnode->dir_flags & DIR_HAS_DOT) == 0) {
967 s_entry = (struct directory_entry *)
968 e_malloc(sizeof (struct directory_entry));
969 memcpy(s_entry, dirnode->self,
970 sizeof (struct directory_entry));
971#ifdef APPLE_HYB
972 if (dirnode->self->hfs_ent) {
973 s_entry->hfs_ent = (hfsdirent *)
974 e_malloc(sizeof (hfsdirent));
975 memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent,
976 sizeof (hfsdirent));
977 }
978#endif
979 s_entry->name = e_strdup(".");
980 s_entry->whole_name = NULL;
981 s_entry->isorec.name_len[0] = 1;
982 s_entry->isorec.flags[0] = ISO_DIRECTORY;
983 iso9660_file_length(".", s_entry, 1);
984 iso9660_date(s_entry->isorec.date, this_stat->st_mtime);
985 set_723(s_entry->isorec.volume_sequence_number,
987 set_733(s_entry->isorec.size, SECTOR_SIZE);
988 memset(s_entry->isorec.extent, 0, 8);
989 s_entry->filedir = dirnode;
990
991 dirnode->contents = s_entry;
992 dirnode->contents->next = orig_contents;
993
994 if (use_XA || use_RockRidge) {
995 if (dirnode == root) {
996 deep_flag |= NEED_CE | NEED_SP; /* For extension record */
997 }
999 ".", s_entry,
1000 this_stat, this_stat, deep_flag);
1001 }
1002 dirnode->dir_flags |= DIR_HAS_DOT;
1003 }
1004}
1005
1006EXPORT char *
1008 unsigned char *pnt;
1009 int len;
1010 char *attr_type;
1011{
1012 pnt = parse_xa(pnt, &len, 0);
1013 while (len >= 4) {
1014 if (pnt[3] != 1 && pnt[3] != 2) {
1016 _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
1017 pnt[3], pnt[0], pnt[1], pnt[0], pnt[1]);
1018 }
1019 if (pnt[2] < 4) {
1021 _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
1022 pnt[2], pnt, pnt[0], pnt[1]);
1023 return (NULL);
1024 }
1025 if (strncmp((char *)pnt, attr_type, 2) == 0)
1026 return ((char *)pnt);
1027 else if (strncmp((char *)pnt, "ST", 2) == 0)
1028 return (NULL);
1029 len -= pnt[2];
1030 pnt += pnt[2];
1031 }
1032 return (NULL);
1033}
1034
1035EXPORT void
1037{
1038 struct directory_entry *s_entry;
1039 struct directory_entry *s_entry1;
1040 struct directory *d_entry;
1041
1042 /*
1043 * If the reloc_dir is hidden (empty), then return
1044 */
1045 if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
1046 return;
1047
1048 s_entry = reloc_dir->contents;
1049 s_entry = s_entry->next->next; /* Skip past . and .. */
1050 for (; s_entry; s_entry = s_entry->next) {
1051 /* skip if it's hidden */
1052 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
1053 continue;
1054 }
1055 d_entry = reloc_dir->subdir;
1056 while (d_entry) {
1057 if (d_entry->self == s_entry)
1058 break;
1059 d_entry = d_entry->next;
1060 };
1061 if (!d_entry) {
1063 _("Unable to locate directory parent\n"));
1064 };
1065
1066 if (s_entry->filedir != NULL && s_entry->parent_rec != NULL) {
1067 char *rr_attr;
1068
1069 /*
1070 * First fix the PL pointer in the directory in the
1071 * rr_reloc dir
1072 */
1073 s_entry1 = d_entry->contents->next;
1074
1075/* set_733((char *) s_entry1->rr_attributes +*/
1076/* s_entry1->total_rr_attr_size - 8,*/
1077/* s_entry->filedir->extent); */
1078 /*
1079 * The line above won't work when entry was read from
1080 * the previous session, because if total_rr_attr_size
1081 * was odd when recording previous session, now we have
1082 * total_rr_attr_size off by 1 due to padding.
1083 *
1084 * So, just search for the attributes by name
1085 */
1086 rr_attr = find_rr_attribute(s_entry1->rr_attributes,
1087 s_entry1->total_rr_attr_size, "PL");
1088 if (rr_attr != NULL)
1089 set_733(rr_attr + 4, s_entry->filedir->extent);
1090
1091
1092 /*
1093 * Now fix the CL pointer
1094 */
1095 s_entry1 = s_entry->parent_rec;
1096
1097/* set_733((char *) s_entry1->rr_attributes +*/
1098/* s_entry1->total_rr_attr_size - 8, d_entry->extent); */
1099 rr_attr = find_rr_attribute(s_entry1->rr_attributes,
1100 s_entry1->total_rr_attr_size, "CL");
1101 if (rr_attr != NULL)
1102 set_733(rr_attr + 4, d_entry->extent);
1103 }
1104 s_entry->filedir = reloc_dir; /* Now we can fix this */
1105 }
1106 /*
1107 * We would need to modify the NLINK terms in the assorted root
1108 * directory records to account for the presence of the RR_MOVED
1109 * directory. We do not do this here because we do it later when
1110 * we correct the link count for all direstories in the tree.
1111 */
1112
1113
1115}
1116
1117LOCAL void
1118dir_nesting_warn(this_dir, path, contflag)
1119 struct directory *this_dir;
1120 char *path;
1121 int contflag;
1122{
1123 static BOOL did_hint = FALSE;
1124
1126 _("Directories too deep for '%s' (%d) max is %d%s.\n"),
1127 path, this_dir->depth, RR_relocation_depth,
1128 contflag?_("; ignored - continuing"):"");
1129 if (!did_hint) {
1130 did_hint = TRUE;
1131 errmsgno(EX_BAD, _("To include the complete directory tree,\n"));
1132 errmsgno(EX_BAD, _("use Rock Ridge extensions via -R or -r,\n"));
1133 errmsgno(EX_BAD, _("or allow deep ISO9660 directory nesting via -D.\n"));
1134 }
1135}
1136
1137/*
1138 * Function: scan_directory_tree
1139 *
1140 * Purpose: Walk through a directory on the local machine
1141 * filter those things we don't want to include
1142 * and build our representation of a dir.
1143 *
1144 * Notes:
1145 */
1146EXPORT int
1148 struct directory *this_dir;
1149 char *path;
1150 struct directory_entry *de;
1151{
1152 DIR *current_dir;
1153 char whole_path[2*PATH_MAX]; /* Avoid stat buffer overflow */
1154 struct dirent *d_entry;
1155 int dflag;
1156extern BOOL nodesc;
1157
1158 if (nodesc)
1159 return (1);
1160
1161 if (verbose > 1) {
1162 fprintf(stderr, _("Scanning %s\n"), path);
1163 }
1164/*#define check_needed*/
1165#ifdef check_needed
1166 /*
1167 * Trying to use this to avoid directory loops from hard links
1168 * or followed symlinks does not work. It would prevent us from
1169 * implementing merge directories.
1170 */
1171 if (this_dir->dir_flags & DIR_WAS_SCANNED) {
1172 fprintf(stderr, _("Already scanned directory %s\n"), path);
1173 return (1); /* It's a directory */
1174 }
1175#endif
1176 this_dir->dir_flags |= DIR_WAS_SCANNED;
1177
1178 errno = 0; /* Paranoia */
1179 current_dir = opendir(path);
1180 d_entry = NULL;
1181
1182 /*
1183 * Apparently NFS sometimes allows you to open the directory, but then
1184 * refuses to allow you to read the contents. Allow for this
1185 */
1186 if (current_dir) {
1187 errno = 0;
1188 d_entry = readdir(current_dir);
1189 }
1190
1191 if (!current_dir || (!d_entry && errno != 0)) {
1192 int ret = 1;
1193
1194 errmsg(_("Unable to open directory %s\n"), path);
1195
1196 if (errno == ENOTDIR) {
1197 /*
1198 * Mark as not a directory
1199 */
1200 de->isorec.flags[0] &= ~ISO_DIRECTORY;
1201 ret = 0;
1202 }
1203 if (current_dir)
1204 closedir(current_dir);
1205 return (ret);
1206 }
1207
1208 /*
1209 * Set up the struct for the current directory, and insert it into
1210 * the tree
1211 */
1212#ifdef VMS
1213 vms_path_fixup(path);
1214#endif
1215
1216 /*
1217 * if entry for this sub-directory is hidden, then hide this directory
1218 */
1220 this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
1221
1223 this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
1224
1225#ifdef SORTING
1226 /*
1227 * set any sort weighting from it's own directory entry - if a
1228 * directory is given a weighting, then all the contents will use
1229 * this as the default weighting
1230 */
1231 this_dir->sort = de->sort;
1232#endif /* SORTING */
1233
1234 /*
1235 * Now we scan the directory itself, and look at what is inside of it.
1236 */
1237 whole_path[0] = '\0';
1238 dflag = -2;
1239 while (1 == 1) {
1240 char *d_name;
1241
1242 if (dflag < 0) {
1243 /*
1244 * Some filesystems do not deliver "." and ".." at all,
1245 * others (on Linux) deliver them in the wrong order.
1246 * Make sure we add "." and ".." before all other
1247 * entries.
1248 */
1249 if (dflag < -1)
1250 d_name = ".";
1251 else
1252 d_name = "..";
1253 dflag++;
1254 } else {
1255 /*
1256 * The first time through, skip this, since we already
1257 * asked for the first entry when we opened the
1258 * directory.
1259 */
1260 if (dflag > 0) {
1261 d_entry = readdir(current_dir);
1262 } else {
1263 dflag++;
1264 }
1265 if (!d_entry)
1266 break;
1267 d_name = d_entry->d_name;
1268 }
1269
1270 /*
1271 * OK, got a valid entry
1272 *
1273 * If we do not want all files, then pitch the backups.
1274 */
1275 if (!all_files) {
1276 if (strchr(d_name, '~') ||
1277 strchr(d_name, '#') ||
1278 rstr(d_name, ".bak")) {
1279 if (verbose > 0) {
1281 _("Ignoring file %s\n"),
1282 d_name);
1283 }
1284 continue;
1285 }
1286 }
1287#ifdef APPLE_HYB
1288 if (apple_both) {
1289 /*
1290 * exclude certain HFS type files/directories for the
1291 * time being
1292 */
1293 if (hfs_exclude(d_name))
1294 continue;
1295 }
1296#endif /* APPLE_HYB */
1297
1298 if (strlen(path) + strlen(d_name) + 2 > sizeof (whole_path)) {
1299 errmsgno(EX_BAD, _("Path name %s/%s too long.\n"),
1300 path, d_name);
1301 comerrno(EX_BAD, _("Overflow of stat buffer\n"));
1302 };
1303
1304 /*
1305 * Generate the complete ASCII path for this file
1306 */
1307 strlcpy(whole_path, path, sizeof (whole_path));
1308#ifndef VMS
1309 if (whole_path[strlen(whole_path) - 1] != '/')
1310 strcat(whole_path, "/");
1311#endif
1312 strcat(whole_path, d_name);
1313
1314 /*
1315 * Should we exclude this file ?
1316 * Do no check "." and ".."
1317 */
1318 if (!(d_name[0] == '.' && (d_name[1] == '\0' ||
1319 (d_name[1] == '.' && d_name[2] == '\0'))) &&
1320 (matches(d_name) || matches(whole_path))) {
1321 if (verbose > 1) {
1323 _("Excluded by match: %s\n"), whole_path);
1324 }
1325 continue;
1326 }
1327 if (generate_tables &&
1328 strcmp(d_name, trans_tbl) == 0) {
1329 /*
1330 * Ignore this entry. We are going to be generating
1331 * new versions of these files, and we need to ignore
1332 * any originals that we might have found.
1333 */
1334 if (verbose > 1) {
1335 fprintf(stderr, _("Excluded: %s\n"), whole_path);
1336 }
1337 continue;
1338 }
1339 /*
1340 * If we already have a '.' or a '..' entry, then don't insert
1341 * new ones.
1342 */
1343 if (strcmp(d_name, ".") == 0 &&
1344 this_dir->dir_flags & DIR_HAS_DOT) {
1345 continue;
1346 }
1347 if (strcmp(d_name, "..") == 0 &&
1348 this_dir->dir_flags & DIR_HAS_DOTDOT) {
1349 continue;
1350 }
1351#if 0
1352 if (verbose > 1)
1353 fprintf(stderr, "%s\n", whole_path);
1354#endif
1355 /*
1356 * This actually adds the entry to the directory in question.
1357 */
1358 insert_file_entry(this_dir, whole_path, d_name, NULL, 0);
1359 }
1360 closedir(current_dir);
1361
1362#ifdef APPLE_HYB
1363 /*
1364 * if we cached the HFS info stuff for this directory, then delete it
1365 */
1366 if (this_dir->hfs_info) {
1367 del_hfs_info(this_dir->hfs_info);
1368 this_dir->hfs_info = 0;
1369 }
1370#endif /* APPLE_HYB */
1371
1372 return (1);
1373}
1374
1375LOCAL struct directory_entry *
1376dup_relocated_dir(this_dir, s_entry, whole_path, short_name, statp)
1377 struct directory *this_dir;
1378 struct directory_entry *s_entry;
1379 char *whole_path;
1380 char *short_name;
1381 struct stat *statp;
1382{
1383 struct directory_entry *s_entry1;
1384
1385 if (!reloc_dir)
1387 init_fstatbuf();
1388
1389 /*
1390 * Replicate the entry for this directory. The old one will
1391 * stay where it is, and it will be neutered so that it no
1392 * longer looks like a directory. The new one will look like
1393 * a directory, and it will be put in the reloc_dir.
1394 */
1395 s_entry1 = (struct directory_entry *)
1396 e_malloc(sizeof (struct directory_entry));
1397 memcpy(s_entry1, s_entry, sizeof (struct directory_entry));
1398 s_entry1->table = NULL;
1399 s_entry1->name = e_strdup(short_name);
1400 s_entry1->whole_name = e_strdup(whole_path);
1401 s_entry1->next = reloc_dir->contents;
1402 reloc_dir->contents = s_entry1;
1403 s_entry1->priority = 32768;
1404 s_entry1->parent_rec = this_dir->contents;
1405 set_723(s_entry1->isorec.volume_sequence_number,
1407 s_entry1->filedir = this_dir;
1408 iso9660_date(s_entry1->isorec.date, fstatbuf.st_mtime);
1409
1410 if (use_XA || use_RockRidge) {
1411 generate_xa_rr_attributes(whole_path,
1412 short_name, s_entry1,
1413 statp, statp, NEED_RE);
1414 }
1415
1416 statp->st_size = (off_t)0;
1417 statp->st_mode &= 0777;
1418 set_733((char *)s_entry->isorec.size, 0);
1419 s_entry->size = 0;
1420 s_entry->isorec.flags[0] = ISO_FILE;
1421 s_entry->inode = UNCACHED_INODE;
1422 s_entry->dev = UNCACHED_DEVICE;
1423 s_entry->de_flags |= RELOCATED_DIRECTORY;
1424
1425 return (s_entry1);
1426}
1427
1428
1429/*
1430 * Function: insert_file_entry
1431 *
1432 * Purpose: Insert one entry into our directory node.
1433 *
1434 * Note:
1435 * This function inserts a single entry into the directory. It
1436 * is assumed that all filtering and decision making regarding what
1437 * we want to include has already been made, so the purpose of this
1438 * is to insert one entry (file, link, dir, etc), into this directory.
1439 * Note that if the entry is a dir (or if we are following links,
1440 * and the thing it points to is a dir), then we will scan those
1441 * trees before we return.
1442 */
1443EXPORT int
1444insert_file_entry(this_dir, whole_path, short_name, statp, have_rsrc)
1445 struct directory *this_dir;
1446 char *whole_path;
1447 char *short_name;
1448 struct stat *statp;
1449 int have_rsrc;
1450{
1451 struct stat statbuf,
1452 lstatbuf;
1453 struct directory_entry *s_entry,
1454 *s_entry1;
1455 int lstatus;
1456 int status;
1457 int deep_flag;
1458#ifdef USE_NO_SCANDIR
1459 int no_scandir = 0;
1460#endif
1461
1462#ifdef APPLE_HYB
1463 int x_hfs = 0;
1464 int htype = TYPE_NONE;
1465
1466#endif /* APPLE_HYB */
1467
1468 if (statp) {
1469 status = lstatus = 0;
1470 lstatbuf = *statp;
1471 if (S_ISLNK(lstatbuf.st_mode)) {
1472 status = stat_filter(short_name, &statbuf);
1473 } else {
1474 statbuf = *statp;
1475 }
1476 } else {
1477 status = stat_filter(whole_path, &statbuf);
1478
1479 lstatus = lstat_filter(whole_path, &lstatbuf);
1480 }
1481
1482 if ((status == -1) && (lstatus == -1)) {
1483 /*
1484 * This means that the file doesn't exist, or isn't accessible.
1485 * Sometimes this is because of NFS permissions problems.
1486 */
1487 errmsg(_("Non-existent or inaccessible: %s\n"), whole_path);
1488 return (0);
1489 }
1490 if (S_ISDIR(statbuf.st_mode) &&
1491 (this_dir->depth > RR_relocation_depth) && !use_RockRidge &&
1492 strcmp(short_name, ".") != 0 && strcmp(short_name, "..") != 0) {
1493 dir_nesting_warn(this_dir, whole_path, TRUE);
1494 return (0);
1495 }
1496 if (this_dir == root && strcmp(short_name, ".") == 0)
1497 root_statbuf = statbuf; /* Save this for later on */
1498
1499 /*
1500 * We do this to make sure that the root entries are consistent
1501 */
1502 if (this_dir == root && strcmp(short_name, "..") == 0) {
1503 statbuf = root_statbuf;
1504 lstatbuf = root_statbuf;
1505 }
1506 if (S_ISLNK(lstatbuf.st_mode)) {
1507 /*
1508 * Here we decide how to handle the symbolic links. Here we
1509 * handle the general case - if we are not following links or
1510 * there is an error, then we must change something. If RR
1511 * is in use, it is easy, we let RR describe the file. If
1512 * not, then we punt the file.
1513 */
1514 if ((status || !follow_links)) {
1515#ifdef UDF
1516 if (use_RockRidge || use_udf) {
1517#else
1518 if (use_RockRidge) {
1519#endif
1520 status = 0;
1521 STAT_INODE(statbuf) = UNCACHED_INODE;
1522 statbuf.st_dev = UNCACHED_DEVICE;
1523#ifdef UDF
1524 if (create_udfsymlinks) {
1525 char symlinkcontents[2048];
1526 off_t size = sizeof (symlinkcontents);
1527
1528 if (udf_get_symlinkcontents(whole_path,
1529 symlinkcontents, &size) == -1) {
1530 statbuf.st_size = (off_t)0;
1531 statbuf.st_mode =
1532 (statbuf.st_mode & ~S_IFMT) | S_IFREG;
1533 } else {
1534 statbuf.st_size = size;
1535 statbuf.st_mode = lstatbuf.st_mode;
1536 }
1537 } else {
1538#endif
1539 statbuf.st_size = (off_t)0;
1540 statbuf.st_mode =
1541 (statbuf.st_mode & ~S_IFMT) | S_IFREG;
1542#ifdef UDF
1543 }
1544#endif
1545 } else {
1546 if (follow_links) {
1547 /* XXX errno may be wrong! */
1548 errmsg(_("Unable to stat file %s - ignoring and continuing.\n"),
1549 whole_path);
1550 } else {
1552 _("Symlink %s ignored - continuing.\n"),
1553 whole_path);
1554 return (0); /* Non Rock Ridge discs */
1555 /* - ignore all symlinks */
1556 }
1557 }
1558 }
1559 /*
1560 * Here we handle a different kind of case. Here we have a
1561 * symlink, but we want to follow symlinks. If we run across
1562 * a directory loop, then we need to pretend that we are not
1563 * following symlinks for this file. If this is the first
1564 * time we have seen this, then make this seem as if there was
1565 * no symlink there in the first place
1566 */
1567 if (follow_links &&
1568 S_ISDIR(statbuf.st_mode)) {
1569 if (strcmp(short_name, ".") != 0 &&
1570 strcmp(short_name, "..") != 0) {
1571 if (find_directory_hash(statbuf.st_dev,
1572 STAT_INODE(statbuf))) {
1573 if (!use_RockRidge) {
1575 _("Already cached directory seen (%s)\n"),
1576 whole_path);
1577 return (0);
1578 }
1579 lstatbuf = statbuf;
1580 /*
1581 * XXX when this line was active,
1582 * XXX mkisofs did not include all
1583 * XXX files if it was called with '-f'
1584 * XXX (follow symlinks).
1585 * XXX Now scan_directory_tree()
1586 * XXX checks if the directory has
1587 * XXX already been scanned via the
1588 * XXX DIR_WAS_SCANNED flag.
1589 */
1590/* no_scandir = 1;*/
1591 } else {
1592 lstatbuf = statbuf;
1593 add_directory_hash(statbuf.st_dev,
1594 STAT_INODE(statbuf));
1595 }
1596 }
1597 }
1598 /*
1599 * For non-directories, we just copy the stat information over
1600 * so we correctly include this file.
1601 */
1602 if (follow_links &&
1603 !S_ISDIR(statbuf.st_mode)) {
1604 lstatbuf = statbuf;
1605 }
1606 }
1607 /*
1608 * Add directories to the cache so that we don't waste space even if
1609 * we are supposed to be following symlinks.
1610 */
1611 if (follow_links &&
1612 strcmp(short_name, ".") != 0 &&
1613 strcmp(short_name, "..") != 0 &&
1614 S_ISDIR(statbuf.st_mode)) {
1615 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
1616 }
1617#ifdef VMS
1618 if (!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX &&
1619 statbuf.st_fab_rfm != FAB$C_STMLF)) {
1621 _("Warning - file %s has an unsupported VMS record format (%d)\n"),
1622 whole_path, statbuf.st_fab_rfm);
1623 }
1624#endif
1625
1626 if (S_ISREG(lstatbuf.st_mode) &&
1627 ((statp != NULL && (status = access(short_name, R_OK))) ||
1628 (statp == NULL && (status = access(whole_path, R_OK))))) {
1629 errmsg(_("File %s is not readable - ignoring\n"),
1630 whole_path);
1631 return (0);
1632 }
1633#ifdef USE_LARGEFILES
1634 if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= maxnonlarge) &&
1635 !do_largefiles) {
1636#else
1637 /*
1638 * >= is required by the large file summit standard.
1639 */
1640 if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= (off_t)0x7FFFFFFF)) {
1641#endif
1642#ifdef EOVERFLOW
1643 errno = EOVERFLOW;
1644#else
1645 errno = EFBIG;
1646#endif
1647 errmsg(_("File %s is too large for current mkisofs settings (-iso-level 3 or more required) - ignoring\n"),
1648 whole_path);
1649 return (0);
1650 }
1651 /*
1652 * Add this so that we can detect directory loops with hard links.
1653 * If we are set up to follow symlinks, then we skip this checking.
1654 */
1655 if (!follow_links &&
1656 S_ISDIR(lstatbuf.st_mode) &&
1657 strcmp(short_name, ".") != 0 &&
1658 strcmp(short_name, "..") != 0) {
1659 if (find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) {
1660/* comerrno(EX_BAD,*/
1661/* _("Directory loop - fatal goof (%s %lx %lu).\n"),*/
1663 _("Warning: Directory loop (%s dev: %lx ino: %lu).\n"),
1664 whole_path, (unsigned long) statbuf.st_dev,
1665 (unsigned long) STAT_INODE(statbuf));
1666 }
1667 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
1668 }
1669 if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
1670 !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) &&
1671 !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
1672 !S_ISDIR(lstatbuf.st_mode)) {
1674 _("Unknown file type (%s) %s - ignoring and continuing.\n"),
1675 filetype((int)lstatbuf.st_mode), whole_path);
1676 return (0);
1677 }
1678 /*
1679 * Who knows what trash this is - ignore and continue
1680 */
1681 if (status) {
1682 errmsg(_("Unable to stat file %s - ignoring and continuing.\n"),
1683 whole_path);
1684 return (0);
1685 }
1686
1687#if !defined(__MINGW32__) && !defined(_MSC_VER)
1688#define is_archive(st) ((st).st_dev == archive_dev && (st).st_ino == archive_ino)
1689 if (archive_isreg && is_archive(statbuf)) {
1691 _("'%s' is the archive. Not dumped.\n"), whole_path);
1692 return (0);
1693 }
1694#endif
1695
1696 /*
1697 * Check to see if we have already seen this directory node. If so,
1698 * then we don't create a new entry for it, but we do want to recurse
1699 * beneath it and add any new files we do find.
1700 */
1701 if (S_ISDIR(statbuf.st_mode)) {
1702 int dflag;
1703
1704 for (s_entry = this_dir->contents; s_entry;
1705 s_entry = s_entry->next) {
1706 if (strcmp(s_entry->name, short_name) == 0) {
1707 break;
1708 }
1709 }
1710 if (s_entry != NULL &&
1711 strcmp(short_name, ".") != 0 &&
1712 strcmp(short_name, "..") != 0) {
1713 struct directory *child;
1714
1715 /*
1716 * This should not create a new directory
1717 */
1718 if ((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) {
1719 for (s_entry = reloc_dir->contents; s_entry;
1720 s_entry = s_entry->next) {
1721 if (strcmp(s_entry->name, short_name)
1722 == 0) {
1723 break;
1724 }
1725 }
1727 whole_path,
1728 s_entry, 1);
1729 } else {
1731 whole_path,
1732 s_entry, 1);
1733 /*
1734 * If unable to scan directory, mark this as a
1735 * non-directory
1736 */
1737 }
1738/* if (no_scandir)*/
1739 if (0)
1740 dflag = 1;
1741 else
1742 dflag = scan_directory_tree(child,
1743 whole_path, s_entry);
1744 if (!dflag) {
1745 lstatbuf.st_mode =
1746 (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
1747 }
1748 return (0);
1749 }
1750 }
1751#ifdef APPLE_HYB
1752 /*
1753 * Should we exclude this HFS file ? - only works with -hfs
1754 */
1755 if (!have_rsrc && apple_hyb && strcmp(short_name, ".") != 0 &&
1756 strcmp(short_name, "..") != 0) {
1757 if ((x_hfs = (hfs_matches(short_name) ||
1758 hfs_matches(whole_path))) == 1) {
1759 if (verbose > 1) {
1760 fprintf(stderr, _("Hidden from HFS tree: %s\n"),
1761 whole_path);
1762 }
1763 }
1764 }
1765 /*
1766 * check we are a file, using Apple extensions and have a .resource
1767 * part and not excluded
1768 */
1769 if (S_ISREG(lstatbuf.st_mode) && !have_rsrc && apple_both && !x_hfs) {
1770 char rsrc_path[PATH_MAX]; /* rsrc fork filename */
1771
1772 /*
1773 * Construct the resource full path
1774 */
1775 htype = get_hfs_rname(whole_path, short_name, rsrc_path);
1776 /*
1777 * Check we can read the resouce fork
1778 */
1779 if (htype) {
1780 struct stat rstatbuf,
1781 rlstatbuf;
1782
1783 /*
1784 * Some further checks on the file
1785 */
1786 status = stat_filter(rsrc_path, &rstatbuf);
1787
1788 lstatus = lstat_filter(rsrc_path, &rlstatbuf);
1789
1790/* if (!status && !lstatus && S_ISREG(rlstatbuf.st_mode)*/
1791/* && rlstatbuf.st_size > (off_t)0) { */
1792 if (!status && !lstatus && S_ISREG(rstatbuf.st_mode) &&
1793 rstatbuf.st_size > (off_t)0) {
1794
1795 /*
1796 * have a resource file - insert it into the
1797 * current directory but flag that we have a
1798 * resource fork
1799 */
1800 insert_file_entry(this_dir, rsrc_path,
1801 short_name, NULL, htype);
1802 }
1803 }
1804 }
1805#endif /* APPLE_HYB */
1806
1807 s_entry = (struct directory_entry *)
1808 e_malloc(sizeof (struct directory_entry));
1809 /* memset the whole struct, not just the isorec.extent part JCP */
1810 memset(s_entry, 0, sizeof (struct directory_entry));
1811 s_entry->next = this_dir->contents;
1812/* memset(s_entry->isorec.extent, 0, 8); */
1813 this_dir->contents = s_entry;
1814 deep_flag = 0;
1815 s_entry->table = NULL;
1816
1817 s_entry->name = e_strdup(short_name);
1818 s_entry->whole_name = e_strdup(whole_path);
1819
1820 s_entry->de_flags = 0;
1821 if (S_ISLNK(lstatbuf.st_mode))
1822 s_entry->de_flags |= IS_SYMLINK;
1823#ifdef DUPLICATES_ONCE
1824 s_entry->digest_fast = NULL;
1825 s_entry->digest_full = NULL;
1826#endif
1827
1828 /*
1829 * If the current directory is hidden, then hide all it's members
1830 * otherwise check if this entry needs to be hidden as well
1831 */
1832 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) {
1833 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
1834 } else if (strcmp(short_name, ".") != 0 &&
1835 strcmp(short_name, "..") != 0) {
1836 if (i_matches(short_name) || i_matches(whole_path)) {
1837 if (verbose > 1) {
1839 _("Hidden from ISO9660 tree: %s\n"),
1840 whole_path);
1841 }
1842 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
1843 }
1844 if (h_matches(short_name) || h_matches(whole_path)) {
1845 if (verbose > 1) {
1847 _("Hidden ISO9660 attribute: %s\n"),
1848 whole_path);
1849 }
1850 s_entry->de_flags |= HIDDEN_FILE;
1851 }
1852 }
1853 if (this_dir != reloc_dir &&
1854 this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) {
1855 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
1856 } else if (strcmp(short_name, ".") != 0 &&
1857 strcmp(short_name, "..") != 0) {
1858 if (j_matches(short_name) || j_matches(whole_path)) {
1859 if (verbose > 1) {
1861 _("Hidden from Joliet tree: %s\n"),
1862 whole_path);
1863 }
1864 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
1865 }
1866 }
1867 if (this_dir != reloc_dir &&
1868 this_dir->dir_flags & INHIBIT_UDF_ENTRY) {
1869 s_entry->de_flags |= INHIBIT_UDF_ENTRY;
1870 } else if (strcmp(short_name, ".") != 0 &&
1871 strcmp(short_name, "..") != 0) {
1872 if (u_matches(short_name) || u_matches(whole_path)) {
1873 if (verbose > 1) {
1875 _("Hidden from UDF tree: %s\n"),
1876 whole_path);
1877 }
1878 s_entry->de_flags |= INHIBIT_UDF_ENTRY;
1879 }
1880 }
1881
1882#ifdef SORTING
1883 /*
1884 * Inherit any sort weight from parent directory
1885 */
1886 s_entry->sort = this_dir->sort;
1887
1888#ifdef DVD_AUD_VID
1889 /*
1890 * No use at all to do a sort if we don't make a dvd video/audio
1891 */
1892 /*
1893 * Assign special weights to VIDEO_TS and AUDIO_TS files.
1894 * This can't be done with sort_matches for two reasons:
1895 * first, we need to match against the destination (DVD)
1896 * path rather than the source path, and second, there are
1897 * about 2400 different file names to check, each needing
1898 * a different priority, and adding that many patterns to
1899 * sort_matches would slow things to a crawl.
1900 */
1901
1902 if (dvd_aud_vid_flag) {
1903 s_entry->sort = assign_dvd_weights(s_entry->name, this_dir, s_entry->sort);
1904 /*
1905 * Turn on sorting if necessary, regardless of cmd-line options
1906 */
1907 if ((s_entry->sort != this_dir->sort) && do_sort == 0)
1908 do_sort++;
1909 }
1910#endif
1911
1912 /*
1913 * See if this entry should have a new weighting
1914 */
1915 if (do_sort && strcmp(short_name, ".") != 0 &&
1916 strcmp(short_name, "..") != 0) {
1917 s_entry->sort = sort_matches(whole_path, s_entry->sort);
1918 }
1919#endif /* SORTING */
1920
1921 s_entry->filedir = this_dir;
1922 s_entry->isorec.flags[0] = ISO_FILE;
1923 if (s_entry->de_flags & HIDDEN_FILE)
1924 s_entry->isorec.flags[0] |= ISO_EXISTENCE;
1925 s_entry->isorec.ext_attr_length[0] = 0;
1926 iso9660_date(s_entry->isorec.date, statbuf.st_mtime);
1927 s_entry->isorec.file_unit_size[0] = 0;
1928 s_entry->isorec.interleave[0] = 0;
1929
1930#ifdef APPLE_HYB
1931 if (apple_both && !x_hfs) {
1932 s_entry->hfs_ent = NULL;
1933 s_entry->assoc = NULL;
1934 s_entry->hfs_off = (off_t)0;
1935 s_entry->hfs_type = htype;
1936 if (have_rsrc) {
1937 /* associated (rsrc) file */
1938 s_entry->isorec.flags[0] |= ISO_ASSOCIATED;
1939 /* set the type of HFS file */
1940 s_entry->hfs_type = have_rsrc;
1941 /*
1942 * don't want the rsrc file to be included in any
1943 * Joliet/UDF tree
1944 */
1945 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
1946 s_entry->de_flags |= INHIBIT_UDF_ENTRY;
1947 } else if (s_entry->next) {
1948 /*
1949 * if previous entry is an associated file,
1950 * then "link" it to this file i.e. we have a
1951 * data/resource pair
1952 */
1953 if (s_entry->next->isorec.flags[0] & ISO_ASSOCIATED) {
1954 s_entry->assoc = s_entry->next;
1955 /*
1956 * share the same HFS parameters
1957 */
1958 s_entry->hfs_ent = s_entry->next->hfs_ent;
1959 s_entry->hfs_type = s_entry->next->hfs_type;
1960 }
1961 }
1962 /*
1963 * Allocate HFS entry if required
1964 */
1965 if (apple_both && strcmp(short_name, ".") != 0 &&
1966 strcmp(short_name, "..") != 0) {
1967 if (!s_entry->hfs_ent) {
1968 hfsdirent *hfs_ent;
1969
1970 hfs_ent =
1971 (hfsdirent *) e_malloc(sizeof (hfsdirent));
1972
1973 /*
1974 * Sill in the defaults
1975 */
1976 memset(hfs_ent, 0, sizeof (hfsdirent));
1977
1978 s_entry->hfs_ent = hfs_ent;
1979 }
1980 /*
1981 * the resource fork is processed first, but the
1982 * data fork's time info is used in preference
1983 * i.e. time info is set from the resource fork
1984 * initially, then it is set from the data fork
1985 */
1986 if (have_rsrc) {
1987 /*
1988 * Set rsrc size
1989 */
1990 s_entry->hfs_ent->u.file.rsize = lstatbuf.st_size;
1991 /*
1992 * This will be overwritten - but might as
1993 * well set it here ...
1994 */
1995 s_entry->hfs_ent->crdate = lstatbuf.st_ctime;
1996 s_entry->hfs_ent->mddate = lstatbuf.st_mtime;
1997 } else {
1998 /*
1999 * Set data size
2000 */
2001 s_entry->hfs_ent->u.file.dsize = lstatbuf.st_size;
2002 s_entry->hfs_ent->crdate = lstatbuf.st_ctime;
2003 s_entry->hfs_ent->mddate = lstatbuf.st_mtime;
2004 }
2005 }
2006 }
2007#endif /* APPLE_HYB */
2008
2009 if (strcmp(short_name, ".") == 0) {
2010 this_dir->dir_flags |= DIR_HAS_DOT;
2011 }
2012 if (strcmp(short_name, "..") == 0) {
2013 this_dir->dir_flags |= DIR_HAS_DOTDOT;
2014 }
2015 if (this_dir->parent &&
2016 this_dir->parent == reloc_dir &&
2017 strcmp(short_name, "..") == 0) {
2018 s_entry->inode = UNCACHED_INODE;
2019 s_entry->dev = UNCACHED_DEVICE;
2020 deep_flag = NEED_PL;
2021 } else
2022#ifdef APPLE_HYB
2023 if (have_rsrc) {
2024 /*
2025 * don't want rsrc files to be cached
2026 */
2027 s_entry->de_flags |= RESOURCE_FORK;
2028 s_entry->inode = UNCACHED_INODE;
2029 s_entry->dev = UNCACHED_DEVICE;
2030 } else
2031#endif /* APPLE_HYB */
2032 {
2033 s_entry->inode = STAT_INODE(statbuf);
2034 s_entry->dev = statbuf.st_dev;
2035 }
2036 set_723(s_entry->isorec.volume_sequence_number,
2038 iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode));
2039 s_entry->rr_attr_size = 0;
2040 s_entry->total_rr_attr_size = 0;
2041 s_entry->rr_attributes = NULL;
2042
2043 /*
2044 * Directories are assigned sizes later on
2045 */
2046 if (!S_ISDIR(statbuf.st_mode)) {
2047 if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) ||
2048 S_ISFIFO(lstatbuf.st_mode) ||
2049 S_ISSOCK(lstatbuf.st_mode) ||
2050#ifdef UDF
2051 (S_ISLNK(lstatbuf.st_mode) && !create_udfsymlinks)) {
2052#else
2053 FALSE) {
2054#endif
2055 s_entry->size = (off_t)0;
2056 statbuf.st_size = (off_t)0;
2057 } else {
2058 s_entry->size = statbuf.st_size;
2059 }
2060
2061 set_733((char *)s_entry->isorec.size, statbuf.st_size);
2062 } else {
2063 s_entry->isorec.flags[0] |= ISO_DIRECTORY;
2064 }
2065#ifdef APPLE_HYB
2066 /*
2067 * If the directory is HFS excluded, then we don't have an hfs_ent
2068 */
2069 if (apple_both && s_entry->hfs_ent &&
2070 (s_entry->isorec.flags[0] & ISO_DIRECTORY)) {
2071 /*
2072 * Get the Mac directory name
2073 */
2074 get_hfs_dir(whole_path, short_name, s_entry);
2075
2076 /*
2077 * If required, set ISO directory name from HFS name
2078 */
2079 if (use_mac_name)
2080 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1);
2081 }
2082#endif /* APPLE_HYB */
2083
2084 if (strcmp(short_name, ".") != 0 && strcmp(short_name, "..") != 0 &&
2085 S_ISDIR(statbuf.st_mode) &&
2086 this_dir->depth > RR_relocation_depth) {
2087 struct directory *child;
2088
2089 /*
2090 * Replicate the entry for this directory. The old one will
2091 * stay where it is, and it will be neutered so that it no
2092 * longer looks like a directory. The new one will look like
2093 * a directory, and it will be put in the reloc_dir.
2094 */
2095 s_entry1 = dup_relocated_dir(this_dir, s_entry,
2096 whole_path, short_name, &statbuf);
2097
2098 /*
2099 * We need to set this temporarily so that the parent to this
2100 * is correctly determined.
2101 */
2102 s_entry1->filedir = reloc_dir;
2104 s_entry1, 0);
2105 free(child->de_path); /* allocated in this case */
2106 set_de_path(this_dir, child);
2107
2108
2109/* if (!no_scandir)*/
2110 if (!0)
2111 scan_directory_tree(child, whole_path, s_entry1);
2112 s_entry1->filedir = this_dir;
2113 deep_flag = NEED_CL;
2114 }
2115 if (generate_tables &&
2116 strcmp(s_entry->name, ".") != 0 &&
2117 strcmp(s_entry->name, "..") != 0) {
2118
2119 char buffer[SECTOR_SIZE];
2120 int nchar;
2121
2122 switch (lstatbuf.st_mode & S_IFMT) {
2123 case S_IFDIR:
2124 sprintf(buffer, "D\t%s\n",
2125 s_entry->name);
2126 break;
2127
2128/*
2129 * extra for WIN32 - if it doesn't have the major/minor defined, then
2130 * S_IFBLK and S_IFCHR type files are unlikely to exist anyway ...
2131 * code similar to that in rock.c
2132 */
2133#if 0
2134/*
2135 * Use the device handling code from <schily/device.h>
2136 */
2137#ifndef major
2138#define major(dev) (sizeof (dev_t) <= 2 ? ((dev) >> 8) : \
2139 (sizeof (dev_t) <= 4 ? (((dev) >> 8) >> 8) : \
2140 (((dev) >> 16) >> 16)))
2141#define minor(dev) (sizeof (dev_t) <= 2 ? (dev) & 0xff : \
2142 (sizeof (dev_t) <= 4 ? (dev) & 0xffff : \
2143 (dev) & 0xffffffff))
2144#endif
2145#endif
2146
2147#ifdef S_IFBLK
2148 case S_IFBLK:
2149 sprintf(buffer, "B\t%s\t%lu %lu\n",
2150 s_entry->name,
2151 (unsigned long) major(statbuf.st_rdev),
2152 (unsigned long) minor(statbuf.st_rdev));
2153 break;
2154#endif
2155#ifdef S_IFIFO
2156 case S_IFIFO:
2157 sprintf(buffer, "P\t%s\n",
2158 s_entry->name);
2159 break;
2160#endif
2161#ifdef S_IFCHR
2162 case S_IFCHR:
2163 sprintf(buffer, "C\t%s\t%lu %lu\n",
2164 s_entry->name,
2165 (unsigned long) major(statbuf.st_rdev),
2166 (unsigned long) minor(statbuf.st_rdev));
2167 break;
2168#endif
2169#ifdef S_IFLNK
2170 case S_IFLNK:
2171#ifdef HAVE_READLINK
2172 nchar = readlink(statp?short_name:whole_path,
2173 (char *)symlink_buff,
2174 sizeof (symlink_buff)-1);
2175 if (nchar < 0) {
2176 errmsg(_("Cannot read link '%s'.\n"),
2177 statp?short_name:whole_path);
2178 }
2179#else
2180 nchar = -1;
2181#endif
2182 symlink_buff[nchar < 0 ? 0 : nchar] = 0;
2183 sprintf(buffer, "L\t%s\t%s\n",
2184 s_entry->name, symlink_buff);
2185 break;
2186#endif
2187#ifdef S_IFSOCK
2188 case S_IFSOCK:
2189 sprintf(buffer, "S\t%s\n",
2190 s_entry->name);
2191 break;
2192#endif
2193 case S_IFREG:
2194 default:
2195 sprintf(buffer, "F\t%s\n",
2196 s_entry->name);
2197 break;
2198 };
2199 s_entry->table = e_strdup(buffer);
2200 }
2201 if (S_ISDIR(statbuf.st_mode)) {
2202 int dflag;
2203
2204 if (strcmp(short_name, ".") != 0 &&
2205 strcmp(short_name, "..") != 0) {
2206 struct directory *child;
2207
2208 child = find_or_create_directory(this_dir, whole_path,
2209 s_entry, 1);
2210#ifdef USE_NO_SCANDIR
2211 if (no_scandir)
2212 dflag = 1;
2213 else
2214#endif
2215 dflag = scan_directory_tree(child, whole_path,
2216 s_entry);
2217
2218 if (!dflag) {
2219 lstatbuf.st_mode =
2220 (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
2221 if (child->contents == NULL) {
2222 delete_directory(this_dir, child);
2223 }
2224 }
2225 }
2226 /* If unable to scan directory, mark this as a non-directory */
2227 }
2228 if (use_RockRidge && this_dir == root &&
2229 strcmp(s_entry->name, ".") == 0) {
2230 deep_flag |= NEED_CE | NEED_SP; /* For extension record */
2231 }
2232 /*
2233 * Now figure out how much room this file will take in the directory
2234 */
2235
2236#ifdef APPLE_HYB
2237 /*
2238 * Ff the file is HFS excluded, then we don't have an hfs_ent
2239 */
2240 if (apple_both && !have_rsrc && s_entry->hfs_ent) {
2241 if (S_ISREG(lstatbuf.st_mode)) { /* it's a regular file */
2242
2243 /*
2244 * Fill in the rest of the HFS entry
2245 */
2246 get_hfs_info(whole_path, short_name, s_entry);
2247
2248 /*
2249 * If required, set ISO directory name from HFS name
2250 */
2251 if (use_mac_name)
2252 iso9660_file_length(s_entry->hfs_ent->name,
2253 s_entry, 0);
2254
2255 /*
2256 * Print details about the HFS file
2257 */
2258 if (verbose > 2)
2259 print_hfs_info(s_entry);
2260
2261 /*
2262 * copy the new ISO9660 name to the rsrc fork
2263 * - if it exists
2264 */
2265 if (s_entry->assoc)
2266 strcpy(s_entry->assoc->isorec.name,
2267 s_entry->isorec.name);
2268
2269 /*
2270 * we can't handle hard links in the hybrid case, so we
2271 * "uncache" the file. The downside to this is that
2272 * hard linked files are added to the output image
2273 * more than once (we've already done this for rsrc
2274 * files)
2275 */
2276 if (apple_hyb && have_rsrc) {
2277 s_entry->de_flags |= RESOURCE_FORK;
2278 s_entry->inode = UNCACHED_INODE;
2279 s_entry->dev = UNCACHED_DEVICE;
2280 }
2281 } else if (!(s_entry->isorec.flags[0] & ISO_DIRECTORY)) {
2282 /* not a directory .. */
2283
2284 /*
2285 * no mac equivalent, so ignore - have to be careful
2286 * here, the hfs_ent may be also be for a relocated
2287 * directory
2288 */
2289 if (s_entry->hfs_ent &&
2290 !(s_entry->de_flags & RELOCATED_DIRECTORY) &&
2291 (s_entry->isorec.flags[0] & ISO_MULTIEXTENT) == 0) {
2292 free(s_entry->hfs_ent);
2293 }
2294 s_entry->hfs_ent = NULL;
2295 }
2296 /*
2297 * if the rsrc size is zero, then we don't need the entry, so
2298 * we might as well delete it - this will only happen if we
2299 * didn't know the rsrc size from the rsrc file size
2300 */
2301 if (s_entry->assoc && s_entry->assoc->size == 0)
2302 delete_rsrc_ent(s_entry);
2303 }
2304 if (apple_ext && s_entry->assoc) {
2305 /*
2306 * Need Apple extensions for the resource fork as well
2307 */
2308 generate_xa_rr_attributes(whole_path,
2309 short_name, s_entry->assoc,
2310 &statbuf, &lstatbuf, deep_flag | (statp?DID_CHDIR:0));
2311 }
2312 /* leave out resource fork for the time being */
2313 /*
2314 * XXX This is most likely wrong and should just be:
2315 * XXX if (use_XA || use_RockRidge) {
2316 */
2317/* if ((use_XA || use_RockRidge) && !have_rsrc) {*/
2318 if (use_XA || use_RockRidge) {
2319#else
2320 if (use_XA || use_RockRidge) {
2321#endif /* APPLE_HYB */
2322 generate_xa_rr_attributes(whole_path,
2323 short_name, s_entry,
2324 &statbuf, &lstatbuf, deep_flag | (statp?DID_CHDIR:0));
2325
2326 }
2327#ifdef UDF
2328 /* set some info used for udf */
2329 s_entry->mode = lstatbuf.st_mode;
2330 s_entry->rdev = lstatbuf.st_rdev;
2331 s_entry->uid = lstatbuf.st_uid;
2332 s_entry->gid = lstatbuf.st_gid;
2333 s_entry->atime.tv_sec = lstatbuf.st_atime;
2334 s_entry->atime.tv_nsec = stat_ansecs(&lstatbuf);
2335 s_entry->mtime.tv_sec = lstatbuf.st_mtime;
2336 s_entry->mtime.tv_nsec = stat_mnsecs(&lstatbuf);
2337 s_entry->ctime.tv_sec = lstatbuf.st_ctime;
2338 s_entry->ctime.tv_nsec = stat_cnsecs(&lstatbuf);
2339#endif
2340
2341#ifdef USE_LARGEFILES
2342#ifndef MAX_EXTENT
2343 /*
2344 * Allow to #define MAX_EXTENT from outside for debug purposes.
2345 */
2346#ifdef PROTOTYPES
2347#define LARGE_EXTENT ((off_t)0xFFFFF800UL)
2348#define MAX_EXTENT ((off_t)0xFFFFFFFEUL)
2349#else
2350#define LARGE_EXTENT ((off_t)0xFFFFF800L)
2351#define MAX_EXTENT ((off_t)0xFFFFFFFEL)
2352#endif
2353#else /* MAX_EXTENT */
2354#define LARGE_EXTENT MAX_EXTENT & ~(off_t)2047L
2355#endif /* !MAX_EXTENT */
2356 /*
2357 * Break up files greater than (4GB -2) into multiple extents.
2358 * The original entry, with ->size untouched, remains for UDF.
2359 * Each of the new file sections will get its own entry.
2360 * The file sections are the only entries actually written out to the
2361 * disk. The UDF entry will use "mxroot" to get the same start
2362 * block as the first file section, and all the sections will end up
2363 * in the ISO9660 directory in the correct order by "mxpart",
2364 * which the directory sorting routine knows about.
2365 *
2366 * If we ever need to be able to find mxpart == 1 after sorting,
2367 * we need to add another pointer to s_entry or to be very careful
2368 * with the loops above where the ISO-9660 name is copied back to
2369 * all multi-extent parts.
2370 */
2371 if (s_entry->size > MAX_EXTENT) {
2372 off_t size;
2373
2374 s_entry->de_flags |= MULTI_EXTENT;
2375 s_entry->isorec.flags[0] |= ISO_MULTIEXTENT;
2376 s_entry->mxroot = s_entry;
2377 s_entry->mxpart = 0;
2378 set_733((char *)s_entry->isorec.size, LARGE_EXTENT);
2379 s_entry1 = dup_directory_entry(s_entry);
2380 s_entry->next = s_entry1;
2381
2382 /*
2383 * full size UDF version
2384 */
2386 if (s_entry->size > (((off_t)190)*0x3FFFF800)) {
2387#ifndef EOVERFLOW
2388#define EOVERFLOW EFBIG
2389#endif
2391 _("File %s is too large - hiding from UDF tree.\n"),
2392 whole_path);
2393 s_entry->de_flags |= INHIBIT_UDF_ENTRY;
2394 }
2395
2396 /*
2397 * Prepare the first file multi-extent section of the file.
2398 */
2399 s_entry = s_entry1;
2400 s_entry->de_flags |= INHIBIT_UDF_ENTRY;
2401 size = s_entry->size;
2402 s_entry->size = LARGE_EXTENT;
2403 s_entry->mxpart++;
2404
2405 /*
2406 * Additional extents, as needed
2407 */
2408 while (size > MAX_EXTENT) {
2409 s_entry1 = dup_directory_entry(s_entry);
2410 s_entry->next = s_entry1;
2411
2412 s_entry = s_entry1;
2413 s_entry->mxpart++;
2414 size -= LARGE_EXTENT;
2415 }
2416 /*
2417 * That was the last one.
2418 */
2419 s_entry->isorec.flags[0] &= ~ISO_MULTIEXTENT;
2420 s_entry->size = size;
2421 set_733((char *)s_entry->isorec.size, (UInt32_t)s_entry->size);
2422 }
2423#endif /* USE_LARGEFILES */
2424
2425 return (1);
2426}
2427
2428EXPORT struct directory_entry *
2430 struct directory_entry *s_entry;
2431{
2432 struct directory_entry *s_entry1;
2433
2434 s_entry1 = (struct directory_entry *)
2435 e_malloc(sizeof (struct directory_entry));
2436 memcpy(s_entry1, s_entry, sizeof (struct directory_entry));
2437
2438 if (s_entry->rr_attributes) {
2439 s_entry1->rr_attributes =
2440 e_malloc(s_entry->total_rr_attr_size);
2441 memcpy(s_entry1->rr_attributes, s_entry->rr_attributes,
2442 s_entry->total_rr_attr_size);
2443 }
2444 if (s_entry->name)
2445 s_entry1->name = e_strdup(s_entry->name);
2446 if (s_entry->whole_name)
2447 s_entry1->whole_name = e_strdup(s_entry->whole_name);
2448#ifdef APPLE_HYB
2449 /*
2450 * If we also duplicate s_entry->hfs_ent, we would need to change
2451 * free_one_directory() and other calls to free(s_entry->hfs_ent) too.
2452 */
2453#endif
2454 return (s_entry1);
2455}
2456
2457EXPORT void
2459 struct directory *node;
2460 FILE *outfile;
2461{
2462 struct directory *dpnt;
2463
2464 dpnt = node;
2465
2466 while (dpnt) {
2467 if (dpnt->extent > session_start) {
2469 }
2470 if (dpnt->subdir)
2472 dpnt = dpnt->next;
2473 }
2474}
2475
2476/*
2477 * XXX This may need some work for the MVS port.
2478 */
2479LOCAL void
2482 struct directory *this;
2483{
2484 char *p;
2485 size_t len;
2486
2487 if (parent == NULL) { /* We are just creating root */
2488 this->de_path = this->whole_name;
2489 return;
2490 } else if (parent == root) { /* full path == component */
2491 this->de_path = this->de_name;
2492 return;
2493 }
2494 len = strlen(parent->de_path)+1+strlen(this->de_name)+1;
2495 p = e_malloc(len);
2496 js_snprintf(p, len, "%s/%s", parent->de_path, this->de_name);
2497 this->de_path = p;
2498}
2499
2500/*
2501 * Function: find_or_create_directory
2502 *
2503 * Purpose: Locate a directory entry in the tree, create if needed.
2504 *
2505 * Arguments: parent & de are never NULL at the same time.
2506 */
2507EXPORT struct directory *
2509 struct directory *parent;
2510 char *path;
2511 struct directory_entry *de;
2512 int flag;
2513{
2514 struct directory *child = 0;
2515 struct directory *dpnt;
2516 struct directory_entry *orig_de;
2517 struct directory *next_brother;
2518 const char *cpnt;
2519 const char *pnt;
2520 int deep_flag = 0;
2521
2522 orig_de = de;
2523
2524 /*
2525 * XXX It seems that the tree that has been read from the
2526 * XXX previous session does not carry whole_name entries.
2527 * XXX We provide a hack in multi.c:find_or_create_directory()
2528 * XXX that should be removed when a reasonable method could
2529 * XXX be found.
2530 */
2531 if (path == NULL) {
2532 error(_("Warning: missing whole name for: '%s'\n"), de->name);
2533 path = de->name;
2534 if (path == NULL)
2535 comerrno(EX_BAD, _("Panic no node name.\n"));
2536 }
2537 pnt = strrchr(path, PATH_SEPARATOR);
2538 if (pnt == NULL) {
2539 pnt = path;
2540 } else {
2541 pnt++;
2542 }
2543
2544 if (parent != NULL) {
2545
2546 dpnt = parent->subdir;
2547 if (dpnt == NULL) {
2548 struct directory_entry *s_entry;
2549
2550 for (s_entry = parent->contents; s_entry;
2551 s_entry = s_entry->next) {
2552 if ((strcmp(s_entry->name, pnt) == 0) &&
2553 (s_entry->de_flags & RELOCATED_DIRECTORY)) {
2555 reloc_dir, path, de,
2556 flag));
2557 }
2558 }
2559 }
2560
2561 while (dpnt) {
2562 /*
2563 * Weird hack time - if there are two directories by
2564 * the same name in the reloc_dir, they are not
2565 * treated as the same thing unless the entire path
2566 * matches completely.
2567 */
2568 if (flag && strcmp(dpnt->de_name, pnt) == 0) {
2569
2570 /*
2571 * XXX Remove test?
2572 * XXX dpnt->de_path should always be != NULL
2573 */
2574 if (dpnt->de_path != NULL &&
2575 strcmp(dpnt->de_path, path) == 0)
2576 return (dpnt);
2577
2578 if (parent != reloc_dir &&
2579 strcmp(dpnt->de_name, pnt) == 0)
2580 return (dpnt);
2581 }
2582 dpnt = dpnt->next;
2583 }
2584 }
2585 /*
2586 * We don't know if we have a valid directory entry for this one yet.
2587 * If not, we need to create one.
2588 */
2589 if (de == NULL) {
2590 de = (struct directory_entry *)
2591 e_malloc(sizeof (struct directory_entry));
2592 memset(de, 0, sizeof (struct directory_entry));
2593 de->next = parent->contents;
2594 parent->contents = de;
2595 de->name = e_strdup(pnt);
2596 de->whole_name = e_strdup(path);
2597 de->filedir = parent;
2598 de->isorec.flags[0] = ISO_DIRECTORY;
2599 de->priority = 32768;
2600 de->inode = UNCACHED_INODE;
2601 de->dev = UNCACHED_DEVICE;
2602 set_723(de->isorec.volume_sequence_number,
2604 iso9660_file_length(pnt, de, 1);
2605
2606 init_fstatbuf();
2607#ifdef APPLE_HYB
2608 if (apple_both) {
2609 /*
2610 * Give the directory an HFS entry
2611 */
2612 hfsdirent *hfs_ent;
2613
2614 hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent));
2615
2616 /*
2617 * Fill in the defaults
2618 */
2619 memset(hfs_ent, 0, sizeof (hfsdirent));
2620 hfs_ent->crdate = fstatbuf.st_ctime;
2621 hfs_ent->mddate = fstatbuf.st_mtime;
2622
2623 de->hfs_ent = hfs_ent;
2624
2625 /*
2626 * Get the Mac directory name
2627 */
2628 get_hfs_dir((char *)path, (char *)pnt, de);
2629 }
2630#endif /* APPLE_HYB */
2631 }
2632 /*
2633 * If we don't have a directory for this one yet, then allocate it now,
2634 * and patch it into the tree in the appropriate place.
2635 */
2636 dpnt = (struct directory *)e_malloc(sizeof (struct directory));
2637 memset(dpnt, 0, sizeof (struct directory));
2638 dpnt->next = NULL;
2639 dpnt->subdir = NULL;
2640 dpnt->self = de;
2641 dpnt->contents = NULL;
2642 dpnt->whole_name = e_strdup(path);
2643 cpnt = strrchr(path, PATH_SEPARATOR);
2644 if (cpnt)
2645 cpnt++;
2646 else
2647 cpnt = path;
2648 dpnt->de_name = e_strdup(cpnt);
2649 dpnt->de_path = NULL;
2650 set_de_path(parent, dpnt);
2651 dpnt->size = 0;
2652 dpnt->extent = 0;
2653 dpnt->jextent = 0;
2654 dpnt->jsize = 0;
2655#ifdef APPLE_HYB
2656 dpnt->hfs_ent = de->hfs_ent;
2657#endif /* APPLE_HYB */
2658
2659 if (orig_de == NULL) {
2660 struct stat xstatbuf;
2661 int sts;
2662
2663 /*
2664 * Now add a . and .. entry in the directory itself. This is a
2665 * little tricky - if the real directory exists, we need to
2666 * stat it first. Otherwise, we use the fictitious fstatbuf
2667 * which points to the time at which mkisofs was started.
2668 */
2669 if (parent == NULL || parent->whole_name[0] == '\0')
2670 sts = -1;
2671 else
2672 sts = stat_filter(parent->whole_name, &xstatbuf);
2673 if (debug && parent) {
2674 error(_("stat parent->whole_name: '%s' -> %d.\n"),
2675 parent->whole_name, sts);
2676 }
2677 if (sts == 0) {
2678 attach_dot_entries(dpnt, NULL, &xstatbuf);
2679 } else {
2681 }
2682 }
2683 if (!parent || parent == root) {
2684 if (!root) {
2685 root = dpnt; /* First time through for root */
2686 /* directory only */
2687 root->depth = 0;
2688 root->parent = root;
2689 } else {
2690 dpnt->depth = 1;
2691 if (!root->subdir) {
2692 root->subdir = dpnt;
2693 } else {
2694 next_brother = root->subdir;
2695 while (next_brother->next)
2696 next_brother = next_brother->next;
2697 next_brother->next = dpnt;
2698 }
2699 dpnt->parent = parent;
2700 }
2701 } else {
2702 struct directory_entry *s_entry1;
2703
2704 /*
2705 * Come through here for normal traversal of tree
2706 */
2707#ifdef DEBUG
2708 fprintf(stderr, "%s(%d) ", path, dpnt->depth);
2709#endif
2710
2711 if (parent->depth > RR_relocation_depth && use_RockRidge) {
2712 /*
2713 * We come here in case that a graft-point needs to
2714 * create a new relocated (deep) directory.
2715 *
2716 * Replicate the entry for this directory. The old one
2717 * will stay where it is, and it will be neutered so
2718 * that it no longer looks like a directory. The new
2719 * one will look like a directory, and it will be put
2720 * in the reloc_dir.
2721 */
2722 s_entry1 = dup_relocated_dir(parent, de, path,
2723 dpnt->de_name, &fstatbuf);
2725 s_entry1, 0);
2726 free(child->de_path); /* allocated in this case */
2728
2729 deep_flag |= NEED_CL;
2730 }
2731 if (parent->depth > RR_relocation_depth && !use_RockRidge) {
2733 exit(EX_BAD);
2734 }
2735 dpnt->parent = parent;
2736 dpnt->depth = parent->depth + 1;
2737
2738 if ((deep_flag & NEED_CL) == 0) {
2739 /*
2740 * Do not add this directory to the list of subdirs if
2741 * this is a relocated directory.
2742 */
2743 if (!parent->subdir) {
2744 parent->subdir = dpnt;
2745 } else {
2746 next_brother = parent->subdir;
2747 while (next_brother->next)
2748 next_brother = next_brother->next;
2749 next_brother->next = dpnt;
2750 }
2751 }
2752 }
2753 /*
2754 * It doesn't exist for real, so we cannot add any
2755 * XA or Rock Ridge attributes.
2756 */
2757 if (orig_de == NULL || (parent == NULL && path[0] == '\0')) {
2758 init_fstatbuf();
2759 fstatbuf.st_mode = new_dir_mode | S_IFDIR;
2760 fstatbuf.st_nlink = 2;
2761 if ((use_XA || use_RockRidge) &&
2762 !(parent == NULL && path[0] == '\0')) {
2763 /*
2764 * We cannot set up RR attrubutes for the real
2765 * ISO-9660 root directory. This is why we
2766 * check for parent == NULL && path[0] == '\0'.
2767 */
2769 (char *)pnt, de,
2770 &fstatbuf,
2771 &fstatbuf, deep_flag);
2772 }
2773#ifdef UDF
2774 /* set some info used for udf */
2775 de->mode = fstatbuf.st_mode;
2776 de->uid = fstatbuf.st_uid;
2777 de->gid = fstatbuf.st_gid;
2778 de->atime.tv_sec = fstatbuf.st_atime;
2779 de->atime.tv_nsec = stat_ansecs(&fstatbuf);
2780 de->mtime.tv_sec = fstatbuf.st_mtime;
2781 de->mtime.tv_nsec = stat_mnsecs(&fstatbuf);
2782 de->ctime.tv_sec = fstatbuf.st_ctime;
2783 de->ctime.tv_nsec = stat_cnsecs(&fstatbuf);
2784#endif
2785 iso9660_date(de->isorec.date, fstatbuf.st_mtime);
2786 }
2787 if (child)
2788 return (child); /* Return reloaction target */
2789
2790 return (dpnt);
2791}
2792
2793/*
2794 * Function: delete_directory
2795 *
2796 * Purpose: Locate a directory entry in the tree, create if needed.
2797 *
2798 * Arguments:
2799 */
2800LOCAL void
2802 struct directory *parent;
2803 struct directory *child;
2804{
2805 struct directory *tdir;
2806
2807 if (child == NULL)
2808 return;
2809 if (child->contents != NULL) {
2810 comerrno(EX_BAD, _("Unable to delete non-empty directory\n"));
2811 }
2812 free(child->whole_name);
2813 child->whole_name = NULL;
2814
2815 free(child->de_name);
2816 child->de_name = NULL;
2817
2818#ifdef APPLE_HYB
2819 if (apple_both && child->hfs_ent)
2820 free(child->hfs_ent);
2821#endif /* APPLE_HYB */
2822
2823 if (parent->subdir == child) {
2824 parent->subdir = child->next;
2825 } else {
2826 for (tdir = parent->subdir; tdir != NULL && tdir->next != NULL;
2827 tdir = tdir->next) {
2828 if (tdir->next == child) {
2829 tdir->next = child->next;
2830 break;
2831 }
2832 }
2833 if (tdir == NULL || tdir->next != child->next) {
2835 _("Unable to locate child directory in parent list\n"));
2836 }
2837 }
2838 free(child);
2839}
2840
2841EXPORT int
2843 struct directory *node;
2844{
2845 struct directory *dpnt;
2846 int ret = 0;
2847
2848 dpnt = node;
2849
2850 while (dpnt) {
2851 ret = sort_n_finish(dpnt);
2852 if (ret) {
2853 break;
2854 }
2855 if (dpnt->subdir)
2856 sort_tree(dpnt->subdir);
2857 dpnt = dpnt->next;
2858 }
2859 return (ret);
2860}
2861
2862EXPORT void
2864 struct directory *node;
2865{
2866 struct directory *dpnt;
2867
2868 dpnt = node;
2869
2870 while (dpnt) {
2871 fprintf(stderr, "%4d %5d %s\n",
2872 dpnt->extent, dpnt->size, dpnt->de_name);
2873 if (dpnt->subdir)
2874 dump_tree(dpnt->subdir);
2875 dpnt = dpnt->next;
2876 }
2877}
2878
2879/*
2880 * something quick and dirty to locate a file given a path
2881 * recursively walks down path in filename until it finds the
2882 * directory entry for the desired file
2883 */
2884EXPORT struct directory_entry *
2886 struct directory *node;
2887 char *filename;
2888{
2889 struct directory_entry *depnt;
2890 struct directory *dpnt;
2891 char *p1;
2892 char *rest;
2893 char *subdir;
2894
2895 /*
2896 * Strip off next directory name from filename:
2897 */
2899
2900 if ((p1 = strchr(subdir, '/')) == subdir) {
2902 _("call to search_tree_file with an absolute path, stripping\n"));
2904 _("initial path separator. Hope this was intended...\n"));
2905 memmove(subdir, subdir + 1, strlen(subdir) - 1);
2906 p1 = strchr(subdir, '/');
2907 }
2908 /*
2909 * Do we need to find a subdirectory?
2910 */
2911 if (p1) {
2912 *p1 = '\0';
2913
2914#ifdef DEBUG_TORITO
2915 fprintf(stderr, _("Looking for subdir called %s\n"), p1);
2916#endif
2917
2918 rest = p1 + 1;
2919
2920#ifdef DEBUG_TORITO
2921 fprintf(stderr, _("Remainder of path name is now %s\n"), rest);
2922#endif
2923
2924 dpnt = node->subdir;
2925 while (dpnt) {
2926#ifdef DEBUG_TORITO
2928 "%4d %5d %s\n", dpnt->extent, dpnt->size,
2929 dpnt->de_name);
2930#endif
2931 if (strcmp(subdir, dpnt->de_name) == 0) {
2932#ifdef DEBUG_TORITO
2934 _("Calling next level with filename = %s\n"), rest);
2935#endif
2936 return (search_tree_file(dpnt, rest));
2937 }
2938 dpnt = dpnt->next;
2939 }
2940
2941 /*
2942 * If we got here means we couldn't find the subdir.
2943 */
2944 return (NULL);
2945 } else {
2946 /*
2947 * Look for a normal file now
2948 */
2949 depnt = node->contents;
2950 while (depnt) {
2951#ifdef DEBUG_TORITO
2952 fprintf(stderr, "%4d %5d %s\n", depnt->isorec.extent,
2953 depnt->size, depnt->name);
2954#endif
2955 if (strcmp(filename, depnt->name) == 0) {
2956#ifdef DEBUG_TORITO
2957 fprintf(stderr, _("Found our file %s"), filename);
2958#endif
2959 return (depnt);
2960 }
2961 depnt = depnt->next;
2962 }
2963 /*
2964 * If we got here means we couldn't find the subdir.
2965 */
2966 return (NULL);
2967 }
2968#ifdef ERIC_FUN
2969 fprintf(stderr, _("We cant get here in search_tree_file :-/ \n"));
2970#endif
2971}
2972
2973EXPORT void
2975{
2976 struct timeval current_time;
2977
2978 if (fstatbuf.st_ctime == 0) {
2979 gettimeofday(&current_time, NULL);
2980 if (rationalize_uid)
2981 fstatbuf.st_uid = uid_to_use;
2982 else
2983 fstatbuf.st_uid = getuid();
2984 if (rationalize_gid)
2985 fstatbuf.st_gid = gid_to_use;
2986 else
2987 fstatbuf.st_gid = getgid();
2988
2989 current_time.tv_usec *= 1000;
2990 fstatbuf.st_ctime = current_time.tv_sec;
2991 stat_set_ansecs(&fstatbuf, current_time.tv_usec);
2992 fstatbuf.st_mtime = current_time.tv_sec;
2993 stat_set_mnsecs(&fstatbuf, current_time.tv_usec);
2994 fstatbuf.st_atime = current_time.tv_sec;
2995 stat_set_cnsecs(&fstatbuf, current_time.tv_usec);
2996 }
2997}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
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 * strchr(const char *String, int ch)
Definition: utclib.c:501
#define S_IFDIR
Definition: acwin.h:115
#define stat
Definition: acwin.h:99
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
const WCHAR * short_name
Definition: reg.c:29
#define PATH_MAX
Definition: types.h:280
#define S_ISDIR(mode)
Definition: various.h:18
#define S_ISREG(mode)
Definition: various.h:17
uid_t getuid()
Definition: uid.c:27
size_t strlcpy(char *d, const char *s, size_t bufsize)
Definition: compat.c:3
#define SECTOR_SIZE
Definition: fs.h:22
struct _root root
#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 int errmsg(char *msg, va_alist)
Definition: comerr.c:192
@ TYPE_NONE
Definition: createspec.c:69
#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
#define off_t
Definition: dosfsck.h:5
r parent
Definition: btrfs.c:3010
#define EOVERFLOW
Definition: errno.h:82
#define ENOTDIR
Definition: errno.h:26
#define EFBIG
Definition: errno.h:33
__kernel_time_t time_t
Definition: linux.h:252
__kernel_off_t off_t
Definition: linux.h:201
#define S_IFREG
Definition: ext2fs.h:361
#define S_IFSOCK
Definition: ext2fs.h:359
#define S_IFIFO
Definition: ext2fs.h:365
#define S_IFBLK
Definition: ext2fs.h:362
#define S_ISBLK(m)
Definition: ext2fs.h:375
#define S_ISSOCK(m)
Definition: ext2fs.h:372
#define S_ISCHR(m)
Definition: ext2fs.h:377
#define S_ISFIFO(m)
Definition: ext2fs.h:378
#define S_ISLNK(m)
Definition: ext2fs.h:373
#define S_IFMT
Definition: ext2fs.h:358
#define S_IFCHR
Definition: ext2fs.h:364
#define S_IFLNK
Definition: ext2fs.h:360
unsigned int BOOL
Definition: ntddk_ex.h:94
EXPORT gid_t getgid()
Definition: gid.c:27
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble t
Definition: gl.h:2047
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
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 flag
Definition: glfuncs.h:52
#define _(X)
Definition: i386-dis.c:35
int __cdecl closedir(DIR *)
DIR *__cdecl opendir(const char *)
struct dirent *__cdecl readdir(DIR *)
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
const char * filename
Definition: ioapi.h:137
#define ISO_FILE
Definition: iso9660.h:263
#define MAX_ISONAME
Definition: iso9660.h:242
#define ISO_ASSOCIATED
Definition: iso9660.h:266
#define ISO_DIRECTORY
Definition: iso9660.h:265
#define ISO_MULTIEXTENT
Definition: iso9660.h:271
#define ISO_EXISTENCE
Definition: iso9660.h:264
EXPORT void set_723(void *vp, UInt32_t i)
Definition: isonum.c:76
EXPORT UInt32_t get_733(void *vp)
Definition: isonum.c:219
EXPORT void set_733(void *vp, UInt32_t i)
Definition: isonum.c:125
#define LOCAL(type)
Definition: jmorecfg.h:289
EXPORT int js_snprintf(char *buf, unsigned maxcnt, char *form, va_alist)
Definition: jssnprintf.c:62
#define c
Definition: ke_i.h:80
#define debug(msg)
Definition: key_call.c:71
#define lstat
Definition: syshdrs.h:49
struct S1 s1
struct S2 s2
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define i_matches(FN)
Definition: match.h:73
#define j_matches(FN)
Definition: match.h:77
#define h_matches(FN)
Definition: match.h:85
#define matches(FN)
Definition: match.h:70
#define u_matches(FN)
Definition: match.h:81
EXPORT int iso9660_date(char *result, time_t crtime)
Definition: mkisofs.c:1868
int rationalize_dirmode
Definition: mkisofs.c:147
int volume_sequence_number
Definition: mkisofs.c:173
int jhide_trans_tbl
Definition: mkisofs.c:232
uid_t uid_to_use
Definition: mkisofs.c:148
int iso9660_level
Definition: mkisofs.c:242
int new_dir_mode
Definition: mkisofs.c:152
off_t maxnonlarge
Definition: mkisofs.c:241
UInt32_t session_start
Definition: mkisofs.c:77
int rationalize
Definition: mkisofs.c:143
int hide_rr_moved
Definition: mkisofs.c:233
int all_files
Definition: mkisofs.c:132
unsigned int path_table_size
Definition: mkisofs.c:78
int use_RockRidge
Definition: mkisofs.c:110
int rationalize_gid
Definition: mkisofs.c:145
int omit_version_number
Definition: mkisofs.c:236
BOOL archive_isreg
Definition: mkisofs.c:93
char * trans_tbl
Definition: mkisofs.c:259
int filemode_to_use
Definition: mkisofs.c:150
int rationalize_uid
Definition: mkisofs.c:144
EXPORT void * e_malloc(size_t size)
Definition: mkisofs.c:3921
int rationalize_filemode
Definition: mkisofs.c:146
int iso9660_namelen
Definition: mkisofs.c:243
BOOL follow_links
Definition: mkisofs.c:134
EXPORT char * e_strdup(char *s) const
Definition: mkisofs.c:3941
int generate_tables
Definition: mkisofs.c:153
gid_t gid_to_use
Definition: mkisofs.c:149
Uint RR_relocation_depth
Definition: mkisofs.c:239
int full_iso9660_filenames
Definition: mkisofs.c:244
int use_XA
Definition: mkisofs.c:111
int do_largefiles
Definition: mkisofs.c:240
int dirmode_to_use
Definition: mkisofs.c:151
BOOL nodesc
Definition: mkisofs.c:202
#define TABLE_INODE
Definition: mkisofs.h:763
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define RESOURCE_FORK
Definition: mkisofs.h:806
#define INHIBIT_JOLIET_ENTRY
Definition: mkisofs.h:799
int create_udfsymlinks
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define DIR_WAS_SCANNED
Definition: mkisofs.h:805
#define RELOCATED_DIRECTORY
Definition: mkisofs.h:801
#define HIDDEN_FILE
Definition: mkisofs.h:804
#define IS_SYMLINK
Definition: mkisofs.h:807
#define INHIBIT_UDF_ENTRY
Definition: mkisofs.h:809
#define DIR_HAS_DOT
Definition: mkisofs.h:797
#define UNCACHED_DEVICE
Definition: mkisofs.h:765
#define STAT_INODE(X)
Definition: mkisofs.h:785
#define DIR_HAS_DOTDOT
Definition: mkisofs.h:798
#define MEMORY_FILE
Definition: mkisofs.h:803
#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 UNCACHED_INODE
Definition: mkisofs.h:764
#define SPATH_SEPARATOR
Definition: mkisofs.h:787
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static HWND child
Definition: cursoricon.c:298
int readlink(const char *path, char *buf, size_t size)
unsigned char * parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt)
Definition: multi.c:169
void finish_cl_pl_for_prev_session()
Definition: multi.c:2167
#define minor(rdev)
Definition: propsheet.cpp:929
#define major(rdev)
Definition: propsheet.cpp:928
#define __PR(a)
Definition: prototyp.h:106
EXPORT int generate_xa_rr_attributes(char *whole_name, char *name, struct directory_entry *s_entry, struct stat *statbuf, struct stat *lstatbuf, int deep_opt)
Definition: rock.c:236
#define NEED_CL
Definition: rock.h:51
#define NEED_SP
Definition: rock.h:53
#define DID_CHDIR
Definition: rock.h:54
#define NEED_CE
Definition: rock.h:52
#define NEED_RE
Definition: rock.h:49
#define NEED_PL
Definition: rock.h:50
#define offsetof(TYPE, MEMBER)
#define errno
Definition: errno.h:18
#define R_OK
Definition: io.h:171
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
EXPORT void add_directory_hash(dev_t dev, ino_t inode)
Definition: hash.c:346
EXPORT struct file_hash * find_directory_hash(dev_t dev, ino_t inode)
Definition: hash.c:375
EXPORT int delete_file_hash(struct directory_entry *de)
Definition: hash.c:559
EXPORT void flush_file_hash()
Definition: hash.c:584
EXPORT struct directory_entry * find_file_hash(char *name)
Definition: hash.c:461
EXPORT void add_file_hash(struct directory_entry *de)
Definition: hash.c:436
int iso9660_file_length(char *name, struct directory_entry *sresult, int dirflag) const
Definition: name.c:105
EXPORT int insert_file_entry(struct directory *this_dir, char *whole_path, char *short_name, struct stat *statp, int have_rsrc)
Definition: tree.c:1444
int verbose
Definition: main.c:60
LOCAL void dir_nesting_warn(struct directory *this_dir, char *path, int contflag)
Definition: tree.c:1118
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 sort_tree(struct directory *node)
Definition: tree.c:2842
LOCAL void delete_directory(struct directory *parent, struct directory *child)
Definition: tree.c:2801
struct stat root_statbuf
Definition: tree.c:110
EXPORT void finish_cl_pl_entries()
Definition: tree.c:1036
LOCAL Uchar symlink_buff[PATH_MAX+1]
Definition: tree.c:55
EXPORT void init_fstatbuf()
Definition: tree.c:2974
LOCAL void generate_reloc_directory()
Definition: tree.c:820
EXPORT struct directory_entry * search_tree_file(struct directory *node, char *filename)
Definition: tree.c:2885
static UConst char sccsid[]
Definition: tree.c:4
EXPORT void dump_tree(struct directory *node)
Definition: tree.c:2863
struct directory * reloc_dir
Definition: tree.c:111
struct stat fstatbuf
Definition: tree.c:108
EXPORT int lstat_filter(char *path, struct stat *st)
Definition: tree.c:244
EXPORT void attach_dot_entries(struct directory *dirnode, struct stat *this_stat, struct stat *parent_stat)
Definition: tree.c:905
#define is_archive(st)
EXPORT int scan_directory_tree(struct directory *this_dir, char *path, struct directory_entry *de)
Definition: tree.c:1147
LOCAL char * filetype(int t)
Definition: tree.c:114
EXPORT void generate_iso9660_directories(struct directory *node, FILE *outfile)
Definition: tree.c:2458
EXPORT struct directory * find_or_create_directory(struct directory *parent, char *path, struct directory_entry *de, int flag)
Definition: tree.c:2508
LOCAL void set_de_path(struct directory *parent, struct directory *this)
Definition: tree.c:2480
LOCAL struct directory_entry * dup_relocated_dir(struct directory *this_dir, struct directory_entry *s_entry, char *whole_path, char *short_name, struct stat *statp)
Definition: tree.c:1376
LOCAL int sort_n_finish(struct directory *this_dir)
Definition: tree.c:256
LOCAL char * rstr(char *s1, char *s2)
Definition: tree.c:165
EXPORT char * find_rr_attribute(unsigned char *pnt, int len, char *attr_type)
Definition: tree.c:1007
LOCAL void stat_fix(struct stat *st)
Definition: tree.c:183
EXPORT void generate_one_directory(struct directory *dpnt, FILE *outfile)
Definition: write.c:1539
EXPORT int sort_directory(struct directory_entry **sort_dir, int rr)
Definition: write.c:814
#define apple_hyb
#define dvd_aud_vid_flag
#define EX_BAD
Definition: standard.h:62
Definition: dirent.h:40
uint64_t parent
Definition: btrfs_drv.h:459
Definition: mkisofs.h:107
char * whole_name
Definition: mkisofs.h:118
dev_t dev
Definition: mkisofs.h:133
struct directory_entry * mxroot
Definition: mkisofs.h:121
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
ino_t inode
Definition: mkisofs.h:132
struct directory * filedir
Definition: mkisofs.h:119
unsigned short priority
Definition: mkisofs.h:114
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
char * de_path
Definition: mkisofs.h:274
unsigned int ce_bytes
Definition: mkisofs.h:276
unsigned int extent
Definition: mkisofs.h:280
unsigned int jsize
Definition: mkisofs.h:281
unsigned int size
Definition: mkisofs.h:279
struct directory * subdir
Definition: mkisofs.h:268
unsigned int depth
Definition: mkisofs.h:278
unsigned int jextent
Definition: mkisofs.h:282
struct directory * next
Definition: mkisofs.h:267
struct directory_entry * self
Definition: mkisofs.h:272
struct directory_entry * contents
Definition: mkisofs.h:270
Definition: fatfs.h:198
char * d_name
Definition: dirent.h:29
Definition: name.c:39
Definition: stat.h:55
time_t st_ctime
Definition: stat.h:66
short st_gid
Definition: stat.h:61
unsigned short st_mode
Definition: stat.h:58
time_t st_mtime
Definition: stat.h:65
_dev_t st_dev
Definition: stat.h:56
short st_uid
Definition: stat.h:60
_dev_t st_rdev
Definition: stat.h:62
_off_t st_size
Definition: stat.h:63
time_t st_atime
Definition: stat.h:64
Definition: ps.c:97
const WCHAR * name
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
#define stat_set_cnsecs(s, n)
Definition: stat.h:399
#define S_ISEVC(m)
Definition: stat.h:177
#define S_ISDOOR(m)
Definition: stat.h:156
#define stat_cnsecs(s)
Definition: stat.h:395
#define S_ISCTG(m)
Definition: stat.h:128
#define stat_mnsecs(s)
Definition: stat.h:394
#define S_ISSHAD(m)
Definition: stat.h:142
#define S_ISMPB(m)
Definition: stat.h:114
#define S_ISNAM(m)
Definition: stat.h:100
#define S_ISWHT(m)
Definition: stat.h:170
#define stat_set_ansecs(s, n)
Definition: stat.h:397
#define stat_set_mnsecs(s, n)
Definition: stat.h:398
#define S_ISMPC(m)
Definition: stat.h:86
#define stat_ansecs(s)
Definition: stat.h:393
Definition: dlist.c:348
unsigned char Uchar
Definition: utypes.h:45
int ret
attr_type
Definition: widltypes.h:69
static FILE * outfile
Definition: wrjpgcom.c:81
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define PATH_SEPARATOR
Definition: xmllint.c:205