2
* Copyright (c) 2003-2007 Tim Kientzle
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
#include "archive_platform.h"
28
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_compression_gzip.c 201082 2009-12-28 02:05:28Z kientzle $");
48
#include "archive_private.h"
49
#include "archive_read_private.h"
55
unsigned char *out_block;
56
size_t out_block_size;
59
char eof; /* True = found end of compressed data. */
63
static ssize_t gzip_filter_read(struct archive_read_filter *, const void **);
64
static int gzip_filter_close(struct archive_read_filter *);
68
* Note that we can detect gzip archives even if we can't decompress
69
* them. (In fact, we like detecting them because we can give better
70
* error messages.) So the bid framework here gets compiled even
71
* if zlib is unavailable.
73
* TODO: If zlib is unavailable, gzip_bidder_init() should
74
* use the compress_program framework to try to fire up an external
77
static int gzip_bidder_bid(struct archive_read_filter_bidder *,
78
struct archive_read_filter *);
79
static int gzip_bidder_init(struct archive_read_filter *);
82
archive_read_support_compression_gzip(struct archive *_a)
84
struct archive_read *a = (struct archive_read *)_a;
85
struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a);
88
return (ARCHIVE_FATAL);
91
bidder->bid = gzip_bidder_bid;
92
bidder->init = gzip_bidder_init;
93
bidder->options = NULL;
94
bidder->free = NULL; /* No data, so no cleanup necessary. */
95
/* Signal the extent of gzip support with the return value here. */
99
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
100
"Using external gunzip program");
101
return (ARCHIVE_WARN);
106
* Read and verify the header.
108
* Returns zero if the header couldn't be validated, else returns
109
* number of bytes in header. If pbits is non-NULL, it receives a
110
* count of bits verified, suitable for use by bidder.
113
peek_at_header(struct archive_read_filter *filter, int *pbits)
115
const unsigned char *p;
120
/* Start by looking at the first ten bytes of the header, which
121
* is all fixed layout. */
123
p = __archive_read_filter_ahead(filter, len, &avail);
124
if (p == NULL || avail == 0)
132
if (p[2] != 8) /* We only support deflation. */
135
if ((p[3] & 0xE0)!= 0) /* No reserved flags set. */
139
/* Bytes 4-7 are mod time. */
140
/* Byte 8 is deflate flags. */
141
/* XXXX TODO: return deflate flags back to consume_header for use
142
in initializing the decompressor. */
145
/* Optional extra data: 2 byte length plus variable body. */
146
if (header_flags & 4) {
147
p = __archive_read_filter_ahead(filter, len + 2, &avail);
150
len += ((int)p[len + 1] << 8) | (int)p[len];
154
/* Null-terminated optional filename. */
155
if (header_flags & 8) {
159
p = __archive_read_filter_ahead(filter,
163
} while (p[len - 1] != 0);
166
/* Null-terminated optional comment. */
167
if (header_flags & 16) {
171
p = __archive_read_filter_ahead(filter,
175
} while (p[len - 1] != 0);
178
/* Optional header CRC */
179
if ((header_flags & 2)) {
180
p = __archive_read_filter_ahead(filter, len + 2, &avail);
184
int hcrc = ((int)p[len + 1] << 8) | (int)p[len];
185
int crc = /* XXX TODO: Compute header CRC. */;
199
* Bidder just verifies the header and returns the number of verified bits.
202
gzip_bidder_bid(struct archive_read_filter_bidder *self,
203
struct archive_read_filter *filter)
207
(void)self; /* UNUSED */
209
if (peek_at_header(filter, &bits_checked))
210
return (bits_checked);
218
* If we don't have the library on this system, we can't do the
219
* decompression directly. We can, however, try to run gunzip
220
* in case that's available.
223
gzip_bidder_init(struct archive_read_filter *self)
227
r = __archive_read_program(self, "gunzip");
228
/* Note: We set the format here even if __archive_read_program()
229
* above fails. We do, after all, know what the format is
230
* even if we weren't able to read it. */
231
self->code = ARCHIVE_COMPRESSION_GZIP;
239
* Initialize the filter object.
242
gzip_bidder_init(struct archive_read_filter *self)
244
struct private_data *state;
245
static const size_t out_block_size = 64 * 1024;
248
self->code = ARCHIVE_COMPRESSION_GZIP;
251
state = (struct private_data *)calloc(sizeof(*state), 1);
252
out_block = (unsigned char *)malloc(out_block_size);
253
if (state == NULL || out_block == NULL) {
256
archive_set_error(&self->archive->archive, ENOMEM,
257
"Can't allocate data for gzip decompression");
258
return (ARCHIVE_FATAL);
262
state->out_block_size = out_block_size;
263
state->out_block = out_block;
264
self->read = gzip_filter_read;
265
self->skip = NULL; /* not supported */
266
self->close = gzip_filter_close;
268
state->in_stream = 0; /* We're not actually within a stream yet. */
274
consume_header(struct archive_read_filter *self)
276
struct private_data *state;
281
state = (struct private_data *)self->data;
283
/* If this is a real header, consume it. */
284
len = peek_at_header(self->upstream, NULL);
286
return (ARCHIVE_EOF);
287
__archive_read_filter_consume(self->upstream, len);
289
/* Initialize CRC accumulator. */
290
state->crc = crc32(0L, NULL, 0);
292
/* Initialize compression library. */
293
state->stream.next_in = (unsigned char *)(uintptr_t)
294
__archive_read_filter_ahead(self->upstream, 1, &avail);
295
state->stream.avail_in = avail;
296
ret = inflateInit2(&(state->stream),
297
-15 /* Don't check for zlib header */);
299
/* Decipher the error code. */
302
state->in_stream = 1;
305
archive_set_error(&self->archive->archive,
307
"Internal error initializing compression library: "
308
"invalid setup parameter");
311
archive_set_error(&self->archive->archive, ENOMEM,
312
"Internal error initializing compression library: "
315
case Z_VERSION_ERROR:
316
archive_set_error(&self->archive->archive,
318
"Internal error initializing compression library: "
319
"invalid library version");
322
archive_set_error(&self->archive->archive,
324
"Internal error initializing compression library: "
325
" Zlib error %d", ret);
328
return (ARCHIVE_FATAL);
332
consume_trailer(struct archive_read_filter *self)
334
struct private_data *state;
335
const unsigned char *p;
338
state = (struct private_data *)self->data;
340
state->in_stream = 0;
341
switch (inflateEnd(&(state->stream))) {
345
archive_set_error(&self->archive->archive,
347
"Failed to clean up gzip decompressor");
348
return (ARCHIVE_FATAL);
351
/* GZip trailer is a fixed 8 byte structure. */
352
p = __archive_read_filter_ahead(self->upstream, 8, &avail);
353
if (p == NULL || avail == 0)
354
return (ARCHIVE_FATAL);
356
/* XXX TODO: Verify the length and CRC. */
358
/* We've verified the trailer, so consume it now. */
359
__archive_read_filter_consume(self->upstream, 8);
365
gzip_filter_read(struct archive_read_filter *self, const void **p)
367
struct private_data *state;
372
state = (struct private_data *)self->data;
374
/* Empty our output buffer. */
375
state->stream.next_out = state->out_block;
376
state->stream.avail_out = state->out_block_size;
378
/* Try to fill the output buffer. */
379
while (state->stream.avail_out > 0 && !state->eof) {
380
/* If we're not in a stream, read a header
381
* and initialize the decompression library. */
382
if (!state->in_stream) {
383
ret = consume_header(self);
384
if (ret == ARCHIVE_EOF) {
388
if (ret < ARCHIVE_OK)
392
/* Peek at the next available data. */
393
/* ZLib treats stream.next_in as const but doesn't declare
394
* it so, hence this ugly cast. */
395
state->stream.next_in = (unsigned char *)(uintptr_t)
396
__archive_read_filter_ahead(self->upstream, 1, &avail_in);
397
if (state->stream.next_in == NULL)
398
return (ARCHIVE_FATAL);
399
state->stream.avail_in = avail_in;
401
/* Decompress and consume some of that data. */
402
ret = inflate(&(state->stream), 0);
404
case Z_OK: /* Decompressor made some progress. */
405
__archive_read_filter_consume(self->upstream,
406
avail_in - state->stream.avail_in);
408
case Z_STREAM_END: /* Found end of stream. */
409
__archive_read_filter_consume(self->upstream,
410
avail_in - state->stream.avail_in);
411
/* Consume the stream trailer; release the
412
* decompression library. */
413
ret = consume_trailer(self);
414
if (ret < ARCHIVE_OK)
418
/* Return an error. */
419
archive_set_error(&self->archive->archive,
421
"gzip decompression failed");
422
return (ARCHIVE_FATAL);
426
/* We've read as much as we can. */
427
decompressed = state->stream.next_out - state->out_block;
428
state->total_out += decompressed;
429
if (decompressed == 0)
432
*p = state->out_block;
433
return (decompressed);
437
* Clean up the decompressor.
440
gzip_filter_close(struct archive_read_filter *self)
442
struct private_data *state;
445
state = (struct private_data *)self->data;
448
if (state->in_stream) {
449
switch (inflateEnd(&(state->stream))) {
453
archive_set_error(&(self->archive->archive),
455
"Failed to clean up gzip compressor");
460
free(state->out_block);
465
#endif /* HAVE_ZLIB_H */