summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwan Le Blond <erwan.LEBLOND@eurogiciel.fr>2013-03-05 18:32:30 +0100
committerErwan Le Blond <erwan.LEBLOND@eurogiciel.fr>2013-03-05 18:32:30 +0100
commit072595200a723d421a125aefb2a098df47e30a58 (patch)
treec07e7dd088ec4faf193d0cf96df62ab3f9c1d1dc
parent8187b89b6b929c8bde675da505f0863fe9ca420a (diff)
downloadcdrkit-072595200a723d421a125aefb2a098df47e30a58.tar.gz
cdrkit-072595200a723d421a125aefb2a098df47e30a58.tar.bz2
cdrkit-072595200a723d421a125aefb2a098df47e30a58.zip
patch genisoimage multi extent
-rw-r--r--genisoimage/diag/isoinfo.c29
-rw-r--r--genisoimage/genisoimage.110
-rw-r--r--genisoimage/genisoimage.c10
-rw-r--r--genisoimage/genisoimage.h14
-rw-r--r--genisoimage/iso9660.h6
-rw-r--r--genisoimage/joliet.c79
-rw-r--r--genisoimage/multi.c223
-rw-r--r--genisoimage/tree.c182
-rw-r--r--genisoimage/udf.c44
-rw-r--r--genisoimage/write.c112
10 files changed, 642 insertions, 67 deletions
diff --git a/genisoimage/diag/isoinfo.c b/genisoimage/diag/isoinfo.c
index 55396c2..07720c6 100644
--- a/genisoimage/diag/isoinfo.c
+++ b/genisoimage/diag/isoinfo.c
@@ -11,6 +11,7 @@
*/
/* @(#)isoinfo.c 1.50 05/05/15 joerg */
+/* Parts from @(#)isoinfo.c 1.63 08/08/25 joerg */
/*
* File isodump.c - dump iso9660 directory information.
*
@@ -618,7 +619,7 @@ dump_stat(struct iso_directory_record *idr, int extent)
sprintf(outline+48, "%4d", date_buf[0]+1900);
sprintf(outline+53, "[%7d", extent); /* XXX up to 20 GB */
- sprintf(outline+61, " %02X]", idr->flags[0]);
+ sprintf(outline+61, " %02X]", idr->flags[0] & 0xFF);
for (i = 0; i < 66; i++) {
if (outline[i] == 0) outline[i] = ' ';
@@ -663,6 +664,9 @@ parse_dir(char *rootname, int extent, int len)
int i;
struct iso_directory_record * idr;
unsigned char uh, ul, uc, *up;
+ unsigned char flags = 0;
+ Llong size = 0;
+ int sextent = 0;
if (do_listing)
@@ -776,8 +780,27 @@ parse_dir(char *rootname, int extent, int len)
strcat(testname, name_buf);
printf("%s\n", testname);
}
- if (do_listing)
- dump_stat(idr, isonum_733((unsigned char *)idr->extent));
+ if (do_listing) {
+ if ((idr->flags[0] & ISO_MULTIEXTENT) && size == 0)
+ sextent = isonum_733((unsigned char *)idr->extent);
+ if (debug ||
+ ((idr->flags[0] & ISO_MULTIEXTENT) == 0 && size == 0)) {
+ dump_stat(idr, isonum_733((unsigned char *)idr->extent));
+ }
+ size += fstat_buf.st_size;
+ if ((flags & ISO_MULTIEXTENT) &&
+ (idr->flags[0] & ISO_MULTIEXTENT) == 0) {
+ fstat_buf.st_size = size;
+ if (!debug)
+ idr->flags[0] |= ISO_MULTIEXTENT;
+ dump_stat(idr, sextent);
+ if (!debug)
+ idr->flags[0] &= ~ISO_MULTIEXTENT;
+ }
+ flags = idr->flags[0];
+ if ((idr->flags[0] & ISO_MULTIEXTENT) == 0)
+ size = 0;
+ }
i += buffer[i];
if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break;
}
diff --git a/genisoimage/genisoimage.1 b/genisoimage/genisoimage.1
index d05b24a..f5473db 100644
--- a/genisoimage/genisoimage.1
+++ b/genisoimage/genisoimage.1
@@ -189,12 +189,14 @@ in the
file.
.TP
.B \-allow\-limited\-size
-When processing files larger than 2GiB which cannot be easily represented in
-ISO9660, add them with a shrunk visible file size to ISO9660 and with the
+When processing files larger than 2GiB which cannot be represented in
+ISO9660 level 1 or 2, add them with a shrunk visible file size to ISO9660 and with the
correct visible file size to the UDF system. The result is an inconsistent
filesystem and users need to make sure that they really use UDF rather than
ISO9660 driver to read a such disk. Implies enabling
.BR \-udf.
+See also
+.BR \-iso\-level\ 3
.TP
.B \-allow\-leading\-dots
.TP
@@ -685,6 +687,8 @@ restricted to 8.3 characters.
With level 2, files may only consist of one section.
.IP
With level 3, no restrictions (other than ISO-9660:1988) do apply.
+Starting with this level, genisoimage also allows files to be larger than 4 GB
+by implementing ISO-9660 multi-extent files.
.IP
With all ISO9660 levels from 1 to 3, all filenames are restricted to
uppercase letters, numbers and underscores (_). Filenames are
@@ -2800,7 +2804,7 @@ Copyright 1993-1998 by Yggdrasil Computing, Inc.
Copyright 1996-1997 by Robert Leslie
Copyright 1997-2001 by James Pearson
Copyright 1999-2006 by J\(:org Schilling
-Copyright 2007 by J\(:org Schilling (originating few updates)
+Copyright 2007-2008 by J\(:org Schilling (originating few updates)
Copyright 2002-2003 by Jungshik Shin
Copyright 2003 by Jaakko Heinonen
Copyright 2006 by the Cdrkit maintainers
diff --git a/genisoimage/genisoimage.c b/genisoimage/genisoimage.c
index 46f0cb7..2008e73 100644
--- a/genisoimage/genisoimage.c
+++ b/genisoimage/genisoimage.c
@@ -19,6 +19,7 @@
*/
/* @(#)mkisofs.c 1.167 06/01/30 joerg */
/* Parts from @(#)mkisofs.c 1.206 07/02/26 joerg */
+/* Parts from @(#)mkisofs.c 1.238 08/06/13 joerg */
/*
* Program genisoimage.c - generate iso9660 filesystem based upon directory
* tree on hard disk.
@@ -189,6 +190,8 @@ int omit_version_number = 0; /* May violate iso9660, but noone uses vers */
int no_rr = 0; /* Do not use RR attributes from old session */
int force_rr = 0; /* Force to use RR attributes from old session */
Uint RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
+int do_largefiles = 0; /* Whether to allow multi-extent files */
+off_t maxnonlarge = (off_t)0xFFFFFFFF;
int iso9660_level = 1;
int iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */
int full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */
@@ -1395,6 +1398,7 @@ int main(int argc, char *argv[])
/*
* No restrictions
*/
+ do_largefiles++;
break;
case 4:
/*
@@ -1413,6 +1417,7 @@ int main(int argc, char *argv[])
relaxed_filenames++; /* all chars */
allow_lowercase++; /* even lowcase */
allow_multidot++; /* > 1 dots */
+ do_largefiles++;
break;
default:
@@ -2751,6 +2756,11 @@ parse_input_files:
exit(1);
#endif
}
+ if (apple_hyb) {
+ if (do_largefiles) printf("Warning: cannot support large files with -hfs\n");
+ do_largefiles = 0;
+ maxnonlarge = (off_t)0x7FFFFFFF;
+ }
if (apple_hyb && use_genboot) {
#ifdef USE_LIBSCHILY
comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n");
diff --git a/genisoimage/genisoimage.h b/genisoimage/genisoimage.h
index bbedfb0..fdd5a11 100644
--- a/genisoimage/genisoimage.h
+++ b/genisoimage/genisoimage.h
@@ -11,6 +11,7 @@
*/
/* @(#)genisoimage.h 1.95 05/05/01 joerg */
+/* Parts from @(#) 1.132 08/08/06 joerg */
/*
* Header file genisoimage.h - assorted structure definitions and typecasts.
*
@@ -60,8 +61,7 @@
#endif
#endif
-/*#if _LFS_LARGEFILE*/
-#ifdef HAVE_LARGEFILES
+#ifdef USE_LARGEFILES
/*
* XXX Hack until fseeko()/ftello() are available everywhere or until
* XXX we know a secure way to let autoconf ckeck for fseeko()/ftello()
@@ -106,6 +106,9 @@ struct directory_entry {
struct iso_directory_record isorec;
unsigned int starting_block;
off_t size;
+#ifdef USE_LARGEFILES
+ int mxpart; /* Extent number */
+#endif
unsigned short priority;
unsigned char jreclen; /* Joliet record len */
char *name;
@@ -113,6 +116,7 @@ struct directory_entry {
char *whole_name;
struct directory *filedir;
struct directory_entry *parent_rec;
+ struct directory_entry *mxroot; /* Pointer to orig entry */
unsigned int de_flags;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
@@ -364,6 +368,8 @@ extern int omit_version_number;
extern int no_rr;
extern int transparent_compression;
extern Uint RR_relocation_depth;
+extern int do_largefiles;
+extern off_t maxnonlarge;
extern int iso9660_level;
extern int iso9660_namelen;
extern int full_iso9660_filenames;
@@ -447,6 +453,8 @@ extern int insert_file_entry(struct directory *, char *, char *, int);
extern int insert_file_entry(struct directory *, char *, char *);
#endif /* APPLE_HYB */
+extern struct directory_entry *
+ dup_directory_entry __PR((struct directory_entry *s_entry));
extern void generate_iso9660_directories(struct directory *, FILE *);
extern void dump_tree(struct directory * node);
extern struct directory_entry *
@@ -749,6 +757,8 @@ extern void *e_malloc(size_t);
#define MEMORY_FILE 0x80 /* de_flags only */
#define HIDDEN_FILE 0x100 /* de_flags only */
#define DIR_WAS_SCANNED 0x200 /* dir_flags only */
+#define MULTI_EXTENT 0x1000 /* de_flags only */
+#define INHIBIT_UDF_ENTRY 0x2000
/*
* Volume sequence number to use in all of the iso directory records.
diff --git a/genisoimage/iso9660.h b/genisoimage/iso9660.h
index c74c2a9..3b6df21 100644
--- a/genisoimage/iso9660.h
+++ b/genisoimage/iso9660.h
@@ -10,7 +10,7 @@
*
*/
-/* @(#)iso9660.h 1.19 04/03/02 joerg */
+/* @(#)iso9660.h 1.21 07/07/26 joerg */
/*
* Header file iso9660.h - assorted structure definitions and typecasts.
* specific to iso9660 filesystem.
@@ -18,7 +18,7 @@
* Written by Eric Youngdale (1993).
*
* Copyright 1993 Yggdrasil Computing, Incorporated
- * Copyright (c) 1999,2000-2004 J. Schilling
+ * Copyright (c) 1999,2000-2008 J. Schilling
*
* 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
@@ -231,7 +231,7 @@ struct iso_directory_record {
char extent [ISODCL(3, 10)]; /* 733 */
char size [ISODCL(11, 18)]; /* 733 */
char date [ISODCL(19, 25)]; /* 7 by 711 */
- char flags [ISODCL(26, 26)];
+ unsigned char flags [ISODCL(26, 26)];
char file_unit_size [ISODCL(27, 27)]; /* 711 */
char interleave [ISODCL(28, 28)]; /* 711 */
char volume_sequence_number [ISODCL(29, 32)]; /* 723 */
diff --git a/genisoimage/joliet.c b/genisoimage/joliet.c
index b36f8f7..9c10d21 100644
--- a/genisoimage/joliet.c
+++ b/genisoimage/joliet.c
@@ -11,6 +11,7 @@
*/
/* @(#)joliet.c 1.38 05/05/01 joerg */
+/* Parts from @(#)joliet.c>1.54 07/10/20 joerg */
/*
* File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.
*
@@ -507,7 +508,9 @@ assign_joliet_directory_addresses(struct directory *node)
}
}
/* skip if hidden - but not for the rr_moved dir */
- if (dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) {
+ if (dpnt->subdir &&
+ ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ||
+ dpnt == reloc_dir)) {
assign_joliet_directory_addresses(dpnt->subdir);
}
dpnt = dpnt->next;
@@ -643,6 +646,7 @@ generate_joliet_path_tables()
char *npnt;
char *npnt1;
int tablesize;
+ unsigned int jpindex;
/* First allocate memory for the tables and initialize the memory */
tablesize = jpath_blocks << 11;
@@ -723,10 +727,10 @@ generate_joliet_path_tables()
set_732(jpath_table_m + jpath_table_index, dpnt->jextent);
jpath_table_index += 4;
- if (dpnt->parent->jpath_index > 0xffff) {
+
+ if (dpnt->parent != reloc_dir) {
#ifdef USE_LIBSCHILY
- comerrno(EX_BAD,
- "Unable to generate sane path tables - too many directories (%d)\n",
+ set_721(jpath_table_l + jpath_table_index,
dpnt->parent->jpath_index);
#else
fprintf(stderr,
@@ -734,18 +738,31 @@ generate_joliet_path_tables()
dpnt->parent->jpath_index);
exit(1);
#endif
- }
-
- if (dpnt->parent != reloc_dir) {
- set_721(jpath_table_l + jpath_table_index,
- dpnt->parent->jpath_index);
set_722(jpath_table_m + jpath_table_index,
dpnt->parent->jpath_index);
+ jpindex = dpnt->parent->jpath_index;
} else {
set_721(jpath_table_l + jpath_table_index,
dpnt->self->parent_rec->filedir->jpath_index);
set_722(jpath_table_m + jpath_table_index,
dpnt->self->parent_rec->filedir->jpath_index);
+ jpindex = dpnt->self->parent_rec->filedir->jpath_index;
+ }
+
+ if (jpindex > 0xffff) {
+ static int warned = 0;
+
+ if (!warned) {
+ warned++;
+ errmsgno(EX_BAD,
+ "Unable to generate sane Joliet path tables - too many directories (%u)\n",
+ jpindex);
+ }
+ /*
+ * Let it point to the root directory instead.
+ */
+ set_721(jpath_table_l + jpath_table_index, 1);
+ set_722(jpath_table_m + jpath_table_index, 1);
}
jpath_table_index += 2;
@@ -1149,18 +1166,25 @@ joliet_compare_dirs(const void *rr, const void *ll)
/*
* If the entries are the same, this is an error.
* Joliet specs allow for a maximum of 64 characters.
+ * If we see different multi extent parts, it is OK to
+ * have the same name more than once.
*/
if (strncmp(rpnt, lpnt, jlen) == 0) {
+#ifdef USE_LARGEFILES
+ if ((*r)->mxpart == (*l)->mxpart)
+#endif
+ {
#ifdef USE_LIBSCHILY
- errmsgno(EX_BAD,
- "Error: %s and %s have the same Joliet name\n",
- (*r)->whole_name, (*l)->whole_name);
+ errmsgno(EX_BAD,
+ "Error: %s and %s have the same Joliet name\n",
+ (*r)->whole_name, (*l)->whole_name);
#else
- fprintf(stderr,
- "Error: %s and %s have the same Joliet name\n",
- (*r)->whole_name, (*l)->whole_name);
+ fprintf(stderr,
+ "Error: %s and %s have the same Joliet name\n",
+ (*r)->whole_name, (*l)->whole_name);
#endif
- jsort_goof++;
+ jsort_goof++;
+ }
}
/*
* Put the '.' and '..' entries on the head of the sorted list.
@@ -1253,6 +1277,15 @@ joliet_compare_dirs(const void *rr, const void *ll)
return (1);
if (*lpnt)
return (-1);
+#ifdef USE_LARGEFILES
+ /*
+ * (*r)->mxpart == (*l)->mxpart cannot happen here
+ */
+ if ((*r)->mxpart < (*l)->mxpart)
+ return (-1);
+ else if ((*r)->mxpart > (*l)->mxpart)
+ return (1);
+#endif
return (0);
}
@@ -1275,8 +1308,11 @@ joliet_sort_directory(struct directory_entry **sort_dir)
s_entry = *sort_dir;
while (s_entry) {
- /* skip hidden entries */
- if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY))
+ /*
+ * only colletc non-hidden entries
+ */
+ if ((s_entry->de_flags & (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) !=
+ (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY))
dcount++;
s_entry = s_entry->next;
}
@@ -1288,8 +1324,11 @@ joliet_sort_directory(struct directory_entry **sort_dir)
dcount = 0;
s_entry = *sort_dir;
while (s_entry) {
- /* skip hidden entries */
- if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) {
+ /*
+ * only collect non-hidden entries
+ */
+ if ((s_entry->de_flags & (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) !=
+ (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) {
sortlist[dcount] = s_entry;
dcount++;
}
diff --git a/genisoimage/multi.c b/genisoimage/multi.c
index e069c91..db83ba8 100644
--- a/genisoimage/multi.c
+++ b/genisoimage/multi.c
@@ -11,6 +11,7 @@
*/
/* @(#)multi.c 1.68 05/05/15 joerg */
+/* Parts from @(#)multi.c 1.88 08/08/28 joerg */
/*
* File multi.c - scan existing iso9660 image and merge into
* iso9660 filesystem. Used for multisession support.
@@ -90,6 +91,9 @@ static int free_mdinfo(struct directory_entry **, int len);
static void free_directory_entry(struct directory_entry * dirp);
static void merge_remaining_entries(struct directory *,
struct directory_entry **, int);
+LOCAL int iso_dir_ents __PR((struct directory_entry *de));
+LOCAL void copy_mult_extent __PR((struct directory_entry *se1,
+ struct directory_entry *se2));
static int merge_old_directory_into_tree(struct directory_entry *,
struct directory *);
@@ -586,6 +590,8 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
int len;
int nbytes;
int nent;
+ int nmult; /* # of multi extent root entries */
+ int mx;
struct directory_entry **pnt;
int rlen;
struct directory_entry **rtn;
@@ -620,6 +626,8 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
i = 0;
*nentp = 0;
nent = 0;
+ nmult = 0;
+ mx = 0;
while (i < len) {
idr = (struct iso_directory_record *) & dirbuff[i];
if (idr->length[0] == 0) {
@@ -627,14 +635,20 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
continue;
}
nent++;
+ if ((mx & ISO_MULTIEXTENT) == 0 &&
+ (idr->flags[0] & ISO_MULTIEXTENT) != 0) {
+ nmult++; /* Need a multi extent root entry */
+ }
+ mx = idr->flags[0];
i += idr->length[0];
}
/*
* Now allocate the buffer which will hold the array we are about to
- * return.
+ * return. We need one entry per real directory entry and in addition
+ * one multi-extent root entry per multi-extent file.
*/
- rtn = (struct directory_entry **) e_malloc(nent * sizeof (*rtn));
+ rtn = (struct directory_entry **) e_malloc((nent+nmult) * sizeof (*rtn));
/*
* Finally, scan the directory one last time, and pick out the relevant
@@ -646,6 +660,7 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
tt_extent = 0;
seen_rockridge = 0;
tt_size = 0;
+ mx = 0;
while (i < len) {
idr = (struct iso_directory_record *) & dirbuff[i];
if (idr->length[0] == 0) {
@@ -790,7 +805,52 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
if (tt_extent == 0)
tt_size = 0;
}
+ /*
+ * The beginning of a new multi extent directory chain is when
+ * the last directory had no ISO_MULTIEXTENT flag set and the
+ * current entry did set ISO_MULTIEXTENT.
+ */
+ if ((mx & ISO_MULTIEXTENT) == 0 &&
+ (idr->flags[0] & ISO_MULTIEXTENT) != 0) {
+ struct directory_entry *s_entry;
+ struct iso_directory_record *idr2 = idr;
+ int i2 = i;
+ off_t tsize = 0;
+
+ /*
+ * Sum up the total file size for the multi extent file
+ */
+ while (i2 < len) {
+ idr2 = (struct iso_directory_record *) &dirbuff[i2];
+
+ tsize += get_733(idr2->size);
+ if ((idr2->flags[0] & ISO_MULTIEXTENT) == 0)
+ break;
+ i2 += idr2->length[0];
+ }
+
+ s_entry = dup_directory_entry(*pnt); /* dup first for mxroot */
+ s_entry->de_flags |= MULTI_EXTENT;
+ s_entry->de_flags |= INHIBIT_ISO9660_ENTRY|INHIBIT_JOLIET_ENTRY;
+ s_entry->size = tsize;
+ s_entry->starting_block = (*pnt)->starting_block;
+ s_entry->mxroot = s_entry;
+ s_entry->mxpart = 0;
+ s_entry->next = *pnt; /* Next in list */
+ pnt[1] = pnt[0]; /* Move to next slot */
+ *pnt = s_entry; /* First slot is mxroot */
+ pnt++; /* Point again to cur. */
+ }
+ if ((mx & ISO_MULTIEXTENT) != 0 ||
+ (idr->flags[0] & ISO_MULTIEXTENT) != 0) {
+ (*pnt)->de_flags |= MULTI_EXTENT;
+ (*pnt)->de_flags |= INHIBIT_UDF_ENTRY;
+ (pnt[-1])->next = *pnt;
+ (*pnt)->mxroot = (pnt[-1])->mxroot;
+ (*pnt)->mxpart = (pnt[-1])->mxpart + 1;
+ }
pnt++;
+ mx = idr->flags[0];
i += idr->length[0];
}
#ifdef APPLE_HYB
@@ -814,6 +874,10 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
* in the Joliet tree
*/
(*pnt)->de_flags |= INHIBIT_JOLIET_ENTRY;
+ /*
+ * XXX Is it correct to exclude UDF too?
+ */
+ (*pnt)->de_flags |= INHIBIT_UDF_ENTRY;
/*
* as we have associated files, then
@@ -927,7 +991,7 @@ read_merging_directory(struct iso_directory_record *mrootp, int *nentp)
if (dirbuff != NULL) {
free(dirbuff);
}
- *nentp = nent;
+ *nentp = nent + nmult;
return (rtn);
}/* read_merging_directory */
@@ -989,7 +1053,7 @@ check_prev_session(struct directory_entry **ptr, int len,
{
int i;
int rr;
- int retcode = 0; /* Default not found */
+ int retcode = -2; /* Default not found */
for (i = 0; i < len; i++) {
if (ptr[i] == NULL) { /* Used or empty entry skip */
@@ -1024,7 +1088,7 @@ check_prev_session(struct directory_entry **ptr, int len,
* in tree.c for an explaination of why this must be the case.
*/
if ((curr_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) {
- retcode = 2; /* Flag directory case */
+ retcode = i;
goto found_it;
}
/*
@@ -1037,7 +1101,7 @@ check_prev_session(struct directory_entry **ptr, int len,
* we probably have a different file, and we need to write it
* out again.
*/
- retcode = 1; /* We found a non directory */
+ retcode = i;
if (ptr[i]->rr_attributes != NULL) {
if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf,
@@ -1066,11 +1130,24 @@ check_prev_session(struct directory_entry **ptr, int len,
memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
curr_entry->starting_block = isonum_733((unsigned char *)ptr[i]->isorec.extent);
curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+
+ if ((curr_entry->isorec.flags[0] & ISO_MULTIEXTENT) ||
+ (ptr[i]->isorec.flags[0] & ISO_MULTIEXTENT)) {
+ copy_mult_extent(curr_entry, ptr[i]);
+ }
goto found_it;
}
return (retcode);
found_it:
+ if (ptr[i]->mxroot == ptr[i]) { /* Remove all multi ext. entries */
+ int j = i + 1; /* First one will be removed below */
+
+ while (j < len && ptr[j] && ptr[j]->mxroot == ptr[i]) {
+ free(ptr[j]);
+ ptr[j++] = NULL;
+ }
+ }
if (odpnt != NULL) {
*odpnt = ptr[i];
} else {
@@ -1081,6 +1158,106 @@ found_it:
}
/*
+ * Return the number of directory entries for a file. This is usually 1
+ * but may be 3 or more in case of multi extent files.
+ */
+LOCAL int
+iso_dir_ents(de)
+ struct directory_entry *de;
+{
+ struct directory_entry *de2;
+ int ret = 0;
+
+ if (de->mxroot == NULL)
+ return (1);
+ de2 = de;
+ while (de2 != NULL && de2->mxroot == de->mxroot) {
+ ret++;
+ de2 = de2->next;
+ }
+ return (ret);
+}
+
+/*
+ * Copy old multi-extent directory information from the previous session.
+ * If both the old session and the current session are created by genisoimage
+ * then this code could be extremely simple as the information is only copied
+ * in case that the file did not change since the last session was made.
+ * As we don't know the other ISO formatter program, any combination of
+ * multi-extent files and even a single extent file could be possible.
+ * We need to handle all files the same way ad the old session was created as
+ * we reuse the data extents from the file in the old session.
+ */
+LOCAL void
+copy_mult_extent(se1, se2)
+ struct directory_entry *se1;
+ struct directory_entry *se2;
+{
+ struct directory_entry *curr_entry = se1;
+ int len1;
+ int len2;
+ int mxpart = 0;
+
+ len1 = iso_dir_ents(se1);
+ len2 = iso_dir_ents(se2);
+
+ if (len1 == 1) {
+ /*
+ * Convert single-extent to multi-extent.
+ * If *se1 is not multi-extent, *se2 definitely is
+ * and we need to set up a MULTI_EXTENT directory header.
+ */
+ se1->de_flags |= MULTI_EXTENT;
+ se1->isorec.flags[0] |= ISO_MULTIEXTENT;
+ se1->mxroot = curr_entry;
+ se1->mxpart = 0;
+ se1 = dup_directory_entry(se1);
+ curr_entry->de_flags |= INHIBIT_ISO9660_ENTRY|INHIBIT_JOLIET_ENTRY;
+ se1->de_flags |= INHIBIT_UDF_ENTRY;
+ se1->next = curr_entry->next;
+ curr_entry->next = se1;
+ se1 = curr_entry;
+ len1 = 2;
+ }
+
+ while (se2->isorec.flags[0] & ISO_MULTIEXTENT) {
+ len1--;
+ len2--;
+ if (len1 <= 0) {
+ struct directory_entry *sex = dup_directory_entry(se1);
+
+ sex->mxroot = curr_entry;
+ sex->next = se1->next;
+ se1->next = sex;
+ len1++;
+ }
+ memcpy(se1->isorec.extent, se2->isorec.extent, 8);
+ se1->starting_block = get_733(se2->isorec.extent);
+ se1->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+ se1->de_flags |= MULTI_EXTENT;
+ se1->isorec.flags[0] |= ISO_MULTIEXTENT;
+ se1->mxroot = curr_entry;
+ se1->mxpart = mxpart++;
+
+ se1 = se1->next;
+ se2 = se2->next;
+ }
+ memcpy(se1->isorec.extent, se2->isorec.extent, 8);
+ se1->starting_block = get_733(se2->isorec.extent);
+ se1->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+ se1->isorec.flags[0] &= ~ISO_MULTIEXTENT; /* Last entry */
+ se1->mxpart = mxpart;
+ while (len1 > 1) { /* Drop other entries */
+ struct directory_entry *sex;
+
+ sex = se1->next;
+ se1->next = sex->next;
+ free(sex);
+ len1--;
+ }
+}
+
+/*
* open_merge_image: Open an existing image.
*/
int
@@ -1631,6 +1808,19 @@ merge_previous_session(struct directory *this_dir,
&statbuf, &lstatbuf, NULL);
if (retcode == -1)
return (-1);
+ /*
+ * Skip other directory entries for multi-extent files
+ */
+ if (s_entry->de_flags & MULTI_EXTENT) {
+ struct directory_entry *s_e;
+
+ for (s_e = s_entry->mxroot;
+ s_e && s_e->mxroot == s_entry->mxroot;
+ s_e = s_e->next) {
+ s_entry = s_e;
+ ;
+ }
+ }
}
merge_remaining_entries(this_dir, orig_contents, n_orig);
@@ -1682,14 +1872,14 @@ merge_previous_session(struct directory *this_dir,
* The check_prev_session function looks for an identical
* entry in the previous session. If we see it, then we copy
* the extent number to s_entry, and cross it off the list.
- * It returns 2 if it's a directory
*/
retcode = check_prev_session(orig_contents, n_orig, s_entry,
&statbuf, &lstatbuf, &odpnt);
if (retcode == -1)
return (-1);
- if (retcode == 2 && odpnt != NULL) {
+ if (odpnt != NULL &&
+ (s_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) {
int dflag;
if (strcmp(s_entry->name, ".") != 0 &&
@@ -1718,6 +1908,23 @@ merge_previous_session(struct directory *this_dir,
odpnt = NULL;
}
}
+ if (odpnt) {
+ free(odpnt);
+ odpnt = NULL;
+ }
+ /*
+ * Skip other directory entries for multi-extent files
+ */
+ if (s_entry->de_flags & MULTI_EXTENT) {
+ struct directory_entry *s_e;
+
+ for (s_e = s_entry->mxroot;
+ s_e && s_e->mxroot == s_entry->mxroot;
+ s_e = s_e->next) {
+ s_entry = s_e;
+ ;
+ }
+ }
}
if (!reloc_old_root) {
diff --git a/genisoimage/tree.c b/genisoimage/tree.c
index 7805888..913012c 100644
--- a/genisoimage/tree.c
+++ b/genisoimage/tree.c
@@ -11,6 +11,7 @@
*/
/* @(#)tree.c 1.82 04/06/12 joerg */
+/* Parets from @(#)tree.c 1.112 08/08/14 joerg */
/*
* File tree.c - scan directory tree and build memory structures for iso9660
* filesystem
@@ -101,6 +102,8 @@ struct directory *find_or_create_directory(struct directory *parent,
struct stat* stat_template);
static void delete_directory(struct directory *parent,
struct directory *child);
+EXPORT struct directory_entry *
+ dup_directory_entry __PR((struct directory_entry *s_entry));
int sort_tree(struct directory *node);
void dump_tree(struct directory *node);
void update_nlink_field(struct directory *node);
@@ -292,6 +295,17 @@ sort_n_finish(struct directory *this_dir)
flush_file_hash();
s_entry = this_dir->contents;
while (s_entry) {
+#ifdef USE_LARGEFILES
+ /*
+ * Skip all but the last extent from a multi extent file,
+ * we like them all have the same name.
+ */
+ if ((s_entry->de_flags & MULTI_EXTENT) &&
+ (s_entry->isorec.flags[0] & ISO_MULTIEXTENT)) {
+ s_entry = s_entry->next;
+ continue;
+ }
+#endif
/* ignore if it's hidden */
if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
s_entry = s_entry->next;
@@ -438,6 +452,7 @@ got_valid_name:
this_dir->whole_name, SPATH_SEPARATOR,
s_entry->name, s_entry1->name);
}
+
s_entry->isorec.name_len[0] = strlen(newname);
new_reclen = offsetof(struct iso_directory_record,
name[0]) +
@@ -451,6 +466,22 @@ got_valid_name:
new_reclen++; /* Pad to an even byte */
s_entry->isorec.length[0] = new_reclen;
strcpy(s_entry->isorec.name, newname);
+#ifdef USE_LARGEFILES
+ if (s_entry->de_flags & MULTI_EXTENT) {
+ struct directory_entry *s_e;
+
+ /*
+ * Copy over the new name to all other entries
+ */
+ for (s_e = s_entry->mxroot;
+ s_e && s_e->mxroot == s_entry->mxroot;
+ s_e = s_e->next) {
+ s_e->isorec.length[0] = new_reclen;
+ s_e->isorec.name_len[0] = s_entry->isorec.name_len[0];
+ strcpy(s_e->isorec.name, newname);
+ }
+ }
+#endif
#ifdef APPLE_HYB
/* has resource fork - needs new name */
if (apple_both && s_entry->assoc) {
@@ -489,6 +520,22 @@ got_valid_name:
new_reclen++; /* Pad to an even byte */
s_entry1->isorec.length[0] = new_reclen;
strcpy(s_entry1->isorec.name, newname);
+#ifdef USE_LARGEFILES
+ if (s_entry1->de_flags & MULTI_EXTENT) {
+ struct directory_entry *s_e;
+
+ /*
+ * Copy over the new name to all other entries
+ */
+ for (s_e = s_entry1->mxroot;
+ s_e && s_e->mxroot == s_entry1->mxroot;
+ s_e = s_e->next) {
+ s_e->isorec.length[0] = new_reclen;
+ s_e->isorec.name_len[0] = s_entry1->isorec.name_len[0];
+ strcpy(s_e->isorec.name, newname);
+ }
+ }
+#endif
add_file_hash(s_entry1);
#ifdef APPLE_HYB
/* has resource fork - needs new name */
@@ -562,6 +609,10 @@ got_valid_name:
table->filedir = this_dir;
if (jhide_trans_tbl)
table->de_flags |= INHIBIT_JOLIET_ENTRY;
+ /*
+ * Always hide transtable from UDF tree.
+ */
+ table->de_flags |= INHIBIT_UDF_ENTRY;
/* table->name = strdup("<translation table>");*/
table->name = strdup(trans_tbl);
/*
@@ -808,9 +859,12 @@ generate_reloc_directory()
s_entry->next = root->contents;
reloc_dir->self = s_entry;
- /* The rr_moved entry will not appear in the Joliet tree. */
+ /* The rr_moved entry will not appear in the Joliet nor the UDF tree. */
reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY;
s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
+
+ reloc_dir->dir_flags |= INHIBIT_UDF_ENTRY;
+ s_entry->de_flags |= INHIBIT_UDF_ENTRY;
/* Hiding RR_MOVED seems not to be possible..... */
#ifdef HIDE_RR
@@ -1551,14 +1605,14 @@ insert_file_entry(struct directory *this_dir, char *whole_path,
return (0);
}
/* print a warning but don't spam too much */
- if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= (off_t)0xFFFFFFFF)) {
+ if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= maxnonlarge) && !do_largefiles) {
static int udf_warned;
if( !allow_limited_size || verbose>1)
fprintf(stderr, "File %s is larger than 4GiB-1.\n", whole_path);
if( !allow_limited_size)
{
- fprintf(stderr, "-allow-limited-size was not specified. There is no way do represent this file size. Aborting.\n");
+ fprintf(stderr, "There is no way do represent this file size. Aborting. See -iso-level 3 or -allow-limited-size options\n");
exit(1);
}
if(verbose>=1 && ! udf_warned ) {
@@ -1773,6 +1827,20 @@ insert_file_entry(struct directory *this_dir, char *whole_path,
s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
}
}
+ if (this_dir != reloc_dir &&
+ this_dir->dir_flags & INHIBIT_UDF_ENTRY) {
+ s_entry->de_flags |= INHIBIT_UDF_ENTRY;
+ } /* else if (strcmp(short_name, ".") != 0 &&
+ strcmp(short_name, "..") != 0) {
+ if (u_matches(short_name) || u_matches(whole_path)) {
+ if (verbose > 1) {
+ fprintf(stderr,
+ "Hidden from UDF tree: %s\n",
+ whole_path);
+ }
+ s_entry->de_flags |= INHIBIT_UDF_ENTRY;
+ }
+ } */
#ifdef SORTING
/* inherit any sort weight from parent directory */
@@ -1829,9 +1897,10 @@ insert_file_entry(struct directory *this_dir, char *whole_path,
s_entry->hfs_type = have_rsrc;
/*
* don't want the rsrc file to be included in any
- * Joliet tree
+ * Joliet/UDF tree
*/
s_entry->de_flags |= INHIBIT_JOLIET_ENTRY;
+ s_entry->de_flags |= INHIBIT_UDF_ENTRY;
} else if (s_entry->next) {
/*
* if previous entry is an associated file,
@@ -2161,8 +2230,10 @@ insert_file_entry(struct directory *this_dir, char *whole_path,
* directory
*/
if (s_entry->hfs_ent &&
- !(s_entry->de_flags & RELOCATED_DIRECTORY))
+ !(s_entry->de_flags & RELOCATED_DIRECTORY) &&
+ (s_entry->isorec.flags[0] & ISO_MULTIEXTENT) == 0) {
free(s_entry->hfs_ent);
+ }
s_entry->hfs_ent = NULL;
}
/*
@@ -2194,9 +2265,110 @@ insert_file_entry(struct directory *this_dir, char *whole_path,
&statbuf, &lstatbuf, deep_flag);
}
+
+#ifdef USE_LARGEFILES
+#define LARGE_EXTENT 0xFFFFF800UL
+#define MAX_EXTENT 0xFFFFFFFEUL
+ /*
+ * Break up files greater than (4GB -2) into multiple extents.
+ * The original entry, with ->size untouched, remains for UDF.
+ * Each of the new file sections will get its own entry.
+ * The file sections are the only entries actually written out to the
+ * disk. The UDF entry will use "mxroot" to get the same start
+ * block as the first file section, and all the sections will end up
+ * in the ISO9660 directory in the correct order by "mxpart",
+ * which the directory sorting routine knows about.
+ *
+ * If we ever need to be able to find mxpart == 1 after sorting,
+ * we need to add another pointer to s_entry or to be very careful
+ * with the loops above where the ISO-9660 name is copied back to
+ * all multi-extent parts.
+ */
+ if (s_entry->size > MAX_EXTENT && do_largefiles) {
+ off_t size;
+
+ s_entry->de_flags |= MULTI_EXTENT;
+ s_entry->isorec.flags[0] |= ISO_MULTIEXTENT;
+ s_entry->mxroot = s_entry;
+ s_entry->mxpart = 0;
+ set_733((char *)s_entry->isorec.size, LARGE_EXTENT);
+ s_entry1 = dup_directory_entry(s_entry);
+ s_entry->next = s_entry1;
+
+ /*
+ * full size UDF version
+ */
+ s_entry->de_flags |= INHIBIT_ISO9660_ENTRY|INHIBIT_JOLIET_ENTRY;
+ if (s_entry->size > (((off_t)190)*0x3FFFF800)) {
+#ifndef EOVERFLOW
+#define EOVERFLOW EFBIG
+#endif
+ errmsgno(EOVERFLOW,
+ "File %s is too large - hiding from UDF tree.\n",
+ whole_path);
+ s_entry->de_flags |= INHIBIT_UDF_ENTRY;
+ }
+
+ /*
+ * Prepare the first file multi-extent section of the file.
+ */
+ s_entry = s_entry1;
+ s_entry->de_flags |= INHIBIT_UDF_ENTRY;
+ size = s_entry->size;
+ s_entry->size = LARGE_EXTENT;
+ s_entry->mxpart++;
+
+ /*
+ * Additional extents, as needed
+ */
+ while (size > MAX_EXTENT) {
+ s_entry1 = dup_directory_entry(s_entry);
+ s_entry->next = s_entry1;
+
+ s_entry = s_entry1;
+ s_entry->mxpart++;
+ size -= LARGE_EXTENT;
+ }
+ /*
+ * That was the last one.
+ */
+ s_entry->isorec.flags[0] &= ~ISO_MULTIEXTENT;
+ s_entry->size = size;
+ set_733((char *)s_entry->isorec.size, (UInt32_t)s_entry->size);
+ }
+#endif /* USE_LARGEFILES */
+
return (1);
}
+EXPORT struct directory_entry *
+dup_directory_entry(s_entry)
+ struct directory_entry *s_entry;
+{
+ struct directory_entry *s_entry1;
+
+ s_entry1 = (struct directory_entry *)
+ e_malloc(sizeof (struct directory_entry));
+ memcpy(s_entry1, s_entry, sizeof (struct directory_entry));
+
+ if (s_entry->rr_attributes) {
+ s_entry1->rr_attributes =
+ e_malloc(s_entry->total_rr_attr_size);
+ memcpy(s_entry1->rr_attributes, s_entry->rr_attributes,
+ s_entry->total_rr_attr_size);
+ }
+ if (s_entry->name)
+ s_entry1->name = strdup(s_entry->name);
+ if (s_entry->whole_name)
+ s_entry1->whole_name = strdup(s_entry->whole_name);
+#ifdef APPLE_HYB
+ /*
+ * If we also duplicate s_entry->hfs_ent, we would need to change
+ * free_one_directory() and other calls to free(s_entry->hfs_ent) too.
+ */
+#endif
+ return (s_entry1);
+}
void
generate_iso9660_directories(struct directory *node, FILE *outfile)
diff --git a/genisoimage/udf.c b/genisoimage/udf.c
index c63d372..eff14e3 100644
--- a/genisoimage/udf.c
+++ b/genisoimage/udf.c
@@ -11,6 +11,7 @@
*/
/* @(#)udf.c 1.14 04/04/15 Copyright 2001 J. Schilling */
+/* Parts from @(#)udf.c 1.31 08/08/13 Copyright 2001-2007 J. Schilling */
/*
* udf.c - UDF support for genisoimage
*
@@ -136,7 +137,7 @@ directory_size(struct directory *dpnt)
/* directory contents */
for (de = dpnt->jcontents; de; de = de->jnext) {
- if (!(de->de_flags & INHIBIT_JOLIET_ENTRY)) {
+ if (!(de->de_flags & INHIBIT_UDF_ENTRY)) {
char *name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
/* skip . and .. */
if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
@@ -150,12 +151,12 @@ directory_size(struct directory *dpnt)
static void
assign_udf_directory_addresses(struct directory *dpnt)
{
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
dpnt->self->udf_file_entry_sector = last_extent;
last_extent += 1 + ISO_BLOCKS(directory_size(dpnt));
++num_udf_directories;
}
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
assign_udf_directory_addresses(dpnt);
}
@@ -165,7 +166,7 @@ assign_udf_directory_addresses(struct directory *dpnt)
static void
assign_udf_file_entry_addresses(struct directory *dpnt)
{
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
struct directory_entry *de;
for (de = dpnt->jcontents; de; de = de->jnext) {
if (!(de->de_flags & RELOCATED_DIRECTORY) &&
@@ -175,7 +176,7 @@ assign_udf_file_entry_addresses(struct directory *dpnt)
}
}
}
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
assign_udf_file_entry_addresses(dpnt);
}
@@ -654,6 +655,13 @@ set_file_ident_desc(unsigned char *buf, unsigned rba, char *name,
}
static void
+udf_size_panic(int n)
+{
+ comerrno(EX_BAD,
+ "Panic: UDF file size error, too many extents (%d).\n", n);
+}
+
+static void
set_file_entry(unsigned char *buf, unsigned rba, unsigned file_rba,
uint64_t length, const char *iso_date, int is_directory,
unsigned link_count, unsigned unique_id)
@@ -752,6 +760,18 @@ set_file_entry(unsigned char *buf, unsigned rba, unsigned file_rba,
file_rba += chunk >> 11;
allocation_desc++;
}
+ if (((Uchar *)allocation_desc) > &buf[2048])
+ udf_size_panic(allocation_desc - &fe->allocation_desc);
+
+ if (((Uchar *)allocation_desc) > &buf[2048])
+ udf_size_panic(allocation_desc - &fe->allocation_desc);
+
+ if (((Uchar *)allocation_desc) > &buf[2048])
+ udf_size_panic(allocation_desc - &fe->allocation_desc);
+
+ if (((Uchar *)allocation_desc) > &buf[2048])
+ udf_size_panic(allocation_desc - &fe->allocation_desc);
+
set32(&fe->length_of_allocation_descs,
(unsigned char *) allocation_desc -
(unsigned char *) &fe->allocation_desc);
@@ -772,14 +792,14 @@ directory_link_count(struct directory *dpnt)
/* count relocated subdirectories */
for (de = dpnt->jcontents; de; de = de->jnext) {
if ((de->de_flags &
- (INHIBIT_JOLIET_ENTRY | RELOCATED_DIRECTORY)) ==
+ (INHIBIT_UDF_ENTRY | RELOCATED_DIRECTORY)) ==
RELOCATED_DIRECTORY) {
link_count++;
}
}
/* count ordinary subdirectories */
for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
link_count++;
}
}
@@ -833,7 +853,7 @@ write_one_udf_directory(struct directory *dpnt, FILE *outfile)
char *name;
struct directory_entry *de1;
- if (de->de_flags & INHIBIT_JOLIET_ENTRY)
+ if (de->de_flags & INHIBIT_UDF_ENTRY)
continue;
name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name;
@@ -888,10 +908,10 @@ write_one_udf_directory(struct directory *dpnt, FILE *outfile)
static void
write_udf_directories(struct directory *dpnt, FILE *outfile)
{
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
write_one_udf_directory(dpnt, outfile);
}
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
write_udf_directories(dpnt, outfile);
}
@@ -905,7 +925,7 @@ write_udf_file_entries(struct directory *dpnt, FILE *outfile)
memset(buf, 0, SECTOR_SIZE);
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) {
struct directory_entry *de;
for (de = dpnt->jcontents; de; de = de->jnext) {
if (!(de->de_flags & RELOCATED_DIRECTORY) &&
@@ -926,7 +946,7 @@ write_udf_file_entries(struct directory *dpnt, FILE *outfile)
}
}
}
- if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) {
+ if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) {
for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) {
write_udf_file_entries(dpnt, outfile);
}
diff --git a/genisoimage/write.c b/genisoimage/write.c
index a423ab1..27ece8e 100644
--- a/genisoimage/write.c
+++ b/genisoimage/write.c
@@ -12,6 +12,7 @@
/* @(#)write.c 1.88 06/02/01 joerg */
/* Parts from @(#)write.c 1.106 07/02/17 joerg */
+/* Parts from @(#)write.c 1.117 07/12/16 joerg */
/*
* Program write.c - dump memory structures to file for iso9660 filesystem.
*
@@ -92,7 +93,7 @@ static int xawrite(void *buffer, int size, int count, FILE *file,
void xfwrite(void *buffer, int size, int count, FILE *file, int submode,
BOOL islast);
static int assign_directory_addresses(struct directory *node);
-#ifdef APPLE_HYB
+#if defined(APPLE_HYB) || defined(USE_LARGEFILES)
static void write_one_file(char *filename, off_t size, FILE *outfile,
off_t off);
#else
@@ -417,13 +418,13 @@ assign_directory_addresses(struct directory *node)
return (0);
}
-#ifdef APPLE_HYB
+#if defined(APPLE_HYB) || defined(USE_LARGEFILES)
static void
write_one_file(char *filename, off_t size, FILE *outfile, off_t off)
#else
static void
write_one_file(char *filename, off_t size, FILE *outfile)
-#endif /* APPLE_HYB */
+#endif /* APPLE_HYB || USE_LARGEFILES */
{
/*
* It seems that there are still stone age C-compilers
@@ -456,9 +457,9 @@ static char buffer[SECTOR_SIZE * NSECT];
exit(1);
#endif
}
-#ifdef APPLE_HYB
+#if defined(APPLE_HYB) || defined(USE_LARGEFILES)
fseek(infile, off, SEEK_SET);
-#endif /* APPLE_HYB */
+#endif /* APPLE_HYB || USE_LARGEFILES */
remain = size;
if (include_in_jigdo)
@@ -655,8 +656,18 @@ compare_dirs(const void *rr, const void *ll)
return (-1);
#endif /* APPLE_HYB */
- /* If the entries are the same, this is an error. */
+ /*
+ * If the names are the same, multiple extent sections of the same file
+ * are sorted by part number. If the part numbers do not differ, this
+ * is an error.
+ */
if (strcmp(rpnt, lpnt) == 0) {
+#ifdef USE_LARGEFILES
+ if ((*r)->mxpart < (*l)->mxpart)
+ return (-1);
+ else if ((*r)->mxpart > (*l)->mxpart)
+ return (1);
+#endif
#ifdef USE_LIBSCHILY
errmsgno(EX_BAD,
"Error: '%s' and '%s' have the same ISO9660 name '%s'.\n",
@@ -1065,11 +1076,10 @@ assign_file_addresses(struct directory *dpnt, BOOL isnest)
}
#endif /* DVD_VIDEO */
- 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
+ * If we already have an extent for this entry, then
* don't assign a new one. It must have come from a
* previous session on the disc. Note that we don't
* end up scheduling the thing for writing either.
@@ -1078,7 +1088,9 @@ assign_file_addresses(struct directory *dpnt, BOOL isnest)
continue;
}
/*
- * This saves some space if there are symlinks present
+ * This saves some space if there are symlinks present.
+ * If this is a multi-extent file, we get mxpart == 1
+ * from find_hash().
*/
s_hash = find_hash(s_entry->dev, s_entry->inode);
if (s_hash) {
@@ -1091,6 +1103,36 @@ assign_file_addresses(struct directory *dpnt, BOOL isnest)
s_hash->starting_block);
set_733((char *) s_entry->isorec.size,
s_hash->size);
+#ifdef USE_LARGEFILES
+ if (s_entry->de_flags & MULTI_EXTENT) {
+ struct directory_entry *s_e;
+ unsigned int ext = s_hash->starting_block;
+
+ /*
+ * Skip the multi extent root entry.
+ */
+ if (s_entry->mxpart == 0)
+ continue;
+ /*
+ * The directory is sorted, so we should
+ * see s_entry->mxpart == 1 first.
+ */
+ if (s_entry->mxpart != 1) {
+ comerrno(EX_BAD,
+ "Panic: Multi extent parts for %s not sorted.\n",
+ s_entry->whole_name);
+ }
+ s_entry->mxroot->starting_block = ext;
+ for (s_e = s_entry;
+ s_e && s_e->mxroot == s_entry->mxroot;
+ s_e = s_e->next) {
+ set_733((char *) s_e->isorec.extent,
+ ext);
+ ext += ISO_BLOCKS(s_e->size);
+ }
+ }
+#endif
+
#ifdef SORTING
/* check for non-directory files */
if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) {
@@ -1247,8 +1289,54 @@ assign_file_addresses(struct directory *dpnt, BOOL isnest)
set_733((char *) s_entry->isorec.extent,
last_extent);
s_entry->starting_block = last_extent;
+#ifdef USE_LARGEFILES
+ /*
+ * Update the entries for multi-section files
+ * as we now know the starting extent numbers.
+ */
+ if (s_entry->de_flags & MULTI_EXTENT) {
+ struct directory_entry *s_e;
+ unsigned int ext = last_extent;
+
+ /*
+ * Skip the multi extent root entry.
+ */
+ if (s_entry->mxpart == 0)
+ continue;
+ /*
+ * The directory is sorted, so we should
+ * see s_entry->mxpart == 1 first.
+ */
+ if (s_entry->mxpart != 1) {
+ comerrno(EX_BAD,
+ "Panic: Multi extent parts for %s not sorted.\n",
+ s_entry->whole_name);
+ }
+ dwpnt->size = s_entry->mxroot->size;
+ s_entry->mxroot->starting_block = ext;
+ /*
+ * Set the mxroot (mxpart == 0) to allow
+ * the UDF code to fetch the starting
+ * extent number.
+ */
+ set_733((char *) s_entry->mxroot->isorec.extent, ext);
+ for (s_e = s_entry;
+ s_e && s_e->mxroot == s_entry->mxroot;
+ s_e = s_e->next) {
+ if (s_e->mxpart == 0)
+ continue;
+ set_733((char *) s_e->isorec.extent,
+ ext);
+ ext += ISO_BLOCKS(s_e->size);
+ }
+ add_hash(s_entry);
+ }
+#endif
add_hash(s_entry);
- last_extent += ISO_BLOCKS(s_entry->size);
+ /*
+ * The cache holds the full size of the file
+ */
+ last_extent += ISO_BLOCKS(dwpnt->size);
#ifdef DVD_VIDEO
/* Shouldn't we always add the pad info? */
if (dvd_video) {
@@ -1343,8 +1431,10 @@ free_one_directory(struct directory *dpnt)
s_entry_d->whole_name = NULL;
}
#ifdef APPLE_HYB
- if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc)
+ if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc &&
+ (s_entry_d->isorec.flags[0] & ISO_MULTIEXTENT) == 0) {
free(s_entry_d->hfs_ent);
+ }
#endif /* APPLE_HYB */
free(s_entry_d);