From f81da3e58463558f4efc2a76aac410e9fc03c096 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sat, 3 Mar 2007 07:37:37 +0000 Subject: libarchive 2.0 * libarchive_test program exercises many of the core features * Refactored old "read_extract" into new "archive_write_disk", which uses archive_write methods to put entries onto disk. In particular, you can now use archive_write_disk to create objects on disk without having an archive available. * Pushed some security checks from bsdtar down into libarchive, where they can be better optimized. * Rearchitected the logic for creating objects on disk to reduce the number of system calls. Several common cases now use a minimum number of system calls. * Virtualized some internal interfaces to provide a clearer separation of read and write handling and make it simpler to override key methods. * New "empty" format reader. * Corrected return types (this ABI breakage required the "2.0" version bump) * Many bug fixes. --- lib/libarchive/archive_read_support_format_zip.c | 108 ++++++++++++----------- 1 file changed, 58 insertions(+), 50 deletions(-) (limited to 'lib/libarchive/archive_read_support_format_zip.c') diff --git a/lib/libarchive/archive_read_support_format_zip.c b/lib/libarchive/archive_read_support_format_zip.c index 5807e560d91e..f15eba0585f0 100644 --- a/lib/libarchive/archive_read_support_format_zip.c +++ b/lib/libarchive/archive_read_support_format_zip.c @@ -44,15 +44,16 @@ __FBSDID("$FreeBSD$"); #include "archive.h" #include "archive_entry.h" #include "archive_private.h" +#include "archive_read_private.h" struct zip { /* entry_bytes_remaining is the number of bytes we expect. */ - off_t entry_bytes_remaining; - off_t entry_offset; + int64_t entry_bytes_remaining; + int64_t entry_offset; /* These count the number of bytes actually read for the entry. */ - off_t entry_compressed_bytes_read; - off_t entry_uncompressed_bytes_read; + int64_t entry_compressed_bytes_read; + int64_t entry_uncompressed_bytes_read; unsigned version; unsigned system; @@ -74,8 +75,8 @@ struct zip { long crc32; ssize_t filename_length; ssize_t extra_length; - off_t uncompressed_size; - off_t compressed_size; + int64_t uncompressed_size; + int64_t compressed_size; unsigned char *uncompressed_buffer; size_t uncompressed_buffer_size; @@ -115,36 +116,40 @@ static const char *compression_names[] = { "deflation" }; -static int archive_read_format_zip_bid(struct archive *); -static int archive_read_format_zip_cleanup(struct archive *); -static int archive_read_format_zip_read_data(struct archive *, +static int archive_read_format_zip_bid(struct archive_read *); +static int archive_read_format_zip_cleanup(struct archive_read *); +static int archive_read_format_zip_read_data(struct archive_read *, const void **, size_t *, off_t *); -static int archive_read_format_zip_read_data_skip(struct archive *a); -static int archive_read_format_zip_read_header(struct archive *, +static int archive_read_format_zip_read_data_skip(struct archive_read *a); +static int archive_read_format_zip_read_header(struct archive_read *, struct archive_entry *); static int i2(const char *); static int i4(const char *); static unsigned int u2(const char *); static unsigned int u4(const char *); static uint64_t u8(const char *); -static int zip_read_data_deflate(struct archive *a, const void **buff, +static int zip_read_data_deflate(struct archive_read *a, const void **buff, size_t *size, off_t *offset); -static int zip_read_data_none(struct archive *a, const void **buff, +static int zip_read_data_none(struct archive_read *a, const void **buff, size_t *size, off_t *offset); -static int zip_read_file_header(struct archive *a, +static int zip_read_file_header(struct archive_read *a, struct archive_entry *entry, struct zip *zip); static time_t zip_time(const char *); static void process_extra(const void* extra, struct zip* zip); +/* Largest 32-bit unsigned value, stored in a 64-bit constant. */ +static const uint64_t max_uint32 = (((uint64_t)1) << 32) - 1; + int -archive_read_support_format_zip(struct archive *a) +archive_read_support_format_zip(struct archive *_a) { + struct archive_read *a = (struct archive_read *)_a; struct zip *zip; int r; zip = (struct zip *)malloc(sizeof(*zip)); if (zip == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate zip data"); + archive_set_error(&a->archive, ENOMEM, "Can't allocate zip data"); return (ARCHIVE_FATAL); } memset(zip, 0, sizeof(*zip)); @@ -164,14 +169,14 @@ archive_read_support_format_zip(struct archive *a) static int -archive_read_format_zip_bid(struct archive *a) +archive_read_format_zip_bid(struct archive_read *a) { int bytes_read; int bid = 0; const void *h; const char *p; - if (a->archive_format == ARCHIVE_FORMAT_ZIP) + if (a->archive.archive_format == ARCHIVE_FORMAT_ZIP) bid += 1; bytes_read = (a->compression_read_ahead)(a, &h, 4); @@ -194,7 +199,7 @@ archive_read_format_zip_bid(struct archive *a) } static int -archive_read_format_zip_read_header(struct archive *a, +archive_read_format_zip_read_header(struct archive_read *a, struct archive_entry *entry) { int bytes_read; @@ -202,9 +207,9 @@ archive_read_format_zip_read_header(struct archive *a, const char *signature; struct zip *zip; - a->archive_format = ARCHIVE_FORMAT_ZIP; - if (a->archive_format_name == NULL) - a->archive_format_name = "ZIP"; + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "ZIP"; zip = (struct zip *)*(a->pformat_data); zip->decompress_init = 0; @@ -218,7 +223,7 @@ archive_read_format_zip_read_header(struct archive *a, signature = (const char *)h; if (signature[0] != 'P' || signature[1] != 'K') { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad ZIP file"); return (ARCHIVE_FATAL); } @@ -243,19 +248,19 @@ archive_read_format_zip_read_header(struct archive *a, * We should never encounter this record here; * see ZIP_LENGTH_AT_END handling below for details. */ - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Bad ZIP file: Unexpected end-of-entry record"); return (ARCHIVE_FATAL); } - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Damaged ZIP file or unsupported format variant (%d,%d)", signature[2], signature[3]); return (ARCHIVE_FATAL); } int -zip_read_file_header(struct archive *a, struct archive_entry *entry, +zip_read_file_header(struct archive_read *a, struct archive_entry *entry, struct zip *zip) { const struct zip_file_header *p; @@ -266,7 +271,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry, bytes_read = (a->compression_read_ahead)(a, &h, sizeof(struct zip_file_header)); if (bytes_read < (int)sizeof(struct zip_file_header)) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_FATAL); } @@ -299,7 +304,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry, /* Read the filename. */ bytes_read = (a->compression_read_ahead)(a, &h, zip->filename_length); if (bytes_read < zip->filename_length) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_FATAL); } @@ -316,7 +321,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry, /* Read the extra data. */ bytes_read = (a->compression_read_ahead)(a, &h, zip->extra_length); if (bytes_read < zip->extra_length) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file header"); return (ARCHIVE_FATAL); } @@ -341,7 +346,7 @@ zip_read_file_header(struct archive *a, struct archive_entry *entry, sprintf(zip->format_name, "ZIP %d.%d (%s)", zip->version / 10, zip->version % 10, zip->compression_name); - a->archive_format_name = zip->format_name; + a->archive.archive_format_name = zip->format_name; return (ARCHIVE_OK); } @@ -368,7 +373,7 @@ zip_time(const char *p) } static int -archive_read_format_zip_read_data(struct archive *a, +archive_read_format_zip_read_data(struct archive_read *a, const void **buff, size_t *size, off_t *offset) { int r; @@ -388,7 +393,7 @@ archive_read_format_zip_read_data(struct archive *a, int bytes_read = (a->compression_read_ahead)(a, &h, 16); if (bytes_read < 16) { - archive_set_error(a, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP end-of-file record"); return (ARCHIVE_FATAL); @@ -402,19 +407,21 @@ archive_read_format_zip_read_data(struct archive *a, /* Check file size, CRC against these values. */ if (zip->compressed_size != zip->entry_compressed_bytes_read) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "ZIP compressed data is wrong size"); return (ARCHIVE_WARN); } - if (zip->uncompressed_size != zip->entry_uncompressed_bytes_read) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, + /* Size field only stores the lower 32 bits of the actual size. */ + if ((zip->uncompressed_size & max_uint32) + != (zip->entry_uncompressed_bytes_read & max_uint32)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "ZIP uncompressed data is wrong size"); return (ARCHIVE_WARN); } /* TODO: Compute CRC. */ /* if (zip->crc32 != zip->entry_crc32_calculated) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "ZIP data CRC error"); return (ARCHIVE_WARN); } @@ -437,7 +444,7 @@ archive_read_format_zip_read_data(struct archive *a, *size = 0; *offset = 0; /* Return a warning. */ - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unsupported ZIP compression method (%s)", zip->compression_name); if (zip->flags & ZIP_LENGTH_AT_END) { @@ -472,7 +479,7 @@ archive_read_format_zip_read_data(struct archive *a, * zip->end_of_entry if it consumes all of the data. */ static int -zip_read_data_none(struct archive *a, const void **buff, +zip_read_data_none(struct archive_read *a, const void **buff, size_t *size, off_t *offset) { struct zip *zip; @@ -495,7 +502,7 @@ zip_read_data_none(struct archive *a, const void **buff, */ bytes_avail = (a->compression_read_ahead)(a, buff, 1); if (bytes_avail <= 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file data"); return (ARCHIVE_FATAL); } @@ -513,7 +520,7 @@ zip_read_data_none(struct archive *a, const void **buff, #ifdef HAVE_ZLIB_H static int -zip_read_data_deflate(struct archive *a, const void **buff, +zip_read_data_deflate(struct archive_read *a, const void **buff, size_t *size, off_t *offset) { struct zip *zip; @@ -529,7 +536,7 @@ zip_read_data_deflate(struct archive *a, const void **buff, zip->uncompressed_buffer = (unsigned char *)malloc(zip->uncompressed_buffer_size); if (zip->uncompressed_buffer == NULL) { - archive_set_error(a, ENOMEM, + archive_set_error(&a->archive, ENOMEM, "No memory for ZIP decompression"); return (ARCHIVE_FATAL); } @@ -540,7 +547,7 @@ zip_read_data_deflate(struct archive *a, const void **buff, r = inflateInit2(&zip->stream, -15 /* Don't check for zlib header */); if (r != Z_OK) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't initialize ZIP decompression."); return (ARCHIVE_FATAL); } @@ -555,7 +562,7 @@ zip_read_data_deflate(struct archive *a, const void **buff, */ bytes_avail = (a->compression_read_ahead)(a, &compressed_buff, 1); if (bytes_avail <= 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file body"); return (ARCHIVE_FATAL); } @@ -581,11 +588,11 @@ zip_read_data_deflate(struct archive *a, const void **buff, zip->end_of_entry = 1; break; case Z_MEM_ERROR: - archive_set_error(a, ENOMEM, + archive_set_error(&a->archive, ENOMEM, "Out of memory for ZIP decompression"); return (ARCHIVE_FATAL); default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "ZIP decompression failed (%d)", r); return (ARCHIVE_FATAL); } @@ -605,20 +612,20 @@ zip_read_data_deflate(struct archive *a, const void **buff, } #else static int -zip_read_data_deflate(struct archive *a, const void **buff, +zip_read_data_deflate(struct archive_read *a, const void **buff, size_t *size, off_t *offset) { *buff = NULL; *size = 0; *offset = 0; - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "libarchive compiled without deflate support (no libz)"); return (ARCHIVE_FATAL); } #endif static int -archive_read_format_zip_read_data_skip(struct archive *a) +archive_read_format_zip_read_data_skip(struct archive_read *a) { struct zip *zip; const void *buff = NULL; @@ -648,7 +655,8 @@ archive_read_format_zip_read_data_skip(struct archive *a) while (zip->entry_bytes_remaining > 0) { bytes_avail = (a->compression_read_ahead)(a, &buff, 1); if (bytes_avail <= 0) { - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file body"); return (ARCHIVE_FATAL); } @@ -663,7 +671,7 @@ archive_read_format_zip_read_data_skip(struct archive *a) } static int -archive_read_format_zip_cleanup(struct archive *a) +archive_read_format_zip_cleanup(struct archive_read *a) { struct zip *zip; -- cgit v1.3