Bug Summary

File:src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/tree.c
Warning:line 871, column 3
Value stored to 'parent' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name tree.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -resource-dir /usr/local/lib/clang/13.0.0 -D SYSTEM_ID_DEFAULT="OpenBSD" -D APPLE_HYB -D VANILLA_AUTOCONF -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/include -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libhfs_iso -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libfile -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/tree.c
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(*__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_H1
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"
53extern 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_MEMMOVE1
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)((m & 0170000) == 0120000) (0)
74#define S_ISSOCK(m)((m & 0170000) == 0140000) (0)
75#define S_ISFIFO(m)((m & 0170000) == 0010000) (0)
76#else
77#ifndef S_ISLNK
78#define S_ISLNK(m)((m & 0170000) == 0120000) (((m) & S_IFMT0170000) == S_IFLNK0120000)
79#endif
80#ifndef S_ISSOCK
81# ifdef S_IFSOCK0140000
82# define S_ISSOCK(m)((m & 0170000) == 0140000) (((m) & S_IFMT0170000) == S_IFSOCK0140000)
83# else
84# define S_ISSOCK(m)((m & 0170000) == 0140000) (0)
85# endif
86#endif
87#endif
88
89#else
90#include <statdefs.h>
91#endif
92
93
94#ifdef __SVR4
95extern char * strdup(const char *);
96#endif
97
98static unsigned char symlink_buff[256];
99
100static void stat_fix __PR((struct stat * st))(struct stat * st);
101static void generate_reloc_directory __PR((void))(void);
102
103static void DECL(attach_dot_entries, (struct directory * dirnode,attach_dot_entries (struct directory * dirnode, struct stat *
parent_stat)
104 struct stat * parent_stat))attach_dot_entries (struct directory * dirnode, struct stat *
parent_stat)
;
105static void DECL(delete_directory, (struct directory * parent, struct directory * child))delete_directory (struct directory * parent, struct directory
* child)
;
106
107extern int verbose;
108
109struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */
110
111struct stat root_statbuf = {0, }; /* Stat buffer for root directory */
112
113struct directory * reloc_dir = NULL((void *)0);
114
115static void
116FDECL1(stat_fix, struct stat *, st)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
137int
138FDECL2(stat_filter, char *, path, struct stat *, st)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
146int
147FDECL2(lstat_filter, char *, path, struct stat *, st)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
155static int FDECL1(sort_n_finish, struct directory *, this_dir)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_ENTRY0x40)
176 {
177 return 0;
178 }
179
180 table = NULL((void *)0);
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_DOT0x02 | DIR_HAS_DOTDOT0x04)) !=
190 (DIR_HAS_DOT0x02 | DIR_HAS_DOTDOT0x04) )
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_ENTRY0x40)
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_HYB1
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(&__sF[2]),"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(&__sF[2]),"Unable to generate unique name for file %s\n", s_entry->name);
288 exit(1);
289
290got_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(&__sF[2]),"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_HYB1
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(&__sF[2]),"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_HYB1
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_HYB1
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_HYB1
382 /* skip table entry for the resource fork */
383 if(apple_both && (s_entry->isorec.flags[0] & ASSOC_FLAG4))
384 continue;
385#endif /* APPLE_HYB */
386 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40) 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((void *)0);
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_mtimest_mtim.tv_sec);
404 table->inode = TABLE_INODE(sizeof(ino_t) >= 8 ? 0x7ffffffffffffffeLL : 0x7ffffffe);
405 table->dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
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 table->de_flags |= INHIBIT_JOLIET_ENTRY0x08;
411 table->name = strdup("<translation table>");
412 table->table = (char *) e_malloc(ROUND_UP(tablesize)((tablesize + ((2048) - 1)) & ~((2048) - 1)));
413 memset(table->table, 0, ROUND_UP(tablesize)((tablesize + ((2048) - 1)) & ~((2048) - 1)));
414#ifdef APPLE_HYB1
415 iso9660_file_length (trans_tbl, table, 0);
416#else
417 iso9660_file_length ("TRANS.TBL", table, 0);
418#endif /* APPLE_HYB */
419
420 if(use_RockRidge)
421 {
422 fstatbuf.st_mode = 0444 | S_IFREG0100000;
423 fstatbuf.st_nlink = 1;
424 generate_rock_ridge_attributes("",
425#ifdef APPLE_HYB1
426 trans_tbl, table,
427#else
428 "TRANS.TBL", table,
429#endif /* APPLE_HYB */
430 &fstatbuf, &fstatbuf, 0);
431 }
432 }
433
434 /*
435 * We have now chosen the 8.3 names and we should now know the length
436 * of every entry in the directory.
437 */
438 for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
439 {
440 /* skip if it's hidden */
441 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40)
442 {
443 continue;
444 }
445
446 new_reclen = strlen(s_entry->isorec.name);
447
448 /*
449 * First update the path table sizes for directories.
450 */
451 if(s_entry->isorec.flags[0] == 2)
452 {
453 if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
454 {
455 path_table_size += new_reclen + sizeof(struct iso_path_table) - 1;
456 if (new_reclen & 1) path_table_size++;
457 }
458 else
459 {
460 new_reclen = 1;
461 if (this_dir == root && strlen(s_entry->name) == 1)
462 {
463 path_table_size += sizeof(struct iso_path_table);
464 }
465 }
466 }
467 if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */
468 s_entry->isorec.name_len[0] = new_reclen;
469
470 new_reclen +=
471 sizeof(struct iso_directory_record) -
472 sizeof(s_entry->isorec.name);
473
474 if (new_reclen & 1)
475 new_reclen++;
476
477 new_reclen += s_entry->rr_attr_size;
478
479 if (new_reclen & 1) new_reclen++;
480
481 if(new_reclen > 0xff)
482 {
483 fprintf(stderr(&__sF[2]),"Fatal error - RR overflow for file %s\n",
484 s_entry->name);
485 exit(1);
486 }
487 s_entry->isorec.length[0] = new_reclen;
488 }
489
490 status = sort_directory(&this_dir->contents);
491 if( status > 0 )
492 {
493 fprintf(stderr(&__sF[2]), "Unable to sort directory %s\n",
494 this_dir->whole_name);
495 }
496
497 /*
498 * If we are filling out a TRANS.TBL, generate the entries that will
499 * go in the thing.
500 */
501 if(table)
502 {
503 count = 0;
504 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
505 if(s_entry == table) continue;
506 if(!s_entry->table) continue;
507 if(strcmp(s_entry->name, ".") == 0 ||
508 strcmp(s_entry->name, "..") == 0) continue;
509#ifdef APPLE_HYB1
510 /* skip table entry for the resource fork */
511 if(apple_both && (s_entry->isorec.flags[0] & ASSOC_FLAG4))
512 continue;
513#endif /* APPLE_HYB */
514 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40) continue;
515 /*
516 * Warning: we cannot use the return value of sprintf because
517 * old BSD based sprintf() implementations will return
518 * a pointer to the result instead of a count.
519 */
520 sprintf(table->table + count, "%c %-34s%s",
521 s_entry->table[0],
522 s_entry->isorec.name, s_entry->table+1);
523 count += strlen(table->table + count);
524 free(s_entry->table);
525 s_entry->table = NULL((void *)0);
526 }
527
528 if(count != tablesize)
529 {
530 fprintf(stderr(&__sF[2]),"Translation table size mismatch %d %d\n",
531 count, tablesize);
532 exit(1);
533 }
534 }
535
536 /*
537 * Now go through the directory and figure out how large this one will be.
538 * Do not split a directory entry across a sector boundary
539 */
540 s_entry = this_dir->contents;
541 this_dir->ce_bytes = 0;
542 while(s_entry)
543 {
544 /* skip if it's hidden */
545 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40) {
546 s_entry = s_entry->next;
547 continue;
548 }
549
550 new_reclen = s_entry->isorec.length[0];
551 if ((this_dir->size & (SECTOR_SIZE(2048) - 1)) + new_reclen >= SECTOR_SIZE(2048))
552 this_dir->size = (this_dir->size + (SECTOR_SIZE(2048) - 1)) &
553 ~(SECTOR_SIZE(2048) - 1);
554 this_dir->size += new_reclen;
555
556 /* See if continuation entries were used on disc */
557 if(use_RockRidge &&
558 s_entry->rr_attr_size != s_entry->total_rr_attr_size)
559 {
560 unsigned char * pnt;
561 int len;
562 int nbytes;
563
564 pnt = s_entry->rr_attributes;
565 len = s_entry->total_rr_attr_size;
566
567 /*
568 * We make sure that each continuation entry record is not
569 * split across sectors, but each file could in theory have more
570 * than one CE, so we scan through and figure out what we need.
571 */
572 while(len > 3)
573 {
574 if(pnt[0] == 'C' && pnt[1] == 'E')
575 {
576 nbytes = get_733((char *) pnt+20);
577
578 if((this_dir->ce_bytes & (SECTOR_SIZE(2048) - 1)) + nbytes >=
579 SECTOR_SIZE(2048)) this_dir->ce_bytes =
580 ROUND_UP(this_dir->ce_bytes)((this_dir->ce_bytes + ((2048) - 1)) & ~((2048) - 1));
581 /* Now store the block in the ce buffer */
582 this_dir->ce_bytes += nbytes;
583 if(this_dir->ce_bytes & 1) this_dir->ce_bytes++;
584 }
585 len -= pnt[2];
586 pnt += pnt[2];
587 }
588 }
589 s_entry = s_entry->next;
590 }
591 return status;
592}
593
594static void generate_reloc_directory()
595{
596 time_t current_time;
597 struct directory_entry *s_entry;
598
599 /* Create an entry for our internal tree */
600 time (&current_time);
601 reloc_dir = (struct directory *)
602 e_malloc(sizeof(struct directory));
603 memset(reloc_dir, 0, sizeof(struct directory));
604 reloc_dir->parent = root;
605 reloc_dir->next = root->subdir;
606 root->subdir = reloc_dir;
607 reloc_dir->depth = 1;
608 reloc_dir->whole_name = strdup("./rr_moved");
609 reloc_dir->de_name = strdup("rr_moved");
610 reloc_dir->extent = 0;
611
612
613 /* Now create an actual directory entry */
614 s_entry = (struct directory_entry *)
615 e_malloc(sizeof (struct directory_entry));
616 memset(s_entry, 0, sizeof(struct directory_entry));
617 s_entry->next = root->contents;
618 reloc_dir->self = s_entry;
619
620 /*
621 * The rr_moved entry will not appear in the Joliet tree.
622 */
623 reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY0x08;
624 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY0x08;
625
626 root->contents = s_entry;
627 root->contents->name = strdup(reloc_dir->de_name);
628 root->contents->filedir = root;
629 root->contents->isorec.flags[0] = 2;
630 root->contents->priority = 32768;
631 iso9660_date(root->contents->isorec.date, current_time);
632 root->contents->inode = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
633 root->contents->dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
634 set_723(root->contents->isorec.volume_sequence_number, volume_sequence_number);
635 iso9660_file_length (reloc_dir->de_name, root->contents, 1);
636
637 if(use_RockRidge){
638 fstatbuf.st_mode = 0555 | S_IFDIR0040000;
639 fstatbuf.st_nlink = 2;
640 generate_rock_ridge_attributes("",
641 "rr_moved", s_entry,
642 &fstatbuf, &fstatbuf, 0);
643 };
644
645 /* Now create the . and .. entries in rr_moved */
646 /* Now create an actual directory entry */
647 attach_dot_entries(reloc_dir, &root_statbuf);
648}
649
650/*
651 * Function: attach_dot_entries
652 *
653 * Purpose: Create . and .. entries for a new directory.
654 *
655 * Notes: Only used for artificial directories that
656 * we are creating.
657 */
658static void FDECL2(attach_dot_entries, struct directory *, dirnode,attach_dot_entries(struct directory * dirnode, struct stat * parent_stat
)
659 struct stat *, parent_stat)attach_dot_entries(struct directory * dirnode, struct stat * parent_stat
)
660{
661 struct directory_entry *s_entry;
662 struct directory_entry *orig_contents;
663 int deep_flag = 0;
664
665 init_fstatbuf();
666
667 orig_contents = dirnode->contents;
668
669 if( (dirnode->dir_flags & DIR_HAS_DOTDOT0x04) == 0 )
670 {
671 s_entry = (struct directory_entry *)
672 e_malloc(sizeof (struct directory_entry));
673 memcpy(s_entry, dirnode->self,
674 sizeof(struct directory_entry));
675 s_entry->name = strdup("..");
676 s_entry->whole_name = NULL((void *)0);
677 s_entry->isorec.name_len[0] = 1;
678 s_entry->isorec.flags[0] = 2; /* Mark as a directory */
679 iso9660_file_length ("..", s_entry, 1);
680 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtimest_mtim.tv_sec);
681 s_entry->filedir = dirnode->parent;
682
683 dirnode->contents = s_entry;
684 dirnode->contents->next = orig_contents;
685 orig_contents = s_entry;
686
687 if(use_RockRidge)
688 {
689 if( parent_stat == NULL((void *)0) )
690 {
691 parent_stat = &fstatbuf;
692 }
693 generate_rock_ridge_attributes("",
694 "..", s_entry,
695 parent_stat,
696 parent_stat, 0);
697 }
698 dirnode->dir_flags |= DIR_HAS_DOTDOT0x04;
699 }
700
701 if( (dirnode->dir_flags & DIR_HAS_DOT0x02) == 0 )
702 {
703 s_entry = (struct directory_entry *)
704 e_malloc(sizeof (struct directory_entry));
705 memcpy(s_entry, dirnode->self,
706 sizeof(struct directory_entry));
707 s_entry->name = strdup(".");
708 s_entry->whole_name = NULL((void *)0);
709 s_entry->isorec.name_len[0] = 1;
710 s_entry->isorec.flags[0] = 2; /* Mark as a directory */
711 iso9660_file_length (".", s_entry, 1);
712 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtimest_mtim.tv_sec);
713 s_entry->filedir = dirnode;
714
715 dirnode->contents = s_entry;
716 dirnode->contents->next = orig_contents;
717
718 if(use_RockRidge)
719 {
720 fstatbuf.st_mode = 0555 | S_IFDIR0040000;
721 fstatbuf.st_nlink = 2;
722
723 if( dirnode == root )
724 {
725 deep_flag |= NEED_CE8 | NEED_SP16; /* For extension record */
726 }
727
728 generate_rock_ridge_attributes("",
729 ".", s_entry,
730 &fstatbuf, &fstatbuf, deep_flag);
731 }
732
733 dirnode->dir_flags |= DIR_HAS_DOT0x02;
734 }
735
736}
737
738static void FDECL2(update_nlink, struct directory_entry *, s_entry, int, value)update_nlink(struct directory_entry * s_entry, int value)
739{
740 unsigned char * pnt;
741 int len;
742
743 pnt = s_entry->rr_attributes;
744 len = s_entry->total_rr_attr_size;
745 while(len)
746 {
747 if(pnt[0] == 'P' && pnt[1] == 'X')
748 {
749 set_733((char *) pnt+12, value);
750 break;
751 }
752 len -= pnt[2];
753 pnt += pnt[2];
754 }
755}
756
757static void FDECL1(increment_nlink, struct directory_entry *, s_entry)increment_nlink(struct directory_entry * s_entry)
758{
759 unsigned char * pnt;
760 int len, nlink;
761
762 pnt = s_entry->rr_attributes;
763 len = s_entry->total_rr_attr_size;
764 while(len)
765 {
766 if(pnt[0] == 'P' && pnt[1] == 'X')
767 {
768 nlink = get_733((char *) pnt+12);
769 set_733((char *) pnt+12, nlink+1);
770 break;
771 }
772 len -= pnt[2];
773 pnt += pnt[2];
774 }
775}
776
777void finish_cl_pl_entries(){
778 struct directory_entry *s_entry, *s_entry1;
779 struct directory * d_entry;
780
781 /* if the reloc_dir is hidden (empty), then return */
782 if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY0x40)
783 return;
784
785 s_entry = reloc_dir->contents;
786 s_entry = s_entry->next->next; /* Skip past . and .. */
787 for(; s_entry; s_entry = s_entry->next){
788 /* skip if it's hidden */
789 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40) {
790 continue;
791 }
792 d_entry = reloc_dir->subdir;
793 while(d_entry){
794 if(d_entry->self == s_entry) break;
795 d_entry = d_entry->next;
796 };
797 if(!d_entry){
798 fprintf(stderr(&__sF[2]),"Unable to locate directory parent\n");
799 exit(1);
800 };
801
802 /* First fix the PL pointer in the directory in the rr_reloc dir */
803 s_entry1 = d_entry->contents->next;
804 set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
805 s_entry->filedir->extent);
806
807 /* Now fix the CL pointer */
808 s_entry1 = s_entry->parent_rec;
809
810 set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8,
811 d_entry->extent);
812
813 s_entry->filedir = reloc_dir; /* Now we can fix this */
814 }
815 /* Next we need to modify the NLINK terms in the assorted root directory records
816 to account for the presence of the RR_MOVED directory */
817
818 increment_nlink(root->self);
819 increment_nlink(root->self->next);
820 d_entry = root->subdir;
821 while(d_entry){
822 increment_nlink(d_entry->contents->next);
823 d_entry = d_entry->next;
824 };
825}
826
827/*
828 * Function: scan_directory_tree
829 *
830 * Purpose: Walk through a directory on the local machine
831 * filter those things we don't want to include
832 * and build our representation of a dir.
833 *
834 * Notes:
835 */
836int
837FDECL3(scan_directory_tree,struct directory *, this_dir,scan_directory_tree(struct directory * this_dir, char * path,
struct directory_entry * de)
838 char *, path,scan_directory_tree(struct directory * this_dir, char * path,
struct directory_entry * de)
839 struct directory_entry *, de)scan_directory_tree(struct directory * this_dir, char * path,
struct directory_entry * de)
840{
841 DIR * current_dir;
842 char whole_path[1024];
843 struct dirent * d_entry;
844 struct directory * parent;
845 int dflag;
846 char * old_path;
847
848 if (verbose > 1)
849 {
850 fprintf(stderr(&__sF[2]), "Scanning %s\n", path);
851 }
852
853 current_dir = opendir(path);
854 d_entry = NULL((void *)0);
855
856 /* Apparently NFS sometimes allows you to open the directory, but
857 then refuses to allow you to read the contents. Allow for this */
858
859 old_path = path;
860
861 if(current_dir) d_entry = readdir(current_dir);
862
863 if(!current_dir || !d_entry)
864 {
865 fprintf(stderr(&__sF[2]),"Unable to open directory %s\n", path);
866 de->isorec.flags[0] &= ~2; /* Mark as not a directory */
867 if(current_dir) closedir(current_dir);
868 return 0;
869 }
870
871 parent = de->filedir;
Value stored to 'parent' is never read
872 /* Set up the struct for the current directory, and insert it into the
873 tree */
874
875#ifdef VMS
876 vms_path_fixup(path);
877#endif
878
879 /*
880 * if entry for this sub-directory is hidden, then hide this directory
881 */
882 if (de->de_flags & INHIBIT_ISO9660_ENTRY0x40)
883 this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY0x40;
884
885 if (de->de_flags & INHIBIT_JOLIET_ENTRY0x08)
886 this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY0x08;
887
888 /*
889 * Now we scan the directory itself, and look at what is inside of it.
890 */
891 dflag = 0;
892 while(1==1){
893
894 /* The first time through, skip this, since we already asked for
895 the first entry when we opened the directory. */
896 if(dflag) d_entry = readdir(current_dir);
897 dflag++;
898
899 if(!d_entry) break;
900
901 /* OK, got a valid entry */
902
903 /* If we do not want all files, then pitch the backups. */
904 if(!all_files){
905 if( strchr(d_entry->d_name,'~')
906 || strchr(d_entry->d_name,'#'))
907 {
908 if( verbose > 0 )
909 {
910 fprintf(stderr(&__sF[2]), "Ignoring file %s\n", d_entry->d_name);
911 }
912 continue;
913 }
914 }
915
916#ifdef APPLE_HYB1
917 if (apple_both) {
918 /* exclude certain HFS type files/directories for the time being */
919 if (hfs_exclude(d_entry->d_name))
920 continue;
921 }
922#endif /* APPLE_HYB */
923
924 if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){
925 fprintf(stderr(&__sF[2]), "Overflow of stat buffer\n");
926 exit(1);
927 };
928
929 /* Generate the complete ASCII path for this file */
930 strcpy(whole_path, path);
931#ifndef VMS
932 if(whole_path[strlen(whole_path)-1] != '/')
933 strcat(whole_path, "/");
934#endif
935 strcat(whole_path, d_entry->d_name);
936
937 /** Should we exclude this file ? */
938 if (matches(d_entry->d_name) || matches(whole_path)) {
939 if (verbose > 1) {
940 fprintf(stderr(&__sF[2]), "Excluded by match: %s\n", whole_path);
941 }
942 continue;
943 }
944
945 if( generate_tables
946#ifdef APPLE_HYB1
947 && strcmp(d_entry->d_name, trans_tbl) == 0 )
948#else
949 && strcmp(d_entry->d_name, "TRANS.TBL") == 0 )
950#endif /* APPLE_HYB */
951 {
952 /*
953 * Ignore this entry. We are going to be generating new
954 * versions of these files, and we need to ignore any
955 * originals that we might have found.
956 */
957 if (verbose > 1)
958 {
959 fprintf(stderr(&__sF[2]), "Excluded: %s\n",whole_path);
960 }
961 continue;
962 }
963
964 /*
965 * If we already have a '.' or a '..' entry, then don't
966 * insert new ones.
967 */
968 if( strcmp(d_entry->d_name, ".") == 0
969 && this_dir->dir_flags & DIR_HAS_DOT0x02 )
970 {
971 continue;
972 }
973
974 if( strcmp(d_entry->d_name, "..") == 0
975 && this_dir->dir_flags & DIR_HAS_DOTDOT0x04 )
976 {
977 continue;
978 }
979
980#if 0
981 if (verbose > 1) fprintf(stderr(&__sF[2]), "%s\n",whole_path);
982#endif
983 /*
984 * This actually adds the entry to the directory in question.
985 */
986#ifdef APPLE_HYB1
987 insert_file_entry(this_dir, whole_path, d_entry->d_name, 0);
988#else
989 insert_file_entry(this_dir, whole_path, d_entry->d_name);
990#endif /* APPLE_HYB */
991 }
992 closedir(current_dir);
993
994#ifdef APPLE_HYB1
995 /* if we cached the HFS info stuff for this directory, then delete it */
996 if (this_dir->hfs_info) {
997 del_hfs_info(this_dir->hfs_info);
998 this_dir->hfs_info = 0;
999 }
1000#endif /* APPLE_HYB */
1001
1002 return 1;
1003}
1004
1005
1006/*
1007 * Function: insert_file_entry
1008 *
1009 * Purpose: Insert one entry into our directory node.
1010 *
1011 * Note:
1012 * This function inserts a single entry into the directory. It
1013 * is assumed that all filtering and decision making regarding what
1014 * we want to include has already been made, so the purpose of this
1015 * is to insert one entry (file, link, dir, etc), into this directory.
1016 * Note that if the entry is a dir (or if we are following links,
1017 * and the thing it points to is a dir), then we will scan those
1018 * trees before we return.
1019 */
1020#ifdef APPLE_HYB1
1021int
1022FDECL4(insert_file_entry,struct directory *, this_dir,insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name, int have_rsrc)
1023 char *, whole_path,insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name, int have_rsrc)
1024 char *, short_name,insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name, int have_rsrc)
1025 int, have_rsrc)insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name, int have_rsrc)
1026#else
1027int
1028FDECL3(insert_file_entry,struct directory *, this_dir,insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name)
1029 char *, whole_path,insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name)
1030 char *, short_name)insert_file_entry(struct directory * this_dir, char * whole_path
, char * short_name)
1031#endif /* APPLE_HYB */
1032{
1033 struct stat statbuf, lstatbuf;
1034 struct directory_entry * s_entry, *s_entry1;
1035 int lstatus;
1036 int status;
1037 int deep_flag;
1038#ifdef APPLE_HYB1
1039 int x_hfs = 0;
1040 int htype = 0;
1041#endif /* APPLE_HYB */
1042
1043 status = stat_filter(whole_path, &statbuf);
1044
1045 lstatus = lstat_filter(whole_path, &lstatbuf);
1046
1047 if( (status == -1) && (lstatus == -1) )
1048 {
1049 /*
1050 * This means that the file doesn't exist, or isn't accessible.
1051 * Sometimes this is because of NFS permissions problems.
1052 */
1053 fprintf(stderr(&__sF[2]), "Non-existant or inaccessible: %s\n",whole_path);
1054 return 0;
1055 }
1056
1057 if(this_dir == root && strcmp(short_name, ".") == 0)
1058 root_statbuf = statbuf; /* Save this for later on */
1059
1060 /* We do this to make sure that the root entries are consistent */
1061 if(this_dir == root && strcmp(short_name, "..") == 0)
1062 {
1063 statbuf = root_statbuf;
1064 lstatbuf = root_statbuf;
1065 }
1066
1067 if(S_ISLNK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0120000))
1068 {
1069
1070 /* Here we decide how to handle the symbolic links. Here
1071 we handle the general case - if we are not following
1072 links or there is an error, then we must change
1073 something. If RR is in use, it is easy, we let RR
1074 describe the file. If not, then we punt the file. */
1075
1076 if((status || !follow_links))
1077 {
1078 if(use_RockRidge)
1079 {
1080 status = 0;
1081 statbuf.st_size = 0;
1082 STAT_INODE(statbuf)(statbuf.st_ino) = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1083 statbuf.st_dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
1084 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT0170000) | S_IFREG0100000;
1085 } else {
1086 if(follow_links)
1087 {
1088 fprintf(stderr(&__sF[2]),
1089 "Unable to stat file %s - ignoring and continuing.\n",
1090 whole_path);
1091 }
1092 else
1093 {
1094 fprintf(stderr(&__sF[2]),
1095 "Symlink %s ignored - continuing.\n",
1096 whole_path);
1097 return 0; /* Non Rock Ridge discs - ignore all symlinks */
1098 }
1099 }
1100 }
1101
1102 /* Here we handle a different kind of case. Here we have
1103 a symlink, but we want to follow symlinks. If we run
1104 across a directory loop, then we need to pretend that
1105 we are not following symlinks for this file. If this
1106 is the first time we have seen this, then make this
1107 seem as if there was no symlink there in the first
1108 place */
1109
1110 if( follow_links
1111 && S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000) )
1112 {
1113 if( strcmp(short_name, ".")
1114 && strcmp(short_name, "..") )
1115 {
1116 if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)(statbuf.st_ino)))
1117 {
1118 if(!use_RockRidge)
1119 {
1120 fprintf(stderr(&__sF[2]), "Already cached directory seen (%s)\n",
1121 whole_path);
1122 return 0;
1123 }
1124 statbuf.st_size = 0;
1125 STAT_INODE(statbuf)(statbuf.st_ino) = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1126 statbuf.st_dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
1127 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT0170000) | S_IFREG0100000;
1128 }
1129 else
1130 {
1131 lstatbuf = statbuf;
1132 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)(statbuf.st_ino));
1133 }
1134 }
1135 }
1136
1137 /*
1138 * For non-directories, we just copy the stat information over
1139 * so we correctly include this file.
1140 */
1141 if( follow_links
1142 && !S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000) )
1143 {
1144 lstatbuf = statbuf;
1145 }
1146 }
1147
1148 /*
1149 * Add directories to the cache so that we don't waste space even
1150 * if we are supposed to be following symlinks.
1151 */
1152 if( follow_links
1153 && strcmp(short_name, ".")
1154 && strcmp(short_name, "..")
1155 && S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000) )
1156 {
1157 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)(statbuf.st_ino));
1158 }
1159#ifdef VMS
1160 if(!S_ISDIR(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0040000) && (statbuf.st_fab_rfm != FAB$C_FIX &&
1161 statbuf.st_fab_rfm != FAB$C_STMLF)) {
1162 fprintf(stderr(&__sF[2]),"Warning - file %s has an unsupported VMS record"
1163 " format (%d)\n",
1164 whole_path, statbuf.st_fab_rfm);
1165 }
1166#endif
1167
1168 if(S_ISREG(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0100000) && (status = access(whole_path, R_OK0x04)))
1169 {
1170 fprintf(stderr(&__sF[2]), "File %s is not readable (errno = %d) - ignoring\n",
1171 whole_path, errno(*__errno()));
1172 return 0;
1173 }
1174
1175 /* Add this so that we can detect directory loops with hard links.
1176 If we are set up to follow symlinks, then we skip this checking. */
1177 if( !follow_links
1178 && S_ISDIR(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0040000)
1179 && strcmp(short_name, ".")
1180 && strcmp(short_name, "..") )
1181 {
1182 if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)(statbuf.st_ino))) {
1183#ifdef APPLE_HYB1
1184 /* NON-HFS change - print just a warning *if* this ever happens */
1185 fprintf(stderr(&__sF[2]),"Warning: Directory loop (%s)\n", whole_path);
1186#else
1187 fprintf(stderr(&__sF[2]),"Directory loop - fatal goof (%s %lx %llu).\n",
1188 whole_path, (unsigned long) statbuf.st_dev,
1189 (unsigned long long) STAT_INODE(statbuf)(statbuf.st_ino));
1190 exit(1);
1191#endif
1192 }
1193 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)(statbuf.st_ino));
1194 }
1195
1196 if (!S_ISCHR(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0020000) && !S_ISBLK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0060000) &&
1197 !S_ISFIFO(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0010000) && !S_ISSOCK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0140000)
1198 && !S_ISLNK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0120000) && !S_ISREG(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0100000) &&
1199 !S_ISDIR(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0040000)) {
1200 fprintf(stderr(&__sF[2]),"Unknown file type %s - ignoring and continuing.\n",
1201 whole_path);
1202 return 0;
1203 }
1204
1205 /* Who knows what trash this is - ignore and continue */
1206
1207 if(status)
1208 {
1209 fprintf(stderr(&__sF[2]),
1210 "Unable to stat file %s - ignoring and continuing.\n",
1211 whole_path);
1212 return 0;
1213 }
1214
1215 /*
1216 * Check to see if we have already seen this directory node.
1217 * If so, then we don't create a new entry for it, but we do want
1218 * to recurse beneath it and add any new files we do find.
1219 */
1220 if (S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000))
1221 {
1222 int dflag;
1223
1224 for( s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
1225 {
1226 if( strcmp(s_entry->name, short_name) == 0 )
1227 {
1228 break;
1229 }
1230 }
1231 if ( s_entry != NULL((void *)0)
1232 && strcmp(short_name,".")
1233 && strcmp(short_name,".."))
1234 {
1235 struct directory * child;
1236
1237 if ( (s_entry->de_flags & RELOCATED_DIRECTORY0x20) != 0)
1238 {
1239 for( s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next)
1240 {
1241 if( strcmp(s_entry->name, short_name) == 0 )
1242 {
1243 break;
1244 }
1245 }
1246 child = find_or_create_directory(reloc_dir, whole_path,
1247 s_entry, 1);
1248 }
1249 else
1250 {
1251 child = find_or_create_directory(this_dir, whole_path,
1252 s_entry, 1);
1253 /* If unable to scan directory, mark this as a non-directory */
1254 }
1255 dflag = scan_directory_tree(child, whole_path, s_entry);
1256 if(!dflag)
1257 {
1258 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT0170000) | S_IFREG0100000;
1259 }
1260 return 0;
1261 }
1262 }
1263#ifdef APPLE_HYB1
1264 /* Should we exclude this HFS file ? - only works with -hfs */
1265 if (!have_rsrc && apple_hyb && strcmp(short_name,".") && strcmp(short_name,"..")) {
1266 x_hfs = hfs_matches(short_name) || hfs_matches(whole_path);
1267 if (x_hfs) {
1268 if (verbose > 1) {
1269 fprintf(stderr(&__sF[2]), "Hidden from HFS tree: %s\n", whole_path);
1270 }
1271 }
1272 }
1273
1274 /* check we are a file, using Apple extensions and have a .resource part
1275 and not excluded */
1276 if (S_ISREG(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0100000) && !have_rsrc && apple_both && !x_hfs) {
1277 char rsrc_path[1024]; /* rsrc fork filename */
1278
1279 /* construct the resource full path */
1280 htype = get_hfs_rname(whole_path, short_name, rsrc_path);
1281 /* check we can read the resouce fork */
1282 if (htype) {
1283 struct stat rstatbuf, rlstatbuf;
1284
1285 /* some further checks on the file */
1286 status = stat_filter(rsrc_path, &rstatbuf);
1287
1288 lstatus = lstat_filter(rsrc_path, &rlstatbuf);
1289
1290 if(!status && !lstatus && S_ISREG(rstatbuf.st_mode)((rstatbuf.st_mode & 0170000) == 0100000) && rstatbuf.st_size > 0) {
1291 /* have a resource file - insert it into the current directory
1292 but flag that we have a resource fork */
1293 insert_file_entry(this_dir, rsrc_path, short_name, htype);
1294 }
1295 }
1296 }
1297#endif /* APPLE_HYB */
1298
1299 s_entry = (struct directory_entry *)
1300 e_malloc(sizeof (struct directory_entry));
1301 /* memset the whole struct, not just the isorec.extent part JCP */
1302 memset(s_entry, 0, sizeof (struct directory_entry));
1303 s_entry->next = this_dir->contents;
1304/*memset(s_entry->isorec.extent, 0, 8); */
1305 this_dir->contents = s_entry;
1306 deep_flag = 0;
1307 s_entry->table = NULL((void *)0);
1308
1309 s_entry->name = strdup(short_name);
1310 s_entry->whole_name = strdup (whole_path);
1311
1312 s_entry->de_flags = 0;
1313
1314 /*
1315 * If the current directory is hidden, then hide all it's members
1316 * otherwise check if this entry needs to be hidden as well */
1317 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY0x40) {
1318 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY0x40;
1319 }
1320 else if (strcmp(short_name,".") && strcmp(short_name,"..")) {
1321 if (i_matches(short_name) || i_matches(whole_path)) {
1322 if (verbose > 1) {
1323 fprintf(stderr(&__sF[2]), "Hidden from ISO9660 tree: %s\n", whole_path);
1324 }
1325 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY0x40;
1326 }
1327 }
1328
1329 if (this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY0x08) {
1330 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY0x08;
1331 }
1332 else if (strcmp(short_name,".") && strcmp(short_name,"..")) {
1333 if (j_matches(short_name) || j_matches(whole_path)) {
1334 if (verbose > 1) {
1335 fprintf(stderr(&__sF[2]), "Hidden from Joliet tree: %s\n", whole_path);
1336 }
1337 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY0x08;
1338 }
1339 }
1340
1341 s_entry->filedir = this_dir;
1342 s_entry->isorec.flags[0] = 0;
1343 s_entry->isorec.ext_attr_length[0] = 0;
1344 iso9660_date(s_entry->isorec.date, statbuf.st_mtimest_mtim.tv_sec);
1345 s_entry->isorec.file_unit_size[0] = 0;
1346 s_entry->isorec.interleave[0] = 0;
1347
1348#ifdef APPLE_HYB1
1349 if (apple_both && !x_hfs) {
1350 s_entry->hfs_ent = NULL((void *)0);
1351 s_entry->assoc = NULL((void *)0);
1352 s_entry->hfs_off = 0;
1353 s_entry->hfs_type = htype;
1354 if (have_rsrc) {
1355 s_entry->isorec.flags[0] = ASSOC_FLAG4; /* associated (rsrc) file */
1356 /* set the type of HFS file */
1357 s_entry->hfs_type = have_rsrc;
1358 /* don't want the rsrc file to be included in any Joliet tree */
1359 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY0x08;
1360 }
1361 else if (s_entry->next) {
1362 /* if previous entry is an associated file, then "link" it
1363 to this file i.e. we have a data/resource pair */
1364 if (s_entry->next->isorec.flags[0] & ASSOC_FLAG4) {
1365 s_entry->assoc = s_entry->next;
1366 /* share the same HFS parameters */
1367 s_entry->hfs_ent = s_entry->next->hfs_ent;
1368 s_entry->hfs_type = s_entry->next->hfs_type;
1369 }
1370 }
1371 /* allocate HFS entry if required */
1372 if (apple_both && strcmp(short_name, ".") && strcmp(short_name, "..")) {
1373 if (!s_entry->hfs_ent) {
1374 hfsdirent *hfs_ent;
1375 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent));
1376
1377 /* fill in the defaults */
1378 hfs_ent->flags = hfs_ent->fdflags = 0;
1379 hfs_ent->crdate = lstatbuf.st_ctimest_ctim.tv_sec;
1380 hfs_ent->mddate = lstatbuf.st_mtimest_mtim.tv_sec;
1381 hfs_ent->dsize = hfs_ent->rsize = 0;
1382 s_entry->hfs_ent = hfs_ent;
1383 }
1384 if (have_rsrc)
1385 /* set rsrc size */
1386 s_entry->hfs_ent->rsize = lstatbuf.st_size;
1387 else
1388 /* set data size */
1389 s_entry->hfs_ent->dsize = lstatbuf.st_size;
1390 }
1391 }
1392#endif /* APPLE_HYB */
1393
1394 if( strcmp(short_name, ".") == 0)
1395 {
1396 this_dir->dir_flags |= DIR_HAS_DOT0x02;
1397 }
1398
1399 if( strcmp(short_name, "..") == 0)
1400 {
1401 this_dir->dir_flags |= DIR_HAS_DOTDOT0x04;
1402 }
1403
1404 if( this_dir->parent
1405 && this_dir->parent == reloc_dir
1406 && strcmp(short_name, "..") == 0)
1407 {
1408 s_entry->inode = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1409 s_entry->dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
1410 deep_flag = NEED_PL2;
1411 }
1412 else
1413#ifdef APPLE_HYB1
1414 if (have_rsrc) {
1415 /* don't want rsrc files to be cached */
1416 s_entry->inode = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1417 s_entry->dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
1418 }
1419 else
1420#endif /* APPLE_HYB */
1421 {
1422 s_entry->inode = STAT_INODE(statbuf)(statbuf.st_ino);
1423 s_entry->dev = statbuf.st_dev;
1424 }
1425 set_723(s_entry->isorec.volume_sequence_number, volume_sequence_number);
1426 iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000));
1427 s_entry->rr_attr_size = 0;
1428 s_entry->total_rr_attr_size = 0;
1429 s_entry->rr_attributes = NULL((void *)0);
1430
1431 /* Directories are assigned sizes later on */
1432 if (!S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000))
1433 {
1434 if (S_ISCHR(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0020000) || S_ISBLK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0060000) ||
1435 S_ISFIFO(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0010000) || S_ISSOCK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0140000)
1436 || S_ISLNK(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0120000))
1437 {
1438 s_entry->size = 0;
1439 statbuf.st_size = 0;
1440 }
1441 else
1442 {
1443 s_entry->size = statbuf.st_size;
1444 }
1445
1446 set_733((char *) s_entry->isorec.size, statbuf.st_size);
1447 }
1448 else
1449 {
1450 s_entry->isorec.flags[0] = 2;
1451 }
1452#ifdef APPLE_HYB1
1453 /* if the directory is HFS excluded, then we don't have an hfs_ent */
1454 if (apple_both && s_entry->hfs_ent && s_entry->isorec.flags[0] & 2) {
1455 /* get the Mac directory name */
1456 get_hfs_dir(whole_path, short_name, s_entry);
1457
1458 /* if required, set ISO directory name from HFS name */
1459 if (mac_name)
1460 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1);
1461 }
1462#endif /* APPLE_HYB */
1463
1464 if (strcmp(short_name,".") && strcmp(short_name,"..") &&
1465 S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000) && this_dir->depth > RR_relocation_depth)
1466 {
1467 struct directory * child;
1468
1469 if(!reloc_dir) generate_reloc_directory();
1470
1471 /*
1472 * Replicate the entry for this directory. The old one will stay where it
1473 * is, and it will be neutered so that it no longer looks like a directory.
1474 * The new one will look like a directory, and it will be put in the reloc_dir.
1475 */
1476 s_entry1 = (struct directory_entry *)
1477 e_malloc(sizeof (struct directory_entry));
1478 memcpy(s_entry1, s_entry, sizeof(struct directory_entry));
1479 s_entry1->table = NULL((void *)0);
1480 s_entry1->name = strdup(this_dir->contents->name);
1481 s_entry1->whole_name = strdup(this_dir->contents->whole_name);
1482 s_entry1->next = reloc_dir->contents;
1483 reloc_dir->contents = s_entry1;
1484 s_entry1->priority = 32768;
1485 s_entry1->parent_rec = this_dir->contents;
1486
1487 deep_flag = NEED_RE1;
1488
1489 if(use_RockRidge)
1490 {
1491 generate_rock_ridge_attributes(whole_path,
1492 short_name, s_entry1,
1493 &statbuf, &lstatbuf, deep_flag);
1494 }
1495
1496 deep_flag = 0;
1497
1498 /* We need to set this temporarily so that the parent to this
1499 is correctly determined. */
1500 s_entry1->filedir = reloc_dir;
1501 child = find_or_create_directory(reloc_dir, whole_path,
1502 s_entry1, 0);
1503 scan_directory_tree(child, whole_path, s_entry1);
1504 s_entry1->filedir = this_dir;
1505
1506 statbuf.st_size = 0;
1507 statbuf.st_mode &= 0777;
1508 set_733((char *) s_entry->isorec.size, 0);
1509 s_entry->size = 0;
1510 s_entry->isorec.flags[0] = 0;
1511 s_entry->inode = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1512 s_entry->de_flags |= RELOCATED_DIRECTORY0x20;
1513 deep_flag = NEED_CL4;
1514 }
1515
1516 if(generate_tables
1517 && strcmp(s_entry->name, ".")
1518 && strcmp(s_entry->name, ".."))
1519 {
1520 char buffer[2048];
1521 int nchar;
1522 switch(lstatbuf.st_mode & S_IFMT0170000)
1523 {
1524 case S_IFDIR0040000:
1525 snprintf(buffer, sizeof buffer, "D\t%s\n",
1526 s_entry->name);
1527 break;
1528#ifdef S_IFBLK0060000
1529/* extra for WIN32 - if it doesn't have the major/minor defined, then
1530 S_IFBLK and S_IFCHR type files are unlikely to exist anyway ...
1531 code similar to that in rock.c */
1532
1533/* for some reason, MAJOR_IN_SYSMACROS isn't defined on a SunOS when
1534 it should be, so see if major() is defined instead */
1535/*
1536#if !(defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV))
1537*/
1538#ifndef major
1539#define major(dev)(((unsigned)(dev) >> 8) & 0xff) (sizeof(dev_t) <= 2 ? ((dev) >> 8) : \
1540 (sizeof(dev_t) <= 4 ? (((dev) >> 8) >> 8) : \
1541 (((dev) >> 16) >> 16)))
1542#define minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
(sizeof(dev_t) <= 2 ? (dev) & 0xff : \
1543 (sizeof(dev_t) <= 4 ? (dev) & 0xffff : \
1544 (dev) & 0xffffffff))
1545#endif
1546 case S_IFBLK0060000:
1547 snprintf(buffer, sizeof buffer, "B\t%s\t%lu %lu\n",
1548 s_entry->name,
1549 (unsigned long) major(statbuf.st_rdev)(((unsigned)(statbuf.st_rdev) >> 8) & 0xff),
1550 (unsigned long) minor(statbuf.st_rdev)((unsigned)((statbuf.st_rdev) & 0xff) | (((statbuf.st_rdev
) & 0xffff0000) >> 8))
);
1551 break;
1552#endif
1553#ifdef S_IFIFO0010000
1554 case S_IFIFO0010000:
1555 snprintf(buffer, sizeof buffer, "P\t%s\n",
1556 s_entry->name);
1557 break;
1558#endif
1559#ifdef S_IFCHR0020000
1560 case S_IFCHR0020000:
1561 snprintf(buffer, sizeof buffer, "C\t%s\t%lu %lu\n",
1562 s_entry->name,
1563 (unsigned long) major(statbuf.st_rdev)(((unsigned)(statbuf.st_rdev) >> 8) & 0xff),
1564 (unsigned long) minor(statbuf.st_rdev)((unsigned)((statbuf.st_rdev) & 0xff) | (((statbuf.st_rdev
) & 0xffff0000) >> 8))
);
1565 break;
1566#endif
1567#ifdef S_IFLNK0120000
1568 case S_IFLNK0120000:
1569 nchar = readlink(whole_path,
1570 (char *)symlink_buff,
1571 sizeof(symlink_buff)-1);
1572 symlink_buff[nchar < 0 ? 0 : nchar] = 0;
1573 snprintf(buffer, sizeof buffer, "L\t%s\t%s\n",
1574 s_entry->name, symlink_buff);
1575 break;
1576#endif
1577#ifdef S_IFSOCK0140000
1578 case S_IFSOCK0140000:
1579 snprintf(buffer, sizeof buffer, "S\t%s\n",
1580 s_entry->name);
1581 break;
1582#endif
1583 case S_IFREG0100000:
1584 default:
1585 snprintf(buffer, sizeof buffer, "F\t%s\n",
1586 s_entry->name);
1587 break;
1588 };
1589 s_entry->table = strdup(buffer);
1590 }
1591
1592 if(S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000))
1593 {
1594 int dflag;
1595 if (strcmp(short_name,".") && strcmp(short_name,".."))
1596 {
1597 struct directory * child;
1598
1599 child = find_or_create_directory(this_dir, whole_path,
1600 s_entry, 1);
1601 dflag = scan_directory_tree(child, whole_path, s_entry);
1602
1603 if(!dflag)
1604 {
1605 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT0170000) | S_IFREG0100000;
1606 if( child->contents == NULL((void *)0) )
1607 {
1608 delete_directory(this_dir, child);
1609 }
1610 }
1611 }
1612 /* If unable to scan directory, mark this as a non-directory */
1613 }
1614
1615 if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0)
1616 {
1617 deep_flag |= NEED_CE8 | NEED_SP16; /* For extension record */
1618 }
1619
1620 /* Now figure out how much room this file will take in the
1621 directory */
1622
1623#ifdef APPLE_HYB1
1624 /* if the file is HFS excluded, then we don't have an hfs_ent */
1625 if (apple_both && !have_rsrc && s_entry->hfs_ent) {
1626 if (S_ISREG(lstatbuf.st_mode)((lstatbuf.st_mode & 0170000) == 0100000)) { /* it's a regular file */
1627
1628 /* fill in the rest of the HFS entry */
1629 get_hfs_info(whole_path, short_name, s_entry);
1630
1631 /* if required, set ISO directory name from HFS name */
1632 if (mac_name)
1633 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 0);
1634
1635 /* print details about the HFS file */
1636 if (verbose > 2)
1637 print_hfs_info(s_entry);
1638
1639 /* copy the new ISO9660 name to the rsrc fork - if it exists */
1640 if (s_entry->assoc)
1641 strcpy(s_entry->assoc->isorec.name, s_entry->isorec.name);
1642
1643 /* we can't handle hard links in the hybrid case, so we "uncache"
1644 the file. The downside to this is that hard linked files
1645 are added to the output image more than once (we've already
1646 done this for rsrc files) */
1647 if (apple_hyb) {
1648 s_entry->inode = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1649 s_entry->dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
1650 }
1651 }
1652 else if (!(s_entry->isorec.flags[0] & 2)) { /* not a directory .. */
1653
1654 /* no mac equivalent, so ignore - have to be careful here, the
1655 hfs_ent may be also be for a relocated directory */
1656 if (s_entry->hfs_ent && !(s_entry->de_flags & RELOCATED_DIRECTORY0x20))
1657 free(s_entry->hfs_ent);
1658 s_entry->hfs_ent = NULL((void *)0);
1659 }
1660
1661 /* if the rsrc size is zero, then we don't need the entry, so we
1662 might as well delete it - this will only happen if we didn't
1663 know the rsrc size from the rsrc file size */
1664 if(s_entry->assoc && s_entry->assoc->size == 0)
1665 delete_rsrc_ent(s_entry);
1666 }
1667
1668 if(apple_ext && s_entry->assoc) {
1669 /* need Apple extensions for the resource fork as well */
1670 generate_rock_ridge_attributes(whole_path,
1671 short_name, s_entry->assoc,
1672 &statbuf, &lstatbuf, deep_flag);
1673 }
1674 /* leave out resource fork for the time being */
1675 if (use_RockRidge && !have_rsrc) {
1676#else
1677 if(use_RockRidge)
1678 {
1679#endif /* APPLE_HYB */
1680 generate_rock_ridge_attributes(whole_path,
1681 short_name, s_entry,
1682 &statbuf, &lstatbuf, deep_flag);
1683
1684 }
1685
1686 return 1;
1687}
1688
1689
1690void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile)generate_iso9660_directories(struct directory * node, FILE* outfile
)
{
1691 struct directory * dpnt;
1692
1693 dpnt = node;
1694
1695 while (dpnt){
1696 if( dpnt->extent > session_start )
1697 {
1698 generate_one_directory(dpnt, outfile);
1699 }
1700 if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile);
1701 dpnt = dpnt->next;
1702 }
1703}
1704
1705/*
1706 * Function: find_or_create_directory
1707 *
1708 * Purpose: Locate a directory entry in the tree, create if needed.
1709 *
1710 * Arguments:
1711 */
1712struct directory * FDECL4(find_or_create_directory, struct directory *, parent,find_or_create_directory(struct directory * parent, const char
* path, struct directory_entry * de, int flag)
1713 const char *, path,find_or_create_directory(struct directory * parent, const char
* path, struct directory_entry * de, int flag)
1714 struct directory_entry *, de, int, flag)find_or_create_directory(struct directory * parent, const char
* path, struct directory_entry * de, int flag)
1715{
1716 struct directory * dpnt;
1717 struct directory_entry * orig_de;
1718 struct directory * next_brother;
1719 const char * cpnt;
1720 const char * pnt;
1721
1722 orig_de = de;
1723
1724 pnt = strrchr(path, PATH_SEPARATOR'/');
1725 if( pnt == NULL((void *)0) )
1726 {
1727 pnt = path;
1728 }
1729 else
1730 {
1731 pnt++;
1732 }
1733
1734 if( parent != NULL((void *)0) )
1735 {
1736 dpnt = parent->subdir;
1737
1738 while (dpnt)
1739 {
1740 /*
1741 * Weird hack time - if there are two directories by the
1742 * same name in the reloc_dir, they are not treated as the
1743 * same thing unless the entire path matches completely.
1744 */
1745 if( flag && strcmp(dpnt->de_name, pnt) == 0 )
1746 {
1747 return dpnt;
1748 }
1749 dpnt = dpnt->next;
1750 }
1751 }
1752
1753 /*
1754 * We don't know if we have a valid directory entry for this one
1755 * yet. If not, we need to create one.
1756 */
1757 if( de == NULL((void *)0) )
1758 {
1759 de = (struct directory_entry *)
1760 e_malloc(sizeof (struct directory_entry));
1761 memset(de, 0, sizeof(struct directory_entry));
1762 de->next = parent->contents;
1763 parent->contents = de;
1764 de->name = strdup(pnt);
1765 de->filedir = parent;
1766 de->isorec.flags[0] = 2;
1767 de->priority = 32768;
1768 de->inode = UNCACHED_INODE(sizeof(ino_t) >= 8 ? 0x7fffffffffffffffLL : 0x7fffffff);
1769 de->dev = (dev_t) UNCACHED_DEVICE(sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff);
1770 set_723(de->isorec.volume_sequence_number, volume_sequence_number);
1771 iso9660_file_length (pnt, de, 1);
1772
1773 init_fstatbuf();
1774 /*
1775 * It doesn't exist for real, so we cannot add any Rock Ridge.
1776 */
1777 if(use_RockRidge)
1778 {
1779 fstatbuf.st_mode = 0555 | S_IFDIR0040000;
1780 fstatbuf.st_nlink = 2;
1781 generate_rock_ridge_attributes("",
1782 (char *) pnt, de,
1783 &fstatbuf,
1784 &fstatbuf, 0);
1785 }
1786 iso9660_date(de->isorec.date, fstatbuf.st_mtimest_mtim.tv_sec);
1787#ifdef APPLE_HYB1
1788 if (apple_both) {
1789 /* give the directory an HFS entry */
1790 hfsdirent *hfs_ent;
1791 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent));
1792
1793 /* fill in the defaults */
1794 hfs_ent->flags = hfs_ent->fdflags = 0;
1795 hfs_ent->crdate = fstatbuf.st_ctimest_ctim.tv_sec;
1796 hfs_ent->mddate = fstatbuf.st_mtimest_mtim.tv_sec;
1797 hfs_ent->dsize = hfs_ent->rsize = 0;
1798
1799 de->hfs_ent = hfs_ent;
1800
1801 /* get the Mac directory name */
1802 get_hfs_dir(path, pnt, de);
1803 }
1804#endif /* APPLE_HYB */
1805 }
1806
1807 /*
1808 * If we don't have a directory for this one yet, then allocate it
1809 * now, and patch it into the tree in the appropriate place.
1810 */
1811 dpnt = (struct directory *) e_malloc(sizeof(struct directory));
1812 memset(dpnt, 0, sizeof(struct directory));
1813 dpnt->next = NULL((void *)0);
1814 dpnt->subdir = NULL((void *)0);
1815 dpnt->self = de;
1816 dpnt->contents = NULL((void *)0);
1817 dpnt->whole_name = strdup(path);
1818 cpnt = strrchr(path, PATH_SEPARATOR'/');
1819 if(cpnt)
1820 cpnt++;
1821 else
1822 cpnt = path;
1823 dpnt->de_name = strdup(cpnt);
1824 dpnt->size = 0;
1825 dpnt->extent = 0;
1826 dpnt->jextent = 0;
1827 dpnt->jsize = 0;
1828#ifdef APPLE_HYB1
1829 dpnt->hfs_ent = de->hfs_ent;
1830#endif /*APPLE_HYB */
1831
1832 if( orig_de == NULL((void *)0) )
1833 {
1834 struct stat xstatbuf;
1835 int sts;
1836
1837 /*
1838 * Now add a . and .. entry in the directory itself.
1839 * This is a little tricky - if the real directory
1840 * exists, we need to stat it first. Otherwise, we
1841 * use the fictitious fstatbuf which points to the time
1842 * at which mkisofs was started.
1843 */
1844 sts = stat_filter(parent->whole_name, &xstatbuf);
1845 if( sts == 0 )
1846 {
1847 attach_dot_entries(dpnt, &xstatbuf);
1848 }
1849 else
1850 {
1851 attach_dot_entries(dpnt, &fstatbuf);
1852 }
1853 }
1854
1855 if(!parent || parent == root)
1856 {
1857 if (!root)
1858 {
1859 root = dpnt; /* First time through for root directory only */
1860 root->depth = 0;
1861 root->parent = root;
1862 } else {
1863 dpnt->depth = 1;
1864 if(!root->subdir)
1865 {
1866 root->subdir = dpnt;
1867 }
1868 else
1869 {
1870 next_brother = root->subdir;
1871 while(next_brother->next) next_brother = next_brother->next;
1872 next_brother->next = dpnt;
1873 }
1874 dpnt->parent = parent;
1875 }
1876 }
1877 else
1878 {
1879 /* Come through here for normal traversal of tree */
1880#ifdef DEBUG
1881 fprintf(stderr(&__sF[2]),"%s(%d) ", path, dpnt->depth);
1882#endif
1883 if(parent->depth > RR_relocation_depth)
1884 {
1885 fprintf(stderr(&__sF[2]),"Directories too deep %s\n", path);
1886 exit(1);
1887 }
1888
1889 dpnt->parent = parent;
1890 dpnt->depth = parent->depth + 1;
1891
1892 if(!parent->subdir)
1893 {
1894 parent->subdir = dpnt;
1895 }
1896 else
1897 {
1898 next_brother = parent->subdir;
1899 while(next_brother->next) next_brother = next_brother->next;
1900 next_brother->next = dpnt;
1901 }
1902 }
1903
1904 return dpnt;
1905}
1906
1907/*
1908 * Function: delete_directory
1909 *
1910 * Purpose: Locate a directory entry in the tree, create if needed.
1911 *
1912 * Arguments:
1913 */
1914static void FDECL2(delete_directory, struct directory *, parent, struct directory *, child)delete_directory(struct directory * parent, struct directory *
child)
1915{
1916 struct directory * tdir;
1917
1918 if( child->contents != NULL((void *)0) )
1919 {
1920 fprintf(stderr(&__sF[2]), "Unable to delete non-empty directory\n");
1921 exit(1);
1922 }
1923
1924 free(child->whole_name);
1925 child->whole_name = NULL((void *)0);
1926
1927 free(child->de_name);
1928 child->de_name = NULL((void *)0);
1929
1930#ifdef APPLE_HYB1
1931 if (apple_both && child->hfs_ent)
1932 free(child->hfs_ent);
1933#endif /* APPLE_HYB */
1934
1935 if( parent->subdir == child )
1936 {
1937 parent->subdir = child->next;
1938 }
1939 else
1940 {
1941 for( tdir = parent->subdir; tdir->next != NULL((void *)0); tdir = tdir->next )
1942 {
1943 if( tdir->next == child )
1944 {
1945 tdir->next = child->next;
1946 break;
1947 }
1948 }
1949 if( tdir == NULL((void *)0) )
1950 {
1951 fprintf(stderr(&__sF[2]), "Unable to locate child directory in parent list\n");
1952 exit(1);
1953 }
1954 }
1955 free(child);
1956 return;
1957}
1958
1959int FDECL1(sort_tree, struct directory *, node)sort_tree(struct directory * node){
1960 struct directory * dpnt;
1961 int ret = 0;
1962
1963 dpnt = node;
1964
1965 while (dpnt){
1966 ret = sort_n_finish(dpnt);
1967 if( ret )
1968 {
1969 break;
1970 }
1971
1972 if(dpnt->subdir) sort_tree(dpnt->subdir);
1973 dpnt = dpnt->next;
1974 }
1975 return ret;
1976}
1977
1978void FDECL1(dump_tree, struct directory *, node)dump_tree(struct directory * node){
1979 struct directory * dpnt;
1980
1981 dpnt = node;
1982
1983 while (dpnt){
1984 fprintf(stderr(&__sF[2]),"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name);
1985 if(dpnt->subdir) dump_tree(dpnt->subdir);
1986 dpnt = dpnt->next;
1987 }
1988}
1989
1990void FDECL1(update_nlink_field, struct directory *, node)update_nlink_field(struct directory * node)
1991{
1992 struct directory * dpnt;
1993 struct directory * xpnt;
1994 struct directory_entry * s_entry;
1995 int i;
1996
1997 dpnt = node;
1998
1999 while (dpnt)
2000 {
2001 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY0x40) {
2002 dpnt = dpnt->next;
2003 continue;
2004 }
2005
2006 /*
2007 * First, count up the number of subdirectories this guy has.
2008 */
2009 for(i=0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
2010 if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY0x40) == 0)
2011 i++;
2012 /*
2013 * Next check to see if we have any relocated directories
2014 * in this directory. The nlink field will include these
2015 * as real directories when they are properly relocated.
2016 *
2017 * In the non-rockridge disk, the relocated entries appear
2018 * as zero length files.
2019 */
2020 for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
2021 {
2022 if( (s_entry->de_flags & RELOCATED_DIRECTORY0x20) != 0 &&
2023 (s_entry->de_flags & INHIBIT_ISO9660_ENTRY0x40) == 0)
2024 {
2025 i++;
2026 }
2027 }
2028 /*
2029 * Now update the field in the Rock Ridge entry.
2030 */
2031 update_nlink(dpnt->self, i + 2);
2032
2033 /*
2034 * Update the '.' entry for this directory.
2035 */
2036 update_nlink(dpnt->contents, i + 2);
2037
2038 /*
2039 * Update all of the '..' entries that point to this guy.
2040 */
2041 for(xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
2042 update_nlink(xpnt->contents->next, i + 2);
2043
2044 if(dpnt->subdir) update_nlink_field(dpnt->subdir);
2045 dpnt = dpnt->next;
2046 }
2047}
2048
2049/*
2050 * something quick and dirty to locate a file given a path
2051 * recursively walks down path in filename until it finds the
2052 * directory entry for the desired file
2053 */
2054struct directory_entry * FDECL2(search_tree_file, struct directory *,search_tree_file(struct directory * node, char * filename)
2055 node,char *, filename)search_tree_file(struct directory * node, char * filename)
2056{
2057 struct directory_entry * depnt;
2058 struct directory * dpnt;
2059 char * p1;
2060 char * rest;
2061 char * subdir;
2062
2063 /*
2064 * strip off next directory name from filename
2065 */
2066 subdir = strdup(filename);
2067
2068 if( (p1=strchr(subdir, '/')) == subdir )
2069 {
2070 fprintf(stderr(&__sF[2]),"call to search_tree_file with an absolute path, stripping\n");
2071 fprintf(stderr(&__sF[2]),"initial path separator. Hope this was intended...\n");
2072 memmove(subdir, subdir+1, strlen(subdir)-1);
2073 p1 = strchr(subdir, '/');
2074 }
2075
2076 /*
2077 * do we need to find a subdirectory
2078 */
2079 if (p1)
2080 {
2081 *p1 = '\0';
2082
2083#ifdef DEBUG_TORITO
2084 fprintf(stderr(&__sF[2]),"Looking for subdir called %s\n",p1);
2085#endif
2086
2087 rest = p1+1;
2088
2089#ifdef DEBUG_TORITO
2090 fprintf(stderr(&__sF[2]),"Remainder of path name is now %s\n", rest);
2091#endif
2092
2093 dpnt = node->subdir;
2094 while( dpnt )
2095 {
2096#ifdef DEBUG_TORITO
2097 fprintf(stderr(&__sF[2]),"%4d %5d %s\n", dpnt->extent, dpnt->size,
2098 dpnt->de_name);
2099#endif
2100 if (!strcmp(subdir, dpnt->de_name))
2101 {
2102#ifdef DEBUG_TORITO
2103 fprintf(stderr(&__sF[2]),"Calling next level with filename = %s", rest);
2104#endif
2105 return(search_tree_file( dpnt, rest ));
2106 }
2107 dpnt = dpnt->next;
2108 }
2109
2110 /* if we got here means we couldnt find the subdir */
2111 return (NULL((void *)0));
2112 }
2113 else
2114 {
2115 /*
2116 * look for a normal file now
2117 */
2118 depnt = node->contents;
2119 while (depnt)
2120 {
2121#ifdef DEBUG_TORITO
2122 fprintf(stderr(&__sF[2]),"%4d %5d %s\n",depnt->isorec.extent,
2123 depnt->size, depnt->name);
2124#endif
2125 if (!strcmp(filename, depnt->name))
2126 {
2127#ifdef DEBUG_TORITO
2128 fprintf(stderr(&__sF[2]),"Found our file %s", filename);
2129#endif
2130 return(depnt);
2131 }
2132 depnt = depnt->next;
2133 }
2134 /*
2135 * if we got here means we couldnt find the subdir
2136 */
2137 return (NULL((void *)0));
2138 }
2139 fprintf(stderr(&__sF[2]),"We cant get here in search_tree_file :-/ \n");
2140}
2141
2142void init_fstatbuf()
2143{
2144 time_t current_time;
2145
2146 if(fstatbuf.st_ctimest_ctim.tv_sec == 0)
2147 {
2148 time (&current_time);
2149 if( rationalize )
2150 {
2151 fstatbuf.st_uid = 0;
2152 fstatbuf.st_gid = 0;
2153 }
2154 else
2155 {
2156 fstatbuf.st_uid = getuid();
2157 fstatbuf.st_gid = getgid();
2158 }
2159 fstatbuf.st_ctimest_ctim.tv_sec = current_time;
2160 fstatbuf.st_mtimest_mtim.tv_sec = current_time;
2161 fstatbuf.st_atimest_atim.tv_sec = current_time;
2162 }
2163}