home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
useful
/
disk
/
cdrom
/
mkisofs
/
tree.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-21
|
27KB
|
936 lines
/*
* File tree.c - scan directory tree and build memory structures 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 <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#ifndef VMS
#ifndef AMIGA
#include <unistd.h>
#ifndef __QNX__
#include <sys/sysmacros.h>
#endif
#endif
#endif
#include "mkisofs.h"
#include "iso9660.h"
#include "trans.h"
#ifndef AMIGA
#include <sys/stat.h>
#endif
#ifdef AMIGA
#include <exec/memory.h>
#ifdef LATTICE
#include <proto/utility.h>
#include <proto/exec.h>
#endif
#if defined(__GNUC__) || defined(AZTEC_C)
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#endif
#endif
#include "exclude.h"
#ifdef VMS
#define S_ISLNK(m) (0)
#define S_ISSOCK(m) (0)
#define S_ISFIFO(m) (0)
#else
#ifndef S_ISLNK
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#ifndef S_ISSOCK
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#endif
#endif
#ifdef __svr4__
extern char * strdup(const char *);
#endif
static unsigned char symlink_buff[256];
extern int verbose;
struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */
struct stat root_statbuf = {0, }; /* Stat buffer for root directory */
struct directory * reloc_dir = NULL;
unsigned long pr_dir_count = 0;
unsigned long pr_file_count = 0;
void FDECL1(sort_n_finish, struct directory *, this_dir)
{
struct directory_entry *s_entry, *s_entry1;
time_t current_time;
struct directory_entry * table;
int count;
int new_reclen;
char * c;
int tablesize = 0;
char newname[15], rootname[15];
/* Here we can take the opportunity to toss duplicate entries from the
directory. */
table = NULL;
if(fstatbuf.st_ctime == 0){
time (¤t_time);
fstatbuf.st_uid = 0;
fstatbuf.st_gid = 0;
fstatbuf.st_ctime = current_time;
fstatbuf.st_mtime = current_time;
fstatbuf.st_atime = current_time;
};
flush_file_hash();
s_entry = this_dir->contents;
while(s_entry){
/* First assume no conflict, and handle this case */
if(!(s_entry1 = find_file_hash(s_entry->isorec.iso_name))){
add_file_hash(s_entry);
s_entry = s_entry->next;
continue;
};
if (!convert_filenames) {
fprintf (stderr, "Duplicate filename: %s\n", s_entry->isorec.iso_name);
fprintf (stderr, "Filenames must be shorter than 30 characters!\n");
exit (1);
}
if (s_entry->isorec.name_len[0] == 1 &&
s_entry->isorec.iso_name[0] < 2) {
fprintf (stderr, "Fatal error: duplicate dot or dotdot entry.\n");
exit (1);
}
if(s_entry1 == s_entry){
fprintf(stderr,"Fatal goof\n");
exit(1);
};
/* OK, handle the conflicts. Try substitute names until we come
up with a winner */
strcpy(rootname, s_entry->isorec.iso_name);
c = strchr(rootname, '.');
if (c) *c = 0;
count = 0;
while(count < 1000){
sprintf(newname,"%s.%3.3d%s", rootname, count,
(s_entry->isorec.flags[0] == 2 ? "" : ";1"));
if(!find_file_hash(newname)) break;
count++;
};
if(count >= 1000){
fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name);
exit(1);
};
/* OK, now we have a good replacement name. Now decide which one
of these two beasts should get the name changed */
if(s_entry->priority < s_entry1->priority) {
fprintf(stderr,"Using %s for %s/%s (%s)\n", newname, this_dir->whole_name, s_entry->name, s_entry1->name);
s_entry->isorec.name_len[0] = strlen(newname);
new_reclen = ISO_REC_SIZE + strlen(newname);
if(use_RockRidge) {
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
new_reclen += s_entry->rr_attr_size;
};
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
s_entry->isorec.length[0] = new_reclen;
s_entry->isorec.iso_name = strdup (newname);
} else {
delete_file_hash(s_entry1);
fprintf(stderr,"Using %s for %s/%s (%s)\n", newname, this_dir->whole_name, s_entry1->name, s_entry->name);
s_entry1->isorec.name_len[0] = strlen(newname);
new_reclen = ISO_REC_SIZE + strlen(newname);
if(use_RockRidge) {
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
new_reclen += s_entry1->rr_attr_size;
};
if (new_reclen & 1) new_reclen++; /* Pad to an even byte */
s_entry1->isorec.length[0] = new_reclen;
s_entry1->isorec.iso_name = strdup (newname);
add_file_hash(s_entry1);
};
add_file_hash(s_entry);
s_entry = s_entry->next;
};
if(generate_tables && /* !find_file_hash("TRANS.TBL;1") && */ (reloc_dir != this_dir)){
/* First we need to figure out how big this table is */
for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
if(strcmp(s_entry->name, ".") == 0 ||
strcmp(s_entry->name, "..") == 0) continue;
if(s_entry->table) tablesize += 35 + strlen(s_entry->table);
};
table = (struct directory_entry *)
malloc(sizeof (struct directory_entry));
memset(table, 0, sizeof(struct directory_entry));
table->table = NULL;
table->next = this_dir->contents;
this_dir->contents = table;
table->filedir = root;
table->isorec.flags[0] = 0;
table->priority = 32768;
iso9660_date(table->isorec.date, current_time);
#ifdef AMIGA
table->is_a_table = 1;
#else
table->inode = TABLE_INODE;
table->dev = UNCACHED_DEVICE;
#endif
set_723(table->isorec.volume_sequence_number, 1);
set_733(table->isorec.size, tablesize);
table->size = tablesize;
table->filedir = this_dir;
table->name = strdup("<translation table>");
table->table = (char *) malloc(ROUND_UP(tablesize));
memset(table->table, 0, ROUND_UP(tablesize));
/* iso9660_file_length ("TRANS.TBL;1", table, 0); */
iso9660_file_length ("TRANS.TBL", table, 0, NULL);
if(use_RockRidge){
fstatbuf.st_mode = 0444 | S_IFREG;
fstatbuf.st_nlink = 1;
generate_rock_ridge_attributes("",
"TRANS.TBL", table,
&fstatbuf, &fstatbuf, 0);
};
};
for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
new_reclen = strlen (s_entry->isorec.iso_name);
if(s_entry->isorec.flags[0] == 2){
if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) {
/* path_table_size += new_reclen + sizeof(struct iso_path_table) - 1; */
path_table_size += new_reclen + 8;
if (new_reclen & 1) path_table_size++;
} else {
new_reclen = 1;
if (this_dir == root && strlen(s_entry->name) == 1)
/* path_table_size += sizeof(struct iso_path_table); */
path_table_size += 9;
}
};
if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */
s_entry->isorec.name_len[0] = new_reclen;
new_reclen += ISO_REC_SIZE;
if (new_reclen & 1)
new_reclen++;
if(use_RockRidge){
new_reclen += s_entry->rr_attr_size;
if (new_reclen & 1)
new_reclen++;
};
if(new_reclen > 0xff) {
fprintf(stderr,"Fatal error - RR overflow for file %s\n",
s_entry->name);
exit(1);
};
s_entry->isorec.length[0] = new_reclen;
};
sort_directory(&this_dir->contents);
if(table){
char buffer[1024];
count = 0;
for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){
if(s_entry == table) continue;
if(!s_entry->table) continue;
if(strcmp(s_entry->name, ".") == 0 ||
strcmp(s_entry->name, "..") == 0) continue;
sprintf(buffer,"%c %-34s%s",s_entry->table[0],
s_entry->isorec.iso_nam