1228753Smm/*- 2228753Smm * Copyright (c) 2003-2007 Tim Kientzle 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "archive_platform.h" 27228753Smm 28229592Smm__FBSDID("$FreeBSD$"); 29228753Smm 30228753Smm 31228753Smm#ifdef HAVE_ERRNO_H 32228753Smm#include <errno.h> 33228753Smm#endif 34228753Smm#ifdef HAVE_STDLIB_H 35228753Smm#include <stdlib.h> 36228753Smm#endif 37228753Smm#ifdef HAVE_STRING_H 38228753Smm#include <string.h> 39228753Smm#endif 40228753Smm#ifdef HAVE_UNISTD_H 41228753Smm#include <unistd.h> 42228753Smm#endif 43228753Smm#ifdef HAVE_ZLIB_H 44228753Smm#include <zlib.h> 45228753Smm#endif 46228753Smm 47228753Smm#include "archive.h" 48228753Smm#include "archive_private.h" 49228753Smm#include "archive_read_private.h" 50228753Smm 51228753Smm#ifdef HAVE_ZLIB_H 52228753Smmstruct private_data { 53228753Smm z_stream stream; 54228753Smm char in_stream; 55228753Smm unsigned char *out_block; 56228753Smm size_t out_block_size; 57228753Smm int64_t total_out; 58228753Smm unsigned long crc; 59228753Smm char eof; /* True = found end of compressed data. */ 60228753Smm}; 61228753Smm 62228753Smm/* Gzip Filter. */ 63228753Smmstatic ssize_t gzip_filter_read(struct archive_read_filter *, const void **); 64228753Smmstatic int gzip_filter_close(struct archive_read_filter *); 65228753Smm#endif 66228753Smm 67228753Smm/* 68228753Smm * Note that we can detect gzip archives even if we can't decompress 69228753Smm * them. (In fact, we like detecting them because we can give better 70228753Smm * error messages.) So the bid framework here gets compiled even 71228753Smm * if zlib is unavailable. 72228753Smm * 73228753Smm * TODO: If zlib is unavailable, gzip_bidder_init() should 74228753Smm * use the compress_program framework to try to fire up an external 75228753Smm * gunzip program. 76228753Smm */ 77228753Smmstatic int gzip_bidder_bid(struct archive_read_filter_bidder *, 78228753Smm struct archive_read_filter *); 79228753Smmstatic int gzip_bidder_init(struct archive_read_filter *); 80228753Smm 81228753Smmint 82228753Smmarchive_read_support_compression_gzip(struct archive *_a) 83228753Smm{ 84228753Smm struct archive_read *a = (struct archive_read *)_a; 85228753Smm struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a); 86228753Smm 87228753Smm if (bidder == NULL) 88228753Smm return (ARCHIVE_FATAL); 89228753Smm 90228753Smm bidder->data = NULL; 91228753Smm bidder->bid = gzip_bidder_bid; 92228753Smm bidder->init = gzip_bidder_init; 93228753Smm bidder->options = NULL; 94228753Smm bidder->free = NULL; /* No data, so no cleanup necessary. */ 95228753Smm /* Signal the extent of gzip support with the return value here. */ 96228753Smm#if HAVE_ZLIB_H 97228753Smm return (ARCHIVE_OK); 98228753Smm#else 99228753Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 100228753Smm "Using external gunzip program"); 101228753Smm return (ARCHIVE_WARN); 102228753Smm#endif 103228753Smm} 104228753Smm 105228753Smm/* 106228753Smm * Read and verify the header. 107228753Smm * 108228753Smm * Returns zero if the header couldn't be validated, else returns 109228753Smm * number of bytes in header. If pbits is non-NULL, it receives a 110228753Smm * count of bits verified, suitable for use by bidder. 111228753Smm */ 112228753Smmstatic int 113228753Smmpeek_at_header(struct archive_read_filter *filter, int *pbits) 114228753Smm{ 115228753Smm const unsigned char *p; 116228753Smm ssize_t avail, len; 117228753Smm int bits = 0; 118228753Smm int header_flags; 119228753Smm 120228753Smm /* Start by looking at the first ten bytes of the header, which 121228753Smm * is all fixed layout. */ 122228753Smm len = 10; 123228753Smm p = __archive_read_filter_ahead(filter, len, &avail); 124228753Smm if (p == NULL || avail == 0) 125228753Smm return (0); 126228753Smm if (p[0] != 037) 127228753Smm return (0); 128228753Smm bits += 8; 129228753Smm if (p[1] != 0213) 130228753Smm return (0); 131228753Smm bits += 8; 132228753Smm if (p[2] != 8) /* We only support deflation. */ 133228753Smm return (0); 134228753Smm bits += 8; 135228753Smm if ((p[3] & 0xE0)!= 0) /* No reserved flags set. */ 136228753Smm return (0); 137228753Smm bits += 3; 138228753Smm header_flags = p[3]; 139228753Smm /* Bytes 4-7 are mod time. */ 140228753Smm /* Byte 8 is deflate flags. */ 141228753Smm /* XXXX TODO: return deflate flags back to consume_header for use 142228753Smm in initializing the decompressor. */ 143228753Smm /* Byte 9 is OS. */ 144228753Smm 145228753Smm /* Optional extra data: 2 byte length plus variable body. */ 146228753Smm if (header_flags & 4) { 147228753Smm p = __archive_read_filter_ahead(filter, len + 2, &avail); 148228753Smm if (p == NULL) 149228753Smm return (0); 150228753Smm len += ((int)p[len + 1] << 8) | (int)p[len]; 151228753Smm len += 2; 152228753Smm } 153228753Smm 154228753Smm /* Null-terminated optional filename. */ 155228753Smm if (header_flags & 8) { 156228753Smm do { 157228753Smm ++len; 158228753Smm if (avail < len) 159228753Smm p = __archive_read_filter_ahead(filter, 160228753Smm len, &avail); 161228753Smm if (p == NULL) 162228753Smm return (0); 163228753Smm } while (p[len - 1] != 0); 164228753Smm } 165228753Smm 166228753Smm /* Null-terminated optional comment. */ 167228753Smm if (header_flags & 16) { 168228753Smm do { 169228753Smm ++len; 170228753Smm if (avail < len) 171228753Smm p = __archive_read_filter_ahead(filter, 172228753Smm len, &avail); 173228753Smm if (p == NULL) 174228753Smm return (0); 175228753Smm } while (p[len - 1] != 0); 176228753Smm } 177228753Smm 178228753Smm /* Optional header CRC */ 179228753Smm if ((header_flags & 2)) { 180228753Smm p = __archive_read_filter_ahead(filter, len + 2, &avail); 181228753Smm if (p == NULL) 182228753Smm return (0); 183228753Smm#if 0 184228753Smm int hcrc = ((int)p[len + 1] << 8) | (int)p[len]; 185228753Smm int crc = /* XXX TODO: Compute header CRC. */; 186228753Smm if (crc != hcrc) 187228753Smm return (0); 188228753Smm bits += 16; 189228753Smm#endif 190228753Smm len += 2; 191228753Smm } 192228753Smm 193228753Smm if (pbits != NULL) 194228753Smm *pbits = bits; 195228753Smm return (len); 196228753Smm} 197228753Smm 198228753Smm/* 199228753Smm * Bidder just verifies the header and returns the number of verified bits. 200228753Smm */ 201228753Smmstatic int 202228753Smmgzip_bidder_bid(struct archive_read_filter_bidder *self, 203228753Smm struct archive_read_filter *filter) 204228753Smm{ 205228753Smm int bits_checked; 206228753Smm 207228753Smm (void)self; /* UNUSED */ 208228753Smm 209228753Smm if (peek_at_header(filter, &bits_checked)) 210228753Smm return (bits_checked); 211228753Smm return (0); 212228753Smm} 213228753Smm 214228753Smm 215228753Smm#ifndef HAVE_ZLIB_H 216228753Smm 217228753Smm/* 218228753Smm * If we don't have the library on this system, we can't do the 219228753Smm * decompression directly. We can, however, try to run gunzip 220228753Smm * in case that's available. 221228753Smm */ 222228753Smmstatic int 223228753Smmgzip_bidder_init(struct archive_read_filter *self) 224228753Smm{ 225228753Smm int r; 226228753Smm 227228753Smm r = __archive_read_program(self, "gunzip"); 228228753Smm /* Note: We set the format here even if __archive_read_program() 229228753Smm * above fails. We do, after all, know what the format is 230228753Smm * even if we weren't able to read it. */ 231228753Smm self->code = ARCHIVE_COMPRESSION_GZIP; 232228753Smm self->name = "gzip"; 233228753Smm return (r); 234228753Smm} 235228753Smm 236228753Smm#else 237228753Smm 238228753Smm/* 239228753Smm * Initialize the filter object. 240228753Smm */ 241228753Smmstatic int 242228753Smmgzip_bidder_init(struct archive_read_filter *self) 243228753Smm{ 244228753Smm struct private_data *state; 245228753Smm static const size_t out_block_size = 64 * 1024; 246228753Smm void *out_block; 247228753Smm 248228753Smm self->code = ARCHIVE_COMPRESSION_GZIP; 249228753Smm self->name = "gzip"; 250228753Smm 251228753Smm state = (struct private_data *)calloc(sizeof(*state), 1); 252228753Smm out_block = (unsigned char *)malloc(out_block_size); 253228753Smm if (state == NULL || out_block == NULL) { 254228753Smm free(out_block); 255228753Smm free(state); 256228753Smm archive_set_error(&self->archive->archive, ENOMEM, 257228753Smm "Can't allocate data for gzip decompression"); 258228753Smm return (ARCHIVE_FATAL); 259228753Smm } 260228753Smm 261228753Smm self->data = state; 262228753Smm state->out_block_size = out_block_size; 263228753Smm state->out_block = out_block; 264228753Smm self->read = gzip_filter_read; 265228753Smm self->skip = NULL; /* not supported */ 266228753Smm self->close = gzip_filter_close; 267228753Smm 268228753Smm state->in_stream = 0; /* We're not actually within a stream yet. */ 269228753Smm 270228753Smm return (ARCHIVE_OK); 271228753Smm} 272228753Smm 273228753Smmstatic int 274228753Smmconsume_header(struct archive_read_filter *self) 275228753Smm{ 276228753Smm struct private_data *state; 277228753Smm ssize_t avail; 278228753Smm size_t len; 279228753Smm int ret; 280228753Smm 281228753Smm state = (struct private_data *)self->data; 282228753Smm 283228753Smm /* If this is a real header, consume it. */ 284228753Smm len = peek_at_header(self->upstream, NULL); 285228753Smm if (len == 0) 286228753Smm return (ARCHIVE_EOF); 287228753Smm __archive_read_filter_consume(self->upstream, len); 288228753Smm 289228753Smm /* Initialize CRC accumulator. */ 290228753Smm state->crc = crc32(0L, NULL, 0); 291228753Smm 292228753Smm /* Initialize compression library. */ 293228753Smm state->stream.next_in = (unsigned char *)(uintptr_t) 294228753Smm __archive_read_filter_ahead(self->upstream, 1, &avail); 295228753Smm state->stream.avail_in = avail; 296228753Smm ret = inflateInit2(&(state->stream), 297228753Smm -15 /* Don't check for zlib header */); 298228753Smm 299228753Smm /* Decipher the error code. */ 300228753Smm switch (ret) { 301228753Smm case Z_OK: 302228753Smm state->in_stream = 1; 303228753Smm return (ARCHIVE_OK); 304228753Smm case Z_STREAM_ERROR: 305228753Smm archive_set_error(&self->archive->archive, 306228753Smm ARCHIVE_ERRNO_MISC, 307228753Smm "Internal error initializing compression library: " 308228753Smm "invalid setup parameter"); 309228753Smm break; 310228753Smm case Z_MEM_ERROR: 311228753Smm archive_set_error(&self->archive->archive, ENOMEM, 312228753Smm "Internal error initializing compression library: " 313228753Smm "out of memory"); 314228753Smm break; 315228753Smm case Z_VERSION_ERROR: 316228753Smm archive_set_error(&self->archive->archive, 317228753Smm ARCHIVE_ERRNO_MISC, 318228753Smm "Internal error initializing compression library: " 319228753Smm "invalid library version"); 320228753Smm break; 321228753Smm default: 322228753Smm archive_set_error(&self->archive->archive, 323228753Smm ARCHIVE_ERRNO_MISC, 324228753Smm "Internal error initializing compression library: " 325228753Smm " Zlib error %d", ret); 326228753Smm break; 327228753Smm } 328228753Smm return (ARCHIVE_FATAL); 329228753Smm} 330228753Smm 331228753Smmstatic int 332228753Smmconsume_trailer(struct archive_read_filter *self) 333228753Smm{ 334228753Smm struct private_data *state; 335228753Smm const unsigned char *p; 336228753Smm ssize_t avail; 337228753Smm 338228753Smm state = (struct private_data *)self->data; 339228753Smm 340228753Smm state->in_stream = 0; 341228753Smm switch (inflateEnd(&(state->stream))) { 342228753Smm case Z_OK: 343228753Smm break; 344228753Smm default: 345228753Smm archive_set_error(&self->archive->archive, 346228753Smm ARCHIVE_ERRNO_MISC, 347228753Smm "Failed to clean up gzip decompressor"); 348228753Smm return (ARCHIVE_FATAL); 349228753Smm } 350228753Smm 351228753Smm /* GZip trailer is a fixed 8 byte structure. */ 352228753Smm p = __archive_read_filter_ahead(self->upstream, 8, &avail); 353228753Smm if (p == NULL || avail == 0) 354228753Smm return (ARCHIVE_FATAL); 355228753Smm 356228753Smm /* XXX TODO: Verify the length and CRC. */ 357228753Smm 358228753Smm /* We've verified the trailer, so consume it now. */ 359228753Smm __archive_read_filter_consume(self->upstream, 8); 360228753Smm 361228753Smm return (ARCHIVE_OK); 362228753Smm} 363228753Smm 364228753Smmstatic ssize_t 365228753Smmgzip_filter_read(struct archive_read_filter *self, const void **p) 366228753Smm{ 367228753Smm struct private_data *state; 368228753Smm size_t decompressed; 369228753Smm ssize_t avail_in; 370228753Smm int ret; 371228753Smm 372228753Smm state = (struct private_data *)self->data; 373228753Smm 374228753Smm /* Empty our output buffer. */ 375228753Smm state->stream.next_out = state->out_block; 376228753Smm state->stream.avail_out = state->out_block_size; 377228753Smm 378228753Smm /* Try to fill the output buffer. */ 379228753Smm while (state->stream.avail_out > 0 && !state->eof) { 380228753Smm /* If we're not in a stream, read a header 381228753Smm * and initialize the decompression library. */ 382228753Smm if (!state->in_stream) { 383228753Smm ret = consume_header(self); 384228753Smm if (ret == ARCHIVE_EOF) { 385228753Smm state->eof = 1; 386228753Smm break; 387228753Smm } 388228753Smm if (ret < ARCHIVE_OK) 389228753Smm return (ret); 390228753Smm } 391228753Smm 392228753Smm /* Peek at the next available data. */ 393228753Smm /* ZLib treats stream.next_in as const but doesn't declare 394228753Smm * it so, hence this ugly cast. */ 395228753Smm state->stream.next_in = (unsigned char *)(uintptr_t) 396228753Smm __archive_read_filter_ahead(self->upstream, 1, &avail_in); 397228753Smm if (state->stream.next_in == NULL) 398228753Smm return (ARCHIVE_FATAL); 399228753Smm state->stream.avail_in = avail_in; 400228753Smm 401228753Smm /* Decompress and consume some of that data. */ 402228753Smm ret = inflate(&(state->stream), 0); 403228753Smm switch (ret) { 404228753Smm case Z_OK: /* Decompressor made some progress. */ 405228753Smm __archive_read_filter_consume(self->upstream, 406228753Smm avail_in - state->stream.avail_in); 407228753Smm break; 408228753Smm case Z_STREAM_END: /* Found end of stream. */ 409228753Smm __archive_read_filter_consume(self->upstream, 410228753Smm avail_in - state->stream.avail_in); 411228753Smm /* Consume the stream trailer; release the 412228753Smm * decompression library. */ 413228753Smm ret = consume_trailer(self); 414228753Smm if (ret < ARCHIVE_OK) 415228753Smm return (ret); 416228753Smm break; 417228753Smm default: 418228753Smm /* Return an error. */ 419228753Smm archive_set_error(&self->archive->archive, 420228753Smm ARCHIVE_ERRNO_MISC, 421228753Smm "gzip decompression failed"); 422228753Smm return (ARCHIVE_FATAL); 423228753Smm } 424228753Smm } 425228753Smm 426228753Smm /* We've read as much as we can. */ 427228753Smm decompressed = state->stream.next_out - state->out_block; 428228753Smm state->total_out += decompressed; 429228753Smm if (decompressed == 0) 430228753Smm *p = NULL; 431228753Smm else 432228753Smm *p = state->out_block; 433228753Smm return (decompressed); 434228753Smm} 435228753Smm 436228753Smm/* 437228753Smm * Clean up the decompressor. 438228753Smm */ 439228753Smmstatic int 440228753Smmgzip_filter_close(struct archive_read_filter *self) 441228753Smm{ 442228753Smm struct private_data *state; 443228753Smm int ret; 444228753Smm 445228753Smm state = (struct private_data *)self->data; 446228753Smm ret = ARCHIVE_OK; 447228753Smm 448228753Smm if (state->in_stream) { 449228753Smm switch (inflateEnd(&(state->stream))) { 450228753Smm case Z_OK: 451228753Smm break; 452228753Smm default: 453228753Smm archive_set_error(&(self->archive->archive), 454228753Smm ARCHIVE_ERRNO_MISC, 455228753Smm "Failed to clean up gzip compressor"); 456228753Smm ret = ARCHIVE_FATAL; 457228753Smm } 458228753Smm } 459228753Smm 460228753Smm free(state->out_block); 461228753Smm free(state); 462228753Smm return (ret); 463228753Smm} 464228753Smm 465228753Smm#endif /* HAVE_ZLIB_H */ 466