~db-keen/tanzanite/rat

« back to all changes in this revision

Viewing changes to sources/libarchive-1.2.53/libarchive/archive_read_support_compression_gzip.c

  • Committer: austin
  • Date: 2007-02-05 03:24:13 UTC
  • Revision ID: svn-v4:8b90d6ed-dc11-0410-98dd-e2d1db709ad4:rat/spikes/2006-05-13:45
Reorganizing the RAT project.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2003-2004 Tim Kientzle
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer
 
10
 *    in this position and unchanged.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 *
 
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
18
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
#include "archive_platform.h"
 
28
 
 
29
__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_gzip.c,v 1.9 2005/03/13 01:48:33 kientzle Exp $");
 
30
 
 
31
 
 
32
#include <errno.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <unistd.h>
 
36
#ifdef HAVE_ZLIB_H
 
37
#include <zlib.h>
 
38
#endif
 
39
 
 
40
#include "archive.h"
 
41
#include "archive_private.h"
 
42
 
 
43
#ifdef HAVE_ZLIB_H
 
44
struct private_data {
 
45
        z_stream         stream;
 
46
        unsigned char   *uncompressed_buffer;
 
47
        size_t           uncompressed_buffer_size;
 
48
        unsigned char   *read_next;
 
49
        int64_t          total_out;
 
50
        unsigned long    crc;
 
51
        char             header_done;
 
52
};
 
53
 
 
54
static int      finish(struct archive *);
 
55
static ssize_t  read_ahead(struct archive *, const void **, size_t);
 
56
static ssize_t  read_consume(struct archive *, size_t);
 
57
static int      drive_decompressor(struct archive *a, struct private_data *);
 
58
#endif
 
59
 
 
60
/* These two functions are defined even if we lack zlib.  See below. */
 
61
static int      bid(const void *, size_t);
 
62
static int      init(struct archive *, const void *, size_t);
 
63
 
 
64
int
 
65
archive_read_support_compression_gzip(struct archive *a)
 
66
{
 
67
        return (__archive_read_register_compression(a, bid, init));
 
68
}
 
69
 
 
70
/*
 
71
 * Test whether we can handle this data.
 
72
 *
 
73
 * This logic returns zero if any part of the signature fails.  It
 
74
 * also tries to Do The Right Thing if a very short buffer prevents us
 
75
 * from verifying as much as we would like.
 
76
 */
 
77
static int
 
78
bid(const void *buff, size_t len)
 
79
{
 
80
        const unsigned char *buffer;
 
81
        int bits_checked;
 
82
 
 
83
        if (len < 1)
 
84
                return (0);
 
85
 
 
86
        buffer = buff;
 
87
        bits_checked = 0;
 
88
        if (buffer[0] != 037)   /* Verify first ID byte. */
 
89
                return (0);
 
90
        bits_checked += 8;
 
91
        if (len < 2)
 
92
                return (bits_checked);
 
93
 
 
94
        if (buffer[1] != 0213)  /* Verify second ID byte. */
 
95
                return (0);
 
96
        bits_checked += 8;
 
97
        if (len < 3)
 
98
                return (bits_checked);
 
99
 
 
100
        if (buffer[2] != 8)     /* Compression must be 'deflate'. */
 
101
                return (0);
 
102
        bits_checked += 8;
 
103
        if (len < 4)
 
104
                return (bits_checked);
 
105
 
 
106
        if ((buffer[3] & 0xE0)!= 0)     /* No reserved flags set. */
 
107
                return (0);
 
108
        bits_checked += 3;
 
109
        if (len < 5)
 
110
                return (bits_checked);
 
111
 
 
112
        /*
 
113
         * TODO: Verify more; in particular, gzip has an optional
 
114
         * header CRC, which would give us 16 more verified bits.  We
 
115
         * may also be able to verify certain constraints on other
 
116
         * fields.
 
117
         */
 
118
 
 
119
        return (bits_checked);
 
120
}
 
121
 
 
122
 
 
123
#ifndef HAVE_ZLIB_H
 
