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