Re: mkisofs -M makes no attempt to reconstruct multi-extent files
You used mkisofs incorrectly
Command line sequence was *tailored* to allow to produce usable input
for *hex editor* in less than minute.
Why did you use -C16,xxx?
This is definitely wrong.
The reason is in the beginning of merge_isofs() in multi.c. In
particular for (i=0;i<100;i++) loop. As area prior sector 16 is allowed
to be and customarily used for other purposes (such as hybrid disks),
there is no guarantee that data there does not resemble iso9660 volume
descriptor. I don't want mkisofs to look at sectors prior 16th at all,
but start directly with volume descriptor. One can argue that mkisofs
should have seek-ed to 16th sector all by itself, but the code has been
around for so long, that it should be considered feature, not bug.
In theory, I could change mkisofs to start looking at sector #16
Once again, the code has been around for so long, that it should be
considered to be a feature, and therefore no modifications should me
made. In other words, don't.
But if you put something that looks like a PVD between sector #0 and
sector #15, then your software is wrong anyway. Are you really doing this?
I'm not putting anything between sectors #0 and #15, but it does not
mean that some other program does not. And by doing so such program does
*not* violate any standards, moreover, it's common practice. mkisofs
itself puts data there if instructed to generate hybrid disk. Data put
by mkisofs does not normally resemble PVD, but *formally* there is no
guarantee that it won't. Therefore it's not inappropriate (or in other
words it's not "definitely wrong") to guide mkisofs directly to 16th sector.
Your claim that the file is non-contiguous is just wrong.
Having 9GB 5G.0 file in XP (previously discussed), if I read byte prior
4GB-2KB offset in the file, I get last byte from LBA X+0x200000-2, and
when I read next byte, i.e. at 4GB-2KB offset in file I get data from
LBA Y, and there is >1GB gap between X+0x200000 and Y.
I cannot speak for the sofware you used to look at the image.....
In other words you're implying that under no circumstances results
obtained with software of my choice could be possibly right.
I looked at my test results using isoinfo and isoinfo did not show
non-contiguous files.
Already mentioned 'isoinfo -l -i /dev/dvd' output:
Directory listing of /
d--------- 0 0 0 2048 May 20 2008 [2621639 02] .
d--------- 0 0 0 2048 May 20 2008 [2621639 02] ..
---------- 0 0 0 9663674368 May 20 2008 [ 24 80] 5G.1;1
---------- 0 0 0 1073743872 May 20 2008 [2097175 00] 5G000.0;1
In other words, like Windows XP kernel, isoinfo also reckoned that there
are one ~9GB and one ~1GB file. Now suggested 'isoinfo -debug -l -i
/dev/dvd' output:
Directory listing of /
d--------- 0 0 0 2048 May 20 2008 [2621639 02] .
d--------- 0 0 0 2048 May 20 2008 [2621639 02] ..
---------- 0 0 0 4294965248 May 20 2008 [ 24 80] 5G.0;1
---------- 0 0 0 4294965248 May 20 2008 [2621640 80] 5G.1;1
---------- 0 0 0 1073743872 May 20 2008 [4718791 00] 5G.1;1
---------- 0 0 0 9663674368 May 20 2008 [ 24 00] 5G.1;1
---------- 0 0 0 1073743872 May 20 2008 [2097175 00] 5G000.0;1
It depicts that 9GB file consists of 3 extents, 1st starting at LBA 24,
2nd at 2621640, and finally 3rd one at 4718791. But where does first
extent end? At 24 + 4294965248 / 2048 = 2097175, which is more than 1GB
apart from start of 2nd extent.
P.S.: The solution to correctly import directory entries from old sessions is
not trivial but a first hacky solution seems to work....
Just for reference, attached patch would handle even shrinking
multi-extent files. Once again I want to point out that I make no claims
that the patches are complete solution to the problem. Their purpose is
to support claims in original bug report. A.
--- ./mkisofs/multi.c.orig 2007-08-20 18:17:17.000000000 +0200
+++ ./mkisofs/multi.c 2008-05-23 14:05:38.000000000 +0200
@@ -538,6 +538,7 @@
unsigned char *tt_buf;
UInt32_t tt_extent;
UInt32_t tt_size;
+ int mxpart;
static int warning_given = 0;
@@ -589,6 +590,7 @@
tt_extent = 0;
seen_rockridge = 0;
tt_size = 0;
+ mxpart = 0;
while (i < len) {
idr = (struct iso_directory_record *) & dirbuff[i];
if ((i + (idr->length[0] & 0xFF)) > len) {
@@ -635,6 +637,20 @@
(*pnt)->rr_attr_size = 0;
(*pnt)->total_rr_attr_size = 0;
(*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY;
+
+ /*
+ * Track multi-extent files.
+ */
+ if (idr->flags[0]&ISO_MULTIEXTENT) {
+ (*pnt)->de_flags |= MULTI_EXTENT;
+ (*pnt)->mxpart = ++mxpart;
+ }
+ else if (mxpart) {
+ (*pnt)->de_flags |= MULTI_EXTENT;
+ (*pnt)->mxpart = ++mxpart;
+ mxpart = 0;
+ }
+
#ifdef APPLE_HYB
(*pnt)->assoc = NULL;
(*pnt)->hfs_ent = NULL;
@@ -947,6 +963,7 @@
{
int i;
int rr;
+ int same;
int retcode = 0; /* Default not found */
for (i = 0; i < len; i++) {
@@ -996,6 +1013,7 @@
* out again.
*/
retcode = 1; /* We found a non directory */
+ same = 0; /* assume not same */
if (ptr[i]->rr_attributes != NULL) {
if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf,
@@ -1024,11 +1042,22 @@
memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8);
curr_entry->starting_block = get_733(ptr[i]->isorec.extent);
curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;
+ same = 1;
goto found_it;
}
return (retcode);
found_it:
+ if (retcode==1 && !same && ptr[i]->mxpart==1) {
+ /* if out-of-date file is multi-extent,
+ * retire all extents */
+ int j=i;
+ while (++j<len && ptr[j] && ptr[j]->mxpart>1) {
+ free(ptr[j]);
+ ptr[j] = NULL;
+ }
+ }
+
if (odpnt != NULL) {
*odpnt = ptr[i];
} else {
Reply to: