Subject: | Errors processing central directory in IO::Uncompress::Unzip |
Date: | Sat, 19 Nov 2011 00:13:28 -0600 |
To: | bug-IO-Compress [...] rt.cpan.org |
From: | David Todd <david [...] dtodd.net> |
My apologies for not having an account into the rt.cpan.org website to
post this directly, I've given this issue a lot of hours of attention
today and would hope that anyone else can do the same.
when extracting members from a zip using ::Unzip via the 'walking a
zip' method, either with the zip stored in a scalar, or allowing the
module to open the file directly the module will not extract the last
member encountered in the zip only in these conditions:
* The last member in the archive must be compressMethod == 0 (stored)
* The last member must have a total size greater than the BlockSize
(if specified) or 4096 (the default) a smaller member will extract
normally.
* There must be at least two members in the zip. I've tested up to
five, if the last member meets the above requirements it will not
extract.
Here's a post of my test code, it's not pretty -- http://pastie.org/2886941
using the zip utility on an example archive I have built on my
machine, the contents listing is thus:
Archive: new.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
73761964 Stored 73761964 0% 10-27-2011 04:17 8410422c city.dir
62593 Stored 62593 0% 11-18-2011 23:37 55f7d5d6 new.log
-------- ------- --- -------
73824557 73824557 0% 2 files
my perl script generates this output:
Offs 73761964 Dec city.dir : 73761964 of
73761964 bytes done HeaderLen: (66) Bytes Left: 4
Offs 4096 Dec new.log : -1 of
62593 bytes done HeaderLen: (65) Bytes Left: 4
Wasn't able to unpack the entire stored file...
Unzip Error:
The trailingData() looks like it is 4 bytes long.
Offs 58674 Dec new.log : 58674 of
62593 bytes done HeaderLen: (65) Bytes Left: 0
Wasn't able to unpack the entire stored file...
Unzip Error:
The trailingData() looks like it is 0 bytes long.
This is in strict => 0; if I set strict => 1 the $UnzipError will be
populated with "Trailer Error: CRC mismatch"
Reproduction is very simple --
create a zip archive with two members in store mode. Alternatively,
one member can be renamed and appended with '.Z' if the zip
application you use will automatically store that file (mine will). so
long as the last member in the list is both larger than the BlockSize
and stored, not deflated, a $u->read(); operation will fail with -1
upon encountering the last file.
My immediate workaround has been to set BlockSize to be larger than
the last member in the archive (if stored) however, since BlockSize
determines memory utilization, this limits the practical usefulness
depending on the number of members in the archive or the max size of
the last member.
I haven't been able to devote much time to debugging to figure out
why, but I have a feeling the BlockSize trigger is a big clue to
something.
Thanks,
David