diff options
author | kientzle <kientzle@FreeBSD.org> | 2008-01-15 16:27:15 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2008-01-15 16:27:15 +0000 |
commit | b00d558d00d204771598eb590cfcf983657e0b1a (patch) | |
tree | e1e745b7e53e96efa2893e5d6a73bed04bb98e1b /lib | |
parent | c02890da0b4e1279b29fcf72906c76e4824c6037 (diff) | |
download | FreeBSD-src-b00d558d00d204771598eb590cfcf983657e0b1a.zip FreeBSD-src-b00d558d00d204771598eb590cfcf983657e0b1a.tar.gz |
Handle Zip archives that are "multi-part archives with only
one part" by simply ignoring the marker at the beginning
of the file. (Zip archivers reserve four bytes at the beginning
of each part of a multi-part archive, if it happens to only
require one part, those four bytes get filled with a placeholder
that can be ignored.)
Thanks to: Marius Nuennerich,
for pointing me to a Zip archive that libarchive couldn't handle
MFC after: 7 days
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libarchive/archive_read_support_format_zip.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/libarchive/archive_read_support_format_zip.c b/lib/libarchive/archive_read_support_format_zip.c index 24a689c..d96bea6 100644 --- a/lib/libarchive/archive_read_support_format_zip.c +++ b/lib/libarchive/archive_read_support_format_zip.c @@ -180,7 +180,8 @@ archive_read_format_zip_bid(struct archive_read *a) if ((p[2] == '\001' && p[3] == '\002') || (p[2] == '\003' && p[3] == '\004') || (p[2] == '\005' && p[3] == '\006') - || (p[2] == '\007' && p[3] == '\010')) + || (p[2] == '\007' && p[3] == '\010') + || (p[2] == '0' && p[3] == '0')) return (30); } return (0); @@ -214,6 +215,23 @@ archive_read_format_zip_read_header(struct archive_read *a, return (ARCHIVE_FATAL); } + /* + * "PK00" signature is used for "split" archives that + * only have a single segment. This means we can just + * skip the PK00; the first real file header should follow. + */ + if (signature[2] == '0' && signature[3] == '0') { + (a->decompressor->consume)(a, 4); + if ((h = __archive_read_ahead(a, 4)) == NULL) + return (ARCHIVE_FATAL); + signature = (const char *)h; + if (signature[0] != 'P' || signature[1] != 'K') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad ZIP file"); + return (ARCHIVE_FATAL); + } + } + if (signature[2] == '\001' && signature[3] == '\002') { /* Beginning of central directory. */ return (ARCHIVE_EOF); |