124
 
 
125
/*
 
126
 * If we don't have zlib on this system, we can't actually do the
 
127
 * decompression.  We can, however, still detect gzip-compressed
 
128
 * archives and emit a useful message.
 
129
 */
 
130
static int
 
131
init(struct archive *a, const void *buff, size_t n)
 
132
{
 
133
        (void)a;        /* UNUSED */
 
134
        (void)buff;     /* UNUSED */
 
135
        (void)n;        /* UNUSED */
 
136
 
 
137
        archive_set_error(a, -1,
 
138
            "This version of libarchive was compiled without gzip support");
 
139
        return (ARCHIVE_FATAL);
 
140
}
 
141
 
 
142
 
 
143
#else
 
144
 
 
145
/*
 
146
 * Setup the callbacks.
 
147
 */
 
148
static int
 
149
init(struct archive *a, const void *buff, size_t n)
 
150
{
 
151
        struct private_data *state;
 
152
        int ret;
 
153
 
 
154
        a->compression_code = ARCHIVE_COMPRESSION_GZIP;
 
155
        a->compression_name = "gzip";
 
156
 
 
157
        state = malloc(sizeof(*state));
 
158
        if (state == NULL) {
 
159
                archive_set_error(a, ENOMEM,
 
160
                    "Can't allocate data for %s decompression",
 
161
                    a->compression_name);
 
162
                return (ARCHIVE_FATAL);
 
163
        }
 
164
        memset(state, 0, sizeof(*state));
 
165
 
 
166
        state->crc = crc32(0L, NULL, 0);
 
167
        state->header_done = 0; /* We've not yet begun to parse header... */
 
168
 
 
169
        state->uncompressed_buffer_size = 64 * 1024;
 
170
        state->uncompressed_buffer = malloc(state->uncompressed_buffer_size);
 
171
        state->stream.next_out = state->uncompressed_buffer;
 
172
        state->read_next = state->uncompressed_buffer;
 
173
        state->stream.avail_out = state->uncompressed_buffer_size;
 
174
 
 
175
        if (state->uncompressed_buffer == NULL) {
 
176
                archive_set_error(a, ENOMEM,
 
177
                    "Can't allocate %s decompression buffers",
 
178
                    a->compression_name);
 
179
                free(state);
 
180
                return (ARCHIVE_FATAL);
 
181
        }
 
182
 
 
183
        /*
 
184
         * A bug in zlib.h: stream.next_in should be marked 'const'
 
185
         * but isn't (the library never alters data through the
 
186
         * next_in pointer, only reads it).  The result: this ugly
 
187
         * cast to remove 'const'.
 
188
         */
 
189
        state->stream.next_in = (void *)(uintptr_t)(const void *)buff;
 
190
        state->stream.avail_in = n;
 
191
 
 
192
        a->compression_read_ahead = read_ahead;
 
193
        a->compression_read_consume = read_consume;
 
194
        a->compression_finish = finish;
 
195
 
 
196
        /*
 
197
         * TODO: Do I need to parse the gzip header before calling
 
198
         * inflateInit2()?  In particular, one of the header bytes
 
199
         * marks "best compression" or "fastest", which may be
 
200
         * appropriate for setting the second parameter here.
 
201
         * However, I think the only penalty for not setting it
 
202
         * correctly is wasted memory.  If this is necessary, it
 
203
         * should probably go into drive_decompressor() below.
 
204
         */
 
205
 
 
206
        /* Initialize compression library. */
 
207
        ret = inflateInit2(&(state->stream),
 
208
            -15 /* Don't check for zlib header */);
 
209
        if (ret == Z_OK) {
 
210
                a->compression_data = state;
 
211
                return (ARCHIVE_OK);
 
212
        }
 
213
 
 
214
        /* Library setup failed: Clean up. */
 
215
        archive_set_error(a, ARCHIVE_ERRNO_MISC,
 
216
            "Internal error initializing %s library", a->compression_name);
 
217
        free(state->uncompressed_buffer);
 
218
        free(state);
 
219
 
 
220
        /* Override the error message if we know what really went wrong. */
 
221
        switch (ret) {
 
222
        case Z_STREAM_ERROR:
 
223
                archive_set_error(a, ARCHIVE_ERRNO_MISC,
 
224
                    "Internal error initializing compression library: "
 
225
                    "invalid setup parameter");
 
226
                break;
 
227
        case Z_MEM_ERROR:
 
228
                archive_set_error(a, ENOMEM,
 
229
                    "Internal error initializing compression library: "
 
230
                    "out of memory");
 
231
                break;
 
232
        case Z_VERSION_ERROR:
 
233
                archive_set_error(a, ARCHIVE_ERRNO_MISC,
 
234
                    "Internal error initializing compression library: "
 
235
                    "invalid library version");
 
236
                break;
 
237
        }
 
238
 
 
239
        return (ARCHIVE_FATAL);
 
240
}
 
