/[debburn]/cdrkit/trunk/genisoimage/tree.c
ViewVC logotype

Contents of /cdrkit/trunk/genisoimage/tree.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5