1 /*
2 * File tree.c - scan directory tree and build memory structures for iso9660
3 * filesystem
4
5 Written by Eric Youngdale (1993).
6
7 Copyright 1993 Yggdrasil Computing, Incorporated
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
24
25 /* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 16/3/1999 */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 #include <errno.h>
31
32 #include "config.h"
33 #include "apple_proto.h"
34
35 #ifndef VMS
36 #if defined(MAJOR_IN_SYSMACROS)
37 #include <sys/sysmacros.h>
38 #endif
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #include <fctldefs.h>
44
45 #if defined(MAJOR_IN_MKDEV)
46 #include <sys/types.h>
47 #include <sys/mkdev.h>
48 #endif
49 #else
50 #include <sys/file.h>
51 #include <vms/fabdef.h>
52 #include "vms.h"
53 extern char * strdup(const char *);
54 #endif
55
56 /*
57 * Autoconf should be able to figure this one out for us and let us know
58 * whether the system has memmove or not.
59 */
60 # ifndef HAVE_MEMMOVE
61 # define memmove(d, s, n) bcopy ((s), (d), (n))
62 # endif
63
64 #include "mkisofs.h"
65 #include "iso9660.h"
66 #include "match.h"
67
68 #include <sys/stat.h>
69
70 #ifdef DOESNT_WORK
71
72 #ifdef NON_UNIXFS
73 #define S_ISLNK(m) (0)
74 #define S_ISSOCK(m) (0)
75 #define S_ISFIFO(m) (0)
76 #else
77 #ifndef S_ISLNK
78 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
79 #endif
80 #ifndef S_ISSOCK
81 # ifdef S_IFSOCK
82 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
83 # else
84 # define S_ISSOCK(m) (0)
85 # endif
86 #endif
87 #endif
88
89 #else
90 #include <statdefs.h>
91 #endif
92
93
94 #ifdef __SVR4
95 extern char * strdup(const char *);
96 #endif
97
98 static unsigned char symlink_buff[256];
99
100 static void stat_fix __PR((struct stat * st));
101 static void generate_reloc_directory __PR((void));
102
103 static void DECL(attach_dot_entries, (struct directory * dirnode,
104 struct stat * parent_stat));
105 static void DECL(delete_directory, (struct directory * parent, struct directory * child));
106
107 extern int verbose;
108
109 struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */
110
111 struct stat root_statbuf = {0, }; /* Stat buffer for root directory */
112
113 struct directory * reloc_dir = NULL;
114
115 static void
FDECL1(stat_fix,struct stat *,st)116 FDECL1(stat_fix, struct stat *, st)
117 {
118 /* Remove the uid and gid, they will only be useful on the author's
119 system. */
120 st->st_uid = 0;
121 st->st_gid = 0;
122
123 /*
124 * Make sure the file modes make sense. Turn on all read bits. Turn
125 * on all exec/search bits if any exec/search bit is set. Turn off
126 * all write bits, and all special mode bits (on a r/o fs lock bits
127 * are useless, and with uid+gid 0 don't want set-id bits, either).
128 */
129 st->st_mode |= 0444;
130 #ifndef _WIN32 /* make all file "executable" */
131 if (st->st_mode & 0111)
132 #endif /* _WIN32 */
133 st->st_mode |= 0111;
134 st->st_mode &= ~07222;
135 }
136
137 int
FDECL2(stat_filter,char *,path,struct stat *,st)138 FDECL2(stat_filter, char *, path, struct stat *, st)
139 {
140 int result = stat(path, st);
141 if (result >= 0 && rationalize)
142 stat_fix(st);
143 return result;
144 }
145
146 int
FDECL2(lstat_filter,char *,path,struct stat *,st)147 FDECL2(lstat_filter, char *, path, struct stat *, st)
148 {
149 int result = lstat(path, st);
150 if (result >= 0 && rationalize)
151 stat_fix(st);
152 return result;
153 }
154
FDECL1(sort_n_finish,struct directory *,this_dir)155 static int FDECL1(sort_n_finish, struct directory *, this_dir)
156 {
157 struct directory_entry * s_entry;
158 struct directory_entry * s_entry1;
159 struct directory_entry * table;
160 int count;
161 int d1;
162 int d2;
163 int d3;
164 int new_reclen;
165 char * c;
166 int status = 0;
167 int tablesize = 0;
168 char newname[34];
169 char rootname[34];
170
171 /* Here we can take the opportunity to toss duplicate entries from the
172 directory. */
173
174 /* ignore if it's hidden */
175 if(this_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
176 {
177 return 0;
178 }
179
180 table = NULL;
181
182 init_fstatbuf();
183
184 /*
185 * If we had artificially created this directory, then we might be
186 * missing the required '.' entries. Create these now if we need
187 * them.
188 */
189 if( (this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) !=
190 (DIR_HAS_DOT | DIR_HAS_DOTDOT) )
191 {
192 attach_dot_entries(this_dir, &fstatbuf);
193 }
194
195 flush_file_hash();
196 s_entry = this_dir->contents;
197 while(s_entry)
198 {
199 /* ignore if it's hidden */
200 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
201 {
202 s_entry = s_entry->next;
203 continue;
204 }
205
206 /*
207 * First assume no conflict, and handle this case
208 */
209 if(!(s_entry1 = find_file_hash(s_entry->isorec.name)))
210 {
211 add_file_hash(s_entry);
212 s_entry = s_entry->next;
213 continue;
214 }
215
216 #ifdef APPLE_HYB
217 /* if the pair are associated, then skip (as they have the same name!) */
218 if(apple_both && s_entry1->assoc && s_entry1->assoc == s_entry)
219 {
220 s_entry = s_entry->next;
221 continue;
222 }
223 #endif /* APPLE_HYB */
224
225 if(s_entry1 == s_entry)
226 {
227 fprintf(stderr,"Fatal goof\n");
228 exit(1);
229 }
230
231 /*
232 * OK, handle the conflicts. Try substitute names until we come
233 * up with a winner
234 */
235 strcpy(rootname, s_entry->isorec.name);
236 if(full_iso9660_filenames)
237 {
238 if(strlen(rootname) > 27) rootname[27] = 0;
239 }
240
241 /*
242 * Strip off the non-significant part of the name so that we are left
243 * with a sensible root filename. If we don't find a '.', then try
244 * a ';'.
245 */
246 c = strchr(rootname, '.');
247 if (c)
248 *c = 0;
249 else
250 {
251 c = strchr(rootname, ';');
252 if (c) *c = 0;
253 }
254 for(d1 = 0; d1 < 36; d1++)
255 {
256 for(d2 = 0; d2 < 36; d2++)
257 {
258 for(d3 = 0; d3 < 36; d3++)
259 {
260 snprintf(newname, sizeof newname, "%s.%c%c%c%s", rootname,
261 (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10),
262 (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10),
263 (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10),
264 (s_entry->isorec.flags[0] == 2 ||
265 omit_version_number ? "" : ";1"));
266
267 #ifdef VMS
268 /* Sigh. VAXCRTL seems to be broken here */
269 {
270 int ijk = 0;
271 while(newname[ijk])
272 {
273 if(newname[ijk] == ' ') newname[ijk] = '0';
274 ijk++;
275 }
276 }
277 #endif
278
279 if(!find_file_hash(newname)) goto got_valid_name;
280 }
281 }
282 }
283
284 /*
285 * If we fell off the bottom here, we were in real trouble.
286 */
287 fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name);
288 exit(1);
289
290 got_valid_name:
291 /*
292 * OK, now we have a good replacement name. Now decide which one
293 * of these two beasts should get the name changed
294 */
295 if(s_entry->priority < s_entry1->priority)
296 {
297 if( verbose > 0 )
298 {
299 fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname,
300 this_dir->whole_name, SPATH_SEPARATOR,
301 s_entry->name, s_entry1->name);
302 }
303 s_entry->isorec.name_len[0] = strlen(newname);
304 new_reclen = sizeof(struct iso_directory_record) -
305 sizeof(s_entry->isorec.name) +
306 strlen(newname);
307 if(use_RockRidge)
308 {
309 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
310 new_reclen += s_entry->rr_attr_size;
311 }
312 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
313 s_entry->isorec.length[0] = new_reclen;
314 strcpy(s_entry->isorec.name, newname);
315 #ifdef APPLE_HYB
316 /* has resource fork - needs new name */
317 if (apple_both && s_entry->assoc) {
318 struct directory_entry *s_entry2 = s_entry->assoc;
319
320 /* resource fork name *should* be the same as the data fork */
321 s_entry2->isorec.name_len[0] = s_entry->isorec.name_len[0];
322 strcpy(s_entry2->isorec.name, s_entry->isorec.name);
323 s_entry2->isorec.length[0] = new_reclen;
324 }
325 #endif /* APPLE_HYB */
326 }
327 else
328 {
329 delete_file_hash(s_entry1);
330 if( verbose > 0 )
331 {
332 fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname,
333 this_dir->whole_name, SPATH_SEPARATOR,
334 s_entry1->name, s_entry->name);
335 }
336 s_entry1->isorec.name_len[0] = strlen(newname);
337 new_reclen = sizeof(struct iso_directory_record) -
338 sizeof(s_entry1->isorec.name) +
339 strlen(newname);
340 if(use_RockRidge)
341 {
342 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
343 new_reclen += s_entry1->rr_attr_size;
344 }
345 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
346 s_entry1->isorec.length[0] = new_reclen;
347 strcpy(s_entry1->isorec.name, newname);
348 add_file_hash(s_entry1);
349 #ifdef APPLE_HYB
350 /* has resource fork - needs new name */
351 if (apple_both && s_entry1->assoc) {
352 struct directory_entry *s_entry2 = s_entry1->assoc;
353
354 /* resource fork name *should* be the same as the data fork */
355 s_entry2->isorec.name_len[0] = s_entry1->isorec.name_len[0];
356 strcpy(s_entry2->isorec.name, s_entry1->isorec.name);
357 s_entry2->isorec.length[0] = new_reclen;
358 }
359 #endif /* APPLE_HYB */
360 }
361 add_file_hash(s_entry);
362 s_entry = s_entry->next;
363 }
364
365 if(generate_tables
366 #ifdef APPLE_HYB
367 && !find_file_hash(trans_tbl)
368 #else
369 && !find_file_hash("TRANS.TBL")
370 #endif /* APPLE_HYB */
371 && (reloc_dir != this_dir)
372 && (this_dir->extent == 0) )
373 {
374 /*
375 * First we need to figure out how big this table is
376 */
377 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
378 {
379 if(strcmp(s_entry->name, ".") == 0 ||
380 strcmp(s_entry->name, "..") == 0) continue;
381 #ifdef APPLE_HYB
382 /* skip table entry for the resource fork */
383 if(apple_both && (s_entry->isorec.flags[0] & ASSOC_FLAG))
384 continue;
385 #endif /* APPLE_HYB */
386 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue;
387 if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
388 }
389 }
390
391 if( tablesize > 0 )
392 {
393 table = (struct directory_entry *)
394 e_malloc(sizeof (struct directory_entry));
395 memset(table, 0, sizeof(struct directory_entry));
396 table->table = NULL;
397 table->next = this_dir->contents;
398 this_dir->contents = table;
399
400 table->filedir = root;
401 table->isorec.flags[0] = 0;
402 table->priority = 32768;
403 iso9660_date(table->isorec.date, fstatbuf.st_mtime);
404 table->inode = TABLE_INODE;
405 table->dev = (dev_t) UNCACHED_DEVICE;
406 set_723(table->isorec.volume_sequence_number, volume_sequence_number);
407 set_733((char *) table->isorec.size, tablesize);
408 table->size = tablesize;
409 table->filedir = this_dir;
410 if (jhide_trans_tbl)
411 table->de_flags |= INHIBIT_JOLIET_ENTRY;
412 table->name = strdup("<translation table>");
413 table->table = (char *) e_malloc(ROUND_UP(tablesize)+1);
414 memset(table->table, 0, ROUND_UP(tablesize)+1);
415 #ifdef APPLE_HYB
416 iso9660_file_length (trans_tbl, table, 0);
417 #else
418 iso9660_file_length ("TRANS.TBL", table, 0);
419 #endif /* APPLE_HYB */
420
421 if(use_RockRidge)
422 {
423 fstatbuf.st_mode = 0444 | S_IFREG;
424 fstatbuf.st_nlink = 1;
425 generate_rock_ridge_attributes("",
426 #ifdef APPLE_HYB
427 trans_tbl, table,
428 #else
429 "TRANS.TBL", table,
430 #endif /* APPLE_HYB */
431 &fstatbuf, &fstatbuf, 0);
432 }
433 }
434
435 /*
436 * We have now chosen the 8.3 names and we should now know the length
437 * of every entry in the directory.
438 */
439 for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
440 {
441 /* skip if it's hidden */
442 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
443 {
444 continue;
445 }
446
447 new_reclen = strlen(s_entry->isorec.name);
448
449 /*
450 * First update the path table sizes for directories.
451 */
452 if(s_entry->isorec.flags[0] == 2)
453 {
454 if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
455 {
456 path_table_size += new_reclen + sizeof(struct iso_path_table) - 1;
457 if (new_reclen & 1) path_table_size++;
458 }
459 else
460 {
461 new_reclen = 1;
462 if (this_dir == root && strlen(s_entry->name) == 1)
463 {
464 path_table_size += sizeof(struct iso_path_table);
465 }
466 }
467 }
468 if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */
469 s_entry->isorec.name_len[0] = new_reclen;
470
471 new_reclen +=
472 sizeof(struct iso_directory_record) -
473 sizeof(s_entry->isorec.name);
474
475 if (new_reclen & 1)
476 new_reclen++;
477
478 new_reclen += s_entry->rr_attr_size;
479
480 if (new_reclen & 1) new_reclen++;
481
482 if(new_reclen > 0xff)
483 {
484 fprintf(stderr,"Fatal error - RR overflow for file %s\n",
485 s_entry->name);
486 exit(1);
487 }
488 s_entry->isorec.length[0] = new_reclen;
489 }
490
491 status = sort_directory(&this_dir->contents);
492 if( status > 0 )
493 {
494 fprintf(stderr, "Unable to sort directory %s\n",
495 this_dir->whole_name);
496 }
497
498 /*
499 * If we are filling out a TRANS.TBL, generate the entries that will
500 * go in the thing.
501 */
502 if(table)
503 {
504 count = 0;
505 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
506 if(s_entry == table) continue;
507 if(!s_entry->table) continue;
508 if(strcmp(s_entry->name, ".") == 0 ||
509 strcmp(s_entry->name, "..") == 0) continue;
510 #ifdef APPLE_HYB
511 /* skip table entry for the resource fork */
512 if(apple_both && (s_entry->isorec.flags[0] & ASSOC_FLAG))
513 continue;
514 #endif /* APPLE_HYB */
515 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue;
516 /*
517 * Warning: we cannot use the return value of sprintf because
518 * old BSD based sprintf() implementations will return
519 * a pointer to the result instead of a count.
520 */
521 sprintf(table->table + count, "%c %-34s%s",
522 s_entry->table[0],
523 s_entry->isorec.name, s_entry->table+1);
524 count += strlen(table->table + count);
525 free(s_entry->table);
526 s_entry->table = NULL;
527 }
528
529 if(count != tablesize)
530 {
531 fprintf(stderr,"Translation table size mismatch %d %d\n",
532 count, tablesize);
533 exit(1);
534 }
535 }
536
537 /*
538 * Now go through the directory and figure out how large this one will be.
539 * Do not split a directory entry across a sector boundary
540 */
541 s_entry = this_dir->contents;
542 this_dir->ce_bytes = 0;
543 while(s_entry)
544 {
545 /* skip if it's hidden */
546 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
547 s_entry = s_entry->next;
548 continue;
549 }
550
551 new_reclen = s_entry->isorec.length[0];
552 if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
553 this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) &
554 ~(SECTOR_SIZE - 1);
555 this_dir->size += new_reclen;
556
557 /* See if continuation entries were used on disc */
558 if(use_RockRidge &&
559 s_entry->rr_attr_size != s_entry->total_rr_attr_size)
560 {
561 unsigned char * pnt;
562 int len;
563 int nbytes;
564
565 pnt = s_entry->rr_attributes;
566 len = s_entry->total_rr_attr_size;
567
568 /*
569 * We make sure that each continuation entry record is not
570 * split across sectors, but each file could in theory have more
571 * than one CE, so we scan through and figure out what we need.
572 */
573 while(len > 3)
574 {
575 if(pnt[0] == 'C' && pnt[1] == 'E')
576 {
577 nbytes = get_733((char *) pnt+20);
578
579 if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
580 SECTOR_SIZE) this_dir->ce_bytes =
581 ROUND_UP(this_dir->ce_bytes);
582 /* Now store the block in the ce buffer */
583 this_dir->ce_bytes += nbytes;
584 if(this_dir->ce_bytes & 1) this_dir->ce_bytes++;
585 }
586 len -= pnt[2];
587 pnt += pnt[2];
588 }
589 }
590 s_entry = s_entry->next;
591 }
592 return status;
593 }
594
generate_reloc_directory()595 static void generate_reloc_directory()
596 {
597 time_t current_time;
598 struct directory_entry *s_entry;
599
600 /* Create an entry for our internal tree */
601 time (¤t_time);
602 reloc_dir = (struct directory *)
603 e_malloc(sizeof(struct directory));
604 memset(reloc_dir, 0, sizeof(struct directory));
605 reloc_dir->parent = root;
606 reloc_dir->next = root->subdir;
607 root->subdir = reloc_dir;
608 reloc_dir->depth = 1;
609 if (hide_rr_moved) {
610 reloc_dir->whole_name = strdup("./.rr_moved");
611 reloc_dir->de_name = strdup(".rr_moved");
612 } else {
613 reloc_dir->whole_name = strdup("./rr_moved");
614 reloc_dir->de_name = strdup("rr_moved");
615 }
616 reloc_dir->extent = 0;
617
618
619 /* Now create an actual directory entry */
620 s_entry = (struct directory_entry *)
621 e_malloc(sizeof (struct directory_entry));
622 memset(s_entry, 0, sizeof(struct directory_entry));
623 s_entry->next = root->contents;
624 reloc_dir->self = s_entry;
625
626 /*
627 * The rr_moved entry will not appear in the Joliet tree.
628 */
629 reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
630 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
631
632 root->contents = s_entry;
633 root->contents->name = strdup(reloc_dir->de_name);
634 root->contents->filedir = root;
635 root->contents->isorec.flags[0] = 2;
636 root->contents->priority = 32768;
637 iso9660_date(root->contents->isorec.date, current_time);
638 root->contents->inode = UNCACHED_INODE;
639 root->contents->dev = (dev_t) UNCACHED_DEVICE;
640 set_723(root->contents->isorec.volume_sequence_number, volume_sequence_number);
641 iso9660_file_length (reloc_dir->de_name, root->contents, 1);
642
643 if(use_RockRidge){
644 fstatbuf.st_mode = 0555 | S_IFDIR;
645 fstatbuf.st_nlink = 2;
646 generate_rock_ridge_attributes("",
647 hide_rr_moved ? ".rr_moved" : "rr_moved",
648 s_entry, &fstatbuf, &fstatbuf, 0);
649 };
650
651 /* Now create the . and .. entries in rr_moved */
652 /* Now create an actual directory entry */
653 attach_dot_entries(reloc_dir, &root_statbuf);
654 }
655
656 /*
657 * Function: attach_dot_entries
658 *
659 * Purpose: Create . and .. entries for a new directory.
660 *
661 * Notes: Only used for artificial directories that
662 * we are creating.
663 */
FDECL2(attach_dot_entries,struct directory *,dirnode,struct stat *,parent_stat)664 static void FDECL2(attach_dot_entries, struct directory *, dirnode,
665 struct stat *, parent_stat)
666 {
667 struct directory_entry *s_entry;
668 struct directory_entry *orig_contents;
669 int deep_flag = 0;
670
671 init_fstatbuf();
672
673 orig_contents = dirnode->contents;
674
675 if( (dirnode->dir_flags & DIR_HAS_DOTDOT) == 0 )
676 {
677 s_entry = (struct directory_entry *)
678 e_malloc(sizeof (struct directory_entry));
679 memcpy(s_entry, dirnode->self,
680 sizeof(struct directory_entry));
681 #ifdef APPLE_HYB
682 if (dirnode->self->hfs_ent) {
683 s_entry->hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent));
684 memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent,
685 sizeof (hfsdirent));
686 }
687 #endif
688 s_entry->name = strdup("..");
689 s_entry->whole_name = NULL;
690 s_entry->isorec.name_len[0] = 1;
691 s_entry->isorec.flags[0] = 2; /* Mark as a directory */
692 iso9660_file_length ("..", s_entry, 1);
693 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
694 s_entry->filedir = dirnode->parent;
695
696 dirnode->contents = s_entry;
697 dirnode->contents->next = orig_contents;
698 orig_contents = s_entry;
699
700 if(use_RockRidge)
701 {
702 if( parent_stat == NULL )
703 {
704 parent_stat = &fstatbuf;
705 }
706 generate_rock_ridge_attributes("",
707 "..", s_entry,
708 parent_stat,
709 parent_stat, 0);
710 }
711 dirnode->dir_flags |= DIR_HAS_DOTDOT;
712 }
713
714 if( (dirnode->dir_flags & DIR_HAS_DOT) == 0 )
715 {
716 s_entry = (struct directory_entry *)
717 e_malloc(sizeof (struct directory_entry));
718 memcpy(s_entry, dirnode->self,
719 sizeof(struct directory_entry));
720 #ifdef APPLE_HYB
721 if (dirnode->self->hfs_ent) {
722 s_entry->hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent));
723 memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent,
724 sizeof (hfsdirent));
725 }
726 #endif
727 s_entry->name = strdup(".");
728 s_entry->whole_name = NULL;
729 s_entry->isorec.name_len[0] = 1;
730 s_entry->isorec.flags[0] = 2; /* Mark as a directory */
731 iso9660_file_length (".", s_entry, 1);
732 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
733 s_entry->filedir = dirnode;
734
735 dirnode->contents = s_entry;
736 dirnode->contents->next = orig_contents;
737
738 if(use_RockRidge)
739 {
740 fstatbuf.st_mode = 0555 | S_IFDIR;
741 fstatbuf.st_nlink = 2;
742
743 if( dirnode == root )
744 {
745 deep_flag |= NEED_CE | NEED_SP; /* For extension record */
746 }
747
748 generate_rock_ridge_attributes("",
749 ".", s_entry,
750 &fstatbuf, &fstatbuf, deep_flag);
751 }
752
753 dirnode->dir_flags |= DIR_HAS_DOT;
754 }
755
756 }
757
FDECL2(update_nlink,struct directory_entry *,s_entry,int,value)758 static void FDECL2(update_nlink, struct directory_entry *, s_entry, int, value)
759 {
760 unsigned char * pnt;
761 int len;
762
763 pnt = s_entry->rr_attributes;
764 len = s_entry->total_rr_attr_size;
765 while(len)
766 {
767 if(pnt[0] == 'P' && pnt[1] == 'X')
768 {
769 set_733((char *) pnt+12, value);
770 break;
771 }
772 len -= pnt[2];
773 pnt += pnt[2];
774 }
775 }
776
FDECL1(increment_nlink,struct directory_entry *,s_entry)777 static void FDECL1(increment_nlink, struct directory_entry *, s_entry)
778 {
779 unsigned char * pnt;
780 int len, nlink;
781
782 pnt = s_entry->rr_attributes;
783 len = s_entry->total_rr_attr_size;
784 while(len)
785 {
786 if(pnt[0] == 'P' && pnt[1] == 'X')
787 {
788 nlink = get_733((char *) pnt+12);
789 set_733((char *) pnt+12, nlink+1);
790 break;
791 }
792 len -= pnt[2];
793 pnt += pnt[2];
794 }
795 }
796
finish_cl_pl_entries()797 void finish_cl_pl_entries(){
798 struct directory_entry *s_entry, *s_entry1;
799 struct directory * d_entry;
800
801 /* if the reloc_dir is hidden (empty), then return */
802 if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
803 return;
804
805 s_entry = reloc_dir->contents;
806 s_entry = s_entry->next->next; /* Skip past . and .. */
807 for(; s_entry; s_entry = s_entry->next){
808 /* skip if it's hidden */
809 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
810 continue;
811 }
812 d_entry = reloc_dir->subdir;
813 while(d_entry){
814 if(d_entry->self == s_entry) break;
815 d_entry = d_entry->next;
816 };
817 if(!d_entry){
818 fprintf(stderr,"Unable to locate directory parent\n");
819 exit(1);
820 };
821
822 /* First fix the PL pointer in the directory in the rr_reloc dir */
823 s_entry1 = d_entry->contents->next;
824 set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
825 s_entry->filedir->extent);
826
827 /* Now fix the CL pointer */
828 s_entry1 = s_entry->parent_rec;
829
830 set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
831 d_entry->extent);
832
833 s_entry->filedir = reloc_dir; /* Now we can fix this */
834 }
835 /* Next we need to modify the NLINK terms in the assorted root directory records
836 to account for the presence of the RR_MOVED directory */
837
838 increment_nlink(root->self);
839 increment_nlink(root->self->next);
840 d_entry = root->subdir;
841 while(d_entry){
842 increment_nlink(d_entry->contents->next);
843 d_entry = d_entry->next;
844 };
845 }
846
847 /*
848 * Function: scan_directory_tree
849 *
850 * Purpose: Walk through a directory on the local machine
851 * filter those things we don't want to include
852 * and build our representation of a dir.
853 *
854 * Notes:
855 */
856 int
FDECL3(scan_directory_tree,struct directory *,this_dir,char *,path,struct directory_entry *,de)857 FDECL3(scan_directory_tree,struct directory *, this_dir,
858 char *, path,
859 struct directory_entry *, de)
860 {
861 DIR * current_dir;
862 char whole_path[1024];
863 struct dirent * d_entry;
864 struct directory * parent;
865 int dflag;
866 char * old_path;
867
868 if (verbose > 1)
869 {
870 fprintf(stderr, "Scanning %s\n", path);
871 }
872
873 current_dir = opendir(path);
874 d_entry = NULL;
875
876 /* Apparently NFS sometimes allows you to open the directory, but
877 then refuses to allow you to read the contents. Allow for this */
878
879 old_path = path;
880
881 if(current_dir) d_entry = readdir(current_dir);
882
883 if(!current_dir || !d_entry)
884 {
885 fprintf(stderr,"Unable to open directory %s\n", path);
886 de->isorec.flags[0] &= ~2; /* Mark as not a directory */
887 if(current_dir) closedir(current_dir);
888 return 0;
889 }
890
891 parent = de->filedir;
892 /* Set up the struct for the current directory, and insert it into the
893 tree */
894
895 #ifdef VMS
896 vms_path_fixup(path);
897 #endif
898
899 /*
900 * if entry for this sub-directory is hidden, then hide this directory
901 */
902 if (de->de_flags & INHIBIT_ISO9660_ENTRY)
903 this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY;
904
905 if (de->de_flags & INHIBIT_JOLIET_ENTRY)
906 this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
907
908 /*
909 * Now we scan the directory itself, and look at what is inside of it.
910 */
911 dflag = 0;
912 while(1==1){
913
914 /* The first time through, skip this, since we already asked for
915 the first entry when we opened the directory. */
916 if(dflag) d_entry = readdir(current_dir);
917 dflag++;
918
919 if(!d_entry) break;
920
921 /* OK, got a valid entry */
922
923 /* If we do not want all files, then pitch the backups. */
924 if(!all_files){
925 if( strchr(d_entry->d_name,'~')
926 || strchr(d_entry->d_name,'#'))
927 {
928 if( verbose > 0 )
929 {
930 fprintf(stderr, "Ignoring file %s\n", d_entry->d_name);
931 }
932 continue;
933 }
934 }
935
936 #ifdef APPLE_HYB
937 if (apple_both) {
938 /* exclude certain HFS type files/directories for the time being */
939 if (hfs_exclude(d_entry->d_name))
940 continue;
941 }
942 #endif /* APPLE_HYB */
943
944 if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){
945 fprintf(stderr, "Overflow of stat buffer\n");
946 exit(1);
947 };
948
949 /* Generate the complete ASCII path for this file */
950 strcpy(whole_path, path);
951 #ifndef VMS
952 if(whole_path[strlen(whole_path)-1] != '/')
953 strcat(whole_path, "/");
954 #endif
955 strcat(whole_path, d_entry->d_name);
956
957 /** Should we exclude this file ? */
958 if (matches(d_entry->d_name) || matches(whole_path)) {
959 if (verbose > 1) {
960 fprintf(stderr, "Excluded by match: %s\n", whole_path);
961 }
962 continue;
963 }
964
965 if( generate_tables
966 #ifdef APPLE_HYB
967 && strcmp(d_entry->d_name, trans_tbl) == 0 )
968 #else
969 && strcmp(d_entry->d_name, "TRANS.TBL") == 0 )
970 #endif /* APPLE_HYB */
971 {
972 /*
973 * Ignore this entry. We are going to be generating new
974 * versions of these files, and we need to ignore any
975 * originals that we might have found.
976 */
977 if (verbose > 1)
978 {
979 fprintf(stderr, "Excluded: %s\n",whole_path);
980 }
981 continue;
982 }
983
984 /*
985 * If we already have a '.' or a '..' entry, then don't
986 * insert new ones.
987 */
988 if( strcmp(d_entry->d_name, ".") == 0
989 && this_dir->dir_flags & DIR_HAS_DOT )
990 {
991 continue;
992 }
993
994 if( strcmp(d_entry->d_name, "..") == 0
995 && this_dir->dir_flags & DIR_HAS_DOTDOT )
996 {
997 continue;
998 }
999
1000 #if 0
1001 if (verbose > 1) fprintf(stderr, "%s\n",whole_path);
1002 #endif
1003 /*
1004 * This actually adds the entry to the directory in question.
1005 */
1006 #ifdef APPLE_HYB
1007 insert_file_entry(this_dir, whole_path, d_entry->d_name, 0);
1008 #else
1009 insert_file_entry(this_dir, whole_path, d_entry->d_name);
1010 #endif /* APPLE_HYB */
1011 }
1012 closedir(current_dir);
1013
1014 #ifdef APPLE_HYB
1015 /* if we cached the HFS info stuff for this directory, then delete it */
1016 if (this_dir->hfs_info) {
1017 del_hfs_info(this_dir->hfs_info);
1018 this_dir->hfs_info = 0;
1019 }
1020 #endif /* APPLE_HYB */
1021
1022 return 1;
1023 }
1024
1025
1026 /*
1027 * Function: insert_file_entry
1028 *
1029 * Purpose: Insert one entry into our directory node.
1030 *
1031 * Note:
1032 * This function inserts a single entry into the directory. It
1033 * is assumed that all filtering and decision making regarding what
1034 * we want to include has already been made, so the purpose of this
1035 * is to insert one entry (file, link, dir, etc), into this directory.
1036 * Note that if the entry is a dir (or if we are following links,
1037 * and the thing it points to is a dir), then we will scan those
1038 * trees before we return.
1039 */
1040 #ifdef APPLE_HYB
1041 int
FDECL4(insert_file_entry,struct directory *,this_dir,char *,whole_path,char *,short_name,int,have_rsrc)1042 FDECL4(insert_file_entry,struct directory *, this_dir,
1043 char *, whole_path,
1044 char *, short_name,
1045 int, have_rsrc)
1046 #else
1047 int
1048 FDECL3(insert_file_entry,struct directory *, this_dir,
1049 char *, whole_path,
1050 char *, short_name)
1051 #endif /* APPLE_HYB */
1052 {
1053 struct stat statbuf, lstatbuf;
1054 struct directory_entry * s_entry, *s_entry1;
1055 int lstatus;
1056 int status;
1057 int deep_flag;
1058 #ifdef APPLE_HYB
1059 int x_hfs = 0;
1060 int htype = 0;
1061 #endif /* APPLE_HYB */
1062
1063 status = stat_filter(whole_path, &statbuf);
1064
1065 lstatus = lstat_filter(whole_path, &lstatbuf);
1066
1067 if( (status == -1) && (lstatus == -1) )
1068 {
1069 /*
1070 * This means that the file doesn't exist, or isn't accessible.
1071 * Sometimes this is because of NFS permissions problems.
1072 */
1073 fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path);
1074 return 0;
1075 }
1076
1077 if(this_dir == root && strcmp(short_name, ".") == 0)
1078 root_statbuf = statbuf; /* Save this for later on */
1079
1080 /* We do this to make sure that the root entries are consistent */
1081 if(this_dir == root && strcmp(short_name, "..") == 0)
1082 {
1083 statbuf = root_statbuf;
1084 lstatbuf = root_statbuf;
1085 }
1086
1087 if(S_ISLNK(lstatbuf.st_mode))
1088 {
1089
1090 /* Here we decide how to handle the symbolic links. Here
1091 we handle the general case - if we are not following
1092 links or there is an error, then we must change
1093 something. If RR is in use, it is easy, we let RR
1094 describe the file. If not, then we punt the file. */
1095
1096 if((status || !follow_links))
1097 {
1098 if(use_RockRidge)
1099 {
1100 status = 0;
1101 statbuf.st_size = 0;
1102 STAT_INODE(statbuf) = UNCACHED_INODE;
1103 statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
1104 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
1105 } else {
1106 if(follow_links)
1107 {
1108 fprintf(stderr,
1109 "Unable to stat file %s - ignoring and continuing.\n",
1110 whole_path);
1111 }
1112 else
1113 {
1114 fprintf(stderr,
1115 "Symlink %s ignored - continuing.\n",
1116 whole_path);
1117 return 0; /* Non Rock Ridge discs - ignore all symlinks */
1118 }
1119 }
1120 }
1121
1122 /* Here we handle a different kind of case. Here we have
1123 a symlink, but we want to follow symlinks. If we run
1124 across a directory loop, then we need to pretend that
1125 we are not following symlinks for this file. If this
1126 is the first time we have seen this, then make this
1127 seem as if there was no symlink there in the first
1128 place */
1129
1130 if( follow_links
1131 && S_ISDIR(statbuf.st_mode) )
1132 {
1133 if( strcmp(short_name, ".")
1134 && strcmp(short_name, "..") )
1135 {
1136 if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)))
1137 {
1138 if(!use_RockRidge)
1139 {
1140 fprintf(stderr, "Already cached directory seen (%s)\n",
1141 whole_path);
1142 return 0;
1143 }
1144 statbuf.st_size = 0;
1145 STAT_INODE(statbuf) = UNCACHED_INODE;
1146 statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
1147 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
1148 }
1149 else
1150 {
1151 lstatbuf = statbuf;
1152 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
1153 }
1154 }
1155 }
1156
1157 /*
1158 * For non-directories, we just copy the stat information over
1159 * so we correctly include this file.
1160 */
1161 if( follow_links
1162 && !S_ISDIR(statbuf.st_mode) )
1163 {
1164 lstatbuf = statbuf;
1165 }
1166 }
1167
1168 /*
1169 * Add directories to the cache so that we don't waste space even
1170 * if we are supposed to be following symlinks.
1171 */
1172 if( follow_links
1173 && strcmp(short_name, ".")
1174 && strcmp(short_name, "..")
1175 && S_ISDIR(statbuf.st_mode) )
1176 {
1177 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
1178 }
1179 #ifdef VMS
1180 if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX &&
1181 statbuf.st_fab_rfm != FAB$C_STMLF)) {
1182 fprintf(stderr,"Warning - file %s has an unsupported VMS record"
1183 " format (%d)\n",
1184 whole_path, statbuf.st_fab_rfm);
1185 }
1186 #endif
1187
1188 if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK)))
1189 {
1190 fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n",
1191 whole_path, errno);
1192 return 0;
1193 }
1194
1195 /* Add this so that we can detect directory loops with hard links.
1196 If we are set up to follow symlinks, then we skip this checking. */
1197 if( !follow_links
1198 && S_ISDIR(lstatbuf.st_mode)
1199 && strcmp(short_name, ".")
1200 && strcmp(short_name, "..") )
1201 {
1202 if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) {
1203 #ifdef APPLE_HYB
1204 /* NON-HFS change - print just a warning *if* this ever happens */
1205 fprintf(stderr,"Warning: Directory loop (%s)\n", whole_path);
1206 #else
1207 fprintf(stderr,"Directory loop - fatal goof (%s %lx %llu).\n",
1208 whole_path, (unsigned long) statbuf.st_dev,
1209 (unsigned long long) STAT_INODE(statbuf));
1210 exit(1);
1211 #endif
1212 }
1213 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
1214 }
1215
1216 if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
1217 !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode)
1218 && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
1219 !S_ISDIR(lstatbuf.st_mode)) {
1220 fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n",
1221 whole_path);
1222 return 0;
1223 }
1224
1225 /* Who knows what trash this is - ignore and continue */
1226
1227 if(status)
1228 {
1229 fprintf(stderr,
1230 "Unable to stat file %s - ignoring and continuing.\n",
1231 whole_path);
1232 return 0;
1233 }
1234
1235 /*
1236 * Check to see if we have already seen this directory node.
1237 * If so, then we don't create a new entry for it, but we do want
1238 * to recurse beneath it and add any new files we do find.
1239 */
1240 if (S_ISDIR(statbuf.st_mode))
1241 {
1242 int dflag;
1243
1244 for( s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
1245 {
1246 if( strcmp(s_entry->name, short_name) == 0 )
1247 {
1248 break;
1249 }
1250 }
1251 if ( s_entry != NULL
1252 && strcmp(short_name,".")
1253 && strcmp(short_name,".."))
1254 {
1255 struct directory * child;
1256
1257 if ( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0)
1258 {
1259 for( s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next)
1260 {
1261 if( strcmp(s_entry->name, short_name) == 0 )
1262 {
1263 break;
1264 }
1265 }
1266 child = find_or_create_directory(reloc_dir, whole_path,
1267 s_entry, 1);
1268 }
1269 else
1270 {
1271 child = find_or_create_directory(this_dir, whole_path,
1272 s_entry, 1);
1273 /* If unable to scan directory, mark this as a non-directory */
1274 }
1275 dflag = scan_directory_tree(child, whole_path, s_entry);
1276 if(!dflag)
1277 {
1278 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
1279 }
1280 return 0;
1281 }
1282 }
1283 #ifdef APPLE_HYB
1284 /* Should we exclude this HFS file ? - only works with -hfs */
1285 if (!have_rsrc && apple_hyb && strcmp(short_name,".") && strcmp(short_name,"..")) {
1286 x_hfs = hfs_matches(short_name) || hfs_matches(whole_path);
1287 if (x_hfs) {
1288 if (verbose > 1) {
1289 fprintf(stderr, "Hidden from HFS tree: %s\n", whole_path);
1290 }
1291 }
1292 }
1293
1294 /* check we are a file, using Apple extensions and have a .resource part
1295 and not excluded */
1296 if (S_ISREG(lstatbuf.st_mode) && !have_rsrc && apple_both && !x_hfs) {
1297 char rsrc_path[1024]; /* rsrc fork filename */
1298
1299 /* construct the resource full path */
1300 htype = get_hfs_rname(whole_path, short_name, rsrc_path);
1301 /* check we can read the resouce fork */
1302 if (htype) {
1303 struct stat rstatbuf, rlstatbuf;
1304
1305 /* some further checks on the file */
1306 status = stat_filter(rsrc_path, &rstatbuf);
1307
1308 lstatus = lstat_filter(rsrc_path, &rlstatbuf);
1309
1310 if(!status && !lstatus && S_ISREG(rstatbuf.st_mode) && rstatbuf.st_size > 0) {
1311 /* have a resource file - insert it into the current directory
1312 but flag that we have a resource fork */
1313 insert_file_entry(this_dir, rsrc_path, short_name, htype);
1314 }
1315 }
1316 }
1317 #endif /* APPLE_HYB */
1318
1319 s_entry = (struct directory_entry *)
1320 e_malloc(sizeof (struct directory_entry));
1321 /* memset the whole struct, not just the isorec.extent part JCP */
1322 memset(s_entry, 0, sizeof (struct directory_entry));
1323 s_entry->next = this_dir->contents;
1324 /*memset(s_entry->isorec.extent, 0, 8); */
1325 this_dir->contents = s_entry;
1326 deep_flag = 0;
1327 s_entry->table = NULL;
1328
1329 s_entry->name = strdup(short_name);
1330 s_entry->whole_name = strdup (whole_path);
1331
1332 s_entry->de_flags = 0;
1333
1334 /*
1335 * If the current directory is hidden, then hide all it's members
1336 * otherwise check if this entry needs to be hidden as well */
1337 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) {
1338 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
1339 }
1340 else if (strcmp(short_name,".") && strcmp(short_name,"..")) {
1341 if (i_matches(short_name) || i_matches(whole_path)) {
1342 if (verbose > 1) {
1343 fprintf(stderr, "Hidden from ISO9660 tree: %s\n", whole_path);
1344 }
1345 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY;
1346 }
1347 }
1348
1349 if (this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) {
1350 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
1351 }
1352 else if (strcmp(short_name,".") && strcmp(short_name,"..")) {
1353 if (j_matches(short_name) || j_matches(whole_path)) {
1354 if (verbose > 1) {
1355 fprintf(stderr, "Hidden from Joliet tree: %s\n", whole_path);
1356 }
1357 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
1358 }
1359 }
1360
1361 s_entry->filedir = this_dir;
1362 s_entry->isorec.flags[0] = 0;
1363 s_entry->isorec.ext_attr_length[0] = 0;
1364 iso9660_date(s_entry->isorec.date, statbuf.st_mtime);
1365 s_entry->isorec.file_unit_size[0] = 0;
1366 s_entry->isorec.interleave[0] = 0;
1367
1368 #ifdef APPLE_HYB
1369 if (apple_both && !x_hfs) {
1370 s_entry->hfs_ent = NULL;
1371 s_entry->assoc = NULL;
1372 s_entry->hfs_off = 0;
1373 s_entry->hfs_type = htype;
1374 if (have_rsrc) {
1375 s_entry->isorec.flags[0] = ASSOC_FLAG; /* associated (rsrc) file */
1376 /* set the type of HFS file */
1377 s_entry->hfs_type = have_rsrc;
1378 /* don't want the rsrc file to be included in any Joliet tree */
1379 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
1380 }
1381 else if (s_entry->next) {
1382 /* if previous entry is an associated file, then "link" it
1383 to this file i.e. we have a data/resource pair */
1384 if (s_entry->next->isorec.flags[0] & ASSOC_FLAG) {
1385 s_entry->assoc = s_entry->next;
1386 /* share the same HFS parameters */
1387 s_entry->hfs_ent = s_entry->next->hfs_ent;
1388 s_entry->hfs_type = s_entry->next->hfs_type;
1389 }
1390 }
1391 /* allocate HFS entry if required */
1392 if (apple_both && strcmp(short_name, ".") && strcmp(short_name, "..")) {
1393 if (!s_entry->hfs_ent) {
1394 hfsdirent *hfs_ent;
1395 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent));
1396
1397 /* fill in the defaults */
1398 hfs_ent->flags = hfs_ent->fdflags = 0;
1399 hfs_ent->crdate = lstatbuf.st_ctime;
1400 hfs_ent->mddate = lstatbuf.st_mtime;
1401 hfs_ent->dsize = hfs_ent->rsize = 0;
1402 s_entry->hfs_ent = hfs_ent;
1403 }
1404 if (have_rsrc)
1405 /* set rsrc size */
1406 s_entry->hfs_ent->rsize = lstatbuf.st_size;
1407 else
1408 /* set data size */
1409 s_entry->hfs_ent->dsize = lstatbuf.st_size;
1410 }
1411 }
1412 #endif /* APPLE_HYB */
1413
1414 if( strcmp(short_name, ".") == 0)
1415 {
1416 this_dir->dir_flags |= DIR_HAS_DOT;
1417 }
1418
1419 if( strcmp(short_name, "..") == 0)
1420 {
1421 this_dir->dir_flags |= DIR_HAS_DOTDOT;
1422 }
1423
1424 if( this_dir->parent
1425 && this_dir->parent == reloc_dir
1426 && strcmp(short_name, "..") == 0)
1427 {
1428 s_entry->inode = UNCACHED_INODE;
1429 s_entry->dev = (dev_t) UNCACHED_DEVICE;
1430 deep_flag = NEED_PL;
1431 }
1432 else
1433 #ifdef APPLE_HYB
1434 if (have_rsrc) {
1435 /* don't want rsrc files to be cached */
1436 s_entry->inode = UNCACHED_INODE;
1437 s_entry->dev = (dev_t) UNCACHED_DEVICE;
1438 }
1439 else
1440 #endif /* APPLE_HYB */
1441 {
1442 s_entry->inode = STAT_INODE(statbuf);
1443 s_entry->dev = statbuf.st_dev;
1444 }
1445 set_723(s_entry->isorec.volume_sequence_number, volume_sequence_number);
1446 iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode));
1447 s_entry->rr_attr_size = 0;
1448 s_entry->total_rr_attr_size = 0;
1449 s_entry->rr_attributes = NULL;
1450
1451 /* Directories are assigned sizes later on */
1452 if (!S_ISDIR(statbuf.st_mode))
1453 {
1454 if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) ||
1455 S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode)
1456 || S_ISLNK(lstatbuf.st_mode))
1457 {
1458 s_entry->size = 0;
1459 statbuf.st_size = 0;
1460 }
1461 else
1462 {
1463 s_entry->size = statbuf.st_size;
1464 }
1465
1466 set_733((char *) s_entry->isorec.size, statbuf.st_size);
1467 }
1468 else
1469 {
1470 s_entry->isorec.flags[0] = 2;
1471 }
1472 #ifdef APPLE_HYB
1473 /* if the directory is HFS excluded, then we don't have an hfs_ent */
1474 if (apple_both && s_entry->hfs_ent && s_entry->isorec.flags[0] & 2) {
1475 /* get the Mac directory name */
1476 get_hfs_dir(whole_path, short_name, s_entry);
1477
1478 /* if required, set ISO directory name from HFS name */
1479 if (mac_name)
1480 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1);
1481 }
1482 #endif /* APPLE_HYB */
1483
1484 if (strcmp(short_name,".") && strcmp(short_name,"..") &&
1485 S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth)
1486 {
1487 struct directory * child;
1488
1489 if(!reloc_dir) generate_reloc_directory();
1490
1491 /*
1492 * Replicate the entry for this directory. The old one will stay where it
1493 * is, and it will be neutered so that it no longer looks like a directory.
1494 * The new one will look like a directory, and it will be put in the reloc_dir.
1495 */
1496 s_entry1 = (struct directory_entry *)
1497 e_malloc(sizeof (struct directory_entry));
1498 memcpy(s_entry1, s_entry, sizeof(struct directory_entry));
1499 s_entry1->table = NULL;
1500 s_entry1->name = strdup(this_dir->contents->name);
1501 s_entry1->whole_name = strdup(this_dir->contents->whole_name);
1502 s_entry1->next = reloc_dir->contents;
1503 reloc_dir->contents = s_entry1;
1504 s_entry1->priority = 32768;
1505 s_entry1->parent_rec = this_dir->contents;
1506
1507 deep_flag = NEED_RE;
1508
1509 if(use_RockRidge)
1510 {
1511 generate_rock_ridge_attributes(whole_path,
1512 short_name, s_entry1,
1513 &statbuf, &lstatbuf, deep_flag);
1514 }
1515
1516 deep_flag = 0;
1517
1518 /* We need to set this temporarily so that the parent to this
1519 is correctly determined. */
1520 s_entry1->filedir = reloc_dir;
1521 child = find_or_create_directory(reloc_dir, whole_path,
1522 s_entry1, 0);
1523 scan_directory_tree(child, whole_path, s_entry1);
1524 s_entry1->filedir = this_dir;
1525
1526 statbuf.st_size = 0;
1527 statbuf.st_mode &= 0777;
1528 set_733((char *) s_entry->isorec.size, 0);
1529 s_entry->size = 0;
1530 s_entry->isorec.flags[0] = 0;
1531 s_entry->inode = UNCACHED_INODE;
1532 s_entry->de_flags |= RELOCATED_DIRECTORY;
1533 deep_flag = NEED_CL;
1534 }
1535
1536 if(generate_tables
1537 && strcmp(s_entry->name, ".")
1538 && strcmp(s_entry->name, ".."))
1539 {
1540 char buffer[2048];
1541 int nchar;
1542 switch(lstatbuf.st_mode & S_IFMT)
1543 {
1544 case S_IFDIR:
1545 snprintf(buffer, sizeof buffer, "D\t%s\n",
1546 s_entry->name);
1547 break;
1548 #ifdef S_IFBLK
1549 /* extra for WIN32 - if it doesn't have the major/minor defined, then
1550 S_IFBLK and S_IFCHR type files are unlikely to exist anyway ...
1551 code similar to that in rock.c */
1552
1553 /* for some reason, MAJOR_IN_SYSMACROS isn't defined on a SunOS when
1554 it should be, so see if major() is defined instead */
1555 /*
1556 #if !(defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV))
1557 */
1558 #ifndef major
1559 #define major(dev) (sizeof(dev_t) <= 2 ? ((dev) >> 8) : \
1560 (sizeof(dev_t) <= 4 ? (((dev) >> 8) >> 8) : \
1561 (((dev) >> 16) >> 16)))
1562 #define minor(dev) (sizeof(dev_t) <= 2 ? (dev) & 0xff : \
1563 (sizeof(dev_t) <= 4 ? (dev) & 0xffff : \
1564 (dev) & 0xffffffff))
1565 #endif
1566 case S_IFBLK:
1567 snprintf(buffer, sizeof buffer, "B\t%s\t%lu %lu\n",
1568 s_entry->name,
1569 (unsigned long) major(statbuf.st_rdev),
1570 (unsigned long) minor(statbuf.st_rdev));
1571 break;
1572 #endif
1573 #ifdef S_IFIFO
1574 case S_IFIFO:
1575 snprintf(buffer, sizeof buffer, "P\t%s\n",
1576 s_entry->name);
1577 break;
1578 #endif
1579 #ifdef S_IFCHR
1580 case S_IFCHR:
1581 snprintf(buffer, sizeof buffer, "C\t%s\t%lu %lu\n",
1582 s_entry->name,
1583 (unsigned long) major(statbuf.st_rdev),
1584 (unsigned long) minor(statbuf.st_rdev));
1585 break;
1586 #endif
1587 #ifdef S_IFLNK
1588 case S_IFLNK:
1589 nchar = readlink(whole_path,
1590 (char *)symlink_buff,
1591 sizeof(symlink_buff)-1);
1592 symlink_buff[nchar < 0 ? 0 : nchar] = 0;
1593 snprintf(buffer, sizeof buffer, "L\t%s\t%s\n",
1594 s_entry->name, symlink_buff);
1595 break;
1596 #endif
1597 #ifdef S_IFSOCK
1598 case S_IFSOCK:
1599 snprintf(buffer, sizeof buffer, "S\t%s\n",
1600 s_entry->name);
1601 break;
1602 #endif
1603 case S_IFREG:
1604 default:
1605 snprintf(buffer, sizeof buffer, "F\t%s\n",
1606 s_entry->name);
1607 break;
1608 };
1609 s_entry->table = strdup(buffer);
1610 }
1611
1612 if(S_ISDIR(statbuf.st_mode))
1613 {
1614 int dflag;
1615 if (strcmp(short_name,".") && strcmp(short_name,".."))
1616 {
1617 struct directory * child;
1618
1619 child = find_or_create_directory(this_dir, whole_path,
1620 s_entry, 1);
1621 dflag = scan_directory_tree(child, whole_path, s_entry);
1622
1623 if(!dflag)
1624 {
1625 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
1626 if( child->contents == NULL )
1627 {
1628 delete_directory(this_dir, child);
1629 }
1630 }
1631 }
1632 /* If unable to scan directory, mark this as a non-directory */
1633 }
1634
1635 if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0)
1636 {
1637 deep_flag |= NEED_CE | NEED_SP; /* For extension record */
1638 }
1639
1640 /* Now figure out how much room this file will take in the
1641 directory */
1642
1643 #ifdef APPLE_HYB
1644 /* if the file is HFS excluded, then we don't have an hfs_ent */
1645 if (apple_both && !have_rsrc && s_entry->hfs_ent) {
1646 if (S_ISREG(lstatbuf.st_mode)) { /* it's a regular file */
1647
1648 /* fill in the rest of the HFS entry */
1649 get_hfs_info(whole_path, short_name, s_entry);
1650
1651 /* if required, set ISO directory name from HFS name */
1652 if (mac_name)
1653 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 0);
1654
1655 /* print details about the HFS file */
1656 if (verbose > 2)
1657 print_hfs_info(s_entry);
1658
1659 /* copy the new ISO9660 name to the rsrc fork - if it exists */
1660 if (s_entry->assoc)
1661 strcpy(s_entry->assoc->isorec.name, s_entry->isorec.name);
1662
1663 /* we can't handle hard links in the hybrid case, so we "uncache"
1664 the file. The downside to this is that hard linked files
1665 are added to the output image more than once (we've already
1666 done this for rsrc files) */
1667 if (apple_hyb) {
1668 s_entry->inode = UNCACHED_INODE;
1669 s_entry->dev = (dev_t) UNCACHED_DEVICE;
1670 }
1671 }
1672 else if (!(s_entry->isorec.flags[0] & 2)) { /* not a directory .. */
1673
1674 /* no mac equivalent, so ignore - have to be careful here, the
1675 hfs_ent may be also be for a relocated directory */
1676 if (s_entry->hfs_ent && !(s_entry->de_flags & RELOCATED_DIRECTORY))
1677 free(s_entry->hfs_ent);
1678 s_entry->hfs_ent = NULL;
1679 }
1680
1681 /* if the rsrc size is zero, then we don't need the entry, so we
1682 might as well delete it - this will only happen if we didn't
1683 know the rsrc size from the rsrc file size */
1684 if(s_entry->assoc && s_entry->assoc->size == 0)
1685 delete_rsrc_ent(s_entry);
1686 }
1687
1688 if(apple_ext && s_entry->assoc) {
1689 /* need Apple extensions for the resource fork as well */
1690 generate_rock_ridge_attributes(whole_path,
1691 short_name, s_entry->assoc,
1692 &statbuf, &lstatbuf, deep_flag);
1693 }
1694 /* leave out resource fork for the time being */
1695 if (use_RockRidge && !have_rsrc) {
1696 #else
1697 if(use_RockRidge)
1698 {
1699 #endif /* APPLE_HYB */
1700 generate_rock_ridge_attributes(whole_path,
1701 short_name, s_entry,
1702 &statbuf, &lstatbuf, deep_flag);
1703
1704 }
1705
1706 return 1;
1707 }
1708
1709
1710 void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){
1711 struct directory * dpnt;
1712
1713 dpnt = node;
1714
1715 while (dpnt){
1716 if( dpnt->extent > session_start )
1717 {
1718 generate_one_directory(dpnt, outfile);
1719 }
1720 if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile);
1721 dpnt = dpnt->next;
1722 }
1723 }
1724
1725 /*
1726 * Function: find_or_create_directory
1727 *
1728 * Purpose: Locate a directory entry in the tree, create if needed.
1729 *
1730 * Arguments:
1731 */
1732 struct directory * FDECL4(find_or_create_directory, struct directory *, parent,
1733 const char *, path,
1734 struct directory_entry *, de, int, flag)
1735 {
1736 struct directory * dpnt;
1737 struct directory_entry * orig_de;
1738 struct directory * next_brother;
1739 const char * cpnt;
1740 const char * pnt;
1741
1742 orig_de = de;
1743
1744 pnt = strrchr(path, PATH_SEPARATOR);
1745 if( pnt == NULL )
1746 {
1747 pnt = path;
1748 }
1749 else
1750 {
1751 pnt++;
1752 }
1753
1754 if( parent != NULL )
1755 {
1756 dpnt = parent->subdir;
1757
1758 while (dpnt)
1759 {
1760 /*
1761 * Weird hack time - if there are two directories by the
1762 * same name in the reloc_dir, they are not treated as the
1763 * same thing unless the entire path matches completely.
1764 */
1765 if( flag && strcmp(dpnt->de_name, pnt) == 0 )
1766 {
1767 return dpnt;
1768 }
1769 dpnt = dpnt->next;
1770 }
1771 }
1772
1773 /*
1774 * We don't know if we have a valid directory entry for this one
1775 * yet. If not, we need to create one.
1776 */
1777 if( de == NULL )
1778 {
1779 de = (struct directory_entry *)
1780 e_malloc(sizeof (struct directory_entry));
1781 memset(de, 0, sizeof(struct directory_entry));
1782 de->next = parent->contents;
1783 parent->contents = de;
1784 de->name = strdup(pnt);
1785 de->filedir = parent;
1786 de->isorec.flags[0] = 2;
1787 de->priority = 32768;
1788 de->inode = UNCACHED_INODE;
1789 de->dev = (dev_t) UNCACHED_DEVICE;
1790 set_723(de->isorec.volume_sequence_number, volume_sequence_number);
1791 iso9660_file_length (pnt, de, 1);
1792
1793 init_fstatbuf();
1794 /*
1795 * It doesn't exist for real, so we cannot add any Rock Ridge.
1796 */
1797 if(use_RockRidge)
1798 {
1799 fstatbuf.st_mode = 0555 | S_IFDIR;
1800 fstatbuf.st_nlink = 2;
1801 generate_rock_ridge_attributes("",
1802 (char *) pnt, de,
1803 &fstatbuf,
1804 &fstatbuf, 0);
1805 }
1806 iso9660_date(de->isorec.date, fstatbuf.st_mtime);
1807 #ifdef APPLE_HYB
1808 if (apple_both) {
1809 /* give the directory an HFS entry */
1810 hfsdirent *hfs_ent;
1811 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent));
1812
1813 /* fill in the defaults */
1814 hfs_ent->flags = hfs_ent->fdflags = 0;
1815 hfs_ent->crdate = fstatbuf.st_ctime;
1816 hfs_ent->mddate = fstatbuf.st_mtime;
1817 hfs_ent->dsize = hfs_ent->rsize = 0;
1818
1819 de->hfs_ent = hfs_ent;
1820
1821 /* get the Mac directory name */
1822 get_hfs_dir(path, pnt, de);
1823 }
1824 #endif /* APPLE_HYB */
1825 }
1826
1827 /*
1828 * If we don't have a directory for this one yet, then allocate it
1829 * now, and patch it into the tree in the appropriate place.
1830 */
1831 dpnt = (struct directory *) e_malloc(sizeof(struct directory));
1832 memset(dpnt, 0, sizeof(struct directory));
1833 dpnt->next = NULL;
1834 dpnt->subdir = NULL;
1835 dpnt->self = de;
1836 dpnt->contents = NULL;
1837 dpnt->whole_name = strdup(path);
1838 cpnt = strrchr(path, PATH_SEPARATOR);
1839 if(cpnt)
1840 cpnt++;
1841 else
1842 cpnt = path;
1843 dpnt->de_name = strdup(cpnt);
1844 dpnt->size = 0;
1845 dpnt->extent = 0;
1846 dpnt->jextent = 0;
1847 dpnt->jsize = 0;
1848 #ifdef APPLE_HYB
1849 dpnt->hfs_ent = de->hfs_ent;
1850 #endif /*APPLE_HYB */
1851
1852 if( orig_de == NULL )
1853 {
1854 struct stat xstatbuf;
1855 int sts;
1856
1857 /*
1858 * Now add a . and .. entry in the directory itself.
1859 * This is a little tricky - if the real directory
1860 * exists, we need to stat it first. Otherwise, we
1861 * use the fictitious fstatbuf which points to the time
1862 * at which mkisofs was started.
1863 */
1864 sts = stat_filter(parent->whole_name, &xstatbuf);
1865 if( sts == 0 )
1866 {
1867 attach_dot_entries(dpnt, &xstatbuf);
1868 }
1869 else
1870 {
1871 attach_dot_entries(dpnt, &fstatbuf);
1872 }
1873 }
1874
1875 if(!parent || parent == root)
1876 {
1877 if (!root)
1878 {
1879 root = dpnt; /* First time through for root directory only */
1880 root->depth = 0;
1881 root->parent = root;
1882 } else {
1883 dpnt->depth = 1;
1884 if(!root->subdir)
1885 {
1886 root->subdir = dpnt;
1887 }
1888 else
1889 {
1890 next_brother = root->subdir;
1891 while(next_brother->next) next_brother = next_brother->next;
1892 next_brother->next = dpnt;
1893 }
1894 dpnt->parent = parent;
1895 }
1896 }
1897 else
1898 {
1899 /* Come through here for normal traversal of tree */
1900 #ifdef DEBUG
1901 fprintf(stderr,"%s(%d) ", path, dpnt->depth);
1902 #endif
1903 if(parent->depth > RR_relocation_depth)
1904 {
1905 fprintf(stderr,"Directories too deep %s\n", path);
1906 exit(1);
1907 }
1908
1909 dpnt->parent = parent;
1910 dpnt->depth = parent->depth + 1;
1911
1912 if(!parent->subdir)
1913 {
1914 parent->subdir = dpnt;
1915 }
1916 else
1917 {
1918 next_brother = parent->subdir;
1919 while(next_brother->next) next_brother = next_brother->next;
1920 next_brother->next = dpnt;
1921 }
1922 }
1923
1924 return dpnt;
1925 }
1926
1927 /*
1928 * Function: delete_directory
1929 *
1930 * Purpose: Locate a directory entry in the tree, create if needed.
1931 *
1932 * Arguments:
1933 */
1934 static void FDECL2(delete_directory, struct directory *, parent, struct directory *, child)
1935 {
1936 struct directory * tdir;
1937
1938 if( child->contents != NULL )
1939 {
1940 fprintf(stderr, "Unable to delete non-empty directory\n");
1941 exit(1);
1942 }
1943
1944 free(child->whole_name);
1945 child->whole_name = NULL;
1946
1947 free(child->de_name);
1948 child->de_name = NULL;
1949
1950 #ifdef APPLE_HYB
1951 if (apple_both && child->hfs_ent)
1952 free(child->hfs_ent);
1953 #endif /* APPLE_HYB */
1954
1955 if( parent->subdir == child )
1956 {
1957 parent->subdir = child->next;
1958 }
1959 else
1960 {
1961 for( tdir = parent->subdir; tdir->next != NULL; tdir = tdir->next )
1962 {
1963 if( tdir->next == child )
1964 {
1965 tdir->next = child->next;
1966 break;
1967 }
1968 }
1969 if( tdir == NULL )
1970 {
1971 fprintf(stderr, "Unable to locate child directory in parent list\n");
1972 exit(1);
1973 }
1974 }
1975 free(child);
1976 return;
1977 }
1978
1979 int FDECL1(sort_tree, struct directory *, node){
1980 struct directory * dpnt;
1981 int ret = 0;
1982
1983 dpnt = node;
1984
1985 while (dpnt){
1986 ret = sort_n_finish(dpnt);
1987 if( ret )
1988 {
1989 break;
1990 }
1991
1992 if(dpnt->subdir) sort_tree(dpnt->subdir);
1993 dpnt = dpnt->next;
1994 }
1995 return ret;
1996 }
1997
1998 void FDECL1(dump_tree, struct directory *, node){
1999 struct directory * dpnt;
2000
2001 dpnt = node;
2002
2003 while (dpnt){
2004 fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name);
2005 if(dpnt->subdir) dump_tree(dpnt->subdir);
2006 dpnt = dpnt->next;
2007 }
2008 }
2009
2010 void FDECL1(update_nlink_field, struct directory *, node)
2011 {
2012 struct directory * dpnt;
2013 struct directory * xpnt;
2014 struct directory_entry * s_entry;
2015 int i;
2016
2017 dpnt = node;
2018
2019 while (dpnt)
2020 {
2021 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
2022 dpnt = dpnt->next;
2023 continue;
2024 }
2025
2026 /*
2027 * First, count up the number of subdirectories this guy has.
2028 */
2029 for(i=0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
2030 if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
2031 i++;
2032 /*
2033 * Next check to see if we have any relocated directories
2034 * in this directory. The nlink field will include these
2035 * as real directories when they are properly relocated.
2036 *
2037 * In the non-rockridge disk, the relocated entries appear
2038 * as zero length files.
2039 */
2040 for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
2041 {
2042 if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 &&
2043 (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0)
2044 {
2045 i++;
2046 }
2047 }
2048 /*
2049 * Now update the field in the Rock Ridge entry.
2050 */
2051 update_nlink(dpnt->self, i + 2);
2052
2053 /*
2054 * Update the '.' entry for this directory.
2055 */
2056 update_nlink(dpnt->contents, i + 2);
2057
2058 /*
2059 * Update all of the '..' entries that point to this guy.
2060 */
2061 for(xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
2062 update_nlink(xpnt->contents->next, i + 2);
2063
2064 if(dpnt->subdir) update_nlink_field(dpnt->subdir);
2065 dpnt = dpnt->next;
2066 }
2067 }
2068
2069 /*
2070 * something quick and dirty to locate a file given a path
2071 * recursively walks down path in filename until it finds the
2072 * directory entry for the desired file
2073 */
2074 struct directory_entry * FDECL2(search_tree_file, struct directory *,
2075 node,char *, filename)
2076 {
2077 struct directory_entry * depnt;
2078 struct directory * dpnt;
2079 char * p1;
2080 char * rest;
2081 char * subdir;
2082
2083 /*
2084 * strip off next directory name from filename
2085 */
2086 subdir = strdup(filename);
2087
2088 if( (p1=strchr(subdir, '/')) == subdir )
2089 {
2090 fprintf(stderr,"call to search_tree_file with an absolute path, stripping\n");
2091 fprintf(stderr,"initial path separator. Hope this was intended...\n");
2092 memmove(subdir, subdir+1, strlen(subdir)-1);
2093 p1 = strchr(subdir, '/');
2094 }
2095
2096 /*
2097 * do we need to find a subdirectory
2098 */
2099 if (p1)
2100 {
2101 *p1 = '\0';
2102
2103 #ifdef DEBUG_TORITO
2104 fprintf(stderr,"Looking for subdir called %s\n",p1);
2105 #endif
2106
2107 rest = p1+1;
2108
2109 #ifdef DEBUG_TORITO
2110 fprintf(stderr,"Remainder of path name is now %s\n", rest);
2111 #endif
2112
2113 dpnt = node->subdir;
2114 while( dpnt )
2115 {
2116 #ifdef DEBUG_TORITO
2117 fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size,
2118 dpnt->de_name);
2119 #endif
2120 if (!strcmp(subdir, dpnt->de_name))
2121 {
2122 #ifdef DEBUG_TORITO
2123 fprintf(stderr,"Calling next level with filename = %s", rest);
2124 #endif
2125 return(search_tree_file( dpnt, rest ));
2126 }
2127 dpnt = dpnt->next;
2128 }
2129
2130 /* if we got here means we couldnt find the subdir */
2131 return (NULL);
2132 }
2133 else
2134 {
2135 /*
2136 * look for a normal file now
2137 */
2138 depnt = node->contents;
2139 while (depnt)
2140 {
2141 #ifdef DEBUG_TORITO
2142 fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent,
2143 depnt->size, depnt->name);
2144 #endif
2145 if (!strcmp(filename, depnt->name))
2146 {
2147 #ifdef DEBUG_TORITO
2148 fprintf(stderr,"Found our file %s", filename);
2149 #endif
2150 return(depnt);
2151 }
2152 depnt = depnt->next;
2153 }
2154 /*
2155 * if we got here means we couldnt find the subdir
2156 */
2157 return (NULL);
2158 }
2159 fprintf(stderr,"We cant get here in search_tree_file :-/ \n");
2160 }
2161
2162 void init_fstatbuf()
2163 {
2164 time_t current_time;
2165
2166 if(fstatbuf.st_ctime == 0)
2167 {
2168 time (¤t_time);
2169 if( rationalize )
2170 {
2171 fstatbuf.st_uid = 0;
2172 fstatbuf.st_gid = 0;
2173 }
2174 else
2175 {
2176 fstatbuf.st_uid = getuid();
2177 fstatbuf.st_gid = getgid();
2178 }
2179 fstatbuf.st_ctime = current_time;
2180 fstatbuf.st_mtime = current_time;
2181 fstatbuf.st_atime = current_time;
2182 }
2183 }
2184