aboutsummaryrefslogtreecommitdiff
path: root/lib/libarchive/archive_read_support_format_zip.c
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2008-12-06 06:45:15 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2008-12-06 06:45:15 +0000
commitb1ff9c25b85752421491eb42f56c4cf65f451f98 (patch)
tree07033908f13a75f6e70696ff70c73d1160bb8e74 /lib/libarchive/archive_read_support_format_zip.c
parent72a4c788ff73a4cbfc61c85335d8d42004822e03 (diff)
Notes
Diffstat (limited to 'lib/libarchive/archive_read_support_format_zip.c')
-rw-r--r--lib/libarchive/archive_read_support_format_zip.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/lib/libarchive/archive_read_support_format_zip.c b/lib/libarchive/archive_read_support_format_zip.c
index 575cd331e4b9..a86c533c0188 100644
--- a/lib/libarchive/archive_read_support_format_zip.c
+++ b/lib/libarchive/archive_read_support_format_zip.c
@@ -36,6 +36,10 @@ __FBSDID("$FreeBSD$");
#include <time.h>
#ifdef HAVE_ZLIB_H
#include <zlib.h>
+#else
+/* Hmmm... This is necessary, but means that we can't correctly extract
+ * even uncompressed entries on platforms that lack zlib. */
+#define crc32(crc, buf, len) (unsigned long)0
#endif
#include "archive.h"
@@ -167,9 +171,9 @@ archive_read_format_zip_bid(struct archive_read *a)
{
const char *p;
const void *buff;
- size_t bytes_avail;
+ size_t bytes_avail, offset;
- if ((p = __archive_read_ahead(a, 4)) == NULL)
+ if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
return (-1);
/*
@@ -189,42 +193,37 @@ archive_read_format_zip_bid(struct archive_read *a)
/*
* Attempt to handle self-extracting archives
* by noting a PE header and searching forward
- * up to 64k for a 'PK\003\004' marker.
+ * up to 128k for a 'PK\003\004' marker.
*/
if (p[0] == 'M' && p[1] == 'Z') {
/*
- * TODO: Additional checks that this really is a PE
- * file before we invoke the 128k lookahead below.
- * No point in allocating a bigger lookahead buffer
- * if we don't need to.
- */
- /*
- * TODO: Of course, the compression layer lookahead
- * buffers aren't dynamically sized yet; they should be.
- */
- bytes_avail = (a->decompressor->read_ahead)(a, &buff, 128*1024);
- p = (const char *)buff;
-
- /*
- * TODO: Optimize by jumping forward based on values
- * in the PE header. Note that we don't need to be
- * exact, but we mustn't skip too far. The search
- * below will compensate if we undershoot. Skipping
- * will also reduce the chance of false positives
- * (which is not really all that high to begin with,
- * so maybe skipping isn't really necessary).
+ * TODO: Optimize by initializing 'offset' to an
+ * estimate of the likely start of the archive data
+ * based on values in the PE header. Note that we
+ * don't need to be exact, but we mustn't skip too
+ * far. The search below will compensate if we
+ * undershoot.
*/
-
- while (p < bytes_avail + (const char *)buff) {
- if (p[0] == 'P' && p[1] == 'K' /* "PK" signature */
- && p[2] == 3 && p[3] == 4 /* File entry */
- && p[8] == 8 /* compression == deflate */
- && p[9] == 0 /* High byte of compression */
- )
- {
- return (30);
+ offset = 0;
+ while (offset < 124000) {
+ /* Get 4k of data beyond where we stopped. */
+ buff = __archive_read_ahead(a, offset + 4096,
+ &bytes_avail);
+ if (bytes_avail < offset + 1)
+ break;
+ p = (const char *)buff + offset;
+ while (p + 9 < (const char *)buff + bytes_avail) {
+ if (p[0] == 'P' && p[1] == 'K' /* signature */
+ && p[2] == 3 && p[3] == 4 /* File entry */
+ && p[8] == 8 /* compression == deflate */
+ && p[9] == 0 /* High byte of compression */
+ )
+ {
+ return (30);
+ }
+ ++p;
}
- ++p;
+ offset = p - (const char *)buff;
}
}
@@ -251,7 +250,7 @@ skip_sfx(struct archive_read *a)
* reduce the chance of a false positive.
*/
for (;;) {
- bytes = (a->decompressor->read_ahead)(a, &h, 4096);
+ h = __archive_read_ahead(a, 4, &bytes);
if (bytes < 4)
return (ARCHIVE_FATAL);
p = h;
@@ -267,7 +266,7 @@ skip_sfx(struct archive_read *a)
/* TODO: Additional verification here. */
if (memcmp("PK\003\004", p, 4) == 0) {
skip = p - (const char *)h;
- (a->decompressor->consume)(a, skip);
+ __archive_read_consume(a, skip);
return (ARCHIVE_OK);
}
p += 4;
@@ -279,7 +278,7 @@ skip_sfx(struct archive_read *a)
}
}
skip = p - (const char *)h;
- (a->decompressor->consume)(a, skip);
+ __archive_read_consume(a, skip);
}
}
@@ -303,7 +302,7 @@ archive_read_format_zip_read_header(struct archive_read *a,
zip->entry_uncompressed_bytes_read = 0;
zip->entry_compressed_bytes_read = 0;
zip->entry_crc32 = crc32(0, NULL, 0);
- if ((h = __archive_read_ahead(a, 4)) == NULL)
+ if ((h = __archive_read_ahead(a, 4, NULL)) == NULL)
return (ARCHIVE_FATAL);
signature = (const char *)h;
@@ -312,7 +311,7 @@ archive_read_format_zip_read_header(struct archive_read *a,
r = skip_sfx(a);
if (r < ARCHIVE_WARN)
return (r);
- if ((h = __archive_read_ahead(a, 4)) == NULL)
+ if ((h = __archive_read_ahead(a, 4, NULL)) == NULL)
return (ARCHIVE_FATAL);
signature = (const char *)h;
}
@@ -329,8 +328,8 @@ archive_read_format_zip_read_header(struct archive_read *a,
* 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)
+ __archive_read_consume(a, 4);
+ if ((h = __archive_read_ahead(a, 4, NULL)) == NULL)
return (ARCHIVE_FATAL);
signature = (const char *)h;
if (signature[0] != 'P' || signature[1] != 'K') {
@@ -381,7 +380,7 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
const struct zip_file_header *p;
const void *h;
- if ((p = __archive_read_ahead(a, sizeof *p)) == NULL) {
+ if ((p = __archive_read_ahead(a, sizeof *p, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
@@ -408,11 +407,11 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
zip->uncompressed_size = archive_le32dec(p->uncompressed_size);
zip->compressed_size = archive_le32dec(p->compressed_size);
- (a->decompressor->consume)(a, sizeof(struct zip_file_header));
+ __archive_read_consume(a, sizeof(struct zip_file_header));
/* Read the filename. */
- if ((h = __archive_read_ahead(a, zip->filename_length)) == NULL) {
+ if ((h = __archive_read_ahead(a, zip->filename_length, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
@@ -420,7 +419,7 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
if (archive_string_ensure(&zip->pathname, zip->filename_length) == NULL)
__archive_errx(1, "Out of memory");
archive_strncpy(&zip->pathname, h, zip->filename_length);
- (a->decompressor->consume)(a, zip->filename_length);
+ __archive_read_consume(a, zip->filename_length);
archive_entry_set_pathname(entry, zip->pathname.s);
if (zip->pathname.s[archive_strlen(&zip->pathname) - 1] == '/')
@@ -429,13 +428,13 @@ zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
zip->mode = AE_IFREG | 0777;
/* Read the extra data. */
- if ((h = __archive_read_ahead(a, zip->extra_length)) == NULL) {
+ if ((h = __archive_read_ahead(a, zip->extra_length, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
}
process_extra(h, zip);
- (a->decompressor->consume)(a, zip->extra_length);
+ __archive_read_consume(a, zip->extra_length);
/* Populate some additional entry fields: */
archive_entry_set_mode(entry, zip->mode);
@@ -504,7 +503,7 @@ archive_read_format_zip_read_data(struct archive_read *a,
if (zip->flags & ZIP_LENGTH_AT_END) {
const char *p;
- if ((p = __archive_read_ahead(a, 16)) == NULL) {
+ if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP end-of-file record");
@@ -513,7 +512,7 @@ archive_read_format_zip_read_data(struct archive_read *a,
zip->crc32 = archive_le32dec(p + 4);
zip->compressed_size = archive_le32dec(p + 8);
zip->uncompressed_size = archive_le32dec(p + 12);
- (a->decompressor->consume)(a, 16);
+ __archive_read_consume(a, 16);
}
/* Check file size, CRC against these values. */
@@ -622,7 +621,7 @@ zip_read_data_none(struct archive_read *a, const void **buff,
* available bytes; asking for more than that forces the
* decompressor to combine reads by copying data.
*/
- bytes_avail = (a->decompressor->read_ahead)(a, buff, 1);
+ *buff = __archive_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file data");
@@ -630,7 +629,7 @@ zip_read_data_none(struct archive_read *a, const void **buff,
}
if (bytes_avail > zip->entry_bytes_remaining)
bytes_avail = zip->entry_bytes_remaining;
- (a->decompressor->consume)(a, bytes_avail);
+ __archive_read_consume(a, bytes_avail);
*size = bytes_avail;
*offset = zip->entry_offset;
zip->entry_offset += *size;
@@ -688,7 +687,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
* available bytes; asking for more than that forces the
* decompressor to combine reads by copying data.
*/
- bytes_avail = (a->decompressor->read_ahead)(a, &compressed_buff, 1);
+ compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
if (bytes_avail <= 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file body");
@@ -727,7 +726,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
/* Consume as much as the compressor actually used. */
bytes_avail = zip->stream.total_in;
- (a->decompressor->consume)(a, bytes_avail);
+ __archive_read_consume(a, bytes_avail);
zip->entry_bytes_remaining -= bytes_avail;
zip->entry_compressed_bytes_read += bytes_avail;
@@ -784,7 +783,7 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
* If the length is at the beginning, we can skip the
* compressed data much more quickly.
*/
- bytes_skipped = (a->decompressor->skip)(a, zip->entry_bytes_remaining);
+ bytes_skipped = __archive_read_skip(a, zip->entry_bytes_remaining);
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);