diff options
Diffstat (limited to 'Utilities/cmlibarchive/libarchive/archive_read_support_compression_gzip.c')
-rw-r--r-- | Utilities/cmlibarchive/libarchive/archive_read_support_compression_gzip.c | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_compression_gzip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_compression_gzip.c deleted file mode 100644 index 5424b96..0000000 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_compression_gzip.c +++ /dev/null @@ -1,463 +0,0 @@ -/*- - * Copyright (c) 2003-2007 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" - -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_gzip.c,v 1.17 2008/12/06 06:45:15 kientzle Exp $"); - - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_ZLIB_H -#include <cm_zlib.h> -#endif - -#include "archive.h" -#include "archive_private.h" -#include "archive_read_private.h" - -#ifdef HAVE_ZLIB_H -struct private_data { - z_stream stream; - char in_stream; - unsigned char *out_block; - size_t out_block_size; - int64_t total_out; - unsigned long crc; - char eof; /* True = found end of compressed data. */ -}; - -/* Gzip Filter. */ -static ssize_t gzip_filter_read(struct archive_read_filter *, const void **); -static int gzip_filter_close(struct archive_read_filter *); -#endif - -/* - * Note that we can detect gzip archives even if we can't decompress - * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if zlib is unavailable. - * - * TODO: If zlib is unavailable, gzip_bidder_init() should - * use the compress_program framework to try to fire up an external - * gunzip program. - */ -static int gzip_bidder_bid(struct archive_read_filter_bidder *, - struct archive_read_filter *); -static int gzip_bidder_init(struct archive_read_filter *); - -int -archive_read_support_compression_gzip(struct archive *_a) -{ - struct archive_read *a = (struct archive_read *)_a; - struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a); - - if (bidder == NULL) - return (ARCHIVE_FATAL); - - bidder->data = NULL; - bidder->bid = gzip_bidder_bid; - bidder->init = gzip_bidder_init; - bidder->options = NULL; - bidder->free = NULL; /* No data, so no cleanup necessary. */ - /* Signal the extent of gzip support with the return value here. */ -#if HAVE_ZLIB_H - return (ARCHIVE_OK); -#else - archive_set_error(_a, ARCHIVE_ERRNO_MISC, - "Using external gunzip program"); - return (ARCHIVE_WARN); -#endif -} - -/* - * Read and verify the header. - * - * Returns zero if the header couldn't be validated, else returns - * number of bytes in header. If pbits is non-NULL, it receives a - * count of bits verified, suitable for use by bidder. - */ -static int -peek_at_header(struct archive_read_filter *filter, int *pbits) -{ - const unsigned char *p; - ssize_t avail, len; - int bits = 0; - int header_flags; - - /* Start by looking at the first ten bytes of the header, which - * is all fixed layout. */ - len = 10; - p = __archive_read_filter_ahead(filter, len, &avail); - if (p == NULL || avail == 0) - return (0); - if (p[0] != 037) - return (0); - bits += 8; - if (p[1] != 0213) - return (0); - bits += 8; - if (p[2] != 8) /* We only support deflation. */ - return (0); - bits += 8; - if ((p[3] & 0xE0)!= 0) /* No reserved flags set. */ - return (0); - bits += 3; - header_flags = p[3]; - /* Bytes 4-7 are mod time. */ - /* Byte 8 is deflate flags. */ - /* XXXX TODO: return deflate flags back to consume_header for use - in initializing the decompressor. */ - /* Byte 9 is OS. */ - - /* Optional extra data: 2 byte length plus variable body. */ - if (header_flags & 4) { - p = __archive_read_filter_ahead(filter, len + 2, &avail); - if (p == NULL) - return (0); - len += ((int)p[len + 1] << 8) | (int)p[len]; - len += 2; - } - - /* Null-terminated optional filename. */ - if (header_flags & 8) { - do { - ++len; - if (avail < len) - p = __archive_read_filter_ahead(filter, - len, &avail); - if (p == NULL) - return (0); - } while (p[len - 1] != 0); - } - - /* Null-terminated optional comment. */ - if (header_flags & 16) { - do { - ++len; - if (avail < len) - p = __archive_read_filter_ahead(filter, - len, &avail); - if (p == NULL) - return (0); - } while (p[len - 1] != 0); - } - - /* Optional header CRC */ - if ((header_flags & 2)) { - p = __archive_read_filter_ahead(filter, len + 2, &avail); - if (p == NULL) - return (0); -#if 0 - int hcrc = ((int)p[len + 1] << 8) | (int)p[len]; - int crc = /* XXX TODO: Compute header CRC. */; - if (crc != hcrc) - return (0); - bits += 16; -#endif - len += 2; - } - - if (pbits != NULL) - *pbits = bits; - return (len); -} - -/* - * Bidder just verifies the header and returns the number of verified bits. - */ -static int -gzip_bidder_bid(struct archive_read_filter_bidder *self, - struct archive_read_filter *filter) -{ - int bits_checked; - - (void)self; /* UNUSED */ - - if (peek_at_header(filter, &bits_checked)) - return (bits_checked); - return (0); -} - - -#ifndef HAVE_ZLIB_H - -/* - * If we don't have the library on this system, we can't do the - * decompression directly. We can, however, try to run gunzip - * in case that's available. - */ -static int -gzip_bidder_init(struct archive_read_filter *self) -{ - int r; - - r = __archive_read_program(self, "gunzip"); - /* Note: We set the format here even if __archive_read_program() - * above fails. We do, after all, know what the format is - * even if we weren't able to read it. */ - self->code = ARCHIVE_COMPRESSION_GZIP; - self->name = "gzip"; - return (r); -} - -#else - -/* - * Initialize the filter object. - */ -static int -gzip_bidder_init(struct archive_read_filter *self) -{ - struct private_data *state; - static const size_t out_block_size = 64 * 1024; - void *out_block; - - self->code = ARCHIVE_COMPRESSION_GZIP; - self->name = "gzip"; - - state = (struct private_data *)calloc(sizeof(*state), 1); - out_block = (unsigned char *)malloc(out_block_size); - if (state == NULL || out_block == NULL) { - free(out_block); - free(state); - archive_set_error(&self->archive->archive, ENOMEM, - "Can't allocate data for gzip decompression"); - return (ARCHIVE_FATAL); - } - - self->data = state; - state->out_block_size = out_block_size; - state->out_block = out_block; - self->read = gzip_filter_read; - self->skip = NULL; /* not supported */ - self->close = gzip_filter_close; - - state->in_stream = 0; /* We're not actually within a stream yet. */ - - return (ARCHIVE_OK); -} - -static int -consume_header(struct archive_read_filter *self) -{ - struct private_data *state; - ssize_t avail; - size_t len; - int ret; - - state = (struct private_data *)self->data; - - /* If this is a real header, consume it. */ - len = peek_at_header(self->upstream, NULL); - if (len == 0) - return (ARCHIVE_EOF); - __archive_read_filter_consume(self->upstream, len); - - /* Initialize CRC accumulator. */ - state->crc = crc32(0L, NULL, 0); - - /* Initialize compression library. */ - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 1, &avail); - state->stream.avail_in = avail; - ret = inflateInit2(&(state->stream), - -15 /* Don't check for zlib header */); - - /* Decipher the error code. */ - switch (ret) { - case Z_OK: - state->in_stream = 1; - return (ARCHIVE_OK); - case Z_STREAM_ERROR: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid setup parameter"); - break; - case Z_MEM_ERROR: - archive_set_error(&self->archive->archive, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - case Z_VERSION_ERROR: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid library version"); - break; - default: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - " Zlib error %d", ret); - break; - } - return (ARCHIVE_FATAL); -} - -static int -consume_trailer(struct archive_read_filter *self) -{ - struct private_data *state; - const unsigned char *p; - ssize_t avail; - - state = (struct private_data *)self->data; - - state->in_stream = 0; - switch (inflateEnd(&(state->stream))) { - case Z_OK: - break; - default: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Failed to clean up gzip decompressor"); - return (ARCHIVE_FATAL); - } - - /* GZip trailer is a fixed 8 byte structure. */ - p = __archive_read_filter_ahead(self->upstream, 8, &avail); - if (p == NULL || avail == 0) - return (ARCHIVE_FATAL); - - /* XXX TODO: Verify the length and CRC. */ - - /* We've verified the trailer, so consume it now. */ - __archive_read_filter_consume(self->upstream, 8); - - return (ARCHIVE_OK); -} - -static ssize_t -gzip_filter_read(struct archive_read_filter *self, const void **p) -{ - struct private_data *state; - size_t decompressed; - ssize_t avail_in; - int ret; - - state = (struct private_data *)self->data; - - /* Empty our output buffer. */ - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Try to fill the output buffer. */ - while (state->stream.avail_out > 0 && !state->eof) { - /* If we're not in a stream, read a header - * and initialize the decompression library. */ - if (!state->in_stream) { - ret = consume_header(self); - if (ret == ARCHIVE_EOF) { - state->eof = 1; - break; - } - if (ret < ARCHIVE_OK) - return (ret); - } - - /* Peek at the next available data. */ - /* ZLib treats stream.next_in as const but doesn't declare - * it so, hence this ugly cast. */ - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 1, &avail_in); - if (state->stream.next_in == NULL) - return (ARCHIVE_FATAL); - state->stream.avail_in = avail_in; - - /* Decompress and consume some of that data. */ - ret = inflate(&(state->stream), 0); - switch (ret) { - case Z_OK: /* Decompressor made some progress. */ - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - break; - case Z_STREAM_END: /* Found end of stream. */ - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - /* Consume the stream trailer; release the - * decompression library. */ - ret = consume_trailer(self); - break; - default: - /* Return an error. */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "gzip decompression failed"); - return (ARCHIVE_FATAL); - } - } - - /* We've read as much as we can. */ - decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; - if (decompressed == 0) - *p = NULL; - else - *p = state->out_block; - return (decompressed); -} - -/* - * Clean up the decompressor. - */ -static int -gzip_filter_close(struct archive_read_filter *self) -{ - struct private_data *state; - int ret; - - state = (struct private_data *)self->data; - ret = ARCHIVE_OK; - - if (state->in_stream) { - switch (inflateEnd(&(state->stream))) { - case Z_OK: - break; - default: - archive_set_error(&(self->archive->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up gzip compressor"); - ret = ARCHIVE_FATAL; - } - } - - free(state->out_block); - free(state); - return (ret); -} - -#endif /* HAVE_ZLIB_H */ |