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