Add our READMEs.
[dragonfly.git] / contrib / libarchive-2.1 / libarchive / archive_read_support_compression_bzip2.c
1 /*-
2  * Copyright (c) 2003-2007 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  * 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.
13  *
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.
24  */
25
26 #include "archive_platform.h"
27
28 __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.15 2007/04/05 05:18:16 kientzle Exp $");
29
30 #ifdef HAVE_ERRNO_H
31 #include <errno.h>
32 #endif
33 #include <stdio.h>
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43 #ifdef HAVE_BZLIB_H
44 #include <bzlib.h>
45 #endif
46
47 #include "archive.h"
48 #include "archive_private.h"
49 #include "archive_read_private.h"
50
51 #if HAVE_BZLIB_H
52 struct private_data {
53         bz_stream        stream;
54         char            *uncompressed_buffer;
55         size_t           uncompressed_buffer_size;
56         char            *read_next;
57         int64_t          total_out;
58 };
59
60 static int      finish(struct archive_read *);
61 static ssize_t  read_ahead(struct archive_read *, const void **, size_t);
62 static ssize_t  read_consume(struct archive_read *, size_t);
63 static int      drive_decompressor(struct archive_read *a, struct private_data *);
64 #endif
65
66 /* These two functions are defined even if we lack bzlib.  See below. */
67 static int      bid(const void *, size_t);
68 static int      init(struct archive_read *, const void *, size_t);
69
70 int
71 archive_read_support_compression_bzip2(struct archive *_a)
72 {
73         struct archive_read *a = (struct archive_read *)_a;
74         if (__archive_read_register_compression(a, bid, init) != NULL)
75                 return (ARCHIVE_OK);
76         return (ARCHIVE_FATAL);
77 }
78
79 /*
80  * Test whether we can handle this data.
81  *
82  * This logic returns zero if any part of the signature fails.  It
83  * also tries to Do The Right Thing if a very short buffer prevents us
84  * from verifying as much as we would like.
85  */
86 static int
87 bid(const void *buff, size_t len)
88 {
89         const unsigned char *buffer;
90         int bits_checked;
91
92         if (len < 1)
93                 return (0);
94
95         buffer = (const unsigned char *)buff;
96         bits_checked = 0;
97         if (buffer[0] != 'B')   /* Verify first ID byte. */
98                 return (0);
99         bits_checked += 8;
100         if (len < 2)
101                 return (bits_checked);
102
103         if (buffer[1] != 'Z')   /* Verify second ID byte. */
104                 return (0);
105         bits_checked += 8;
106         if (len < 3)
107                 return (bits_checked);
108
109         if (buffer[2] != 'h')   /* Verify third ID byte. */
110                 return (0);
111         bits_checked += 8;
112         if (len < 4)
113                 return (bits_checked);
114
115         if (buffer[3] < '1' || buffer[3] > '9')
116                 return (0);
117         bits_checked += 5;
118
119         /*
120          * Research Question: Can we do any more to verify that this
121          * really is BZip2 format??  For 99.9% of the time, the above
122          * test is sufficient, but it would be nice to do a more
123          * thorough check.  It's especially troubling that the BZip2
124          * signature begins with all ASCII characters; a tar archive
125          * whose first filename begins with 'BZh3' would potentially
126          * fool this logic.  (It may also be possible to guard against
127          * such anomalies in archive_read_support_compression_none.)
128          */
129
130         return (bits_checked);
131 }
132
133 #ifndef HAVE_BZLIB_H
134
135 /*
136  * If we don't have bzlib on this system, we can't actually do the
137  * decompression.  We can, however, still detect bzip2-compressed
138  * archives and emit a useful message.
139  */
140 static int
141 init(struct archive_read *a, const void *buff, size_t n)
142 {
143         (void)a;        /* UNUSED */
144         (void)buff;     /* UNUSED */
145         (void)n;        /* UNUSED */
146
147         archive_set_error(a, -1,
148             "This version of libarchive was compiled without bzip2 support");
149         return (ARCHIVE_FATAL);
150 }
151
152
153 #else
154
155 /*
156  * Setup the callbacks.
157  */
158 static int
159 init(struct archive_read *a, const void *buff, size_t n)
160 {
161         struct private_data *state;
162         int ret;
163
164         a->archive.compression_code = ARCHIVE_COMPRESSION_BZIP2;
165         a->archive.compression_name = "bzip2";
166
167         state = (struct private_data *)malloc(sizeof(*state));
168         if (state == NULL) {
169                 archive_set_error(&a->archive, ENOMEM,
170                     "Can't allocate data for %s decompression",
171                     a->archive.compression_name);
172                 return (ARCHIVE_FATAL);
173         }
174         memset(state, 0, sizeof(*state));
175
176         state->uncompressed_buffer_size = 64 * 1024;
177         state->uncompressed_buffer = (char *)malloc(state->uncompressed_buffer_size);
178         state->stream.next_out = state->uncompressed_buffer;
179         state->read_next = state->uncompressed_buffer;
180         state->stream.avail_out = state->uncompressed_buffer_size;
181
182         if (state->uncompressed_buffer == NULL) {
183                 archive_set_error(&a->archive, ENOMEM,
184                     "Can't allocate %s decompression buffers",
185                     a->archive.compression_name);
186                 free(state);
187                 return (ARCHIVE_FATAL);
188         }
189
190         /*
191          * A bug in bzlib.h: stream.next_in should be marked 'const'
192          * but isn't (the library never alters data through the
193          * next_in pointer, only reads it).  The result: this ugly
194          * cast to remove 'const'.
195          */
196         state->stream.next_in = (char *)(uintptr_t)(const void *)buff;
197         state->stream.avail_in = n;
198
199         a->decompressor->read_ahead = read_ahead;
200         a->decompressor->consume = read_consume;
201         a->decompressor->skip = NULL; /* not supported */
202         a->decompressor->finish = finish;
203
204         /* Initialize compression library. */
205         ret = BZ2_bzDecompressInit(&(state->stream),
206             0 /* library verbosity */,
207             0 /* don't use slow low-mem algorithm */);
208
209         /* If init fails, try using low-memory algorithm instead. */
210         if (ret == BZ_MEM_ERROR) {
211                 ret = BZ2_bzDecompressInit(&(state->stream),
212                     0 /* library verbosity */,
213                     1 /* do use slow low-mem algorithm */);
214         }
215
216         if (ret == BZ_OK) {
217                 a->decompressor->data = state;
218                 return (ARCHIVE_OK);
219         }
220
221         /* Library setup failed: Clean up. */
222         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
223             "Internal error initializing %s library",
224             a->archive.compression_name);
225         free(state->uncompressed_buffer);
226         free(state);
227
228         /* Override the error message if we know what really went wrong. */
229         switch (ret) {
230         case BZ_PARAM_ERROR:
231                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
232                     "Internal error initializing compression library: "
233                     "invalid setup parameter");
234                 break;
235         case BZ_MEM_ERROR:
236                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
237                     "Internal error initializing compression library: "
238                     "out of memory");
239                 break;
240         case BZ_CONFIG_ERROR:
241                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
242                     "Internal error initializing compression library: "
243                     "mis-compiled library");
244                 break;
245         }
246
247         return (ARCHIVE_FATAL);
248 }
249
250 /*
251  * Return a block of data from the decompression buffer.  Decompress more
252  * as necessary.
253  */
254 static ssize_t
255 read_ahead(struct archive_read *a, const void **p, size_t min)
256 {
257         struct private_data *state;
258         size_t read_avail, was_avail;
259         int ret;
260
261         state = (struct private_data *)a->decompressor->data;
262         if (!a->client_reader) {
263                 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
264                     "No read callback is registered?  "
265                     "This is probably an internal programming error.");
266                 return (ARCHIVE_FATAL);
267         }
268
269         read_avail = state->stream.next_out - state->read_next;
270
271         if (read_avail + state->stream.avail_out < min) {
272                 memmove(state->uncompressed_buffer, state->read_next,
273                     read_avail);
274                 state->read_next = state->uncompressed_buffer;
275                 state->stream.next_out = state->read_next + read_avail;
276                 state->stream.avail_out
277                     = state->uncompressed_buffer_size - read_avail;
278         }
279
280         while (read_avail < min &&              /* Haven't satisfied min. */
281             read_avail < state->uncompressed_buffer_size) { /* !full */
282                 was_avail = read_avail;
283                 if ((ret = drive_decompressor(a, state)) != ARCHIVE_OK)
284                         return (ret);
285                 read_avail = state->stream.next_out - state->read_next;
286                 if (was_avail == read_avail) /* No progress? */
287                         break;
288         }
289
290         *p = state->read_next;
291         return (read_avail);
292 }
293
294 /*
295  * Mark a previously-returned block of data as read.
296  */
297 static ssize_t
298 read_consume(struct archive_read *a, size_t n)
299 {
300         struct private_data *state;
301
302         state = (struct private_data *)a->decompressor->data;
303         a->archive.file_position += n;
304         state->read_next += n;
305         if (state->read_next > state->stream.next_out)
306                 __archive_errx(1, "Request to consume too many "
307                     "bytes from bzip2 decompressor");
308         return (n);
309 }
310
311 /*
312  * Clean up the decompressor.
313  */
314 static int
315 finish(struct archive_read *a)
316 {
317         struct private_data *state;
318         int ret;
319
320         state = (struct private_data *)a->decompressor->data;
321         ret = ARCHIVE_OK;
322         switch (BZ2_bzDecompressEnd(&(state->stream))) {
323         case BZ_OK:
324                 break;
325         default:
326                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
327                     "Failed to clean up %s compressor",
328                     a->archive.compression_name);
329                 ret = ARCHIVE_FATAL;
330         }
331
332         free(state->uncompressed_buffer);
333         free(state);
334
335         a->decompressor->data = NULL;
336         return (ret);
337 }
338
339 /*
340  * Utility function to pull data through decompressor, reading input
341  * blocks as necessary.
342  */
343 static int
344 drive_decompressor(struct archive_read *a, struct private_data *state)
345 {
346         ssize_t ret;
347         int decompressed, total_decompressed;
348         char *output;
349         const void *read_buf;
350
351         total_decompressed = 0;
352         for (;;) {
353                 if (state->stream.avail_in == 0) {
354                         read_buf = state->stream.next_in;
355                         ret = (a->client_reader)(&a->archive, a->client_data,
356                             &read_buf);
357                         state->stream.next_in = (void *)(uintptr_t)read_buf;
358                         if (ret < 0) {
359                                 /*
360                                  * TODO: Find a better way to handle
361                                  * this read failure.
362                                  */
363                                 goto fatal;
364                         }
365                         if (ret == 0  &&  total_decompressed == 0) {
366                                 archive_set_error(&a->archive, EIO,
367                                     "Premature end of %s compressed data",
368                                     a->archive.compression_name);
369                                 return (ARCHIVE_FATAL);
370                         }
371                         a->archive.raw_position += ret;
372                         state->stream.avail_in = ret;
373                 }
374
375                 {
376                         output = state->stream.next_out;
377
378                         /* Decompress some data. */
379                         ret = BZ2_bzDecompress(&(state->stream));
380                         decompressed = state->stream.next_out - output;
381
382                         /* Accumulate the total bytes of output. */
383                         state->total_out += decompressed;
384                         total_decompressed += decompressed;
385
386                         switch (ret) {
387                         case BZ_OK: /* Decompressor made some progress. */
388                                 if (decompressed > 0)
389                                         return (ARCHIVE_OK);
390                                 break;
391                         case BZ_STREAM_END:     /* Found end of stream. */
392                                 return (ARCHIVE_OK);
393                         default:
394                                 /* Any other return value is an error. */
395                                 goto fatal;
396                         }
397                 }
398         }
399         return (ARCHIVE_OK);
400
401         /* Return a fatal error. */
402 fatal:
403         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
404             "%s decompression failed", a->archive.compression_name);
405         return (ARCHIVE_FATAL);
406 }
407
408 #endif /* HAVE_BZLIB_H */