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