home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / useful / disk / cdrom / mkisofs / write.c < prev   
C/C++ Source or Header  |  1994-12-18  |  27KB  |  920 lines

  1. /*
  2.  * Program write.c - dump memory  structures to  file for iso9660 filesystem.
  3.  
  4.    Written by Eric Youngdale (1993).
  5.  
  6.    Copyright 1993 Yggdrasil Computing, Incorporated
  7.  
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2, or (at your option)
  11.    any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include "mkisofs.h"
  25. #include "iso9660.h"
  26. #include <time.h>
  27. #include <errno.h>
  28.  
  29. #ifdef AMIGA
  30. #include <exec/memory.h>
  31. #ifdef LATTICE
  32. #include <proto/utility.h>
  33. #include <proto/exec.h>
  34. #include <proto/dos.h>
  35. #endif
  36. #if defined(__GNUC__) || defined(AZTEC_C)
  37. #include <clib/utility_protos.h>
  38. #include <clib/exec_protos.h>
  39. #include <clib/dos_protos.h>
  40. #endif
  41. #endif
  42.  
  43. #ifndef AMIGA
  44. #include <ctype.h>
  45. #endif
  46.  
  47. #ifdef __svr4__
  48. extern char * strdup(const char *);
  49. #endif
  50.  
  51.  
  52. /* Max number of sectors we will write at  one time */
  53. #define NSECT 16
  54.  
  55. /* Counters for statistics */
  56.  
  57. static int table_size = 0;
  58. static int total_dir_size = 0;
  59. static int rockridge_size = 0;
  60. static struct directory ** pathlist;
  61. static next_path_index = 1;
  62.  
  63. /* Used to fill in some  of the information in the volume descriptor. */
  64. static struct tm *local;
  65.  
  66. /* Location and length of extent of cdtv.tm file: */
  67. static unsigned long cdtv_trademark_extent = 0;
  68. static unsigned long cdtv_trademark_length = 0;
  69.  
  70. /* Routines to actually write the disc.  We write sequentially so that
  71.    we could write a tape, or write the disc directly */
  72.  
  73.  
  74. #define FILL_SPACE(X)   memset(vol_desc.X, ' ', sizeof(vol_desc.X))
  75. #define FILL_NULL(X)    memset(vol_desc.X, 0, sizeof(vol_desc.X))
  76.  
  77. void FDECL2(set_721, char *, pnt, unsigned int, i){
  78.      pnt[0] = i & 0xff;
  79.     pnt[1] = (i >> 8) &  0xff;
  80. }
  81.  
  82. void FDECL2(set_722, char *, pnt, unsigned int, i){
  83.     pnt[0] = (i >> 8) &  0xff;
  84.      pnt[1] = i & 0xff;
  85. }
  86.  
  87. void FDECL2(set_723, char *, pnt, unsigned int, i){
  88.      pnt[3] = pnt[0] = i & 0xff;
  89.     pnt[2] = pnt[1] = (i >> 8) &  0xff;
  90. }
  91.  
  92. void FDECL2(set_731, char *, pnt, unsigned int, i){
  93.      pnt[0] = i & 0xff;
  94.     pnt[1] = (i >> 8) &  0xff;
  95.     pnt[2] = (i >> 16) &  0xff;
  96.     pnt[3] = (i >> 24) &  0xff;
  97. }
  98.  
  99. void FDECL2(set_732, char *, pnt, unsigned int, i){
  100.      pnt[3] = i & 0xff;
  101.     pnt[2] = (i >> 8) &  0xff;
  102.     pnt[1] = (i >> 16) &  0xff;
  103.     pnt[0] = (i >> 24) &  0xff;
  104. }
  105.  
  106. int FDECL1(get_733, char *, p){
  107.     return ((p[0] & 0xff)
  108.         | ((p[1] & 0xff) << 8)
  109.         | ((p[2] & 0xff) << 16)
  110.         | ((p[3] & 0xff) << 24));
  111. }
  112.  
  113. void FDECL2(set_733, char *, pnt, unsigned int, i){
  114.      pnt[7] = pnt[0] = i & 0xff;
  115.     pnt[6] = pnt[1] = (i >> 8) &  0xff;
  116.     pnt[5] = pnt[2] = (i >> 16) &  0xff;
  117.     pnt[4] = pnt[3] = (i >> 24) &  0xff;
  118. }
  119.  
  120. static int xfwrite(void * buffer, int count, int size, FILE * file)
  121. {
  122.   if (fwrite(buffer, count, size, file) == size) return size;
  123.   fprintf(stderr,"cannot write raw file\n");
  124.   exit(1);
  125. }
  126.  
  127. #define DEFERRED_CHUNK_SIZE 65000
  128.  
  129. static struct directory_entry **deferred = NULL;
  130. static unsigned int deferred_count = 0;
  131. static unsigned int deferred_size = 0;
  132.  
  133. static struct directory_entry * sort_dir;
  134.  
  135. static unsigned int last_extent_written  =0;
  136. static struct iso_primary_descriptor vol_desc;
  137. static path_table_index;
  138.  
  139. /* We recursively walk through all of the directories and assign extent
  140.    numbers to them.  We have already assigned extent numbers to everything that
  141.    goes in front of them */
  142.  
  143. void FDECL1(assign_directory_addresses, struct directory *, node){
  144.   struct directory * dpnt;
  145.   int dir_size;
  146.   static unsigned long cnt = 0;
  147.  
  148.   dpnt = node;
  149.  
  150.   while (dpnt){
  151.     cnt++;
  152.     dpnt->extent = last_extent;
  153.     dpnt->path_index = next_path_index++;
  154.     dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;
  155.  
  156.     last_extent += dir_size;
  157.     if(dpnt->subdir) assign_directory_addresses(dpnt->subdir);
  158.     dpnt = dpnt->next;
  159.   };
  160. #ifdef AMIGA
  161.   if (progress_indicator) {
  162.     printf ("Assigning addresses for directories (%d%% complete);"
  163.             " free mem: %lu   \r",
  164.         pr_dir_count ? (int)(((cnt-1)*100)/pr_dir_count) : 100,
  165.         AvailMem (MEMF_ANY));
  166.     fflush (stdout);
  167.   }
  168. #endif
  169. }
  170.  
  171. static void FDECL3(write_one_file, char *, filename, unsigned int, size, FILE *, outfile){
  172.   FILE * infile;
  173. #ifdef AMIGA
  174. #ifdef LATTICE
  175.   __far static char buffer[SECTOR_SIZE * NSECT];
  176. #else
  177.   static char buffer[SECTOR_SIZE * NSECT];
  178. #endif
  179. #else
  180.   char buffer[SECTOR_SIZE * NSECT];
  181. #endif
  182.   int use;
  183.   int remain;
  184.   if ((infile = fopen(filename, "rb")) == NULL) {
  185. #ifdef sun
  186.       fprintf(stderr, "cannot open %s: (%d)\n", filename, errno);
  187. #else
  188.       fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
  189. #endif
  190.       exit(1);
  191.   }
  192.   remain = size;
  193.  
  194.   while(remain > 0){
  195.       use =  (remain >  SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
  196.       use = ROUND_UP(use); /* Round up to nearest sector boundary */
  197.       memset(buffer, 0, use);
  198.       if (fread(buffer, 1, use, infile) == 0) {
  199.         fprintf(stderr,"cannot read from %s\n",filename); 
  200.         exit(1);
  201.       }
  202.       xfwrite(buffer, 1, use, outfile);
  203.       last_extent_written += use/SECTOR_SIZE;
  204.       if(verbose && (last_extent_written % 1000) < use/SECTOR_SIZE) {
  205.         fprintf(stderr,"%d..", last_extent_written);
  206. #ifdef AMIGA
  207.         fflush (stderr);
  208. #endif
  209.       }
  210.       remain -= use;
  211.   };
  212.   fclose(infile);
  213. }
  214.  
  215. static void FDECL1(write_files, FILE *, outfile){
  216.   unsigned int i;
  217.   for (i=0; i<deferred_count; i++) {
  218. #ifdef AMIGA
  219.     if (progress_indicator &&
  220.         ((i&31) == 0 || i+1 == deferred_count)) {
  221.       printf ("Writing files (%d%% complete); free mem: %lu   \r",
  222.                 (int) ((100*(i+1))/deferred_count),
  223.                 AvailMem (MEMF_ANY));
  224.       fflush (stdout);
  225.     }
  226. #endif
  227. #ifdef AMIGA
  228.       if(deferred[i]->is_a_table) {
  229. #else
  230.       if(deferred[i]->inode == TABLE_INODE) {
  231. #endif
  232.           xfwrite(deferred[i]->table, 1, ROUND_UP(deferred[i]->size),
  233.                   outfile);
  234.           table_size += deferred[i]->size;
  235.       } else {
  236.             static char whole_path[1024];
  237.           strcpy (whole_path, deferred[i]->filedir->whole_name);
  238. #ifdef AMIGA
  239.                 if(strlen(whole_path) && whole_path[strlen(whole_path)-1] != ':')
  240.             strcat(whole_path, "/");
  241. #else
  242.                 if(strlen(whole_path)) strcat(whole_path, "/");
  243. #endif
  244.           strcat (whole_path, deferred[i]->name);
  245.           write_one_file(whole_path, deferred[i]->size, outfile);
  246.       };
  247.   };
  248.   if (progress_indicator)
  249.     putchar ('\n');
  250. }
  251.  
  252. /* compare strings of unsigned char: */
  253.  
  254. #ifdef AMIGA
  255. typedef unsigned char UChar;
  256.  
  257. static int stringcmp (UChar *str1, UChar *str2)
  258. {
  259.   for (;;) {
  260.     register unsigned char a = *str1++;
  261.     register unsigned char b = *str2++;
  262.     if (a < b)
  263.       return -1;
  264.     if (a > b)
  265.       return 1;
  266.     if (a == 0)
  267.       return 0;
  268.   }
  269. }
  270. #endif
  271.  
  272. int FDECL2(compare_dirs, const struct directory_entry **, r, const struct directory_entry **, l) {
  273.   static char left[40];
  274.   static char right[40];
  275.   char *cp;
  276.   strcpy (left, (*l)->isorec.iso_name);
  277.   strcpy (right, (*r)->isorec.iso_name);
  278.   if (((*l)->isorec.flags[0] & 2) == 0) {
  279.     if ((cp = strrchr (left, ';')) != 0) {
  280.       *cp = 0;
  281.     }
  282.   }
  283.   if (((*r)->isorec.flags[0] & 2) == 0) {
  284.     if ((cp = strrchr (right, ';')) != 0) {
  285.       *cp = 0;
  286.     }
  287.   }
  288. #ifdef AMIGA
  289.   return stringcmp(right, left);
  290. #else
  291.   return strcmp(right, left);
  292. #endif
  293. }
  294.  
  295. void FDECL1(sort_directory, struct directory_entry **, sort_dir){
  296.   int dcount = 0;
  297.   int i, len;
  298.   struct directory_entry * s_entry;
  299.   struct directory_entry ** sortlist;
  300.  
  301.   s_entry = *sort_dir;
  302.   while(s_entry){
  303.     dcount++;
  304.     s_entry = s_entry->next;
  305.   };
  306.   /* OK, now we know how many there are.  Build a vector for sorting. */
  307.  
  308.   sortlist =   (struct directory_entry **) 
  309.     malloc(sizeof(struct directory_entry *) * dcount);
  310.  
  311.   dcount = 0;
  312.   s_entry = *sort_dir;
  313.   while(s_entry){
  314.     sortlist[dcount] = s_entry;
  315.     len = s_entry->iso