diff options
| author | Tim Kientzle <kientzle@FreeBSD.org> | 2008-12-06 06:45:15 +0000 |
|---|---|---|
| committer | Tim Kientzle <kientzle@FreeBSD.org> | 2008-12-06 06:45:15 +0000 |
| commit | b1ff9c25b85752421491eb42f56c4cf65f451f98 (patch) | |
| tree | 07033908f13a75f6e70696ff70c73d1160bb8e74 /lib/libarchive/archive_read_support_format_zip.c | |
| parent | 72a4c788ff73a4cbfc61c85335d8d42004822e03 (diff) | |
Notes
Diffstat (limited to 'lib/libarchive/archive_read_support_format_zip.c')
| -rw-r--r-- | lib/libarchive/archive_read_support_format_zip.c | 105 |
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); |
