home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 10 / Fresh_Fish_10_2352.bin / useful / disk / cdrom / mkisofs / tree.c < prev    next >
C/C++ Source or Header  |  1994-11-21  |  27KB  |  936 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. #include <stdlib.h>
  24. #include <string.h>
  25. #include <time.h>
  26. #include <errno.h>
  27.  
  28. #ifndef VMS
  29. #ifndef AMIGA
  30. #include <unistd.h>
  31. #ifndef __QNX__
  32. #include <sys/sysmacros.h>
  33. #endif
  34. #endif
  35. #endif
  36.  
  37. #include "mkisofs.h"
  38. #include "iso9660.h"
  39. #include "trans.h"
  40.  
  41. #ifndef AMIGA
  42. #include <sys/stat.h>
  43. #endif
  44.  
  45. #ifdef AMIGA
  46. #include <exec/memory.h>
  47. #ifdef LATTICE
  48. #include <proto/utility.h>
  49. #include <proto/exec.h>
  50. #endif
  51. #if defined(__GNUC__) || defined(AZTEC_C)
  52. #include <clib/exec_protos.h>
  53. #include <clib/utility_protos.h>
  54. #endif
  55. #endif
  56.  
  57. #include "exclude.h"
  58.  
  59. #ifdef VMS
  60. #define S_ISLNK(m)    (0)
  61. #define S_ISSOCK(m)    (0)
  62. #define S_ISFIFO(m)    (0)
  63. #else
  64. #ifndef S_ISLNK
  65. #define S_ISLNK(m)    (((m) & S_IFMT) == S_IFLNK)
  66. #endif
  67. #ifndef S_ISSOCK
  68. #define S_ISSOCK(m)    (((m) & S_IFMT) == S_IFSOCK)
  69. #endif
  70. #endif
  71.  
  72. #ifdef __svr4__
  73. extern char * strdup(const char *);
  74. #endif
  75.  
  76. static unsigned char symlink_buff[256];
  77.  
  78. extern int verbose;
  79.  
  80. struct stat fstatbuf = {0,};  /* We use this for the artificial entries we create */
  81.  
  82. struct stat root_statbuf = {0, };  /* Stat buffer for root directory */
  83.  
  84. struct directory * reloc_dir = NULL;
  85.  
  86. unsigned long pr_dir_count = 0;
  87. unsigned long pr_file_count = 0;
  88.  
  89. void FDECL1(sort_n_finish, struct directory *, this_dir)
  90. {
  91.   struct directory_entry  *s_entry, *s_entry1;
  92.   time_t current_time;
  93.   struct directory_entry * table;
  94.   int count;
  95.   int new_reclen;
  96.   char *  c;
  97.   int tablesize = 0;
  98.   char newname[15],  rootname[15];
  99.  
  100.   /* Here we can take the opportunity to toss duplicate entries from the
  101.      directory.  */
  102.  
  103.   table = NULL;
  104.  
  105.   if(fstatbuf.st_ctime == 0){
  106.       time (¤t_time);
  107.       fstatbuf.st_uid = 0;
  108.       fstatbuf.st_gid = 0;
  109.       fstatbuf.st_ctime = current_time;
  110.       fstatbuf.st_mtime = current_time;
  111.       fstatbuf.st_atime = current_time;
  112.   };
  113.  
  114.   flush_file_hash();
  115.   s_entry = this_dir->contents;
  116.   while(s_entry){
  117.       
  118.       /* First assume no conflict, and handle this case */
  119.       
  120.       if(!(s_entry1 = find_file_hash(s_entry->isorec.iso_name))){
  121.           add_file_hash(s_entry);
  122.           s_entry = s_entry->next;
  123.           continue;
  124.       };
  125.       
  126.       if (!convert_filenames) {
  127.         fprintf (stderr, "Duplicate filename: %s\n", s_entry->isorec.iso_name);
  128.         fprintf (stderr, "Filenames must be shorter than 30 characters!\n");
  129.         exit (1);
  130.       }
  131.  
  132.           if (s_entry->isorec.name_len[0] == 1 &&
  133.           s_entry->isorec.iso_name[0] < 2) {
  134.         fprintf (stderr, "Fatal error: duplicate dot or dotdot entry.\n");
  135.         exit (1);
  136.       }
  137.  
  138.       if(s_entry1 == s_entry){
  139.           fprintf(stderr,"Fatal goof\n");
  140.           exit(1);
  141.       };
  142.       /* OK, handle the conflicts.  Try substitute names until we come
  143.          up with a winner */
  144.       strcpy(rootname, s_entry->isorec.iso_name);
  145.       c  = strchr(rootname, '.');
  146.       if (c) *c = 0;
  147.       count = 0;
  148.       while(count < 1000){
  149.           sprintf(newname,"%s.%3.3d%s", rootname,  count,
  150.               (s_entry->isorec.flags[0] == 2 ? "" : ";1"));
  151.           if(!find_file_hash(newname)) break;
  152.           count++;
  153.       };
  154.       if(count >= 1000){
  155.           fprintf(stderr,"Unable to  generate unique  name for file %s\n", s_entry->name);
  156.           exit(1);
  157.       };
  158.       
  159.       /* OK, now we have a good replacement name.  Now decide which one
  160.          of these two beasts should get the name changed */
  161.       
  162.       if(s_entry->priority < s_entry1->priority) {
  163.           fprintf(stderr,"Using %s for  %s/%s (%s)\n", newname,  this_dir->whole_name, s_entry->name, s_entry1->name);
  164.           s_entry->isorec.name_len[0] =  strlen(newname);
  165.           new_reclen = ISO_REC_SIZE + strlen(newname);
  166.           if(use_RockRidge) {
  167.               if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  168.               new_reclen += s_entry->rr_attr_size;
  169.           };
  170.           if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  171.           s_entry->isorec.length[0] = new_reclen;
  172.           s_entry->isorec.iso_name = strdup (newname);
  173.       } else {
  174.           delete_file_hash(s_entry1);
  175.           fprintf(stderr,"Using %s for  %s/%s (%s)\n", newname,  this_dir->whole_name, s_entry1->name, s_entry->name);
  176.           s_entry1->isorec.name_len[0] =  strlen(newname);
  177.           new_reclen = ISO_REC_SIZE + strlen(newname);
  178.           if(use_RockRidge) {
  179.               if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  180.               new_reclen += s_entry1->rr_attr_size;
  181.           };
  182.           if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */
  183.           s_entry1->isorec.length[0] = new_reclen;
  184.           s_entry1->isorec.iso_name = strdup (newname);
  185.           add_file_hash(s_entry1);
  186.       };
  187.       add_file_hash(s_entry);
  188.       s_entry = s_entry->next;
  189.   };
  190.  
  191.   if(generate_tables && /* !find_file_hash("TRANS.TBL;1") && */ (reloc_dir != this_dir)){
  192.       /* First we need to figure out how big this table is */
  193.       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
  194.           if(strcmp(s_entry->name, ".") == 0  ||
  195.              strcmp(s_entry->name, "..") == 0) continue; 
  196.           if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
  197.       };
  198.           table = (struct directory_entry *) 
  199.         malloc(sizeof (struct directory_entry));
  200.      memset(table, 0, sizeof(struct directory_entry));
  201.     table->table = NULL;
  202.     table->next = this_dir->contents;
  203.     this_dir->contents = table;
  204.  
  205.     table->filedir = root;
  206.     table->isorec.flags[0] = 0;
  207.     table->priority  = 32768;
  208.     iso9660_date(table->isorec.date, current_time);
  209. #ifdef AMIGA
  210.     table->is_a_table = 1;
  211. #else
  212.     table->inode = TABLE_INODE;
  213.     table->dev = UNCACHED_DEVICE;
  214. #endif
  215.     set_723(table->isorec.volume_sequence_number, 1);
  216.     set_733(table->isorec.size, tablesize);
  217.     table->size = tablesize;
  218.     table->filedir = this_dir;
  219.     table->name = strdup("<translation table>");
  220.     table->table = (char *) malloc(ROUND_UP(tablesize));
  221.     memset(table->table, 0, ROUND_UP(tablesize));
  222.     /* iso9660_file_length  ("TRANS.TBL;1", table, 0); */
  223.     iso9660_file_length  ("TRANS.TBL", table, 0, NULL);
  224.         
  225.     if(use_RockRidge){
  226.         fstatbuf.st_mode = 0444 | S_IFREG;
  227.         fstatbuf.st_nlink = 1;
  228.         generate_rock_ridge_attributes("",
  229.                            "TRANS.TBL", table,
  230.                            &fstatbuf, &fstatbuf, 0);
  231.     };
  232.   };
  233.  
  234.   for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
  235.       new_reclen = strlen (s_entry->isorec.iso_name);
  236.       
  237.       if(s_entry->isorec.flags[0] ==  2){
  238.           if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) {
  239.                /* path_table_size += new_reclen + sizeof(struct iso_path_table) - 1; */
  240.               path_table_size += new_reclen + 8;
  241.               if (new_reclen & 1) path_table_size++;
  242.           } else {
  243.               new_reclen = 1;
  244.               if (this_dir == root && strlen(s_entry->name) == 1)
  245.                 /* path_table_size += sizeof(struct iso_path_table); */
  246.                 path_table_size += 9;
  247.           }
  248.       };
  249.       if(path_table_size & 1) path_table_size++;  /* For odd lengths we pad */
  250.       s_entry->isorec.name_len[0] = new_reclen;
  251.  
  252.       new_reclen += ISO_REC_SIZE;
  253.       
  254.       if (new_reclen & 1)    
  255.           new_reclen++;
  256.       if(use_RockRidge){
  257.           new_reclen += s_entry->rr_attr_size;
  258.  
  259.           if (new_reclen & 1)    
  260.               new_reclen++;
  261.       };
  262.       if(new_reclen > 0xff) {
  263.           fprintf(stderr,"Fatal error - RR overflow for file %s\n",
  264.               s_entry->name);
  265.           exit(1);
  266.       };
  267.       s_entry->isorec.length[0] = new_reclen;
  268.   };
  269.  
  270.   sort_directory(&this_dir->contents);
  271.  
  272.   if(table){
  273.       char buffer[1024];
  274.       count = 0;
  275.       for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
  276.           if(s_entry == table) continue;
  277.           if(!s_entry->table) continue;
  278.           if(strcmp(s_entry->name, ".") == 0  ||
  279.              strcmp(s_entry->name, "..") == 0) continue;
  280.  
  281.           sprintf(buffer,"%c %-34s%s",s_entry->table[0],  
  282.               s_entry->isorec.iso_nam