home *** CD-ROM | disk | FTP | other *** search
- /*
- * Program write.c - dump memory structures to file for iso9660 filesystem.
-
- Written by Eric Youngdale (1993).
-
- Copyright 1993 Yggdrasil Computing, Incorporated
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <string.h>
- #include <stdlib.h>
- #include "mkisofs.h"
- #include "iso9660.h"
- #include <time.h>
- #include <errno.h>
-
- #ifdef AMIGA
- #include <exec/memory.h>
- #ifdef LATTICE
- #include <proto/utility.h>
- #include <proto/exec.h>
- #include <proto/dos.h>
- #endif
- #if defined(__GNUC__) || defined(AZTEC_C)
- #include <clib/utility_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #endif
- #endif
-
- #ifndef AMIGA
- #include <ctype.h>
- #endif
-
- #ifdef __svr4__
- extern char * strdup(const char *);
- #endif
-
-
- /* Max number of sectors we will write at one time */
- #define NSECT 16
-
- /* Counters for statistics */
-
- static int table_size = 0;
- static int total_dir_size = 0;
- static int rockridge_size = 0;
- static struct directory ** pathlist;
- static next_path_index = 1;
-
- /* Used to fill in some of the information in the volume descriptor. */
- static struct tm *local;
-
- /* Location and length of extent of cdtv.tm file: */
- static unsigned long cdtv_trademark_extent = 0;
- static unsigned long cdtv_trademark_length = 0;
-
- /* Routines to actually write the disc. We write sequentially so that
- we could write a tape, or write the disc directly */
-
-
- #define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof(vol_desc.X))
- #define FILL_NULL(X) memset(vol_desc.X, 0, sizeof(vol_desc.X))
-
- void FDECL2(set_721, char *, pnt, unsigned int, i){
- pnt[0] = i & 0xff;
- pnt[1] = (i >> 8) & 0xff;
- }
-
- void FDECL2(set_722, char *, pnt, unsigned int, i){
- pnt[0] = (i >> 8) & 0xff;
- pnt[1] = i & 0xff;
- }
-
- void FDECL2(set_723, char *, pnt, unsigned int, i){
- pnt[3] = pnt[0] = i & 0xff;
- pnt[2] = pnt[1] = (i >> 8) & 0xff;
- }
-
- void FDECL2(set_731, char *, pnt, unsigned int, i){
- pnt[0] = i & 0xff;
- pnt[1] = (i >> 8) & 0xff;
- pnt[2] = (i >> 16) & 0xff;
- pnt[3] = (i >> 24) & 0xff;
- }
-
- void FDECL2(set_732, char *, pnt, unsigned int, i){
- pnt[3] = i & 0xff;
- pnt[2] = (i >> 8) & 0xff;
- pnt[1] = (i >> 16) & 0xff;
- pnt[0] = (i >> 24) & 0xff;
- }
-
- int FDECL1(get_733, char *, p){
- return ((p[0] & 0xff)
- | ((p[1] & 0xff) << 8)
- | ((p[2] & 0xff) << 16)
- | ((p[3] & 0xff) << 24));
- }
-
- void FDECL2(set_733, char *, pnt, unsigned int, i){
- pnt[7] = pnt[0] = i & 0xff;
- pnt[6] = pnt[1] = (i >> 8) & 0xff;
- pnt[5] = pnt[2] = (i >> 16) & 0xff;
- pnt[4] = pnt[3] = (i >> 24) & 0xff;
- }
-
- static int xfwrite(void * buffer, int count, int size, FILE * file)
- {
- if (fwrite(buffer, count, size, file) == size) return size;
- fprintf(stderr,"cannot write raw file\n");
- exit(1);
- }
-
- #define DEFERRED_CHUNK_SIZE 65000
-
- static struct directory_entry **deferred = NULL;
- static unsigned int deferred_count = 0;
- static unsigned int deferred_size = 0;
-
- static struct directory_entry * sort_dir;
-
- static unsigned int last_extent_written =0;
- static struct iso_primary_descriptor vol_desc;
- static path_table_index;
-
- /* We recursively walk through all of the directories and assign extent
- numbers to them. We have already assigned extent numbers to everything that
- goes in front of them */
-
- void FDECL1(assign_directory_addresses, struct directory *, node){
- struct directory * dpnt;
- int dir_size;
- static unsigned long cnt = 0;
-
- dpnt = node;
-
- while (dpnt){
- cnt++;
- dpnt->extent = last_extent;
- dpnt->path_index = next_path_index++;
- dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;
-
- last_extent += dir_size;
- if(dpnt->subdir) assign_directory_addresses(dpnt->subdir);
- dpnt = dpnt->next;
- };
- #ifdef AMIGA
- if (progress_indicator) {
- printf ("Assigning addresses for directories (%d%% complete);"
- " free mem: %lu \r",
- pr_dir_count ? (int)(((cnt-1)*100)/pr_dir_count) : 100,
- AvailMem (MEMF_ANY));
- fflush (stdout);
- }
- #endif
- }
-
- static void FDECL3(write_one_file, char *, filename, unsigned int, size, FILE *, outfile){
- FILE * infile;
- #ifdef AMIGA
- #ifdef LATTICE
- __far static char buffer[SECTOR_SIZE * NSECT];
- #else
- static char buffer[SECTOR_SIZE * NSECT];
- #endif
- #else
- char buffer[SECTOR_SIZE * NSECT];
- #endif
- int use;
- int remain;
- if ((infile = fopen(filename, "rb")) == NULL) {
- #ifdef sun
- fprintf(stderr, "cannot open %s: (%d)\n", filename, errno);
- #else
- fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
- #endif
- exit(1);
- }
- remain = size;
-
- while(remain > 0){
- use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
- use = ROUND_UP(use); /* Round up to nearest sector boundary */
- memset(buffer, 0, use);
- if (fread(buffer, 1, use, infile) == 0) {
- fprintf(stderr,"cannot read from %s\n",filename);
- exit(1);
- }
- xfwrite(buffer, 1, use, outfile);
- last_extent_written += use/SECTOR_SIZE;
- if(verbose && (last_extent_written % 1000) < use/SECTOR_SIZE) {
- fprintf(stderr,"%d..", last_extent_written);
- #ifdef AMIGA
- fflush (stderr);
- #endif
- }
- remain -= use;
- };
- fclose(infile);
- }
-
- static void FDECL1(write_files, FILE *, outfile){
- unsigned int i;
- for (i=0; i<deferred_count; i++) {
- #ifdef AMIGA
- if (progress_indicator &&
- ((i&31) == 0 || i+1 == deferred_count)) {
- printf ("Writing files (%d%% complete); free mem: %lu \r",
- (int) ((100*(i+1))/deferred_count),
- AvailMem (MEMF_ANY));
- fflush (stdout);
- }
- #endif
- #ifdef AMIGA
- if(deferred[i]->is_a_table) {
- #else
- if(deferred[i]->inode == TABLE_INODE) {
- #endif
- xfwrite(deferred[i]->table, 1, ROUND_UP(deferred[i]->size),
- outfile);
- table_size += deferred[i]->size;
- } else {
- static char whole_path[1024];
- strcpy (whole_path, deferred[i]->filedir->whole_name);
- #ifdef AMIGA
- if(strlen(whole_path) && whole_path[strlen(whole_path)-1] != ':')
- strcat(whole_path, "/");
- #else
- if(strlen(whole_path)) strcat(whole_path, "/");
- #endif
- strcat (whole_path, deferred[i]->name);
- write_one_file(whole_path, deferred[i]->size, outfile);
- };
- };
- if (progress_indicator)
- putchar ('\n');
- }
-
- /* compare strings of unsigned char: */
-
- #ifdef AMIGA
- typedef unsigned char UChar;
-
- static int stringcmp (UChar *str1, UChar *str2)
- {
- for (;;) {
- register unsigned char a = *str1++;
- register unsigned char b = *str2++;
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- if (a == 0)
- return 0;
- }
- }
- #endif
-
- int FDECL2(compare_dirs, const struct directory_entry **, r, const struct directory_entry **, l) {
- #ifdef AMIGA
- return stringcmp((UChar*) (*r)->isorec.iso_name, (UChar*) (*l)->isorec.iso_name);
- #else
- return strcmp((*r)->isorec.iso_name, (*l)->isorec.iso_name);
- #endif
- }
-
- void FDECL1(sort_directory, struct directory_entry **, sort_dir){
- int dcount = 0;
- int i, len;
- struct directory_entry * s_entry;
- struct directory_entry ** sortlist;
-
- s_entry = *sort_dir;
- while(s_entry){
- dcount++;
- s_entry = s_entry->next;
- };
- /* OK, now we know how many there are. Build a vector for sorting. */
-
- sortlist = (struct directory_entry **)
- malloc(sizeof(struct directory_entry *) * dcount);
-
- dcount = 0;
- s_entry = *sort_dir;
- while(s_entry){
- sortlist[dcount] = s_entry;
- len = s_entry->isorec.name_len[0];
- /* s_entry->isorec.name[len] = 0; */
- dcount++;
- s_entry = s_entry->next;
- };
-
- qsort(sortlist, dcount, sizeof(struct directory_entry *),
- (int(*)(const void*, const void*)) compare_dirs);
-
- /* Now reassemble the linked list in the proper sorted order */
- for(i=0; i<dcount-1; i++)
- sortlist[i]->next = sortlist[i+1];
-
- sortlist[dcount-1]->next = NULL;
- *sort_dir = sortlist[0];
-
- free(sortlist);
-
- }
-
- void generate_root_record(){
- time_t ctime;
-
- time (&ctime);
- local = localtime(&ctime);
-
- root_record.length[0] = 1 + sizeof(struct iso_directory_record);
- root_record.ext_attr_length[0] = 0;
- set_733(root_record.extent, root->extent);
- set_733(root_record.size, ROUND_UP(root->size));
- iso9660_date(root_record.date, ctime);
- root_record.flags[0] = 2;
- root_record.file_unit_size[0] = 0;
- root_record.interleave[0] = 0;
- set_723(root_record.volume_sequence_number, 1);
- root_record.name_len[0] = 1;
- }
-
- static int compare_extension (const struct directory_entry **e1,
- const struct directory_entry **e2)
- {
- char *ext1, *ext2;
- int res;
-
- if ((*e1)->isorec.iso_name[0] < 2 || (*e2)->isorec.iso_name[0] < 2)
- return (*e1)->isorec.iso_name[0] - (*e2)->isorec.iso_name[0];
-
- ext1 = strrchr ((*e1)->isorec.iso_name, '.');
- ext2 = strrchr ((*e2)->isorec.iso_name, '.');
-
- if (ext1 && !ext2)
- return 1;
- if (!ext1 && ext2)
- return -1;
- if (ext1 && ext2) {
- #ifdef AMIGA
- if (res = stringcmp ((UChar*) ext1+1, (UChar*) ext2+1))
- #else
- if ((res = strcmp (ext1+1, ext2+1)))
- #endif
- return res;
- }
- #ifdef AMIGA
- return stringcmp ((UChar*) (*e1)->isorec.iso_name,
- (UChar*) (*e2)->isorec.iso_name);
- #else
- return strcmp ((*e1)->isorec.iso_name,
- (*e2)->isorec.iso_name);
- #endif
- }
-
- static void FDECL1(assign_file_addresses, struct directory *, dpnt){
- struct directory * finddir;
- struct directory_entry * s_entry;
- #ifndef AMIGA
- struct file_hash *s_hash;
- #endif
- char whole_path[1024];
- int entries;
- struct directory_entry **entry_array;
- int i;
- #ifdef AMIGA
- static unsigned long cnt = 1;
- #endif
-
- while (dpnt){
- /* compute number of entries: */
- for (entries=0, s_entry=dpnt->contents; s_entry; s_entry=s_entry->next)
- entries++;
-
- entry_array = (struct directory_entry **)
- malloc (sizeof (struct directory_entry *) * entries);
- for (i=0, s_entry=dpnt->contents; s_entry; s_entry=s_entry->next)
- entry_array[i++] = s_entry;
-
- if (sort_extents)
- qsort (entry_array, entries, sizeof (struct directory_entry *),
- (int(*)(const void*, const void*)) compare_extension);
-
- for (i=0; i<entries; i++) {
- s_entry = entry_array[i];
-
- #ifndef AMIGA
- /* This saves some space if there are symlinks present */
- s_hash = find_hash(s_entry->dev, s_entry->inode);
- if(s_hash){
- if(verbose)
- fprintf(stderr, "Cache hit for %s/%s\n",s_entry->filedir->de_name,
- s_entry->name);
- set_733(s_entry->isorec.extent, s_hash->starting_block);
- set_733(s_entry->isorec.size, s_hash->size);
- continue;
- };
- #endif
- if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") &&
- s_entry->isorec.flags[0] == 2){
- finddir = dpnt->subdir;
- while(1==1){
- if(finddir->self == s_entry) break;
- finddir = finddir->next;
- if(!finddir) {fprintf(stderr,"Fatal goof\n"); exit(1);};
- };
- set_733(s_entry->isorec.extent, finddir->extent);
- s_entry->size = ROUND_UP(finddir->size);
- #ifndef AMIGA
- s_entry->starting_block = finddir->extent;
- add_hash(s_entry);
- #endif
- total_dir_size += s_entry->size;
- set_733(s_entry->isorec.size, ROUND_UP(finddir->size));
- } else {
- if(strcmp(s_entry->name,".") ==0 || strcmp(s_entry->name,"..") == 0) {
- if(strcmp(s_entry->name,".") == 0) {
- set_733(s_entry->isorec.extent, dpnt->extent);
-
- s_entry->size = ROUND_UP(dpnt->size);
- #ifndef AMIGA
- /* Set these so that the hash table has the correct information */
- s_entry->starting_block = dpnt->extent;
- add_hash(s_entry);
- s_entry->starting_block = dpnt->extent;
- #endif
- set_733(s_entry->isorec.size, ROUND_UP(dpnt->size));
- } else {
- if(dpnt == root) total_dir_size += root->size;
- set_733(s_entry->isorec.extent, dpnt->parent->extent);
-
- s_entry->size = ROUND_UP(dpnt->parent->size);
- #ifndef AMIGA
- /* Set these so that the hash table has the correct information */
- s_entry->starting_block = dpnt->parent->extent;
- add_hash(s_entry);
- s_entry->starting_block = dpnt->parent->extent;
- #endif
- set_733(s_entry->isorec.size, ROUND_UP(dpnt->parent->size));
- };
- } else {
- /* Now we schedule the file to be written. This is all quite
- straightforward, just make a list and assign extents as we go.
- Once we get through writing all of the directories, we should
- be ready write out these files */
-
- #ifdef AMIGA
- if (progress_indicator) {
- if ((cnt & 31) == 0 || cnt == pr_file_count) {
- printf ("Assigning addresses for files (%d%% complete);"
- " free mem: %lu \r",
- pr_file_count ? (int) ((100*cnt)/pr_file_count) : 100,
- AvailMem (MEMF_ANY));
- fflush (stdout);
- }
- cnt++;
- }
- #endif
-
- if(s_entry->size) {
- if (deferred_count == deferred_size) {
- deferred_size += DEFERRED_CHUNK_SIZE;
- if (deferred)
- deferred =
- realloc (deferred,
- deferred_size * sizeof (struct directory_entry*));
- else
- deferred =
- malloc (deferred_size * sizeof (struct directory_entry*));
- if (!deferred) {
- fprintf (stderr, "cannot allocate file table - out of memory!\n");
- exit (1);
- }
- }
- deferred[deferred_count++] = s_entry;
- set_733(s_entry->isorec.extent, last_extent);
- #ifndef AMIGA
- s_entry->starting_block = last_extent;
- add_hash(s_entry);
- #endif
- #ifdef AMIGA
- if (dpnt == root &&
- Stricmp ((UBYTE*) s_entry->name, (UBYTE*) "cdtv.tm") == 0) {
- cdtv_trademark_extent = last_extent;
- cdtv_trademark_length = s_entry->size;
- }
- #endif
-
- last_extent += ROUND_UP(s_entry->size) >> 11;
- if (verbose >= 2) {
- char *whole = s_entry->filedir->whole_name;
- char last = whole[0] ? whole[strlen(whole)-1] : 0;
- fprintf(stderr,"%d %d %s%s%s\n", last_extent,
- last_extent-1,
- whole, (last == ':' || last == '/') ? "" : "/",
- s_entry->name);
- }
- #ifdef DBG_ISO
- if((ROUND_UP(s_entry->size) >> 11) > 500){
- fprintf(stderr,"Warning: large file %s\n", whole_path);
- fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
- fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
-
- };
- #endif
- if(last_extent > (700000000 >> 11)) { /* More than 700Mb? Punt */
- fprintf(stderr,"Extent overflow processing file %s\n", whole_path);
- #ifndef AMIGA
- fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
- #endif
- fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
- exit(1);
- };
- } else
- set_733(s_entry->isorec.extent, 0);
- };
- };
- };
- free (entry_array);
- if(dpnt->subdir) assign_file_addresses(dpnt->subdir);
- dpnt = dpnt->next;
- };
- }
-
- void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile){
- unsigned int total_size;
- char * directory_buffer;
- struct directory_entry * s_entry, *s_entry_d;
- int new_reclen;
- unsigned int dir_index;
- #ifdef AMIGA
- static unsigned long cnt = 1;
- #endif
-
- #ifdef AMIGA
- if (progress_indicator) {
- printf ("Generate directory %lu; free mem: %lu \r",
- cnt, AvailMem (MEMF_ANY));
- Delay (5);
- fflush (stdout);
- }
- cnt++;
- #endif
-
- total_size = (dpnt->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);
- directory_buffer = (char *) malloc(total_size);
- memset(directory_buffer, 0, total_size);
- dir_index = 0;
-
- s_entry = dpnt->contents;
- while(s_entry) {
-
- /* We do not allow directory entries to cross sector boundaries. Simply
- pad, and then start the next entry at the next sector */
- new_reclen = s_entry->isorec.length[0];
- if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE)
- dir_index = (dir_index + (SECTOR_SIZE - 1)) &
- ~(SECTOR_SIZE - 1);
-
- memcpy (directory_buffer + dir_index, &s_entry->isorec, ISO_REC_SIZE);
- memcpy (directory_buffer + dir_index + ISO_REC_SIZE,
- s_entry->isorec.iso_name,
- s_entry->isorec.name_len[0]);
- dir_index += ISO_REC_SIZE + s_entry->isorec.name_len[0];
-
- /* Add the Rock Ridge attributes, if present */
- if(s_entry->rr_attr_size){
- if(dir_index & 1)
- directory_buffer[dir_index++] = 0;
-
- rockridge_size += s_entry->rr_attr_size;
- memcpy(directory_buffer + dir_index, s_entry->rr_attributes,
- s_entry->rr_attr_size);
- dir_index += s_entry->rr_attr_size;
-
- };
- if(dir_index & 1)
- directory_buffer[dir_index++] = 0;
-
- s_entry_d = s_entry;
- s_entry = s_entry->next;
- /* free (s_entry_d); */
- };
- sort_dir = NULL;
-
- if(dpnt->size != dir_index)
- fprintf(stderr,"Unexpected directory length %d %d %s\n",dpnt->size,
- dir_index, dpnt->de_name);
- xfwrite(directory_buffer, 1, total_size, outfile);
- last_extent_written += total_size >> 11;
- free(directory_buffer);
- }
-
- static void FDECL1(build_pathlist, struct directory *, node){
- struct directory * dpnt;
-
- dpnt = node;
-
- while (dpnt){
- pathlist[dpnt->path_index] = dpnt;
- if(dpnt->subdir) build_pathlist(dpnt->subdir);
- dpnt = dpnt->next;
- };
- }
-
- int FDECL2(compare_paths, const struct directory **, r, const struct directory **, l) {
- if((*r)->parent->path_index < (*l)->parent->path_index) return -1;
- if((*r)->parent->path_index > (*l)->parent->path_index) return 1;
- #ifdef AMIGA
- return Stricmp ((STRPTR) (*r)->self->isorec.iso_name,
- (STRPTR) (*l)->self->isorec.iso_name);
- #else
- return strcmp((*r)->self->isorec.iso_name, (*l)->self->isorec.iso_name);
- #endif
-
- }
-
- void generate_path_tables(){
- struct directory * dpnt;
- int namelen;
- struct directory_entry * de;
- int fix;
- int tablesize;
- int i,j;
- /* First allocate memory for the tables and initialize the memory */
-
- tablesize = path_blocks << 11;
- path_table_m = (char *) malloc(tablesize);
- path_table_l = (char *) malloc(tablesize);
- memset(path_table_l, 0, tablesize);
- memset(path_table_m, 0, tablesize);
-
- /* Now start filling in the path tables. Start with root directory */
- path_table_index = 0;
- pathlist = (struct directory **) malloc(sizeof(struct directory *) * next_path_index);
- memset(pathlist, 0, sizeof(struct directory *) * next_path_index);
- build_pathlist(root);
-
- do{
- fix = 0;
- qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
- (int(*)(const void*, const void*)) compare_paths);
-
- for(j=1; j<next_path_index; j++)
- if(pathlist[j]->path_index != j){
- pathlist[j]->path_index = j;
- fix++;
- };
- } while(fix);
-
- for(j=1; j<next_path_index; j++){
- dpnt = pathlist[j];
- if(!dpnt){
- fprintf(stderr,"Entry %d not in path tables\n", j);
- exit(1);
- };
-
- de = dpnt->self;
- if(!de) {fprintf(stderr,"Fatal goof\n"); exit(1);};
-
-
- namelen = de->isorec.name_len[0];
-
- path_table_l[path_table_index] = namelen;
- path_table_m[path_table_index] = namelen;
- path_table_index += 2;
- set_731(path_table_l + path_table_index, dpnt->extent);
- set_732(path_table_m + path_table_index, dpnt->extent);
- path_table_index += 4;
- set_721(path_table_l + path_table_index, dpnt->parent->path_index);
- set_722(path_table_m + path_table_index, dpnt->parent->path_index);
- path_table_index += 2;
- for(i =0; i<namelen; i++){
- #ifdef AMIGA
- path_table_l[path_table_index] = ToUpper (de->isorec.iso_name[i]);
- path_table_m[path_table_index] = ToUpper (de->isorec.iso_name[i]);
- #else
- path_table_l[path_table_index] = toupper (de->isorec.iso_name[i]);
- path_table_m[path_table_index] = toupper (de->isorec.iso_name[i]);
- #endif
- path_table_index++;
- };
- if(path_table_index & 1) path_table_index++; /* For odd lengths we pad */
- };
- free(pathlist);
- if(path_table_index != path_table_size)
- fprintf(stderr,"Path table lengths do not match %d %d\n",path_table_index,
- path_table_size);
- }
-
- void preallocate_space (FILE *outfile)
- {
- long oldpos = ftell (outfile);
- int numblocks = last_extent - oldpos / 2048;
- int i;
- static char empty[2048];
-
- fprintf (stderr, "Preallocating space for output file...\n");
- memset (empty, 0, sizeof (empty));
- for (i=0; i<numblocks; i++)
- if (!fwrite (empty, sizeof (empty), 1, outfile)) {
- fprintf (stderr, ">>>> WARNING: not enough space on output device\n");
- break;
- }
- if (fseek (outfile, oldpos, SEEK_SET) == -1) {
- fprintf (stderr, "cannot seek() on output file\n");
- perror ("");
- exit (1);
- }
- }
-
- int FDECL2(iso_write, FILE *, outfile, char *, volid){
- static char buffer[2048];
- char iso_time[17];
- int should_write;
- int i;
-
- if (verbose)
- printf ("assigning file addresses\n");
-
- assign_file_addresses(root);
- if (progress_indicator)
- putchar ('\n');
-
- memset(buffer, 0, sizeof(buffer));
-
- /* This will break in the year 2000, I supose, but there is no good way
- to get the top two digits of the year. */
- sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local->tm_year,
- local->tm_mon+1, local->tm_mday,
- local->tm_hour, local->tm_min, local->tm_sec);
-
- /* First, we output 16 sectors of all zero */
-
- for(i=0; i<16; i++)
- xfwrite(buffer, 1, sizeof(buffer), outfile);
-
- last_extent_written += 16;
-
- /* Next we write out the primary descriptor for the disc */
- memset(&vol_desc, 0, sizeof(vol_desc));
- vol_desc.type[0] = ISO_VD_PRIMARY;
- memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
- vol_desc.version[0] = 1;
-
- memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id));
- if (system_identifier)
- memcpy(vol_desc.system_id, system_identifier, strlen (system_identifier));
- else
- #ifdef AMIGA
- memcpy(vol_desc.system_id, "AMIGA", sizeof("AMIGA"));
- #else
- #ifdef __QNX__
- memcpy(vol_desc.system_id, "QNX", sizeof("QNX"));
- #else
- memcpy(vol_desc.system_id, "LINUX", sizeof("LINUX"));
- #endif
- #endif
-
- memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
- memcpy(vol_desc.volume_id, volid, strlen(volid));
-
- should_write = last_extent;
- set_733(vol_desc.volume_space_size, last_extent);
- set_723(vol_desc.volume_set_size, 1);
- set_723(vol_desc.volume_sequence_number, 1);
- set_723(vol_desc.logical_block_size, 2048);
-
- /* The path tables are used by DOS based machines to cache directory
- locations */
-
- set_733(vol_desc.path_table_size, path_table_size);
- set_731(vol_desc.type_l_path_table, path_table[0]);
- set_731(vol_desc.opt_type_l_path_table, path_table[1]);
- set_732(vol_desc.type_m_path_table, path_table[2]);
- set_732(vol_desc.opt_type_m_path_table, path_table[3]);
-
- /* Now we copy the actual root directory record */
-
- memcpy(vol_desc.root_directory_record, &root_record,
- sizeof(struct iso_directory_record) + 1);
-
- /* The rest is just fluff. It looks nice to fill in many of these fields,
- though */
-
- FILL_SPACE(volume_set_id);
- FILL_SPACE(publisher_id);
- if(publisher) memcpy(vol_desc.publisher_id, publisher, strlen(publisher));
- FILL_SPACE(preparer_id);
- if(preparer) memcpy(vol_desc.preparer_id, preparer, strlen(preparer));
- FILL_SPACE(application_id);
- FILL_SPACE(copyright_file_id);
- FILL_SPACE(abstract_file_id);
- FILL_SPACE(bibliographic_file_id);
- FILL_SPACE(creation_date);
- FILL_SPACE(modification_date);
- FILL_SPACE(expiration_date);
- FILL_SPACE(effective_date);
- vol_desc.file_structure_version[0] = 1;
- FILL_NULL(application_data);
- if (cdtv_trademark_file) {
- vol_desc.application_data[1] = 'F';
- vol_desc.application_data[2] = 'S';
- vol_desc.application_data[5] = 'T';
- vol_desc.application_data[6] = 'M';
- vol_desc.application_data[8] = 0x14;
- vol_desc.application_data[11] = cdtv_trademark_length >> 8;
- vol_desc.application_data[12] = cdtv_trademark_length & 255;
- vol_desc.application_data[13] = cdtv_trademark_extent >> 24;
- vol_desc.application_data[14] = (cdtv_trademark_extent >> 16) & 255;
- vol_desc.application_data[15] = (cdtv_trademark_extent >> 8) & 255;
- vol_desc.application_data[16] = cdtv_trademark_extent & 255;
- }
-
- memcpy(vol_desc.creation_date, iso_time, 16);
- memcpy(vol_desc.modification_date, iso_time, 16);
- memcpy(vol_desc.expiration_date, "0000000000000000", 16);
- memcpy(vol_desc.effective_date, iso_time, 16);
-
- /* For some reason, Young Minds writes this twice. Aw, what the heck */
- xfwrite(&vol_desc, 1, 2048, outfile);
- xfwrite(&vol_desc, 1, 2048, outfile);
-
- last_extent_written += 2;
-
- /* Now write the end volume descriptor. Much simpler than the other one */
- memset(&vol_desc, 0, sizeof(vol_desc));
- vol_desc.type[0] = ISO_VD_END;
- memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
- vol_desc.version[0] = 1;
- xfwrite(&vol_desc, 1, 2048, outfile);
- xfwrite(&vol_desc, 1, 2048, outfile);
- last_extent_written += 2;
-
- /* Next we write the path tables */
- xfwrite(path_table_l, 1, path_blocks << 11, outfile);
- xfwrite(path_table_l, 1, path_blocks << 11, outfile);
- xfwrite(path_table_m, 1, path_blocks << 11, outfile);
- xfwrite(path_table_m, 1, path_blocks << 11, outfile);
- last_extent_written += 4*path_blocks;
- free(path_table_l);
- free(path_table_m);
- path_table_l = NULL;
- path_table_m = NULL;
-
- /* OK, all done with that crap. Now write out the directories.
- This is where the fur starts to fly, because we need to keep track of
- each file as we find it and keep track of where we put it. */
-
- #ifdef DBG_ISO
- fprintf(stderr,"Total directory extents being written = %d\n", last_extent);
- #endif
- #if 0
- generate_one_directory(root, outfile);
- #endif
- if (verbose)
- printf ("writing directories\n");
-
- generate_iso9660_directories(root, outfile);
- if (progress_indicator)
- putchar ('\n');
-
- if(extension_record) xfwrite(extension_record, 1, SECTOR_SIZE, outfile);
-
- /* Now write all of the files that we need. */
- if (verbose)
- printf ("writing files\n");
-
- fprintf(stderr,"Total extents being written = %d\n", last_extent);
- if (preallocate)
- preallocate_space (outfile);
- write_files(outfile);
-
- /* Hard links throw us off here */
- if(should_write != last_extent){
- fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n");
- fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent);
- };
- fprintf(stderr,"Total translation table size: %d\n", table_size);
- fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size);
- fprintf(stderr,"Total directory bytes: %d\n", total_dir_size);
- fprintf(stderr,"Path table size(bytes): %d\n", path_table_size);
- #ifdef DEBUG
- fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n",
- next_extent, last_extent, last_extent_written);
- #endif
-
- return 0;
- }
-