241
 
 
242
/*
 
243
 * Return a block of data from the decompression buffer.  Decompress more
 
244
 * as necessary.
 
245
 */
 
246
static ssize_t
 
247
read_ahead(struct archive *a, const void **p, size_t min)
 
248
{
 
249
        struct private_data *state;
 
250
        int read_avail, was_avail, ret;
 
251
 
 
252
        state = a->compression_data;
 
253
        was_avail = -1;
 
254
        if (!a->client_reader) {
 
255
                archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
 
256
                    "No read callback is registered?  "
 
257
                    "This is probably an internal programming error.");
 
258
                return (ARCHIVE_FATAL);
 
259
        }
 
260
 
 
261
        read_avail = state->stream.next_out - state->read_next;
 
262
 
 
263
        if (read_avail + state->stream.avail_out < min) {
 
264
                memmove(state->uncompressed_buffer, state->read_next,
 
265
                    read_avail);
 
266
                state->read_next = state->uncompressed_buffer;
 
267
                state->stream.next_out = state->read_next + read_avail;
 
268
                state->stream.avail_out
 
269
                    = state->uncompressed_buffer_size - read_avail;
 
270
        }
 
271
 
 
272
        while (was_avail < read_avail &&        /* Made some progress. */
 
273
            read_avail < (int)min &&            /* Haven't satisfied min. */
 
274
            read_avail < (int)state->uncompressed_buffer_size) { /* !full */
 
275
                if ((ret = drive_decompressor(a, state)) != ARCHIVE_OK)
 
276
                        return (ret);
 
277
                was_avail = read_avail;
 
278
                read_avail = state->stream.next_out - state->read_next;
 
279
        }
 
280
 
 
281
        *p = state->read_next;
 
282
        return (read_avail);
 
283
}
 
284
 
 
285
/*
 
286
 * Mark a previously-returned block of data as read.
 
287
 */
 
288
static ssize_t
 
289
read_consume(struct archive *a, size_t n)
 
290
{
 
291
        struct private_data *state;
 
292
 
 
293
        state = a->compression_data;
 
294
        a->file_position += n;
 
295
        state->read_next += n;
 
296
        if (state->read_next > state->stream.next_out)
 
297
                __archive_errx(1, "Request to consume too many "
 
298
                    "bytes from gzip decompressor");
 
299
        return (n);
 
300
}
 
301
 
 
302
/*
 
303
 * Clean up the decompressor.
 
304
 */
 
305
static int
 
306
finish(struct archive *a)
 
307
{
 
308
        struct private_data *state;
 
309
        int ret;
 
310
 
 
311
        state = a->compression_data;
 
312
        ret = ARCHIVE_OK;
 
313
        switch (inflateEnd(&(state->stream))) {
 
314
        case Z_OK:
 
315
                break;
 
316
        default:
 
317
                archive_set_error(a, ARCHIVE_ERRNO_MISC,
 
318
                    "Failed to clean up %s compressor", a->compression_name);
 
319
                ret = ARCHIVE_FATAL;
 
320
        }
 
321
 
 
322
        free(state->uncompressed_buffer);
 
323
        free(state);
 
324
 
 
325
        a->compression_data = NULL;
 
326
        if (a->client_closer != NULL)
 
327
                (a->client_closer)(a, a->client_data);
 
328
 
 
329
        return (ret);
 
330
}
 
