home *** CD-ROM | disk | FTP | other *** search
/ Dream 49 / Amiga_Dream_49.iso / beos / utils / mkisofs-1.000 / mkisofs-1.11-beos / tree.c < prev    next >
C/C++ Source or Header  |  1998-01-25  |  36KB  |  1,275 lines

  1. /*
  2.  * File tree.c - scan directory  tree and build memory structures for iso9660
  3.  * filesystem
  4.  
  5.    Written by Eric Youngdale (1993).
  6.  
  7.    Copyright 1993 Yggdrasil Computing, Incorporated
  8.  
  9.    This program is free software; you can redistribute it and/or modify
  10.    it under the terms of the GNU General Public License as published by
  11.    the Free Software Foundation; either version 2, or (at your option)
  12.    any later version.
  13.  
  14.    This program is distributed in the hope that it will be useful,
  15.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    You should have received a copy of the GNU General Public License
  20.    along with this program; if not, write to the Free Software
  21.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  22.  
  23. static char rcsid[] ="$Id: tree.c,v 1.1 1998/01/25 20:34:15 chrish Exp chrish $";
  24.  
  25. /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
  26.  
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <time.h>
  30. #include <errno.h>
  31.  
  32. #include "config.h"
  33.  
  34. #ifndef VMS
  35. #if defined(MAJOR_IN_SYSMACROS)
  36. #include <sys/sysmacros.h>
  37. #endif
  38.  
  39. #ifdef HAVE_UNISTD_H
  40. #include <unistd.h>
  41. #endif
  42.  
  43. #if defined(MAJOR_IN_MKDEV)
  44. #include <sys/types.h>
  45. #include <sys/mkdev.h>
  46. #endif
  47. #else
  48. #include <sys/file.h>
  49. #include <vms/fabdef.h>
  50. #include "vms.h"
  51. extern char * strdup(const char *);
  52. #endif
  53.  
  54. /*
  55.  * Autoconf should be able to figure this one out for us and let us know
  56.  * whether the system has memmove or not.
  57.  */
  58. # ifndef HAVE_MEMMOVE
  59. #  define memmove(d, s, n) bcopy ((s), (d), (n))
  60. # endif
  61.  
  62. #include "mkisofs.h"
  63. #include "iso9660.h"
  64.  
  65. #include <sys/stat.h>
  66.  
  67. #include "exclude.h"
  68.  
  69. #ifdef NON_UNIXFS
  70. #define S_ISLNK(m)    (0)
  71. #define S_ISSOCK(m)    (0)
  72. #define S_ISFIFO(m)    (0)
  73. #else
  74. #ifndef S_ISLNK
  75. #define S_ISLNK(m)    (((m) & S_IFMT) == S_IFLNK)
  76. #endif
  77. #ifndef S_ISSOCK
  78. # ifdef S_IFSOCK
  79. #   define S_ISSOCK(m)    (((m) & S_IFMT) == S_IFSOCK)
  80. # else
  81. #   define S_ISSOCK(m)    (0)
  82. # endif
  83. #endif
  84. #endif
  85.  
  86. #ifdef __svr4__
  87. extern char * strdup(const char *);
  88. #endif
  89.  
  90. static unsigned char symlink_buff[256];
  91.  
  92. extern int verbose;
  93.  
  94. struct stat fstatbuf = {0,};  /* We use this for the artificial entries we create */
  95.  
  96. struct stat root_statbuf = {0, };  /* Stat buffer for root directory */
  97.  
  98. struct directory * reloc_dir = NULL;
  99.  
  100. void
  101. FDECL1(stat_fix, struct stat *, st)
  102. {
  103.   /* Remove the uid and gid, they will only be useful on the author's
  104.      system.  */
  105.   st->st_uid = 0;
  106.   st->st_gid = 0;
  107.  
  108.  /*
  109.   * Make sure the file modes make sense.  Turn on all read bits.  Turn
  110.   * on all exec/search bits if any exec/search bit is set.  Turn off
  111.   * all write bits, and all special mode bits (on a r/o fs lock bits
  112.   * are useless, and with uid+gid 0 don't want set-id bits, either).
  113.   */
  114.   st->st_mode |= 0444;
  115.   if (st->st_mode & 0111)
  116.     st->st_mode |= 0111;
  117.   st->st_mode &= ~07222;
  118. }
  119.  
  120. int
  121. FDECL2(stat_filter, char *, path, struct stat *, st)
  122. {
  123.   int result = stat(path, st);
  124.   if (result >= 0 && rationalize)
  125.     stat_fix(st);
  126.   return result;
  127. }
  128.  
  129. int
  130. FDECL2(lstat_filter, char *, path, struct stat *, st)
  131. {
  132.   int result = lstat(path, st);
  133.   if (result >= 0 && rationalize)
  134.     stat_fix(st);
  135.   return result;
  136. }
  137.  
  138. void FDECL1(sort_n_finish, struct directory *, this_dir)
  139. {
  140.   struct directory_entry  * s_entry;
  141.   struct directory_entry  * s_entry1;
  142.   time_t            current_time;
  143.   struct directory_entry  * table;
  144.   int                count;
  145.   int                new_reclen;
  146.   char             *  c;
  147.   int                tablesize = 0;
  148.   char                newname[34];
  149.   char                rootname[34];
  150.  
  151.   /* Here we can take the opportunity to toss duplicate entries from the
  152.      directory.  */
  153.  
  154.   table = NULL;
  155.  
  156.   if(fstatbuf.st_ctime == 0)
  157.     {
  158.       time (¤t_time);
  159.       fstatbuf.st_uid = 0;
  160.       fstatbuf.st_gid = 0;
  161.       fstatbuf.st_ctime = current_time;
  162.       fstatbuf.st_mtime = current_time;
  163.       fstatbuf.st_atime = current_time;
  164.     }
  165.  
  166.   flush_file_hash();
  167.   s_entry = this_dir->contents;
  168.   while(s_entry)
  169.     {
  170.       
  171.       /*
  172.        * First assume no conflict, and handle this case 
  173.        */
  174.       if(!(s_entry1 = find_file_hash(s_entry->isorec.name)))
  175.     {
  176.       add_file_hash(s_entry);
  177.       s_entry = s_entry->next;
  178.       continue;
  179.     }
  180.       
  181.       if(s_entry1 == s_entry)
  182.     {
  183.       fprintf(stderr,"Fatal goof\n");
  184.       exit(1);
  185.     }
  186.       
  187.       /* 
  188.        * OK, handle the conflicts.  Try substitute names until we come
  189.        * up with a winner 
  190.        */
  191.       strcpy(rootname, s_entry->isorec.name);
  192.       if(full_iso9660_filenames) 
  193.     {
  194.       if(strlen(rootname) > 27) rootname[27] = 0;
  195.     }
  196.  
  197.       /*
  198.        * Strip off the non-significant part of the name so that we are left
  199.        * with a sensible root filename.  If we don't find a '.', then try
  200.        * a ';'.
  201.        */
  202.       c  = strchr(rootname, '.');
  203.       if (c) 
  204.     *c = 0;
  205.       else
  206.     {
  207.       c  = strchr(rootname, ';');
  208.       if (c) *c = 0;
  209.     }
  210.       count = 0;
  211.       while(count < 0x1000)
  212.     {
  213.       sprintf(newname,"%s.%3.3X%s", rootname,  count,
  214.           (s_entry->isorec.flags[0] == 2 || 
  215.            omit_version_number ? "" : ";1"));
  216.       
  217. #ifdef VMS
  218.       /* Sigh.  VAXCRTL seems to be broken here */
  219.       {
  220.         int ijk = 0;
  221.         while(newname[ijk]) 
  222.           {
  223.         if(newname[ijk] == ' ') newname[ijk] = '0';
  224.         ijk++;
  225.           }
  226.       }
  227. #endif
  228.       
  229.       if(!find_file_hash(newname)) break;
  230.       count++;
  231.     }
  232.       if(count >= 0x1000)
  233.     {
  234.       fprintf(stderr,"Unable to  generate unique  name for file %s\n", s_entry->name);
  235.       exit(1);
  236.     }
  237.       
  238.       /* 
  239.        * OK, now we have a good replacement name.  Now decide which one
  240.        * of these two beasts should get the name changed 
  241.        */
  242.       if(s_entry->priority < s_entry1->priority) 
  243.     {
  244.       fprintf(stderr,"Using %s for  %s%s%s (%s)\n", newname,  this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name);
  245.       s_entry->isorec.name_len[0] =  strlen(newname);
  246.       new_reclen =  sizeof(struct iso_directory_record) -
  247.         sizeof(s_entry->isorec.name) +
  248.         strlen(newname);
  249.       if(use_RockRidge) 
  250.         {
  251.           if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  252.           new_reclen += s_entry->rr_attr_size;
  253.         }
  254.       if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  255.       s_entry->isorec.length[0] = new_reclen;
  256.       strcpy(s_entry->isorec.name, newname);
  257.     }
  258.       else 
  259.     {
  260.       delete_file_hash(s_entry1);
  261.       fprintf(stderr,"Using %s for  %s%s%s (%s)\n", newname,  this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name);
  262.       s_entry1->isorec.name_len[0] =  strlen(newname);
  263.       new_reclen =  sizeof(struct iso_directory_record) -
  264.         sizeof(s_entry1->isorec.name) +
  265.         strlen(newname);
  266.       if(use_RockRidge) 
  267.         {
  268.           if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  269.           new_reclen += s_entry1->rr_attr_size;
  270.         }
  271.       if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  272.       s_entry1->isorec.length[0] = new_reclen;
  273.       strcpy(s_entry1->isorec.name, newname);
  274.       add_file_hash(s_entry1);
  275.     }
  276.       add_file_hash(s_entry);
  277.       s_entry = s_entry->next;
  278.     }
  279.   
  280.   if(generate_tables 
  281.      && !find_file_hash("TRANS.TBL") 
  282.      && (reloc_dir != this_dir)
  283.      && (this_dir->extent == 0) )
  284.     {
  285.       /* 
  286.        * First we need to figure out how big this table is 
  287.        */
  288.       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  289.     {
  290.       if(strcmp(s_entry->name, ".") == 0  ||
  291.          strcmp(s_entry->name, "..") == 0) continue; 
  292.       if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
  293.     }
  294.     }
  295.  
  296.   if( tablesize > 0 )
  297.     {
  298.       table = (struct directory_entry *) 
  299.     e_malloc(sizeof (struct directory_entry));
  300.       memset(table, 0, sizeof(struct directory_entry));
  301.       table->table = NULL;
  302.       table->next = this_dir->contents;
  303.       this_dir->contents = table;
  304.       
  305.       table->filedir = root;
  306.       table->isorec.flags[0] = 0;
  307.       table->priority  = 32768;
  308.       iso9660_date(table->isorec.date, fstatbuf.st_mtime);
  309.       table->inode = TABLE_INODE;
  310.       table->dev = (dev_t) UNCACHED_DEVICE;
  311.       set_723(table->isorec.volume_sequence_number, DEF_VSN);
  312.       set_733((char *) table->isorec.size, tablesize);
  313.       table->size = tablesize;
  314.       table->filedir = this_dir;
  315.       table->name = strdup("<translation table>");
  316.       table->table = (char *) e_malloc(ROUND_UP(tablesize));
  317.       memset(table->table, 0, ROUND_UP(tablesize));
  318.       iso9660_file_length  ("TRANS.TBL", table, 1);
  319.       
  320.       if(use_RockRidge)
  321.     {
  322.       fstatbuf.st_mode = 0444 | S_IFREG;
  323.       fstatbuf.st_nlink = 1;
  324.       generate_rock_ridge_attributes("",
  325.                      "TRANS.TBL", table,
  326.                      &fstatbuf, &fstatbuf, 0);
  327.     }
  328.     }
  329.   
  330.   for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
  331.     {
  332.       new_reclen = strlen(s_entry->isorec.name);
  333.       
  334.       if(s_entry->isorec.flags[0] ==  2)
  335.     {
  336.       if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) 
  337.         {
  338.           path_table_size += new_reclen + sizeof(struct iso_path_table) - 1;
  339.           if (new_reclen & 1) path_table_size++;
  340.         }
  341.       else 
  342.         {
  343.           new_reclen = 1;
  344.           if (this_dir == root && strlen(s_entry->name) == 1)
  345.         path_table_size += sizeof(struct iso_path_table);
  346.         }
  347.     }
  348.       if(path_table_size & 1) path_table_size++;  /* For odd lengths we pad */
  349.       s_entry->isorec.name_len[0] = new_reclen;
  350.       
  351.       new_reclen += 
  352.     sizeof(struct iso_directory_record) -
  353.     sizeof(s_entry->isorec.name);
  354.       
  355.       if (new_reclen & 1)    
  356.     new_reclen++;
  357.       
  358.       new_reclen += s_entry->rr_attr_size;
  359.       
  360.       if (new_reclen & 1) new_reclen++;
  361.       
  362.       if(new_reclen > 0xff) 
  363.     {
  364.       fprintf(stderr,"Fatal error - RR overflow for file %s\n",
  365.           s_entry->name);
  366.       exit(1);
  367.     }
  368.       s_entry->isorec.length[0] = new_reclen;
  369.     }
  370.  
  371.   sort_directory(&this_dir->contents);
  372.  
  373.   if(table)
  374.     {
  375.       char buffer[1024];
  376.       count = 0;
  377.       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
  378.     if(s_entry == table) continue;
  379.     if(!s_entry->table) continue;
  380.     if(strcmp(s_entry->name, ".") == 0  ||
  381.        strcmp(s_entry->name, "..") == 0) continue;
  382.     
  383.     sprintf(buffer,"%c %-34s%s",s_entry->table[0],  
  384.         s_entry->isorec.name, s_entry->table+1);
  385.     memcpy(table->table + count, buffer, strlen(buffer));
  386.     count +=  strlen(buffer);
  387.     free(s_entry->table);
  388.     s_entry->table = NULL;
  389.       }
  390.  
  391.       if(count !=  tablesize) 
  392.     {
  393.       fprintf(stderr,"Translation table size mismatch %d %d\n",
  394.           count, tablesize);
  395.       exit(1);
  396.     }
  397.     }
  398.  
  399.   /* 
  400.    * Now go through the directory and figure out how large this one will be.
  401.    * Do not split a directory entry across a sector boundary 
  402.    */
  403.   s_entry = this_dir->contents;
  404.   this_dir->ce_bytes = 0;
  405.   while(s_entry)
  406.     {
  407.       new_reclen = s_entry->isorec.length[0];
  408.       if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
  409.     this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & 
  410.     ~(SECTOR_SIZE - 1);
  411.       this_dir->size += new_reclen;
  412.       
  413.       /* See if continuation entries were used on disc */
  414.       if(use_RockRidge && 
  415.      s_entry->rr_attr_size != s_entry->total_rr_attr_size) 
  416.     {
  417.       unsigned char * pnt;
  418.       int len;
  419.       int nbytes;
  420.       
  421.       pnt = s_entry->rr_attributes;
  422.       len = s_entry->total_rr_attr_size;
  423.       
  424.       /*
  425.        * We make sure that each continuation entry record is not
  426.        * split across sectors, but each file could in theory have more
  427.        * than one CE, so we scan through and figure out what we need. 
  428.        */
  429.       while(len > 3)
  430.         {
  431.           if(pnt[0] == 'C' && pnt[1] == 'E') 
  432.         {
  433.           nbytes = get_733((char *) pnt+20);
  434.           
  435.           if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >=
  436.              SECTOR_SIZE) this_dir->ce_bytes = 
  437.                     ROUND_UP(this_dir->ce_bytes);
  438.           /* Now store the block in the ce buffer */
  439.           this_dir->ce_bytes += nbytes;
  440.           if(this_dir->ce_bytes & 1) this_dir->ce_bytes++;
  441.         }
  442.           len -= pnt[2];
  443.           pnt += pnt[2];
  444.         }
  445.     }
  446.       s_entry = s_entry->next;
  447.     }
  448. }
  449.  
  450. static void generate_reloc_directory()
  451. {
  452.     int new_reclen;
  453.     time_t current_time;
  454.     struct directory_entry  *s_entry;
  455.  
  456.     /* Create an  entry for our internal tree */
  457.     time (¤t_time);
  458.     reloc_dir = (struct directory *) 
  459.         e_malloc(sizeof(struct directory));
  460.     memset(reloc_dir, 0, sizeof(struct directory));
  461.     reloc_dir->parent = root;
  462.     reloc_dir->next = root->subdir;
  463.     root->subdir = reloc_dir;
  464.     reloc_dir->depth = 1;
  465.     reloc_dir->whole_name = strdup("./rr_moved");
  466.     reloc_dir->de_name =  strdup("rr_moved");
  467.     reloc_dir->extent = 0;
  468.     
  469.     new_reclen  = strlen(reloc_dir->de_name);
  470.     
  471.     /* Now create an actual directory  entry */
  472.     s_entry = (struct directory_entry *) 
  473.         e_malloc(sizeof (struct directory_entry));
  474.     memset(s_entry, 0, sizeof(struct directory_entry));
  475.     s_entry->next = root->contents;
  476.     reloc_dir->self = s_entry;
  477.  
  478.     root->contents = s_entry;
  479.     root->contents->name = strdup(reloc_dir->de_name);
  480.     root->contents->filedir = root;
  481.     root->contents->isorec.flags[0] = 2;
  482.     root->contents->priority  = 32768;
  483.     iso9660_date(root->contents->isorec.date, current_time);
  484.     root->contents->inode = UNCACHED_INODE;
  485.     root->contents->dev = (dev_t) UNCACHED_DEVICE;
  486.     set_723(root->contents->isorec.volume_sequence_number, DEF_VSN);
  487.     iso9660_file_length (reloc_dir->de_name, root->contents, 1);
  488.  
  489.     if(use_RockRidge){
  490.         fstatbuf.st_mode = 0555 | S_IFDIR;
  491.         fstatbuf.st_nlink = 2;
  492.         generate_rock_ridge_attributes("",
  493.                            "rr_moved", s_entry,
  494.                            &fstatbuf, &fstatbuf, 0);
  495.     };
  496.     
  497.     /* Now create the . and .. entries in rr_moved */
  498.     /* Now create an actual directory  entry */
  499.     s_entry = (struct directory_entry *) 
  500.         e_malloc(sizeof (struct directory_entry));
  501.     memcpy(s_entry, root->contents, 
  502.            sizeof(struct directory_entry));
  503.     s_entry->name = strdup(".");
  504.     iso9660_file_length (".", s_entry, 1);
  505.  
  506.     s_entry->filedir = reloc_dir;
  507.     reloc_dir->contents = s_entry;
  508.  
  509.     if(use_RockRidge){
  510.         fstatbuf.st_mode = 0555 | S_IFDIR;
  511.         fstatbuf.st_nlink = 2;
  512.         generate_rock_ridge_attributes("",
  513.                            ".", s_entry,
  514.                            &fstatbuf, &fstatbuf, 0);
  515.     };
  516.     
  517.     s_entry = (struct directory_entry *) 
  518.         e_malloc(sizeof (struct directory_entry));
  519.     memcpy(s_entry, root->contents, 
  520.            sizeof(struct directory_entry));
  521.     s_entry->name = strdup("..");
  522.     iso9660_file_length ("..", s_entry, 1);
  523.     s_entry->filedir = root;
  524.     reloc_dir->contents->next = s_entry;
  525.     reloc_dir->contents->next->next = NULL;
  526.     if(use_RockRidge){
  527.         fstatbuf.st_mode = 0555 | S_IFDIR;
  528.         fstatbuf.st_nlink = 2;
  529.         generate_rock_ridge_attributes("",
  530.                            "..", s_entry,
  531.                            &root_statbuf, &root_statbuf, 0);
  532.     };
  533. }
  534.  
  535. static void FDECL1(increment_nlink, struct directory_entry *, s_entry){
  536.   unsigned char * pnt;
  537.   int len, nlink;
  538.  
  539.   pnt = s_entry->rr_attributes;
  540.   len = s_entry->total_rr_attr_size;
  541.   while(len){
  542.     if(pnt[0] == 'P' && pnt[1] == 'X') {
  543.       nlink =  get_733((char *) pnt+12);
  544.       set_733((char *) pnt+12, nlink+1);
  545.       break;
  546.     };
  547.     len -= pnt[2];
  548.     pnt += pnt[2];
  549.   };
  550. }
  551.  
  552. void finish_cl_pl_entries(){
  553.   struct directory_entry  *s_entry, *s_entry1;
  554.   struct directory *  d_entry;
  555.  
  556.   s_entry = reloc_dir->contents;
  557.    s_entry  = s_entry->next->next;  /* Skip past . and .. */
  558.   for(; s_entry; s_entry = s_entry->next){
  559.       d_entry = reloc_dir->subdir;
  560.       while(d_entry){
  561.           if(d_entry->self == s_entry) break;
  562.           d_entry = d_entry->next;
  563.       };
  564.       if(!d_entry){
  565.           fprintf(stderr,"Unable to locate directory parent\n");
  566.           exit(1);
  567.       };
  568.  
  569.       /* First fix the PL pointer in the directory in the rr_reloc dir */
  570.       s_entry1 = d_entry->contents->next;
  571.       set_733((char *) s_entry1->rr_attributes +  s_entry1->total_rr_attr_size - 8,
  572.           s_entry->filedir->extent);
  573.  
  574.       /* Now fix the CL pointer */
  575.       s_entry1 = s_entry->parent_rec;
  576.  
  577.       set_733((char *) s_entry1->rr_attributes +  s_entry1->total_rr_attr_size - 8,
  578.           d_entry->extent);
  579.  
  580.       s_entry->filedir = reloc_dir;  /* Now we can fix this */
  581.   }
  582.   /* Next we need to modify the NLINK terms in the assorted root directory records
  583.      to account for the presence of the RR_MOVED directory */
  584.  
  585.   increment_nlink(root->self);
  586.   increment_nlink(root->self->next);
  587.   d_entry = root->subdir;
  588.   while(d_entry){
  589.     increment_nlink(d_entry->contents->next);
  590.     d_entry = d_entry->next;
  591.   };
  592. }
  593.  
  594. /*
  595.  * This function scans the directory tree, looking for files, and it makes
  596.  * note of everything that is found.  We also begin to construct the ISO9660
  597.  * directory entries, so that we can determine how large each directory is.
  598.  */
  599.  
  600. int
  601. FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de,
  602.        struct iso_directory_record *, mrootp){
  603.   DIR                * current_dir;
  604.   char                  whole_path[1024];
  605.   struct dirent            * d_entry;
  606.   struct directory_entry    * s_entry, *s_entry1;
  607.   struct directory        * this_dir, *next_brother, *parent;
  608.   struct stat              statbuf, lstatbuf;
  609.   int                  status, dflag;
  610.   int                  lstatus;
  611.   int                  n_orig;
  612.   struct directory_entry    **orig_contents = NULL;
  613.   struct directory_entry        * odpnt = NULL;
  614.   char                * cpnt;
  615.   int                  new_reclen;
  616.   int                  deep_flag;
  617.   char                * old_path;
  618.  
  619.   current_dir = opendir(path);
  620.   d_entry = NULL;
  621.  
  622.   /* Apparently NFS sometimes allows you to open the directory, but
  623.      then refuses to allow you to read the contents.  Allow for this */
  624.  
  625.   old_path = path;
  626.  
  627.   if(current_dir) d_entry = readdir_add_files(&path, old_path, current_dir);
  628.  
  629.   if(!current_dir || !d_entry) {
  630.       fprintf(stderr,"Unable to open directory %s\n", path);
  631.       de->isorec.flags[0] &= ~2; /* Mark as not a directory */
  632.       if(current_dir) closedir(current_dir);
  633.       return 0;
  634.   };
  635.  
  636.   parent = de->filedir;
  637.   /* Set up the struct for the current directory, and insert it into the
  638.      tree */
  639.  
  640. #ifdef VMS
  641.   vms_path_fixup(path);
  642. #endif
  643.  
  644.   this_dir = (struct directory *) e_malloc(sizeof(struct directory));
  645.   this_dir->next = NULL;
  646.   new_reclen = 0;
  647.   this_dir->subdir = NULL;
  648.   this_dir->self = de;
  649.   this_dir->contents = NULL;
  650.   this_dir->whole_name = strdup(path);
  651.   cpnt = strrchr(path, PATH_SEPARATOR);
  652.   if(cpnt)
  653.     cpnt++;
  654.   else
  655.     cpnt = path;
  656.   this_dir->de_name = strdup(cpnt);
  657.   this_dir->size = 0;
  658.   this_dir->extent = 0;
  659.  
  660.   if(!parent || parent == root){
  661.     if (!root) {
  662.       root = this_dir;  /* First time through for root directory only */
  663.       root->depth = 0;
  664.       root->parent = root;
  665.     } else {
  666.       this_dir->depth = 1;
  667.       if(!root->subdir)
  668.     root->subdir = this_dir;
  669.       else {
  670.     next_brother = root->subdir;
  671.     while(next_brother->next) next_brother = next_brother->next;
  672.     next_brother->next = this_dir;
  673.       };
  674.       this_dir->parent = parent;
  675.     };
  676.   } else {
  677.       /* Come through here for  normal traversal of  tree */
  678. #ifdef DEBUG
  679.       fprintf(stderr,"%s(%d) ", path, this_dir->depth);
  680. #endif
  681.       if(parent->depth >  RR_relocation_depth) {
  682.           fprintf(stderr,"Directories too deep  %s\n", path);
  683.           exit(1);
  684.       };
  685.  
  686.       this_dir->parent = parent; 
  687.       this_dir->depth = parent->depth + 1;
  688.  
  689.       if(!parent->subdir)
  690.           parent->subdir = this_dir;
  691.       else {
  692.           next_brother = parent->subdir;
  693.           while(next_brother->next) next_brother = next_brother->next;
  694.           next_brother->next = this_dir;
  695.       }
  696.   }
  697.  
  698.   /*
  699.    * Parse the same directory in the image that we are merging
  700.    * for multisession stuff.
  701.    */
  702.   if( mrootp != NULL )
  703.     {
  704.       orig_contents = read_merging_directory(mrootp, &n_orig);
  705.     }
  706.  
  707. /* Now we scan the directory itself, and look at what is inside of it. */
  708.  
  709.   dflag = 0;
  710.   while(1==1){
  711.  
  712.     /* The first time through, skip this, since we already asked for
  713.        the first entry when we opened the directory. */
  714.     if(dflag) d_entry = readdir_add_files(&path, old_path, current_dir);
  715.     dflag++;
  716.  
  717.     if(!d_entry) break;
  718.  
  719.     /* OK, got a valid entry */
  720.  
  721.     /* If we do not want all files, then pitch the backups. */
  722.     if(!all_files){
  723.         if(strchr(d_entry->d_name,'~')) continue;
  724.         if(strchr(d_entry->d_name,'#')) continue;
  725.     };
  726.  
  727.     if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){
  728.       fprintf(stderr, "Overflow of stat buffer\n");
  729.       exit(1);
  730.     };
  731.  
  732.     /* Generate the complete ASCII path for this file */
  733.     strcpy(whole_path, path);
  734. #ifndef VMS
  735.     if(whole_path[strlen(whole_path)-1] != '/')
  736.       strcat(whole_path, "/");
  737. #endif
  738.     strcat(whole_path, d_entry->d_name);
  739.  
  740.     /* Should we exclude this file? */
  741.     if (is_excluded(whole_path)) {
  742.       if (verbose) {
  743.         fprintf(stderr, "Excluded: %s\n",whole_path);
  744.       }
  745.       continue;
  746.     }
  747.     /** Should we exclude this file ? */
  748.     if (matches(d_entry->d_name)) {
  749.       if (verbose) {
  750.     fprintf(stderr, "Excluded by match: %s\n", whole_path);
  751.       }
  752.       continue;
  753.     }
  754.  
  755.     if(    generate_tables 
  756.     && strcmp(d_entry->d_name, "TRANS.TBL") == 0 )
  757.       {
  758.     /*
  759.      * Ignore this entry.  We are going to be generating new
  760.      * versions of these files, and we need to ignore any
  761.      * originals that we might have found.
  762.      */
  763.     if (verbose) 
  764.       {
  765.         fprintf(stderr, "Excluded: %s\n",whole_path);
  766.       }
  767.     continue;
  768.       }
  769.  
  770. #if 0
  771.     if (verbose)  fprintf(stderr, "%s\n",whole_path);
  772. #endif
  773.     status = stat_filter(whole_path, &statbuf);
  774.  
  775.     lstatus = lstat_filter(whole_path, &lstatbuf);
  776.  
  777.     if( (status == -1) && (lstatus == -1) )
  778.       {
  779.     /*
  780.      * This means that the file doesn't exist, or isn't accessible.
  781.      * Sometimes this is because of NFS permissions problems
  782.      * or it could mean that the user has attempted to 'add' something
  783.      * with the -i option and the directory being added doesn't exist.
  784.      */
  785.     fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path);
  786.     continue;
  787.       }
  788.  
  789.     if(this_dir == root && strcmp(d_entry->d_name, ".") == 0)
  790.       root_statbuf = statbuf;  /* Save this for later on */
  791.  
  792.     /* We do this to make sure that the root entries are consistent */
  793.     if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) {
  794.       statbuf = root_statbuf;
  795.       lstatbuf = root_statbuf;
  796.     };
  797.  
  798.     if(S_ISLNK(lstatbuf.st_mode)){
  799.  
  800.         /* Here we decide how to handle the symbolic links.  Here
  801.            we handle the general case - if we are not following
  802.            links or there is an error, then we must change
  803.            something.  If RR is in use, it is easy, we let RR
  804.            describe the file.  If not, then we punt the file. */
  805.  
  806.         if((status || !follow_links)){
  807.             if(use_RockRidge){
  808.                 status = 0;
  809.                 statbuf.st_size = 0;
  810.                 STAT_INODE(statbuf) = UNCACHED_INODE;
  811.                 statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
  812.                 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
  813.             } else {
  814.                 if(follow_links) fprintf(stderr,
  815.                     "Unable to stat file %s - ignoring and continuing.\n",
  816.                     whole_path);
  817.                 else fprintf(stderr,
  818.                     "Symlink %s ignored - continuing.\n",
  819.                     whole_path);
  820.                 continue;  /* Non Rock Ridge discs - ignore all symlinks */
  821.             };
  822.         }
  823.         
  824.         /* Here we handle a different kind of case.  Here we have
  825.            a symlink, but we want to follow symlinks.  If we run
  826.            across a directory loop, then we need to pretend that
  827.            we are not following symlinks for this file.  If this
  828.            is the first time we have seen this, then make this
  829.            seem as if there was no symlink there in the first
  830.            place */
  831.                       
  832.         if( follow_links
  833.            && S_ISDIR(statbuf.st_mode) ) 
  834.           {
  835.         if(   strcmp(d_entry->d_name, ".")
  836.            && strcmp(d_entry->d_name, "..") )
  837.           {
  838.             if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)))
  839.               {
  840.             if(!use_RockRidge) 
  841.               {
  842.                 fprintf(stderr, "Already cached directory seen (%s)\n", 
  843.                     whole_path);
  844.                 continue;
  845.               }
  846.             statbuf.st_size = 0;
  847.             STAT_INODE(statbuf) = UNCACHED_INODE;
  848.             statbuf.st_dev = (dev_t) UNCACHED_DEVICE;
  849.             statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG;
  850.             } else {
  851.               lstatbuf = statbuf;
  852.               add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  853.             }
  854.           }
  855.           }
  856.  
  857.         /*
  858.          * For non-directories, we just copy the stat information over
  859.          * so we correctly include this file.
  860.          */
  861.         if( follow_links
  862.            && !S_ISDIR(statbuf.st_mode) ) 
  863.           {
  864.         lstatbuf = statbuf;
  865.           }
  866.     }
  867.  
  868.     /*
  869.      * Add directories to the cache so that we don't waste space even
  870.      * if we are supposed to be following symlinks.
  871.      */
  872.     if( follow_links
  873.        && strcmp(d_entry->d_name, ".")
  874.        && strcmp(d_entry->d_name, "..")
  875.        && S_ISDIR(statbuf.st_mode) ) 
  876.       {
  877.         add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  878.       }
  879. #ifdef VMS
  880.     if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && 
  881.                       statbuf.st_fab_rfm != FAB$C_STMLF)) {
  882.       fprintf(stderr,"Warning - file %s has an unsupported VMS record"
  883.           " format (%d)\n",
  884.           whole_path, statbuf.st_fab_rfm);
  885.     }
  886. #endif
  887.  
  888.     if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))){
  889.       fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", 
  890.           whole_path, errno);
  891.       continue;
  892.     }
  893.  
  894.     /* Add this so that we can detect directory loops with hard links.
  895.      If we are set up to follow symlinks, then we skip this checking. */
  896.     if(   !follow_links 
  897.        && S_ISDIR(lstatbuf.st_mode) 
  898.        && strcmp(d_entry->d_name, ".") 
  899.        && strcmp(d_entry->d_name, "..") ) 
  900.       {
  901.         if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) {
  902.             fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n",
  903.                 whole_path, (unsigned long) statbuf.st_dev,
  904.                 (unsigned long) STAT_INODE(statbuf));
  905.             exit(1);
  906.         };
  907.         add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
  908.     };
  909.  
  910.     if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) &&
  911.     !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode)
  912.     && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) &&
  913.     !S_ISDIR(lstatbuf.st_mode)) {
  914.       fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n",
  915.           whole_path);
  916.       continue;
  917.     };
  918.  
  919.     /* Who knows what trash this is - ignore and continue */
  920.  
  921.     if(status) {
  922.         fprintf(stderr,
  923.             "Unable to stat file %s - ignoring and continuing.\n",
  924.             whole_path);
  925.         continue; 
  926.     };
  927.  
  928.     s_entry = (struct directory_entry *) 
  929.       e_malloc(sizeof (struct directory_entry));
  930.     s_entry->next = this_dir->contents;
  931.     memset(s_entry->isorec.extent, 0, 8);
  932.     this_dir->contents = s_entry;
  933.     deep_flag = 0;
  934.     s_entry->table = NULL;
  935.  
  936.     s_entry->name = strdup(d_entry->d_name);
  937.     s_entry->whole_name = strdup (whole_path);
  938.  
  939.     s_entry->de_flags = 0;
  940.     s_entry->filedir = this_dir;
  941.     s_entry->isorec.flags[0] = 0;
  942.     s_entry->isorec.ext_attr_length[0] = 0;
  943.     iso9660_date(s_entry->isorec.date, statbuf.st_mtime);
  944.     s_entry->isorec.file_unit_size[0] = 0;
  945.     s_entry->isorec.interleave[0] = 0;
  946.     if(parent && parent ==  reloc_dir && strcmp(d_entry->d_name,  "..") == 0){
  947.         s_entry->inode = UNCACHED_INODE;
  948.         s_entry->dev = (dev_t) UNCACHED_DEVICE;
  949.         deep_flag  = NEED_PL;
  950.     } else  {
  951.         s_entry->inode = STAT_INODE(statbuf);
  952.         s_entry->dev = statbuf.st_dev;
  953.     };
  954.     set_723(s_entry->isorec.volume_sequence_number, DEF_VSN);
  955.     iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode));
  956.     s_entry->rr_attr_size = 0;
  957.     s_entry->total_rr_attr_size = 0;
  958.     s_entry->rr_attributes = NULL;
  959.  
  960.     /* Directories are assigned sizes later on */
  961.     if (!S_ISDIR(statbuf.st_mode)) {
  962.     set_733((char *) s_entry->isorec.size, statbuf.st_size); 
  963.  
  964.     if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || 
  965.         S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode)
  966.       || S_ISLNK(lstatbuf.st_mode))
  967.       s_entry->size = 0; 
  968.     else
  969.       s_entry->size = statbuf.st_size; 
  970.     } else
  971.       s_entry->isorec.flags[0] = 2;
  972.  
  973.     /*
  974.      * We always should create an entirely new directory tree whenever
  975.      * we generate a new session, unless there were *no* changes whatsoever
  976.      * to any of the directories, in which case it would be kind of pointless
  977.      * to generate a new session.
  978.      *
  979.      * I believe it is possible to rigorously prove that any change anywhere
  980.      * in the filesystem will force the entire tree to be regenerated
  981.      * because the modified directory will get a new extent number.  Since
  982.      * each subdirectory of the changed directory has a '..' entry, all of
  983.      * them will need to be rewritten too, and since the parent directory
  984.      * of the modified directory will have an extent pointer to the directory
  985.      * it too will need to be rewritten.  Thus we will never be able to reuse
  986.      * any directory information when writing new sessions.
  987.      *
  988.      * We still check the previous session so we can mark off the equivalent
  989.      * entry in the list we got from the original disc, however.
  990.      */
  991.     if(S_ISDIR(statbuf.st_mode) && orig_contents != NULL){
  992.       check_prev_session(orig_contents, n_orig, s_entry,
  993.              &statbuf, &lstatbuf, &odpnt);
  994.     }
  995.  
  996.     if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") && 
  997.     S_ISDIR(statbuf.st_mode) && this_dir->depth >  RR_relocation_depth){
  998.           if(!reloc_dir) generate_reloc_directory();
  999.  
  1000.           s_entry1 = (struct directory_entry *) 
  1001.               e_malloc(sizeof (struct directory_entry));
  1002.           memcpy(s_entry1, this_dir->contents, 
  1003.              sizeof(struct directory_entry));
  1004.           s_entry1->table = NULL;
  1005.           s_entry1->name = strdup(this_dir->contents->name);
  1006.           s_entry1->next = reloc_dir->contents;
  1007.           reloc_dir->contents = s_entry1;
  1008.           s_entry1->priority  =  32768;
  1009.           s_entry1->parent_rec = this_dir->contents;
  1010.  
  1011.           deep_flag = NEED_RE;
  1012.  
  1013.           if(use_RockRidge) {
  1014.               generate_rock_ridge_attributes(whole_path,
  1015.                              d_entry->d_name, s_entry1,
  1016.                              &statbuf, &lstatbuf, deep_flag);
  1017.           }
  1018.  
  1019.           deep_flag = 0;
  1020.  
  1021.           /* We need to set this temporarily so that the parent to this is correctly
  1022.              determined. */
  1023.           s_entry1->filedir = reloc_dir;
  1024.           if( odpnt != NULL )
  1025.             {
  1026.               scan_directory_tree(whole_path, s_entry1, &odpnt->isorec);
  1027.             }
  1028.           else
  1029.             {
  1030.               scan_directory_tree(whole_path, s_entry1, NULL);
  1031.             }
  1032.           if( odpnt != NULL )
  1033.             {
  1034.               free(odpnt);
  1035.               odpnt = NULL;
  1036.             }
  1037.           s_entry1->filedir = this_dir;
  1038.  
  1039.           statbuf.st_size = 0;
  1040.           statbuf.st_mode &= 0777;
  1041.           set_733((char *) s_entry->isorec.size, 0);
  1042.           s_entry->size = 0;
  1043.           s_entry->isorec.flags[0] = 0;
  1044.           s_entry->inode = UNCACHED_INODE;
  1045.           deep_flag = NEED_CL;
  1046.       };
  1047.  
  1048.     if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) {
  1049.         char  buffer[2048];
  1050.         int nchar;
  1051.         switch(lstatbuf.st_mode & S_IFMT){
  1052.         case S_IFDIR:
  1053.             sprintf(buffer,"D\t%s\n",
  1054.                 s_entry->name);
  1055.             break;
  1056. #ifndef NON_UNIXFS
  1057.         case S_IFBLK:
  1058.             sprintf(buffer,"B\t%s\t%lu %lu\n",
  1059.                 s_entry->name,
  1060.                 (unsigned long) major(statbuf.st_rdev),
  1061.                 (unsigned long) minor(statbuf.st_rdev));
  1062.             break;
  1063.         case S_IFIFO:
  1064.             sprintf(buffer,"P\t%s\n",
  1065.                 s_entry->name);
  1066.             break;
  1067.         case S_IFCHR:
  1068.             sprintf(buffer,"C\t%s\t%lu %lu\n",
  1069.                 s_entry->name,
  1070.                 (unsigned long) major(statbuf.st_rdev),
  1071.                 (unsigned long) minor(statbuf.st_rdev));
  1072.             break;
  1073.         case S_IFLNK:
  1074.             nchar = readlink(whole_path, 
  1075.                      (char *)symlink_buff, 
  1076.                      sizeof(symlink_buff));
  1077.             symlink_buff[nchar < 0 ? 0 : nchar] = 0;
  1078.             sprintf(buffer,"L\t%s\t%s\n",
  1079.                 s_entry->name, symlink_buff);
  1080.             break;
  1081. #ifdef S_IFSOCK
  1082.         case S_IFSOCK:
  1083.             sprintf(buffer,"S\t%s\n",
  1084.                 s_entry->name);
  1085.             break;
  1086. #endif
  1087. #endif /* NON_UNIXFS */
  1088.         case S_IFREG:
  1089.         default:
  1090.             sprintf(buffer,"F\t%s\n",
  1091.                 s_entry->name);
  1092.             break;
  1093.         };
  1094.         s_entry->table = strdup(buffer);
  1095.     };
  1096.     
  1097.     /*
  1098.      * See if we have an entry for this guy in the previous session.
  1099.      */
  1100.     if( orig_contents != NULL && !S_ISDIR(statbuf.st_mode))
  1101.       {
  1102.     check_prev_session(orig_contents, n_orig, s_entry, 
  1103.                &statbuf, &lstatbuf, NULL);
  1104.       }
  1105.  
  1106.     if(S_ISDIR(statbuf.st_mode)){
  1107.             int dflag;
  1108.         if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) {
  1109.           if( odpnt != NULL )
  1110.         {
  1111.           dflag = scan_directory_tree(whole_path, s_entry, 
  1112.                           &odpnt->isorec);
  1113.         }
  1114.           else
  1115.         {
  1116.           dflag = scan_directory_tree(whole_path, s_entry, NULL);
  1117.         }
  1118.         /* If unable to scan directory, mark this as a non-directory */
  1119.             if(!dflag)
  1120.           lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
  1121.         if( odpnt != NULL )
  1122.           {
  1123.             free(odpnt);
  1124.             odpnt = NULL;
  1125.           }
  1126.           }
  1127.       }
  1128.  
  1129.   if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".")  == 0)
  1130.       deep_flag |= NEED_CE | NEED_SP;  /* For extension record */
  1131.  
  1132.     /* Now figure out how much room this file will take in the directory */
  1133.  
  1134.     if(use_RockRidge) {
  1135.         generate_rock_ridge_attributes(whole_path,
  1136.                        d_entry->d_name, s_entry,
  1137.                        &statbuf, &lstatbuf, deep_flag);
  1138.         
  1139.     }
  1140.   }
  1141.   closedir(current_dir);
  1142.  
  1143.   if( orig_contents != NULL )
  1144.     {
  1145.       merge_remaining_entries(this_dir, orig_contents, n_orig);
  1146.       free_mdinfo(orig_contents, n_orig);
  1147.     }
  1148.  
  1149.   sort_n_finish(this_dir);
  1150.  
  1151.   return 1;
  1152. }
  1153.  
  1154.  
  1155. void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){
  1156.   struct directory * dpnt;
  1157.  
  1158.   dpnt = node;
  1159.  
  1160.   while (dpnt){
  1161.     if( dpnt->extent > session_start )
  1162.       {
  1163.     generate_one_directory(dpnt, outfile);
  1164.       }
  1165.     if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile);
  1166.     dpnt = dpnt->next;
  1167.   }
  1168. }
  1169.  
  1170. void FDECL1(dump_tree, struct directory *, node){
  1171.   struct directory * dpnt;
  1172.  
  1173.   dpnt = node;
  1174.  
  1175.   while (dpnt){
  1176.     fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name);
  1177.     if(dpnt->subdir) dump_tree(dpnt->subdir);
  1178.     dpnt = dpnt->next;
  1179.   }
  1180. }
  1181.  
  1182. /*
  1183.  * something quick and dirty to locate a file given a path
  1184.  * recursively walks down path in filename until it finds the
  1185.  * directory entry for the desired file 
  1186.  */
  1187. struct directory_entry * FDECL2(search_tree_file, struct directory *, 
  1188.                 node,char *, filename)
  1189. {
  1190.   struct directory_entry * depnt;
  1191.   struct directory     * dpnt;
  1192.   char             * p1;
  1193.   char             * rest;
  1194.   char             * subdir;
  1195.  
  1196.   /*
  1197.    * strip off next directory name from filename 
  1198.    */
  1199.   subdir = strdup(filename);
  1200.  
  1201.   if( (p1=strchr(subdir, '/')) == subdir )
  1202.     {
  1203.       fprintf(stderr,"call to search_tree_file with an absolute path, stripping\n");
  1204.       fprintf(stderr,"initial path separator. Hope this was intended...\n");
  1205.       memmove(subdir, subdir+1, strlen(subdir)-1);
  1206.       p1 = strchr(subdir, '/');
  1207.     }
  1208.  
  1209.   /*
  1210.    * do we need to find a subdirectory 
  1211.    */
  1212.   if (p1) 
  1213.     {
  1214.       *p1 = '\0';
  1215.  
  1216. #ifdef DEBUG_TORITO
  1217.       printf("Looking for subdir called %s\n",p1); 
  1218. #endif
  1219.  
  1220.       rest = p1+1;
  1221.  
  1222. #ifdef DEBUG_TORITO
  1223.       printf("Remainder of path name is now %s\n", rest); 
  1224. #endif
  1225.       
  1226.       dpnt = node->subdir;
  1227.      while( dpnt )
  1228.        {
  1229. #ifdef DEBUG_TORITO
  1230.      fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size, 
  1231.          dpnt->de_name); 
  1232. #endif
  1233.      if (!strcmp(subdir, dpnt->de_name)) 
  1234.        {
  1235. #ifdef DEBUG_TORITO
  1236.          printf("Calling next level with filename = %s", rest); 
  1237. #endif
  1238.          return(search_tree_file( dpnt, rest ));
  1239.        }
  1240.      dpnt = dpnt->next;
  1241.        }
  1242.       
  1243.      /* if we got here means we couldnt find the subdir */
  1244.      return (NULL);
  1245.     }    
  1246.   else 
  1247.     {
  1248.       /* 
  1249.        * look for a normal file now 
  1250.        */
  1251.       depnt = node->contents;
  1252.       while (depnt)
  1253.     {
  1254. #ifdef DEBUG_TORITO
  1255.       fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent, 
  1256.           depnt->size, depnt->name); 
  1257. #endif
  1258.       if (!strcmp(filename, depnt->name)) 
  1259.         {
  1260. #ifdef DEBUG_TORITO
  1261.           printf("Found our file %s", filename); 
  1262. #endif
  1263.           return(depnt);
  1264.         }
  1265.       depnt = depnt->next;
  1266.     }
  1267.       /* 
  1268.        * if we got here means we couldnt find the subdir 
  1269.        */
  1270.       return (NULL);
  1271.     }
  1272.   fprintf(stderr,"We cant get here in search_tree_file :-/ \n");
  1273. }
  1274.  
  1275.