Robert Millan 2009-11-08 22:52:08 +00:00
parent 63eb2d63b1
commit 11e9a11511
18 changed files with 1364 additions and 218 deletions

View file

@ -19,7 +19,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
static char rcsid[] ="$Id: write.c,v 1.18 1998/06/02 02:40:39 eric Exp $";
static char rcsid[] ="$Id: write.c,v 1.21 1999/03/07 17:41:19 eric Exp $";
#include <string.h>
#include <stdlib.h>
@ -37,7 +37,7 @@ static char rcsid[] ="$Id: write.c,v 1.18 1998/06/02 02:40:39 eric Exp $";
#include <unistd.h>
#endif
#ifdef __svr4__
#ifdef __SVR4
extern char * strdup(const char *);
#endif
@ -55,7 +55,7 @@ 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;
static int next_path_index = 1;
static int sort_goof;
struct output_fragment * out_tail;
@ -63,6 +63,11 @@ struct output_fragment * out_list;
struct iso_primary_descriptor vol_desc;
static int root_gen __PR((void));
static int generate_path_tables __PR((void));
static int file_gen __PR((void));
static int dirtree_dump __PR((void));
/* Routines to actually write the disc. We write sequentially so that
we could write a tape, or write the disc directly */
@ -121,30 +126,33 @@ void FDECL2(set_733, char *, pnt, unsigned int, i)
void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file)
{
/*
* This is a hack that could be made better. XXXIs this the only place?
* It is definitely needed on Operating Systems that do not
* allow to write files that are > 2GB.
* If the system is fast enough to be able to feed 1400 KB/s
* writing speed of a DVD-R drive, use stdout.
* If the system cannot do this reliable, you need to use this
* hacky option.
*/
if (split_output != 0 && ftell(file) > (1024 * 1024 * 1024) ) {
static int idx = 0;
char nbuf[128];
sprintf(nbuf, "part_%02d", idx++);
file = freopen(nbuf, "w", file);
if (file == NULL) {
fprintf(stderr, "Cannot open '%s'.\n", nbuf);
exit(1);
}
}
/*
* This is a hack that could be made better. XXXIs this the only place?
* It is definitely needed on Operating Systems that do not
* allow to write files that are > 2GB.
* If the system is fast enough to be able to feed 1400 KB/s
* writing speed of a DVD-R drive, use stdout.
* If the system cannot do this reliable, you need to use this
* hacky option.
*/
static int idx = 0;
if (split_output != 0 &&
(idx == 0 || ftell(file) >= (1024 * 1024 * 1024) )) {
char nbuf[512];
extern char *outfile;
while(count)
{
if (idx == 0)
unlink(outfile);
sprintf(nbuf, "%s_%02d", outfile, idx++);
file = freopen(nbuf, "wb", file);
if (file == NULL) {
fprintf(stderr, "Cannot open '%s'.\n", nbuf);
exit(1);
}
}
while(count)
{
int got = fwrite(buffer,size,count,file);
if(got<=0)
@ -168,7 +176,7 @@ struct deferred_write
static struct deferred_write * dw_head = NULL, * dw_tail = NULL;
unsigned int last_extent_written =0;
static path_table_index;
static int path_table_index;
static time_t begun;
/* We recursively walk through all of the directories and assign extent
@ -184,6 +192,12 @@ static int FDECL1(assign_directory_addresses, struct directory *, node)
while (dpnt)
{
/* skip if it's hidden */
if(dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
dpnt = dpnt->next;
continue;
}
/*
* If we already have an extent for this (i.e. it came from
* a multisession disc), then don't reassign a new extent.
@ -346,11 +360,26 @@ static int FDECL2(compare_dirs, const void *, rr, const void *, ll)
* and thus should always be sorted correctly. I need to figure
* out why I thought I needed this in the first place.
*/
#if 0
if( strcmp(rpnt, ".") == 0 ) return -1;
if( strcmp(lpnt, ".") == 0 ) return 1;
if( strcmp(rpnt, "..") == 0 ) return -1;
if( strcmp(lpnt, "..") == 0 ) return 1;
#else
/*
* The code above is wrong (as explained in Eric's comment), leading to incorrect
* sort order iff the -L option ("allow leading dots") is in effect and a directory
* contains entries that start with a dot.
*
* (TF, Tue Dec 29 13:49:24 CET 1998)
*/
if((*r)->isorec.name_len[0] == 1 && *rpnt == 0) return -1; /* '.' */
if((*l)->isorec.name_len[0] == 1 && *lpnt == 0) return 1;
if((*r)->isorec.name_len[0] == 1 && *rpnt == 1) return -1; /* '..' */
if((*l)->isorec.name_len[0] == 1 && *lpnt == 1) return 1;
#endif
while(*rpnt && *lpnt)
{
@ -382,13 +411,18 @@ static int FDECL2(compare_dirs, const void *, rr, const void *, ll)
int FDECL1(sort_directory, struct directory_entry **, sort_dir)
{
int dcount = 0;
int xcount = 0;
int j;
int i, len;
struct directory_entry * s_entry;
struct directory_entry ** sortlist;
/* need to keep a count of how many entries are hidden */
s_entry = *sort_dir;
while(s_entry)
{
if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
xcount++;
dcount++;
s_entry = s_entry->next;
}
@ -404,15 +438,24 @@ int FDECL1(sort_directory, struct directory_entry **, sort_dir)
sortlist = (struct directory_entry **)
e_malloc(sizeof(struct directory_entry *) * dcount);
j = dcount - 1;
dcount = 0;
s_entry = *sort_dir;
while(s_entry)
{
if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
{
/* put any hidden entries at the end of the vector */
sortlist[j--] = s_entry;
}
else
{
sortlist[dcount] = s_entry;
len = s_entry->isorec.name_len[0];
s_entry->isorec.name[len] = 0;
dcount++;
s_entry = s_entry->next;
}
len = s_entry->isorec.name_len[0];
s_entry->isorec.name[len] = 0;
s_entry = s_entry->next;
}
/*
@ -425,19 +468,27 @@ int FDECL1(sort_directory, struct directory_entry **, sort_dir)
}
else
{
/* only sort the non-hidden entries */
sort_goof = 0;
#ifdef __STDC__
qsort(sortlist, dcount, sizeof(struct directory_entry *),
(int (*)(const void *, const void *))compare_dirs);
#else
qsort(sortlist, dcount, sizeof(struct directory_entry *),
compare_dirs);
#endif
/*
* Now reassemble the linked list in the proper sorted order
* We still need the hidden entries, as they may be used in the
* Joliet tree.
*/
for(i=0; i<dcount-1; i++)
for(i=0; i<dcount+xcount-1; i++)
{
sortlist[i]->next = sortlist[i+1];
}
sortlist[dcount-1]->next = NULL;
sortlist[dcount+xcount-1]->next = NULL;
*sort_dir = sortlist[0];
}
@ -458,7 +509,7 @@ static int root_gen()
root_record.flags[0] = 2;
root_record.file_unit_size[0] = 0;
root_record.interleave[0] = 0;
set_723(root_record.volume_sequence_number, DEF_VSN);
set_723(root_record.volume_sequence_number, volume_sequence_number);
root_record.name_len[0] = 1;
return 0;
}
@ -470,13 +521,12 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
struct file_hash *s_hash;
struct deferred_write * dwpnt;
char whole_path[1024];
while (dpnt)
{
s_entry = dpnt->contents;
for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next)
{
/*
* If we already have an extent for this entry,
* then don't assign a new one. It must have come
@ -495,7 +545,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
s_hash = find_hash(s_entry->dev, s_entry->inode);
if(s_hash)
{
if(verbose > 1)
if(verbose > 2)
{
fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name,
SPATH_SEPARATOR, s_entry->name);
@ -618,7 +668,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
s_entry->starting_block = last_extent;
add_hash(s_entry);
last_extent += ROUND_UP(s_entry->size) >> 11;
if(verbose > 1)
if(verbose > 2)
{
fprintf(stderr,"%d %d %s\n", s_entry->starting_block,
last_extent-1, whole_path);
@ -633,6 +683,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
}
#endif
#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */
if(last_extent > (800000000 >> 11))
{
/*
@ -640,7 +691,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
*/
fprintf(stderr,"Extent overflow processing file %s\n", whole_path);
fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
fprintf(stderr,"Reported file size is %d bytes\n", s_entry->size);
fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
exit(1);
}
#endif
@ -735,6 +786,11 @@ void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile)
s_entry = dpnt->contents;
while(s_entry)
{
/* skip if it's hidden */
if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
s_entry = s_entry->next;
continue;
}
/*
* We do not allow directory entries to cross sector boundaries.
@ -878,9 +934,12 @@ void FDECL1(build_pathlist, struct directory *, node)
while (dpnt)
{
/* skip if it's hidden */
if( (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0 )
pathlist[dpnt->path_index] = dpnt;
if(dpnt->subdir) build_pathlist(dpnt->subdir);
dpnt = dpnt->next;
if(dpnt->subdir) build_pathlist(dpnt->subdir);
dpnt = dpnt->next;
}
} /* build_pathlist(... */
@ -927,6 +986,13 @@ static int generate_path_tables()
/*
* Now start filling in the path tables. Start with root directory
*/
if( next_path_index > 0xffff )
{
fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)\n",
next_path_index);
exit(1);
}
path_table_index = 0;
pathlist = (struct directory **) e_malloc(sizeof(struct directory *)
* next_path_index);
@ -936,8 +1002,13 @@ static int generate_path_tables()
do
{
fix = 0;
#ifdef __STDC__
qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
(int (*)(const void *, const void *))compare_paths);
#else
qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
compare_paths);
#endif
for(j=1; j<next_path_index; j++)
{
@ -1061,8 +1132,7 @@ static int FDECL1(file_write, FILE *, outfile)
last_extent - session_start);
exit(0);
}
if( verbose > 0 )
if( verbose > 2 )
{
#ifdef DBG_ISO
fprintf(stderr,"Total directory extents being written = %d\n", last_extent);
@ -1156,8 +1226,8 @@ static int FDECL1(pvd_write, FILE *, outfile)
should_write = last_extent - session_start;
set_733((char *) vol_desc.volume_space_size, should_write);
set_723(vol_desc.volume_set_size, 1);
set_723(vol_desc.volume_sequence_number, DEF_VSN);
set_723(vol_desc.volume_set_size, volume_set_size);
set_723(vol_desc.volume_sequence_number, volume_sequence_number);
set_723(vol_desc.logical_block_size, 2048);
/*
@ -1175,7 +1245,7 @@ static int FDECL1(pvd_write, FILE *, outfile)
* Now we copy the actual root directory record
*/
memcpy(vol_desc.root_directory_record, &root_record,
sizeof(struct iso_directory_record));
sizeof(struct iso_directory_record) + 1);
/*
* The rest is just fluff. It looks nice to fill in many of these fields,
@ -1230,16 +1300,16 @@ static int FDECL1(pvd_write, FILE *, outfile)
*/
static int FDECL1(evd_write, FILE *, outfile)
{
struct iso_primary_descriptor vol_desc;
struct iso_primary_descriptor evol_desc;
/*
* 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);
memset(&evol_desc, 0, sizeof(evol_desc));
evol_desc.type[0] = ISO_VD_END;
memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
evol_desc.version[0] = 1;
xfwrite(&evol_desc, 1, 2048, outfile);
last_extent_written += 1;
return 0;
}
@ -1306,8 +1376,10 @@ static int file_gen()
static int dirtree_dump()
{
if (verbose > 1)
dump_tree(root);
if (verbose > 2)
{
dump_tree(root);
}
return 0;
}