160b4ad09SPeter Avalos /*- 260b4ad09SPeter Avalos * Copyright (c) 2004 Tim Kientzle 360b4ad09SPeter Avalos * All rights reserved. 460b4ad09SPeter Avalos * 560b4ad09SPeter Avalos * Redistribution and use in source and binary forms, with or without 660b4ad09SPeter Avalos * modification, are permitted provided that the following conditions 760b4ad09SPeter Avalos * are met: 860b4ad09SPeter Avalos * 1. Redistributions of source code must retain the above copyright 960b4ad09SPeter Avalos * notice, this list of conditions and the following disclaimer. 1060b4ad09SPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright 1160b4ad09SPeter Avalos * notice, this list of conditions and the following disclaimer in the 1260b4ad09SPeter Avalos * documentation and/or other materials provided with the distribution. 1360b4ad09SPeter Avalos * 1460b4ad09SPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 1560b4ad09SPeter Avalos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1660b4ad09SPeter Avalos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1760b4ad09SPeter Avalos * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 1860b4ad09SPeter Avalos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1960b4ad09SPeter Avalos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2060b4ad09SPeter Avalos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2160b4ad09SPeter Avalos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2260b4ad09SPeter Avalos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2360b4ad09SPeter Avalos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2460b4ad09SPeter Avalos */ 2560b4ad09SPeter Avalos 2660b4ad09SPeter Avalos #include "archive_platform.h" 27*8029ab02SPeter Avalos __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_zip.c,v 1.28 2008/12/06 06:45:15 kientzle Exp $"); 2860b4ad09SPeter Avalos 2960b4ad09SPeter Avalos #ifdef HAVE_ERRNO_H 3060b4ad09SPeter Avalos #include <errno.h> 3160b4ad09SPeter Avalos #endif 3260b4ad09SPeter Avalos #include <stdio.h> 3360b4ad09SPeter Avalos #ifdef HAVE_STDLIB_H 3460b4ad09SPeter Avalos #include <stdlib.h> 3560b4ad09SPeter Avalos #endif 3660b4ad09SPeter Avalos #include <time.h> 3760b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H 3860b4ad09SPeter Avalos #include <zlib.h> 39*8029ab02SPeter Avalos #else 40*8029ab02SPeter Avalos /* Hmmm... This is necessary, but means that we can't correctly extract 41*8029ab02SPeter Avalos * even uncompressed entries on platforms that lack zlib. */ 42*8029ab02SPeter Avalos #define crc32(crc, buf, len) (unsigned long)0 4360b4ad09SPeter Avalos #endif 4460b4ad09SPeter Avalos 4560b4ad09SPeter Avalos #include "archive.h" 4660b4ad09SPeter Avalos #include "archive_entry.h" 4760b4ad09SPeter Avalos #include "archive_private.h" 4860b4ad09SPeter Avalos #include "archive_read_private.h" 4960b4ad09SPeter Avalos #include "archive_endian.h" 5060b4ad09SPeter Avalos 5160b4ad09SPeter Avalos struct zip { 5260b4ad09SPeter Avalos /* entry_bytes_remaining is the number of bytes we expect. */ 5360b4ad09SPeter Avalos int64_t entry_bytes_remaining; 5460b4ad09SPeter Avalos int64_t entry_offset; 5560b4ad09SPeter Avalos 5660b4ad09SPeter Avalos /* These count the number of bytes actually read for the entry. */ 5760b4ad09SPeter Avalos int64_t entry_compressed_bytes_read; 5860b4ad09SPeter Avalos int64_t entry_uncompressed_bytes_read; 5960b4ad09SPeter Avalos 60*8029ab02SPeter Avalos /* Running CRC32 of the decompressed data */ 61*8029ab02SPeter Avalos unsigned long entry_crc32; 62*8029ab02SPeter Avalos 6360b4ad09SPeter Avalos unsigned version; 6460b4ad09SPeter Avalos unsigned system; 6560b4ad09SPeter Avalos unsigned flags; 6660b4ad09SPeter Avalos unsigned compression; 6760b4ad09SPeter Avalos const char * compression_name; 6860b4ad09SPeter Avalos time_t mtime; 6960b4ad09SPeter Avalos time_t ctime; 7060b4ad09SPeter Avalos time_t atime; 7160b4ad09SPeter Avalos mode_t mode; 7260b4ad09SPeter Avalos uid_t uid; 7360b4ad09SPeter Avalos gid_t gid; 7460b4ad09SPeter Avalos 7560b4ad09SPeter Avalos /* Flags to mark progress of decompression. */ 7660b4ad09SPeter Avalos char decompress_init; 7760b4ad09SPeter Avalos char end_of_entry; 7860b4ad09SPeter Avalos 79*8029ab02SPeter Avalos unsigned long crc32; 8060b4ad09SPeter Avalos ssize_t filename_length; 8160b4ad09SPeter Avalos ssize_t extra_length; 8260b4ad09SPeter Avalos int64_t uncompressed_size; 8360b4ad09SPeter Avalos int64_t compressed_size; 8460b4ad09SPeter Avalos 8560b4ad09SPeter Avalos unsigned char *uncompressed_buffer; 8660b4ad09SPeter Avalos size_t uncompressed_buffer_size; 8760b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H 8860b4ad09SPeter Avalos z_stream stream; 8960b4ad09SPeter Avalos char stream_valid; 9060b4ad09SPeter Avalos #endif 9160b4ad09SPeter Avalos 9260b4ad09SPeter Avalos struct archive_string pathname; 9360b4ad09SPeter Avalos struct archive_string extra; 9460b4ad09SPeter Avalos char format_name[64]; 9560b4ad09SPeter Avalos }; 9660b4ad09SPeter Avalos 9760b4ad09SPeter Avalos #define ZIP_LENGTH_AT_END 8 9860b4ad09SPeter Avalos 9960b4ad09SPeter Avalos struct zip_file_header { 10060b4ad09SPeter Avalos char signature[4]; 10160b4ad09SPeter Avalos char version[2]; 10260b4ad09SPeter Avalos char flags[2]; 10360b4ad09SPeter Avalos char compression[2]; 10460b4ad09SPeter Avalos char timedate[4]; 10560b4ad09SPeter Avalos char crc32[4]; 10660b4ad09SPeter Avalos char compressed_size[4]; 10760b4ad09SPeter Avalos char uncompressed_size[4]; 10860b4ad09SPeter Avalos char filename_length[2]; 10960b4ad09SPeter Avalos char extra_length[2]; 11060b4ad09SPeter Avalos }; 11160b4ad09SPeter Avalos 11260b4ad09SPeter Avalos static const char *compression_names[] = { 11360b4ad09SPeter Avalos "uncompressed", 11460b4ad09SPeter Avalos "shrinking", 11560b4ad09SPeter Avalos "reduced-1", 11660b4ad09SPeter Avalos "reduced-2", 11760b4ad09SPeter Avalos "reduced-3", 11860b4ad09SPeter Avalos "reduced-4", 11960b4ad09SPeter Avalos "imploded", 12060b4ad09SPeter Avalos "reserved", 12160b4ad09SPeter Avalos "deflation" 12260b4ad09SPeter Avalos }; 12360b4ad09SPeter Avalos 12460b4ad09SPeter Avalos static int archive_read_format_zip_bid(struct archive_read *); 12560b4ad09SPeter Avalos static int archive_read_format_zip_cleanup(struct archive_read *); 12660b4ad09SPeter Avalos static int archive_read_format_zip_read_data(struct archive_read *, 12760b4ad09SPeter Avalos const void **, size_t *, off_t *); 12860b4ad09SPeter Avalos static int archive_read_format_zip_read_data_skip(struct archive_read *a); 12960b4ad09SPeter Avalos static int archive_read_format_zip_read_header(struct archive_read *, 13060b4ad09SPeter Avalos struct archive_entry *); 13160b4ad09SPeter Avalos static int zip_read_data_deflate(struct archive_read *a, const void **buff, 13260b4ad09SPeter Avalos size_t *size, off_t *offset); 13360b4ad09SPeter Avalos static int zip_read_data_none(struct archive_read *a, const void **buff, 13460b4ad09SPeter Avalos size_t *size, off_t *offset); 13560b4ad09SPeter Avalos static int zip_read_file_header(struct archive_read *a, 13660b4ad09SPeter Avalos struct archive_entry *entry, struct zip *zip); 13760b4ad09SPeter Avalos static time_t zip_time(const char *); 13860b4ad09SPeter Avalos static void process_extra(const void* extra, struct zip* zip); 13960b4ad09SPeter Avalos 14060b4ad09SPeter Avalos int 14160b4ad09SPeter Avalos archive_read_support_format_zip(struct archive *_a) 14260b4ad09SPeter Avalos { 14360b4ad09SPeter Avalos struct archive_read *a = (struct archive_read *)_a; 14460b4ad09SPeter Avalos struct zip *zip; 14560b4ad09SPeter Avalos int r; 14660b4ad09SPeter Avalos 14760b4ad09SPeter Avalos zip = (struct zip *)malloc(sizeof(*zip)); 14860b4ad09SPeter Avalos if (zip == NULL) { 14960b4ad09SPeter Avalos archive_set_error(&a->archive, ENOMEM, "Can't allocate zip data"); 15060b4ad09SPeter Avalos return (ARCHIVE_FATAL); 15160b4ad09SPeter Avalos } 15260b4ad09SPeter Avalos memset(zip, 0, sizeof(*zip)); 15360b4ad09SPeter Avalos 15460b4ad09SPeter Avalos r = __archive_read_register_format(a, 15560b4ad09SPeter Avalos zip, 156*8029ab02SPeter Avalos "zip", 15760b4ad09SPeter Avalos archive_read_format_zip_bid, 158*8029ab02SPeter Avalos NULL, 15960b4ad09SPeter Avalos archive_read_format_zip_read_header, 16060b4ad09SPeter Avalos archive_read_format_zip_read_data, 16160b4ad09SPeter Avalos archive_read_format_zip_read_data_skip, 16260b4ad09SPeter Avalos archive_read_format_zip_cleanup); 16360b4ad09SPeter Avalos 16460b4ad09SPeter Avalos if (r != ARCHIVE_OK) 16560b4ad09SPeter Avalos free(zip); 16660b4ad09SPeter Avalos return (ARCHIVE_OK); 16760b4ad09SPeter Avalos } 16860b4ad09SPeter Avalos 16960b4ad09SPeter Avalos 17060b4ad09SPeter Avalos static int 17160b4ad09SPeter Avalos archive_read_format_zip_bid(struct archive_read *a) 17260b4ad09SPeter Avalos { 17360b4ad09SPeter Avalos const char *p; 17460b4ad09SPeter Avalos const void *buff; 175*8029ab02SPeter Avalos ssize_t bytes_avail, offset; 17660b4ad09SPeter Avalos 177*8029ab02SPeter Avalos if ((p = __archive_read_ahead(a, 4, NULL)) == NULL) 17860b4ad09SPeter Avalos return (-1); 17960b4ad09SPeter Avalos 18060b4ad09SPeter Avalos /* 18160b4ad09SPeter Avalos * Bid of 30 here is: 16 bits for "PK", 18260b4ad09SPeter Avalos * next 16-bit field has four options (-2 bits). 18360b4ad09SPeter Avalos * 16 + 16-2 = 30. 18460b4ad09SPeter Avalos */ 18560b4ad09SPeter Avalos if (p[0] == 'P' && p[1] == 'K') { 18660b4ad09SPeter Avalos if ((p[2] == '\001' && p[3] == '\002') 18760b4ad09SPeter Avalos || (p[2] == '\003' && p[3] == '\004') 18860b4ad09SPeter Avalos || (p[2] == '\005' && p[3] == '\006') 18960b4ad09SPeter Avalos || (p[2] == '\007' && p[3] == '\010') 19060b4ad09SPeter Avalos || (p[2] == '0' && p[3] == '0')) 19160b4ad09SPeter Avalos return (30); 19260b4ad09SPeter Avalos } 19360b4ad09SPeter Avalos 19460b4ad09SPeter Avalos /* 19560b4ad09SPeter Avalos * Attempt to handle self-extracting archives 19660b4ad09SPeter Avalos * by noting a PE header and searching forward 197*8029ab02SPeter Avalos * up to 128k for a 'PK\003\004' marker. 19860b4ad09SPeter Avalos */ 19960b4ad09SPeter Avalos if (p[0] == 'M' && p[1] == 'Z') { 20060b4ad09SPeter Avalos /* 201*8029ab02SPeter Avalos * TODO: Optimize by initializing 'offset' to an 202*8029ab02SPeter Avalos * estimate of the likely start of the archive data 203*8029ab02SPeter Avalos * based on values in the PE header. Note that we 204*8029ab02SPeter Avalos * don't need to be exact, but we mustn't skip too 205*8029ab02SPeter Avalos * far. The search below will compensate if we 206*8029ab02SPeter Avalos * undershoot. 20760b4ad09SPeter Avalos */ 208*8029ab02SPeter Avalos offset = 0; 209*8029ab02SPeter Avalos while (offset < 124000) { 210*8029ab02SPeter Avalos /* Get 4k of data beyond where we stopped. */ 211*8029ab02SPeter Avalos buff = __archive_read_ahead(a, offset + 4096, 212*8029ab02SPeter Avalos &bytes_avail); 213*8029ab02SPeter Avalos if (bytes_avail < offset + 1) 214*8029ab02SPeter Avalos break; 215*8029ab02SPeter Avalos p = (const char *)buff + offset; 216*8029ab02SPeter Avalos while (p + 9 < (const char *)buff + bytes_avail) { 217*8029ab02SPeter Avalos if (p[0] == 'P' && p[1] == 'K' /* signature */ 21860b4ad09SPeter Avalos && p[2] == 3 && p[3] == 4 /* File entry */ 21960b4ad09SPeter Avalos && p[8] == 8 /* compression == deflate */ 22060b4ad09SPeter Avalos && p[9] == 0 /* High byte of compression */ 22160b4ad09SPeter Avalos ) 22260b4ad09SPeter Avalos { 22360b4ad09SPeter Avalos return (30); 22460b4ad09SPeter Avalos } 22560b4ad09SPeter Avalos ++p; 22660b4ad09SPeter Avalos } 227*8029ab02SPeter Avalos offset = p - (const char *)buff; 228*8029ab02SPeter Avalos } 22960b4ad09SPeter Avalos } 23060b4ad09SPeter Avalos 23160b4ad09SPeter Avalos return (0); 23260b4ad09SPeter Avalos } 23360b4ad09SPeter Avalos 23460b4ad09SPeter Avalos /* 23560b4ad09SPeter Avalos * Search forward for a "PK\003\004" file header. This handles the 23660b4ad09SPeter Avalos * case of self-extracting archives, where there is an executable 23760b4ad09SPeter Avalos * prepended to the ZIP archive. 23860b4ad09SPeter Avalos */ 23960b4ad09SPeter Avalos static int 24060b4ad09SPeter Avalos skip_sfx(struct archive_read *a) 24160b4ad09SPeter Avalos { 24260b4ad09SPeter Avalos const void *h; 24360b4ad09SPeter Avalos const char *p, *q; 244*8029ab02SPeter Avalos size_t skip; 245*8029ab02SPeter Avalos ssize_t bytes; 24660b4ad09SPeter Avalos 24760b4ad09SPeter Avalos /* 24860b4ad09SPeter Avalos * TODO: We should be able to skip forward by a bunch 24960b4ad09SPeter Avalos * by lifting some values from the PE header. We don't 25060b4ad09SPeter Avalos * need to be exact (we're still going to search forward 25160b4ad09SPeter Avalos * to find the header), but it will speed things up and 25260b4ad09SPeter Avalos * reduce the chance of a false positive. 25360b4ad09SPeter Avalos */ 25460b4ad09SPeter Avalos for (;;) { 255*8029ab02SPeter Avalos h = __archive_read_ahead(a, 4, &bytes); 25660b4ad09SPeter Avalos if (bytes < 4) 25760b4ad09SPeter Avalos return (ARCHIVE_FATAL); 25860b4ad09SPeter Avalos p = h; 25960b4ad09SPeter Avalos q = p + bytes; 26060b4ad09SPeter Avalos 26160b4ad09SPeter Avalos /* 26260b4ad09SPeter Avalos * Scan ahead until we find something that looks 26360b4ad09SPeter Avalos * like the zip header. 26460b4ad09SPeter Avalos */ 26560b4ad09SPeter Avalos while (p + 4 < q) { 26660b4ad09SPeter Avalos switch (p[3]) { 26760b4ad09SPeter Avalos case '\004': 26860b4ad09SPeter Avalos /* TODO: Additional verification here. */ 26960b4ad09SPeter Avalos if (memcmp("PK\003\004", p, 4) == 0) { 27060b4ad09SPeter Avalos skip = p - (const char *)h; 271*8029ab02SPeter Avalos __archive_read_consume(a, skip); 27260b4ad09SPeter Avalos return (ARCHIVE_OK); 27360b4ad09SPeter Avalos } 27460b4ad09SPeter Avalos p += 4; 27560b4ad09SPeter Avalos break; 27660b4ad09SPeter Avalos case '\003': p += 1; break; 27760b4ad09SPeter Avalos case 'K': p += 2; break; 27860b4ad09SPeter Avalos case 'P': p += 3; break; 27960b4ad09SPeter Avalos default: p += 4; break; 28060b4ad09SPeter Avalos } 28160b4ad09SPeter Avalos } 28260b4ad09SPeter Avalos skip = p - (const char *)h; 283*8029ab02SPeter Avalos __archive_read_consume(a, skip); 28460b4ad09SPeter Avalos } 28560b4ad09SPeter Avalos } 28660b4ad09SPeter Avalos 28760b4ad09SPeter Avalos static int 28860b4ad09SPeter Avalos archive_read_format_zip_read_header(struct archive_read *a, 28960b4ad09SPeter Avalos struct archive_entry *entry) 29060b4ad09SPeter Avalos { 29160b4ad09SPeter Avalos const void *h; 29260b4ad09SPeter Avalos const char *signature; 29360b4ad09SPeter Avalos struct zip *zip; 29460b4ad09SPeter Avalos int r = ARCHIVE_OK, r1; 29560b4ad09SPeter Avalos 29660b4ad09SPeter Avalos a->archive.archive_format = ARCHIVE_FORMAT_ZIP; 29760b4ad09SPeter Avalos if (a->archive.archive_format_name == NULL) 29860b4ad09SPeter Avalos a->archive.archive_format_name = "ZIP"; 29960b4ad09SPeter Avalos 30060b4ad09SPeter Avalos zip = (struct zip *)(a->format->data); 30160b4ad09SPeter Avalos zip->decompress_init = 0; 30260b4ad09SPeter Avalos zip->end_of_entry = 0; 30360b4ad09SPeter Avalos zip->entry_uncompressed_bytes_read = 0; 30460b4ad09SPeter Avalos zip->entry_compressed_bytes_read = 0; 305*8029ab02SPeter Avalos zip->entry_crc32 = crc32(0, NULL, 0); 306*8029ab02SPeter Avalos if ((h = __archive_read_ahead(a, 4, NULL)) == NULL) 30760b4ad09SPeter Avalos return (ARCHIVE_FATAL); 30860b4ad09SPeter Avalos 30960b4ad09SPeter Avalos signature = (const char *)h; 31060b4ad09SPeter Avalos if (signature[0] == 'M' && signature[1] == 'Z') { 31160b4ad09SPeter Avalos /* This is an executable? Must be self-extracting... */ 31260b4ad09SPeter Avalos r = skip_sfx(a); 31360b4ad09SPeter Avalos if (r < ARCHIVE_WARN) 31460b4ad09SPeter Avalos return (r); 315*8029ab02SPeter Avalos if ((h = __archive_read_ahead(a, 4, NULL)) == NULL) 31660b4ad09SPeter Avalos return (ARCHIVE_FATAL); 31760b4ad09SPeter Avalos signature = (const char *)h; 31860b4ad09SPeter Avalos } 31960b4ad09SPeter Avalos 32060b4ad09SPeter Avalos if (signature[0] != 'P' || signature[1] != 'K') { 32160b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 32260b4ad09SPeter Avalos "Bad ZIP file"); 32360b4ad09SPeter Avalos return (ARCHIVE_FATAL); 32460b4ad09SPeter Avalos } 32560b4ad09SPeter Avalos 32660b4ad09SPeter Avalos /* 32760b4ad09SPeter Avalos * "PK00" signature is used for "split" archives that 32860b4ad09SPeter Avalos * only have a single segment. This means we can just 32960b4ad09SPeter Avalos * skip the PK00; the first real file header should follow. 33060b4ad09SPeter Avalos */ 33160b4ad09SPeter Avalos if (signature[2] == '0' && signature[3] == '0') { 332*8029ab02SPeter Avalos __archive_read_consume(a, 4); 333*8029ab02SPeter Avalos if ((h = __archive_read_ahead(a, 4, NULL)) == NULL) 33460b4ad09SPeter Avalos return (ARCHIVE_FATAL); 33560b4ad09SPeter Avalos signature = (const char *)h; 33660b4ad09SPeter Avalos if (signature[0] != 'P' || signature[1] != 'K') { 33760b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 33860b4ad09SPeter Avalos "Bad ZIP file"); 33960b4ad09SPeter Avalos return (ARCHIVE_FATAL); 34060b4ad09SPeter Avalos } 34160b4ad09SPeter Avalos } 34260b4ad09SPeter Avalos 34360b4ad09SPeter Avalos if (signature[2] == '\001' && signature[3] == '\002') { 34460b4ad09SPeter Avalos /* Beginning of central directory. */ 34560b4ad09SPeter Avalos return (ARCHIVE_EOF); 34660b4ad09SPeter Avalos } 34760b4ad09SPeter Avalos 34860b4ad09SPeter Avalos if (signature[2] == '\003' && signature[3] == '\004') { 34960b4ad09SPeter Avalos /* Regular file entry. */ 35060b4ad09SPeter Avalos r1 = zip_read_file_header(a, entry, zip); 35160b4ad09SPeter Avalos if (r1 != ARCHIVE_OK) 35260b4ad09SPeter Avalos return (r1); 35360b4ad09SPeter Avalos return (r); 35460b4ad09SPeter Avalos } 35560b4ad09SPeter Avalos 35660b4ad09SPeter Avalos if (signature[2] == '\005' && signature[3] == '\006') { 35760b4ad09SPeter Avalos /* End-of-archive record. */ 35860b4ad09SPeter Avalos return (ARCHIVE_EOF); 35960b4ad09SPeter Avalos } 36060b4ad09SPeter Avalos 36160b4ad09SPeter Avalos if (signature[2] == '\007' && signature[3] == '\010') { 36260b4ad09SPeter Avalos /* 36360b4ad09SPeter Avalos * We should never encounter this record here; 36460b4ad09SPeter Avalos * see ZIP_LENGTH_AT_END handling below for details. 36560b4ad09SPeter Avalos */ 36660b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 36760b4ad09SPeter Avalos "Bad ZIP file: Unexpected end-of-entry record"); 36860b4ad09SPeter Avalos return (ARCHIVE_FATAL); 36960b4ad09SPeter Avalos } 37060b4ad09SPeter Avalos 37160b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 37260b4ad09SPeter Avalos "Damaged ZIP file or unsupported format variant (%d,%d)", 37360b4ad09SPeter Avalos signature[2], signature[3]); 37460b4ad09SPeter Avalos return (ARCHIVE_FATAL); 37560b4ad09SPeter Avalos } 37660b4ad09SPeter Avalos 377*8029ab02SPeter Avalos static int 37860b4ad09SPeter Avalos zip_read_file_header(struct archive_read *a, struct archive_entry *entry, 37960b4ad09SPeter Avalos struct zip *zip) 38060b4ad09SPeter Avalos { 38160b4ad09SPeter Avalos const struct zip_file_header *p; 38260b4ad09SPeter Avalos const void *h; 38360b4ad09SPeter Avalos 384*8029ab02SPeter Avalos if ((p = __archive_read_ahead(a, sizeof *p, NULL)) == NULL) { 38560b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 38660b4ad09SPeter Avalos "Truncated ZIP file header"); 38760b4ad09SPeter Avalos return (ARCHIVE_FATAL); 38860b4ad09SPeter Avalos } 38960b4ad09SPeter Avalos 39060b4ad09SPeter Avalos zip->version = p->version[0]; 39160b4ad09SPeter Avalos zip->system = p->version[1]; 39260b4ad09SPeter Avalos zip->flags = archive_le16dec(p->flags); 39360b4ad09SPeter Avalos zip->compression = archive_le16dec(p->compression); 39460b4ad09SPeter Avalos if (zip->compression < 39560b4ad09SPeter Avalos sizeof(compression_names)/sizeof(compression_names[0])) 39660b4ad09SPeter Avalos zip->compression_name = compression_names[zip->compression]; 39760b4ad09SPeter Avalos else 39860b4ad09SPeter Avalos zip->compression_name = "??"; 39960b4ad09SPeter Avalos zip->mtime = zip_time(p->timedate); 40060b4ad09SPeter Avalos zip->ctime = 0; 40160b4ad09SPeter Avalos zip->atime = 0; 40260b4ad09SPeter Avalos zip->mode = 0; 40360b4ad09SPeter Avalos zip->uid = 0; 40460b4ad09SPeter Avalos zip->gid = 0; 40560b4ad09SPeter Avalos zip->crc32 = archive_le32dec(p->crc32); 40660b4ad09SPeter Avalos zip->filename_length = archive_le16dec(p->filename_length); 40760b4ad09SPeter Avalos zip->extra_length = archive_le16dec(p->extra_length); 40860b4ad09SPeter Avalos zip->uncompressed_size = archive_le32dec(p->uncompressed_size); 40960b4ad09SPeter Avalos zip->compressed_size = archive_le32dec(p->compressed_size); 41060b4ad09SPeter Avalos 411*8029ab02SPeter Avalos __archive_read_consume(a, sizeof(struct zip_file_header)); 41260b4ad09SPeter Avalos 41360b4ad09SPeter Avalos 41460b4ad09SPeter Avalos /* Read the filename. */ 415*8029ab02SPeter Avalos if ((h = __archive_read_ahead(a, zip->filename_length, NULL)) == NULL) { 41660b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 41760b4ad09SPeter Avalos "Truncated ZIP file header"); 41860b4ad09SPeter Avalos return (ARCHIVE_FATAL); 41960b4ad09SPeter Avalos } 42060b4ad09SPeter Avalos if (archive_string_ensure(&zip->pathname, zip->filename_length) == NULL) 42160b4ad09SPeter Avalos __archive_errx(1, "Out of memory"); 42260b4ad09SPeter Avalos archive_strncpy(&zip->pathname, h, zip->filename_length); 423*8029ab02SPeter Avalos __archive_read_consume(a, zip->filename_length); 42460b4ad09SPeter Avalos archive_entry_set_pathname(entry, zip->pathname.s); 42560b4ad09SPeter Avalos 42660b4ad09SPeter Avalos if (zip->pathname.s[archive_strlen(&zip->pathname) - 1] == '/') 42760b4ad09SPeter Avalos zip->mode = AE_IFDIR | 0777; 42860b4ad09SPeter Avalos else 42960b4ad09SPeter Avalos zip->mode = AE_IFREG | 0777; 43060b4ad09SPeter Avalos 43160b4ad09SPeter Avalos /* Read the extra data. */ 432*8029ab02SPeter Avalos if ((h = __archive_read_ahead(a, zip->extra_length, NULL)) == NULL) { 43360b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 43460b4ad09SPeter Avalos "Truncated ZIP file header"); 43560b4ad09SPeter Avalos return (ARCHIVE_FATAL); 43660b4ad09SPeter Avalos } 43760b4ad09SPeter Avalos process_extra(h, zip); 438*8029ab02SPeter Avalos __archive_read_consume(a, zip->extra_length); 43960b4ad09SPeter Avalos 44060b4ad09SPeter Avalos /* Populate some additional entry fields: */ 44160b4ad09SPeter Avalos archive_entry_set_mode(entry, zip->mode); 44260b4ad09SPeter Avalos archive_entry_set_uid(entry, zip->uid); 44360b4ad09SPeter Avalos archive_entry_set_gid(entry, zip->gid); 44460b4ad09SPeter Avalos archive_entry_set_mtime(entry, zip->mtime, 0); 44560b4ad09SPeter Avalos archive_entry_set_ctime(entry, zip->ctime, 0); 44660b4ad09SPeter Avalos archive_entry_set_atime(entry, zip->atime, 0); 447*8029ab02SPeter Avalos /* Set the size only if it's meaningful. */ 448*8029ab02SPeter Avalos if (0 == (zip->flags & ZIP_LENGTH_AT_END)) 44960b4ad09SPeter Avalos archive_entry_set_size(entry, zip->uncompressed_size); 45060b4ad09SPeter Avalos 45160b4ad09SPeter Avalos zip->entry_bytes_remaining = zip->compressed_size; 45260b4ad09SPeter Avalos zip->entry_offset = 0; 45360b4ad09SPeter Avalos 45460b4ad09SPeter Avalos /* If there's no body, force read_data() to return EOF immediately. */ 45560b4ad09SPeter Avalos if (0 == (zip->flags & ZIP_LENGTH_AT_END) 45660b4ad09SPeter Avalos && zip->entry_bytes_remaining < 1) 45760b4ad09SPeter Avalos zip->end_of_entry = 1; 45860b4ad09SPeter Avalos 45960b4ad09SPeter Avalos /* Set up a more descriptive format name. */ 46060b4ad09SPeter Avalos sprintf(zip->format_name, "ZIP %d.%d (%s)", 46160b4ad09SPeter Avalos zip->version / 10, zip->version % 10, 46260b4ad09SPeter Avalos zip->compression_name); 46360b4ad09SPeter Avalos a->archive.archive_format_name = zip->format_name; 46460b4ad09SPeter Avalos 46560b4ad09SPeter Avalos return (ARCHIVE_OK); 46660b4ad09SPeter Avalos } 46760b4ad09SPeter Avalos 46860b4ad09SPeter Avalos /* Convert an MSDOS-style date/time into Unix-style time. */ 46960b4ad09SPeter Avalos static time_t 47060b4ad09SPeter Avalos zip_time(const char *p) 47160b4ad09SPeter Avalos { 47260b4ad09SPeter Avalos int msTime, msDate; 47360b4ad09SPeter Avalos struct tm ts; 47460b4ad09SPeter Avalos 47560b4ad09SPeter Avalos msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]); 47660b4ad09SPeter Avalos msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]); 47760b4ad09SPeter Avalos 47860b4ad09SPeter Avalos memset(&ts, 0, sizeof(ts)); 47960b4ad09SPeter Avalos ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ 48060b4ad09SPeter Avalos ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ 48160b4ad09SPeter Avalos ts.tm_mday = msDate & 0x1f; /* Day of month. */ 48260b4ad09SPeter Avalos ts.tm_hour = (msTime >> 11) & 0x1f; 48360b4ad09SPeter Avalos ts.tm_min = (msTime >> 5) & 0x3f; 48460b4ad09SPeter Avalos ts.tm_sec = (msTime << 1) & 0x3e; 48560b4ad09SPeter Avalos ts.tm_isdst = -1; 48660b4ad09SPeter Avalos return mktime(&ts); 48760b4ad09SPeter Avalos } 48860b4ad09SPeter Avalos 48960b4ad09SPeter Avalos static int 49060b4ad09SPeter Avalos archive_read_format_zip_read_data(struct archive_read *a, 49160b4ad09SPeter Avalos const void **buff, size_t *size, off_t *offset) 49260b4ad09SPeter Avalos { 49360b4ad09SPeter Avalos int r; 49460b4ad09SPeter Avalos struct zip *zip; 49560b4ad09SPeter Avalos 49660b4ad09SPeter Avalos zip = (struct zip *)(a->format->data); 49760b4ad09SPeter Avalos 49860b4ad09SPeter Avalos /* 49960b4ad09SPeter Avalos * If we hit end-of-entry last time, clean up and return 50060b4ad09SPeter Avalos * ARCHIVE_EOF this time. 50160b4ad09SPeter Avalos */ 50260b4ad09SPeter Avalos if (zip->end_of_entry) { 50360b4ad09SPeter Avalos *offset = zip->entry_uncompressed_bytes_read; 50460b4ad09SPeter Avalos *size = 0; 50560b4ad09SPeter Avalos *buff = NULL; 50660b4ad09SPeter Avalos return (ARCHIVE_EOF); 50760b4ad09SPeter Avalos } 50860b4ad09SPeter Avalos 50960b4ad09SPeter Avalos switch(zip->compression) { 51060b4ad09SPeter Avalos case 0: /* No compression. */ 51160b4ad09SPeter Avalos r = zip_read_data_none(a, buff, size, offset); 51260b4ad09SPeter Avalos break; 51360b4ad09SPeter Avalos case 8: /* Deflate compression. */ 51460b4ad09SPeter Avalos r = zip_read_data_deflate(a, buff, size, offset); 51560b4ad09SPeter Avalos break; 51660b4ad09SPeter Avalos default: /* Unsupported compression. */ 51760b4ad09SPeter Avalos *buff = NULL; 51860b4ad09SPeter Avalos *size = 0; 51960b4ad09SPeter Avalos *offset = 0; 52060b4ad09SPeter Avalos /* Return a warning. */ 52160b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 52260b4ad09SPeter Avalos "Unsupported ZIP compression method (%s)", 52360b4ad09SPeter Avalos zip->compression_name); 52460b4ad09SPeter Avalos if (zip->flags & ZIP_LENGTH_AT_END) { 52560b4ad09SPeter Avalos /* 52660b4ad09SPeter Avalos * ZIP_LENGTH_AT_END requires us to 52760b4ad09SPeter Avalos * decompress the entry in order to 52860b4ad09SPeter Avalos * skip it, but we don't know this 52960b4ad09SPeter Avalos * compression method, so we give up. 53060b4ad09SPeter Avalos */ 53160b4ad09SPeter Avalos r = ARCHIVE_FATAL; 53260b4ad09SPeter Avalos } else { 53360b4ad09SPeter Avalos /* We can't decompress this entry, but we will 53460b4ad09SPeter Avalos * be able to skip() it and try the next entry. */ 53560b4ad09SPeter Avalos r = ARCHIVE_WARN; 53660b4ad09SPeter Avalos } 53760b4ad09SPeter Avalos break; 53860b4ad09SPeter Avalos } 539*8029ab02SPeter Avalos if (r != ARCHIVE_OK) 54060b4ad09SPeter Avalos return (r); 541*8029ab02SPeter Avalos /* Update checksum */ 542*8029ab02SPeter Avalos if (*size) 543*8029ab02SPeter Avalos zip->entry_crc32 = 544*8029ab02SPeter Avalos crc32(zip->entry_crc32, *buff, *size); 545*8029ab02SPeter Avalos /* If we hit the end, swallow any end-of-data marker. */ 546*8029ab02SPeter Avalos if (zip->end_of_entry) { 547*8029ab02SPeter Avalos if (zip->flags & ZIP_LENGTH_AT_END) { 548*8029ab02SPeter Avalos const char *p; 549*8029ab02SPeter Avalos 550*8029ab02SPeter Avalos if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) { 551*8029ab02SPeter Avalos archive_set_error(&a->archive, 552*8029ab02SPeter Avalos ARCHIVE_ERRNO_FILE_FORMAT, 553*8029ab02SPeter Avalos "Truncated ZIP end-of-file record"); 554*8029ab02SPeter Avalos return (ARCHIVE_FATAL); 555*8029ab02SPeter Avalos } 556*8029ab02SPeter Avalos zip->crc32 = archive_le32dec(p + 4); 557*8029ab02SPeter Avalos zip->compressed_size = archive_le32dec(p + 8); 558*8029ab02SPeter Avalos zip->uncompressed_size = archive_le32dec(p + 12); 559*8029ab02SPeter Avalos __archive_read_consume(a, 16); 560*8029ab02SPeter Avalos } 561*8029ab02SPeter Avalos /* Check file size, CRC against these values. */ 562*8029ab02SPeter Avalos if (zip->compressed_size != zip->entry_compressed_bytes_read) { 563*8029ab02SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 564*8029ab02SPeter Avalos "ZIP compressed data is wrong size"); 565*8029ab02SPeter Avalos return (ARCHIVE_WARN); 566*8029ab02SPeter Avalos } 567*8029ab02SPeter Avalos /* Size field only stores the lower 32 bits of the actual size. */ 568*8029ab02SPeter Avalos if ((zip->uncompressed_size & UINT32_MAX) 569*8029ab02SPeter Avalos != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { 570*8029ab02SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 571*8029ab02SPeter Avalos "ZIP uncompressed data is wrong size"); 572*8029ab02SPeter Avalos return (ARCHIVE_WARN); 573*8029ab02SPeter Avalos } 574*8029ab02SPeter Avalos /* Check computed CRC against header */ 575*8029ab02SPeter Avalos if (zip->crc32 != zip->entry_crc32) { 576*8029ab02SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 577*8029ab02SPeter Avalos "ZIP bad CRC: 0x%lx should be 0x%lx", 578*8029ab02SPeter Avalos zip->entry_crc32, zip->crc32); 579*8029ab02SPeter Avalos return (ARCHIVE_WARN); 580*8029ab02SPeter Avalos } 581*8029ab02SPeter Avalos } 582*8029ab02SPeter Avalos 583*8029ab02SPeter Avalos /* Return EOF immediately if this is a non-regular file. */ 584*8029ab02SPeter Avalos if (AE_IFREG != (zip->mode & AE_IFMT)) 585*8029ab02SPeter Avalos return (ARCHIVE_EOF); 586*8029ab02SPeter Avalos return (ARCHIVE_OK); 58760b4ad09SPeter Avalos } 58860b4ad09SPeter Avalos 58960b4ad09SPeter Avalos /* 59060b4ad09SPeter Avalos * Read "uncompressed" data. According to the current specification, 59160b4ad09SPeter Avalos * if ZIP_LENGTH_AT_END is specified, then the size fields in the 59260b4ad09SPeter Avalos * initial file header are supposed to be set to zero. This would, of 59360b4ad09SPeter Avalos * course, make it impossible for us to read the archive, since we 59460b4ad09SPeter Avalos * couldn't determine the end of the file data. Info-ZIP seems to 59560b4ad09SPeter Avalos * include the real size fields both before and after the data in this 59660b4ad09SPeter Avalos * case (the CRC only appears afterwards), so this works as you would 59760b4ad09SPeter Avalos * expect. 59860b4ad09SPeter Avalos * 59960b4ad09SPeter Avalos * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets 60060b4ad09SPeter Avalos * zip->end_of_entry if it consumes all of the data. 60160b4ad09SPeter Avalos */ 60260b4ad09SPeter Avalos static int 60360b4ad09SPeter Avalos zip_read_data_none(struct archive_read *a, const void **buff, 60460b4ad09SPeter Avalos size_t *size, off_t *offset) 60560b4ad09SPeter Avalos { 60660b4ad09SPeter Avalos struct zip *zip; 60760b4ad09SPeter Avalos ssize_t bytes_avail; 60860b4ad09SPeter Avalos 60960b4ad09SPeter Avalos zip = (struct zip *)(a->format->data); 61060b4ad09SPeter Avalos 61160b4ad09SPeter Avalos if (zip->entry_bytes_remaining == 0) { 61260b4ad09SPeter Avalos *buff = NULL; 61360b4ad09SPeter Avalos *size = 0; 61460b4ad09SPeter Avalos *offset = zip->entry_offset; 61560b4ad09SPeter Avalos zip->end_of_entry = 1; 61660b4ad09SPeter Avalos return (ARCHIVE_OK); 61760b4ad09SPeter Avalos } 61860b4ad09SPeter Avalos /* 61960b4ad09SPeter Avalos * Note: '1' here is a performance optimization. 62060b4ad09SPeter Avalos * Recall that the decompression layer returns a count of 62160b4ad09SPeter Avalos * available bytes; asking for more than that forces the 62260b4ad09SPeter Avalos * decompressor to combine reads by copying data. 62360b4ad09SPeter Avalos */ 624*8029ab02SPeter Avalos *buff = __archive_read_ahead(a, 1, &bytes_avail); 62560b4ad09SPeter Avalos if (bytes_avail <= 0) { 62660b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 62760b4ad09SPeter Avalos "Truncated ZIP file data"); 62860b4ad09SPeter Avalos return (ARCHIVE_FATAL); 62960b4ad09SPeter Avalos } 63060b4ad09SPeter Avalos if (bytes_avail > zip->entry_bytes_remaining) 63160b4ad09SPeter Avalos bytes_avail = zip->entry_bytes_remaining; 632*8029ab02SPeter Avalos __archive_read_consume(a, bytes_avail); 63360b4ad09SPeter Avalos *size = bytes_avail; 63460b4ad09SPeter Avalos *offset = zip->entry_offset; 63560b4ad09SPeter Avalos zip->entry_offset += *size; 63660b4ad09SPeter Avalos zip->entry_bytes_remaining -= *size; 63760b4ad09SPeter Avalos zip->entry_uncompressed_bytes_read += *size; 63860b4ad09SPeter Avalos zip->entry_compressed_bytes_read += *size; 63960b4ad09SPeter Avalos return (ARCHIVE_OK); 64060b4ad09SPeter Avalos } 64160b4ad09SPeter Avalos 64260b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H 64360b4ad09SPeter Avalos static int 64460b4ad09SPeter Avalos zip_read_data_deflate(struct archive_read *a, const void **buff, 64560b4ad09SPeter Avalos size_t *size, off_t *offset) 64660b4ad09SPeter Avalos { 64760b4ad09SPeter Avalos struct zip *zip; 64860b4ad09SPeter Avalos ssize_t bytes_avail; 64960b4ad09SPeter Avalos const void *compressed_buff; 65060b4ad09SPeter Avalos int r; 65160b4ad09SPeter Avalos 65260b4ad09SPeter Avalos zip = (struct zip *)(a->format->data); 65360b4ad09SPeter Avalos 65460b4ad09SPeter Avalos /* If the buffer hasn't been allocated, allocate it now. */ 65560b4ad09SPeter Avalos if (zip->uncompressed_buffer == NULL) { 65660b4ad09SPeter Avalos zip->uncompressed_buffer_size = 32 * 1024; 65760b4ad09SPeter Avalos zip->uncompressed_buffer 65860b4ad09SPeter Avalos = (unsigned char *)malloc(zip->uncompressed_buffer_size); 65960b4ad09SPeter Avalos if (zip->uncompressed_buffer == NULL) { 66060b4ad09SPeter Avalos archive_set_error(&a->archive, ENOMEM, 66160b4ad09SPeter Avalos "No memory for ZIP decompression"); 66260b4ad09SPeter Avalos return (ARCHIVE_FATAL); 66360b4ad09SPeter Avalos } 66460b4ad09SPeter Avalos } 66560b4ad09SPeter Avalos 66660b4ad09SPeter Avalos /* If we haven't yet read any data, initialize the decompressor. */ 66760b4ad09SPeter Avalos if (!zip->decompress_init) { 66860b4ad09SPeter Avalos if (zip->stream_valid) 66960b4ad09SPeter Avalos r = inflateReset(&zip->stream); 67060b4ad09SPeter Avalos else 67160b4ad09SPeter Avalos r = inflateInit2(&zip->stream, 67260b4ad09SPeter Avalos -15 /* Don't check for zlib header */); 67360b4ad09SPeter Avalos if (r != Z_OK) { 67460b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 67560b4ad09SPeter Avalos "Can't initialize ZIP decompression."); 67660b4ad09SPeter Avalos return (ARCHIVE_FATAL); 67760b4ad09SPeter Avalos } 67860b4ad09SPeter Avalos /* Stream structure has been set up. */ 67960b4ad09SPeter Avalos zip->stream_valid = 1; 68060b4ad09SPeter Avalos /* We've initialized decompression for this stream. */ 68160b4ad09SPeter Avalos zip->decompress_init = 1; 68260b4ad09SPeter Avalos } 68360b4ad09SPeter Avalos 68460b4ad09SPeter Avalos /* 68560b4ad09SPeter Avalos * Note: '1' here is a performance optimization. 68660b4ad09SPeter Avalos * Recall that the decompression layer returns a count of 68760b4ad09SPeter Avalos * available bytes; asking for more than that forces the 68860b4ad09SPeter Avalos * decompressor to combine reads by copying data. 68960b4ad09SPeter Avalos */ 690*8029ab02SPeter Avalos compressed_buff = __archive_read_ahead(a, 1, &bytes_avail); 69160b4ad09SPeter Avalos if (bytes_avail <= 0) { 69260b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 69360b4ad09SPeter Avalos "Truncated ZIP file body"); 69460b4ad09SPeter Avalos return (ARCHIVE_FATAL); 69560b4ad09SPeter Avalos } 69660b4ad09SPeter Avalos 69760b4ad09SPeter Avalos /* 69860b4ad09SPeter Avalos * A bug in zlib.h: stream.next_in should be marked 'const' 69960b4ad09SPeter Avalos * but isn't (the library never alters data through the 70060b4ad09SPeter Avalos * next_in pointer, only reads it). The result: this ugly 70160b4ad09SPeter Avalos * cast to remove 'const'. 70260b4ad09SPeter Avalos */ 70360b4ad09SPeter Avalos zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff; 70460b4ad09SPeter Avalos zip->stream.avail_in = bytes_avail; 70560b4ad09SPeter Avalos zip->stream.total_in = 0; 70660b4ad09SPeter Avalos zip->stream.next_out = zip->uncompressed_buffer; 70760b4ad09SPeter Avalos zip->stream.avail_out = zip->uncompressed_buffer_size; 70860b4ad09SPeter Avalos zip->stream.total_out = 0; 70960b4ad09SPeter Avalos 71060b4ad09SPeter Avalos r = inflate(&zip->stream, 0); 71160b4ad09SPeter Avalos switch (r) { 71260b4ad09SPeter Avalos case Z_OK: 71360b4ad09SPeter Avalos break; 71460b4ad09SPeter Avalos case Z_STREAM_END: 71560b4ad09SPeter Avalos zip->end_of_entry = 1; 71660b4ad09SPeter Avalos break; 71760b4ad09SPeter Avalos case Z_MEM_ERROR: 71860b4ad09SPeter Avalos archive_set_error(&a->archive, ENOMEM, 71960b4ad09SPeter Avalos "Out of memory for ZIP decompression"); 72060b4ad09SPeter Avalos return (ARCHIVE_FATAL); 72160b4ad09SPeter Avalos default: 72260b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 72360b4ad09SPeter Avalos "ZIP decompression failed (%d)", r); 72460b4ad09SPeter Avalos return (ARCHIVE_FATAL); 72560b4ad09SPeter Avalos } 72660b4ad09SPeter Avalos 72760b4ad09SPeter Avalos /* Consume as much as the compressor actually used. */ 72860b4ad09SPeter Avalos bytes_avail = zip->stream.total_in; 729*8029ab02SPeter Avalos __archive_read_consume(a, bytes_avail); 73060b4ad09SPeter Avalos zip->entry_bytes_remaining -= bytes_avail; 73160b4ad09SPeter Avalos zip->entry_compressed_bytes_read += bytes_avail; 73260b4ad09SPeter Avalos 73360b4ad09SPeter Avalos *offset = zip->entry_offset; 73460b4ad09SPeter Avalos *size = zip->stream.total_out; 73560b4ad09SPeter Avalos zip->entry_uncompressed_bytes_read += *size; 73660b4ad09SPeter Avalos *buff = zip->uncompressed_buffer; 73760b4ad09SPeter Avalos zip->entry_offset += *size; 73860b4ad09SPeter Avalos return (ARCHIVE_OK); 73960b4ad09SPeter Avalos } 74060b4ad09SPeter Avalos #else 74160b4ad09SPeter Avalos static int 74260b4ad09SPeter Avalos zip_read_data_deflate(struct archive_read *a, const void **buff, 74360b4ad09SPeter Avalos size_t *size, off_t *offset) 74460b4ad09SPeter Avalos { 74560b4ad09SPeter Avalos *buff = NULL; 74660b4ad09SPeter Avalos *size = 0; 74760b4ad09SPeter Avalos *offset = 0; 74860b4ad09SPeter Avalos archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 74960b4ad09SPeter Avalos "libarchive compiled without deflate support (no libz)"); 75060b4ad09SPeter Avalos return (ARCHIVE_FATAL); 75160b4ad09SPeter Avalos } 75260b4ad09SPeter Avalos #endif 75360b4ad09SPeter Avalos 75460b4ad09SPeter Avalos static int 75560b4ad09SPeter Avalos archive_read_format_zip_read_data_skip(struct archive_read *a) 75660b4ad09SPeter Avalos { 75760b4ad09SPeter Avalos struct zip *zip; 75860b4ad09SPeter Avalos const void *buff = NULL; 75960b4ad09SPeter Avalos off_t bytes_skipped; 76060b4ad09SPeter Avalos 76160b4ad09SPeter Avalos zip = (struct zip *)(a->format->data); 76260b4ad09SPeter Avalos 76360b4ad09SPeter Avalos /* If we've already read to end of data, we're done. */ 764*8029ab02SPeter Avalos if (zip->end_of_entry) 76560b4ad09SPeter Avalos return (ARCHIVE_OK); 76660b4ad09SPeter Avalos 76760b4ad09SPeter Avalos /* 76860b4ad09SPeter Avalos * If the length is at the end, we have no choice but 76960b4ad09SPeter Avalos * to decompress all the data to find the end marker. 77060b4ad09SPeter Avalos */ 77160b4ad09SPeter Avalos if (zip->flags & ZIP_LENGTH_AT_END) { 77260b4ad09SPeter Avalos size_t size; 77360b4ad09SPeter Avalos off_t offset; 77460b4ad09SPeter Avalos int r; 77560b4ad09SPeter Avalos do { 77660b4ad09SPeter Avalos r = archive_read_format_zip_read_data(a, &buff, 77760b4ad09SPeter Avalos &size, &offset); 77860b4ad09SPeter Avalos } while (r == ARCHIVE_OK); 77960b4ad09SPeter Avalos return (r); 78060b4ad09SPeter Avalos } 78160b4ad09SPeter Avalos 78260b4ad09SPeter Avalos /* 78360b4ad09SPeter Avalos * If the length is at the beginning, we can skip the 78460b4ad09SPeter Avalos * compressed data much more quickly. 78560b4ad09SPeter Avalos */ 786*8029ab02SPeter Avalos bytes_skipped = __archive_read_skip(a, zip->entry_bytes_remaining); 78760b4ad09SPeter Avalos if (bytes_skipped < 0) 78860b4ad09SPeter Avalos return (ARCHIVE_FATAL); 78960b4ad09SPeter Avalos 79060b4ad09SPeter Avalos /* This entry is finished and done. */ 791*8029ab02SPeter Avalos zip->end_of_entry = 1; 79260b4ad09SPeter Avalos return (ARCHIVE_OK); 79360b4ad09SPeter Avalos } 79460b4ad09SPeter Avalos 79560b4ad09SPeter Avalos static int 79660b4ad09SPeter Avalos archive_read_format_zip_cleanup(struct archive_read *a) 79760b4ad09SPeter Avalos { 79860b4ad09SPeter Avalos struct zip *zip; 79960b4ad09SPeter Avalos 80060b4ad09SPeter Avalos zip = (struct zip *)(a->format->data); 80160b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H 80260b4ad09SPeter Avalos if (zip->stream_valid) 80360b4ad09SPeter Avalos inflateEnd(&zip->stream); 80460b4ad09SPeter Avalos #endif 80560b4ad09SPeter Avalos free(zip->uncompressed_buffer); 80660b4ad09SPeter Avalos archive_string_free(&(zip->pathname)); 80760b4ad09SPeter Avalos archive_string_free(&(zip->extra)); 80860b4ad09SPeter Avalos free(zip); 80960b4ad09SPeter Avalos (a->format->data) = NULL; 81060b4ad09SPeter Avalos return (ARCHIVE_OK); 81160b4ad09SPeter Avalos } 81260b4ad09SPeter Avalos 81360b4ad09SPeter Avalos /* 81460b4ad09SPeter Avalos * The extra data is stored as a list of 81560b4ad09SPeter Avalos * id1+size1+data1 + id2+size2+data2 ... 81660b4ad09SPeter Avalos * triplets. id and size are 2 bytes each. 81760b4ad09SPeter Avalos */ 81860b4ad09SPeter Avalos static void 81960b4ad09SPeter Avalos process_extra(const void* extra, struct zip* zip) 82060b4ad09SPeter Avalos { 82160b4ad09SPeter Avalos int offset = 0; 82260b4ad09SPeter Avalos const char *p = (const char *)extra; 82360b4ad09SPeter Avalos while (offset < zip->extra_length - 4) 82460b4ad09SPeter Avalos { 82560b4ad09SPeter Avalos unsigned short headerid = archive_le16dec(p + offset); 82660b4ad09SPeter Avalos unsigned short datasize = archive_le16dec(p + offset + 2); 82760b4ad09SPeter Avalos offset += 4; 82860b4ad09SPeter Avalos if (offset + datasize > zip->extra_length) 82960b4ad09SPeter Avalos break; 83060b4ad09SPeter Avalos #ifdef DEBUG 83160b4ad09SPeter Avalos fprintf(stderr, "Header id 0x%04x, length %d\n", 83260b4ad09SPeter Avalos headerid, datasize); 83360b4ad09SPeter Avalos #endif 83460b4ad09SPeter Avalos switch (headerid) { 83560b4ad09SPeter Avalos case 0x0001: 83660b4ad09SPeter Avalos /* Zip64 extended information extra field. */ 83760b4ad09SPeter Avalos if (datasize >= 8) 83860b4ad09SPeter Avalos zip->uncompressed_size = archive_le64dec(p + offset); 83960b4ad09SPeter Avalos if (datasize >= 16) 84060b4ad09SPeter Avalos zip->compressed_size = archive_le64dec(p + offset + 8); 84160b4ad09SPeter Avalos break; 84260b4ad09SPeter Avalos case 0x5455: 84360b4ad09SPeter Avalos { 84460b4ad09SPeter Avalos /* Extended time field "UT". */ 84560b4ad09SPeter Avalos int flags = p[offset]; 84660b4ad09SPeter Avalos offset++; 84760b4ad09SPeter Avalos datasize--; 84860b4ad09SPeter Avalos /* Flag bits indicate which dates are present. */ 84960b4ad09SPeter Avalos if (flags & 0x01) 85060b4ad09SPeter Avalos { 85160b4ad09SPeter Avalos #ifdef DEBUG 85260b4ad09SPeter Avalos fprintf(stderr, "mtime: %lld -> %d\n", 85360b4ad09SPeter Avalos (long long)zip->mtime, 85460b4ad09SPeter Avalos archive_le32dec(p + offset)); 85560b4ad09SPeter Avalos #endif 85660b4ad09SPeter Avalos if (datasize < 4) 85760b4ad09SPeter Avalos break; 85860b4ad09SPeter Avalos zip->mtime = archive_le32dec(p + offset); 85960b4ad09SPeter Avalos offset += 4; 86060b4ad09SPeter Avalos datasize -= 4; 86160b4ad09SPeter Avalos } 86260b4ad09SPeter Avalos if (flags & 0x02) 86360b4ad09SPeter Avalos { 86460b4ad09SPeter Avalos if (datasize < 4) 86560b4ad09SPeter Avalos break; 86660b4ad09SPeter Avalos zip->atime = archive_le32dec(p + offset); 86760b4ad09SPeter Avalos offset += 4; 86860b4ad09SPeter Avalos datasize -= 4; 86960b4ad09SPeter Avalos } 87060b4ad09SPeter Avalos if (flags & 0x04) 87160b4ad09SPeter Avalos { 87260b4ad09SPeter Avalos if (datasize < 4) 87360b4ad09SPeter Avalos break; 87460b4ad09SPeter Avalos zip->ctime = archive_le32dec(p + offset); 87560b4ad09SPeter Avalos offset += 4; 87660b4ad09SPeter Avalos datasize -= 4; 87760b4ad09SPeter Avalos } 87860b4ad09SPeter Avalos break; 87960b4ad09SPeter Avalos } 88060b4ad09SPeter Avalos case 0x7855: 88160b4ad09SPeter Avalos /* Info-ZIP Unix Extra Field (type 2) "Ux". */ 88260b4ad09SPeter Avalos #ifdef DEBUG 88360b4ad09SPeter Avalos fprintf(stderr, "uid %d gid %d\n", 88460b4ad09SPeter Avalos archive_le16dec(p + offset), 88560b4ad09SPeter Avalos archive_le16dec(p + offset + 2)); 88660b4ad09SPeter Avalos #endif 88760b4ad09SPeter Avalos if (datasize >= 2) 88860b4ad09SPeter Avalos zip->uid = archive_le16dec(p + offset); 88960b4ad09SPeter Avalos if (datasize >= 4) 89060b4ad09SPeter Avalos zip->gid = archive_le16dec(p + offset + 2); 89160b4ad09SPeter Avalos break; 89260b4ad09SPeter Avalos default: 89360b4ad09SPeter Avalos break; 89460b4ad09SPeter Avalos } 89560b4ad09SPeter Avalos offset += datasize; 89660b4ad09SPeter Avalos } 89760b4ad09SPeter Avalos #ifdef DEBUG 89860b4ad09SPeter Avalos if (offset != zip->extra_length) 89960b4ad09SPeter Avalos { 90060b4ad09SPeter Avalos fprintf(stderr, 90160b4ad09SPeter Avalos "Extra data field contents do not match reported size!"); 90260b4ad09SPeter Avalos } 90360b4ad09SPeter Avalos #endif 90460b4ad09SPeter Avalos } 905