331
 
 
332
/*
 
333
 * Utility function to pull data through decompressor, reading input
 
334
 * blocks as necessary.
 
335
 */
 
336
static int
 
337
drive_decompressor(struct archive *a, struct private_data *state)
 
338
{
 
339
        ssize_t ret;
 
340
        int decompressed, total_decompressed;
 
341
        int count, flags, header_state;
 
342
        unsigned char *output;
 
343
        unsigned char b;
 
344
 
 
345
        flags = 0;
 
346
        count = 0;
 
347
        header_state = 0;
 
348
        total_decompressed = 0;
 
349
        for (;;) {
 
350
                if (state->stream.avail_in == 0) {
 
351
                        ret = (a->client_reader)(a, a->client_data,
 
352
                            (const void **)&state->stream.next_in);
 
353
                        if (ret < 0) {
 
354
                                /*
 
355
                                 * TODO: Find a better way to handle
 
356
                                 * this read failure.
 
357
                                 */
 
358
                                goto fatal;
 
359
                        }
 
360
                        if (ret == 0  &&  total_decompressed == 0) {
 
361
                                archive_set_error(a, EIO,
 
362
                                    "Premature end of %s compressed data",
 
363
                                    a->compression_name);
 
364
                                return (ARCHIVE_FATAL);
 
365
                        }
 
366
                        a->raw_position += ret;
 
367
                        state->stream.avail_in = ret;
 
368
                }
 
369
 
 
370
                if (!state->header_done) {
 
371
                        /*
 
372
                         * If still parsing the header, interpret the
 
373
                         * next byte.
 
374
                         */
 
375
                        b = *(state->stream.next_in++);
 
376
                        state->stream.avail_in--;
 
377
 
 
378
                        /*
 
379
                         * Yes, this is somewhat crude, but it works,
 
380
                         * GZip format isn't likely to change anytime
 
381
                         * in the near future, and header parsing is
 
382
                         * certainly not a performance issue, so
 
383
                         * there's little point in making this more
 
384
                         * elegant.  Of course, if you see an easy way
 
385
                         * to make this more elegant, please let me
 
386
                         * know.. ;-)
 
387
                         */
 
388
                        switch (header_state) {
 
389
                        case 0: /* First byte of signature. */
 
390
                                if (b != 037)
 
391
                                        goto fatal;
 
392
                                header_state = 1;
 
393
                                break;
 
394
                        case 1: /* Second byte of signature. */
 
395
                                if (b != 0213)
 
396
                                        goto fatal;
 
397
                                header_state = 2;
 
398
                                break;
 
399
                        case 2: /* Compression type must be 8. */
 
400
                                if (b != 8)
 
401
                                        goto fatal;
 
402
                                header_state = 3;
 
403
                                break;
 
404
                        case 3: /* GZip flags. */
 
405
                                flags = b;
 
406
                                header_state = 4;
 
407
                                break;
 
408
                        case 4: case 5: case 6: case 7: /* Mod time. */
 
409
                                header_state++;
 
410
                                break;
 
411
                        case 8: /* Deflate flags. */
 
412
                                header_state = 9;
 
413
                                break;
 
414
                        case 9: /* OS. */
 
415
                                header_state = 10;
 
416
                                break;
 
417
                        case 10: /* Optional Extra: First byte of Length. */
 
418
                                if ((flags & 4)) {
 
419
                                        count = 255 & (int)b;
 
420
                                        header_state = 11;
 
421
                                        break;
 
422
                                }
 
423
                                /*
 
424
                                 * Fall through if there is no
 
425
                                 * Optional Extra field.
 
426
                                 */
 
427
                        case 11: /* Optional Extra: Second byte of Length. */
 
428
                                if ((flags & 4)) {
 
429
                                        count = (0xff00 & ((int)b << 8)) | count;
 
430
                                        header_state = 12;
 
431
                                        break;
 
432
                                }
 
433
                                /*
 
434
                                 * Fall through if there is no
 
435
                                 * Optional Extra field.
 
436
                                 */
 
437
                        case 12: /* Optional Extra Field: counted length. */
 
438
                                if ((flags & 4)) {
 
439
                                        --count;
 
440
                                        if (count == 0) header_state = 13;
 
441
                                        else header_state = 12;
 
442
                                        break;
 
443
                                }
 
444
                                /*
 
445
                                 * Fall through if there is no
 
446
                                 * Optional Extra field.
 
447
                                 */
 
448
                        case 13: /* Optional Original Filename. */
 
449
                                if ((flags & 8)) {
 
450
                                        if (b == 0) header_state = 14;
 
451
                                        else header_state = 13;
 
452
                                        break;
 
453
                                }
 
454
                                /*
 
455
                                 * Fall through if no Optional
 
456
                                 * Original Filename.
 
457
                                 */
 
458
                        case 14: /* Optional Comment. */
 
459
                                if ((flags & 16)) {
 
460
                                        if (b == 0) header_state = 15;
 
461
                                        else header_state = 14;
 
462
                                        break;
 
463
                                }
 
464
                                /* Fall through if no Optional Comment. */
 
465
                        case 15: /* Optional Header CRC: First byte. */
 
466
                                if ((flags & 2)) {
 
467
                                        header_state = 16;
 
468
                                        break;
 
469
                                }
 
470
                                /* Fall through if no Optional Header CRC. */
 
471
                        case 16: /* Optional Header CRC: Second byte. */
 
472
                                if ((flags & 2)) {
 
473
                                        header_state = 17;
 
474
                                        break;
 
475
                                }
 
476
                                /* Fall through if no Optional Header CRC. */
 
477
                        case 17: /* First byte of compressed data. */
 
478
                                state->header_done = 1; /* done with header */
 
479
                                state->stream.avail_in++;
 
480
                                state->stream.next_in--;
 
481
                        }
 
482
 
 
483
                        /*
 
484
                         * TODO: Consider moving the inflateInit2 call
 
485
                         * here so it can include the compression type
 
486
                         * from the header?
 
487
                         */
 
488
                } else {
 
489
                        output = state->stream.next_out;
 
490
 
 
491
                        /* Decompress some data. */
 
492
                        ret = inflate(&(state->stream), 0);
 
493
                        decompressed = state->stream.next_out - output;
 
494
 
 
495
                        /* Accumulate the CRC of the uncompressed data. */
 
496
                        state->crc = crc32(state->crc, output, decompressed);
 
497
 
 
498
                        /* Accumulate the total bytes of output. */
 
499
                        state->total_out += decompressed;
 
500
                        total_decompressed += decompressed;
 
501
 
 
502
                        switch (ret) {
 
503
                        case Z_OK: /* Decompressor made some progress. */
 
504
                                if (decompressed > 0)
 
505
                                        return (ARCHIVE_OK);
 
506
                                break;
 
507
                        case Z_STREAM_END: /* Found end of stream. */
 
508
                                /*
 
509
                                 * TODO: Verify gzip trailer
 
510
                                 * (uncompressed length and CRC).
 
511
                                 */
 
512
                                return (ARCHIVE_OK);
 
513
                        default:
 
514
                                /* Any other return value is an error. */
 
515
                                archive_set_error(a, ARCHIVE_ERRNO_MISC,
 
516
                                    "gzip decompression failed (%s)",
 
517
                                    state->stream.msg);
 
518
                                goto fatal;
 
519
                        }
 
520
                }
 
521
        }
 
522
        return (ARCHIVE_OK);
 
523
 
 
524
        /* Return a fatal error. */
 
525
fatal:
 
526
        archive_set_error(a, ARCHIVE_ERRNO_MISC, "%s decompression failed",
 
527
            a->compression_name);
 
528
        return (ARCHIVE_FATAL);
 
529
}
 
530
 
 
531
#endif /* HAVE_ZLIB_H */