home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
cdrom
/
Misc
/
mkisofs
/
write.c
< prev
Wrap
C/C++ Source or Header
|
1994-12-18
|
27KB
|
920 lines
/*
* 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) {
static char left[40];
static char right[40];
char *cp;
strcpy (left, (*l)->isorec.iso_name);
strcpy (right, (*r)->isorec.iso_name);
if (((*l)->isorec.flags[0] & 2) == 0) {
if ((cp = strrchr (left, ';')) != 0) {
*cp = 0;
}
}
if (((*r)->isorec.flags[0] & 2) == 0) {
if ((cp = strrchr (right, ';')) != 0) {
*cp = 0;
}
}
#ifdef AMIGA
return stringcmp(right, left);
#else
return strcmp(right, left);
#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;
}