Import libarchive-2.5.4b.
[dragonfly.git] / contrib / libarchive-2 / libarchive / archive_read_support_compression_bzip2.c
blobe6397df96344104e744de43e8cd54d7c77e17852
1 /*-
2 * Copyright (c) 2003-2007 Tim Kientzle
3 * All rights reserved.
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.
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: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.17 2008/02/19 05:44:59 kientzle Exp $");
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
47 #include "archive.h"
48 #include "archive_private.h"
49 #include "archive_read_private.h"
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 char eof; /* True = found end of compressed data. */
61 static int finish(struct archive_read *);
62 static ssize_t read_ahead(struct archive_read *, const void **, size_t);
63 static ssize_t read_consume(struct archive_read *, size_t);
64 static int drive_decompressor(struct archive_read *a, struct private_data *);
65 #endif
67 /* These two functions are defined even if we lack the library. See below. */
68 static int bid(const void *, size_t);
69 static int init(struct archive_read *, const void *, size_t);
71 int
72 archive_read_support_compression_bzip2(struct archive *_a)
74 struct archive_read *a = (struct archive_read *)_a;
75 if (__archive_read_register_compression(a, bid, init) != NULL)
76 return (ARCHIVE_OK);
77 return (ARCHIVE_FATAL);
81 * Test whether we can handle this data.
83 * This logic returns zero if any part of the signature fails. It
84 * also tries to Do The Right Thing if a very short buffer prevents us
85 * from verifying as much as we would like.
87 static int
88 bid(const void *buff, size_t len)
90 const unsigned char *buffer;
91 int bits_checked;
93 if (len < 1)
94 return (0);
96 buffer = (const unsigned char *)buff;
97 bits_checked = 0;
98 if (buffer[0] != 'B') /* Verify first ID byte. */
99 return (0);
100 bits_checked += 8;
101 if (len < 2)
102 return (bits_checked);
104 if (buffer[1] != 'Z') /* Verify second ID byte. */
105 return (0);
106 bits_checked += 8;
107 if (len < 3)
108 return (bits_checked);
110 if (buffer[2] != 'h') /* Verify third ID byte. */
111 return (0);
112 bits_checked += 8;
113 if (len < 4)
114 return (bits_checked);
116 if (buffer[3] < '1' || buffer[3] > '9')
117 return (0);
118 bits_checked += 5;
119 if (len < 5)
120 return (bits_checked);
122 /* After BZh[1-9], there must be either a data block
123 * which begins with 0x314159265359 or an end-of-data
124 * marker of 0x177245385090. */
126 if (buffer[4] == 0x31) {
127 /* Verify the data block signature. */
128 size_t s = len;
129 if (s > 10) s = 10;
130 if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", s - 4) != 0)
131 return (0);
132 bits_checked += 8 * (s - 4);
133 } else if (buffer[4] == 0x17) {
134 /* Verify the end-of-data marker. */
135 size_t s = len;
136 if (s > 10) s = 10;
137 if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", s - 4) != 0)
138 return (0);
139 bits_checked += 8 * (s - 4);
140 } else
141 return (0);
143 return (bits_checked);
146 #ifndef HAVE_BZLIB_H
149 * If we don't have the library on this system, we can't actually do the
150 * decompression. We can, however, still detect compressed archives
151 * and emit a useful message.
153 static int
154 init(struct archive_read *a, const void *buff, size_t n)
156 (void)a; /* UNUSED */
157 (void)buff; /* UNUSED */
158 (void)n; /* UNUSED */
160 archive_set_error(&a->archive, -1,
161 "This version of libarchive was compiled without bzip2 support");
162 return (ARCHIVE_FATAL);
166 #else
169 * Setup the callbacks.
171 static int
172 init(struct archive_read *a, const void *buff, size_t n)
174 struct private_data *state;
175 int ret;
177 a->archive.compression_code = ARCHIVE_COMPRESSION_BZIP2;
178 a->archive.compression_name = "bzip2";
180 state = (struct private_data *)malloc(sizeof(*state));
181 if (state == NULL) {
182 archive_set_error(&a->archive, ENOMEM,
183 "Can't allocate data for %s decompression",
184 a->archive.compression_name);
185 return (ARCHIVE_FATAL);
187 memset(state, 0, sizeof(*state));
189 state->uncompressed_buffer_size = 64 * 1024;
190 state->uncompressed_buffer = (char *)malloc(state->uncompressed_buffer_size);
191 state->stream.next_out = state->uncompressed_buffer;
192 state->read_next = state->uncompressed_buffer;
193 state->stream.avail_out = state->uncompressed_buffer_size;
195 if (state->uncompressed_buffer == NULL) {
196 archive_set_error(&a->archive, ENOMEM,
197 "Can't allocate %s decompression buffers",
198 a->archive.compression_name);
199 free(state);
200 return (ARCHIVE_FATAL);
204 * A bug in bzlib.h: stream.next_in should be marked 'const'
205 * but isn't (the library never alters data through the
206 * next_in pointer, only reads it). The result: this ugly
207 * cast to remove 'const'.
209 state->stream.next_in = (char *)(uintptr_t)(const void *)buff;
210 state->stream.avail_in = n;
212 a->decompressor->read_ahead = read_ahead;
213 a->decompressor->consume = read_consume;
214 a->decompressor->skip = NULL; /* not supported */
215 a->decompressor->finish = finish;
217 /* Initialize compression library. */
218 ret = BZ2_bzDecompressInit(&(state->stream),
219 0 /* library verbosity */,
220 0 /* don't use slow low-mem algorithm */);
222 /* If init fails, try using low-memory algorithm instead. */
223 if (ret == BZ_MEM_ERROR) {
224 ret = BZ2_bzDecompressInit(&(state->stream),
225 0 /* library verbosity */,
226 1 /* do use slow low-mem algorithm */);
229 if (ret == BZ_OK) {
230 a->decompressor->data = state;
231 return (ARCHIVE_OK);
234 /* Library setup failed: Clean up. */
235 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
236 "Internal error initializing %s library",
237 a->archive.compression_name);
238 free(state->uncompressed_buffer);
239 free(state);
241 /* Override the error message if we know what really went wrong. */
242 switch (ret) {
243 case BZ_PARAM_ERROR:
244 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
245 "Internal error initializing compression library: "
246 "invalid setup parameter");
247 break;
248 case BZ_MEM_ERROR:
249 archive_set_error(&a->archive, ENOMEM,
250 "Internal error initializing compression library: "
251 "out of memory");
252 break;
253 case BZ_CONFIG_ERROR:
254 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
255 "Internal error initializing compression library: "
256 "mis-compiled library");
257 break;
260 return (ARCHIVE_FATAL);
264 * Return a block of data from the decompression buffer. Decompress more
265 * as necessary.
267 static ssize_t
268 read_ahead(struct archive_read *a, const void **p, size_t min)
270 struct private_data *state;
271 size_t read_avail, was_avail;
272 int ret;
274 state = (struct private_data *)a->decompressor->data;
275 if (!a->client_reader) {
276 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
277 "No read callback is registered? "
278 "This is probably an internal programming error.");
279 return (ARCHIVE_FATAL);
282 read_avail = state->stream.next_out - state->read_next;
284 if (read_avail + state->stream.avail_out < min) {
285 memmove(state->uncompressed_buffer, state->read_next,
286 read_avail);
287 state->read_next = state->uncompressed_buffer;
288 state->stream.next_out = state->read_next + read_avail;
289 state->stream.avail_out
290 = state->uncompressed_buffer_size - read_avail;
293 while (read_avail < min && /* Haven't satisfied min. */
294 read_avail < state->uncompressed_buffer_size) { /* !full */
295 was_avail = read_avail;
296 if ((ret = drive_decompressor(a, state)) < ARCHIVE_OK)
297 return (ret);
298 if (ret == ARCHIVE_EOF)
299 break; /* Break on EOF even if we haven't met min. */
300 read_avail = state->stream.next_out - state->read_next;
301 if (was_avail == read_avail) /* No progress? */
302 break;
305 *p = state->read_next;
306 return (read_avail);
310 * Mark a previously-returned block of data as read.
312 static ssize_t
313 read_consume(struct archive_read *a, size_t n)
315 struct private_data *state;
317 state = (struct private_data *)a->decompressor->data;
318 a->archive.file_position += n;
319 state->read_next += n;
320 if (state->read_next > state->stream.next_out)
321 __archive_errx(1, "Request to consume too many "
322 "bytes from bzip2 decompressor");
323 return (n);
327 * Clean up the decompressor.
329 static int
330 finish(struct archive_read *a)
332 struct private_data *state;
333 int ret;
335 state = (struct private_data *)a->decompressor->data;
336 ret = ARCHIVE_OK;
337 switch (BZ2_bzDecompressEnd(&(state->stream))) {
338 case BZ_OK:
339 break;
340 default:
341 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
342 "Failed to clean up %s compressor",
343 a->archive.compression_name);
344 ret = ARCHIVE_FATAL;
347 free(state->uncompressed_buffer);
348 free(state);
350 a->decompressor->data = NULL;
351 return (ret);
355 * Utility function to pull data through decompressor, reading input
356 * blocks as necessary.
358 static int
359 drive_decompressor(struct archive_read *a, struct private_data *state)
361 ssize_t ret;
362 int decompressed, total_decompressed;
363 char *output;
364 const void *read_buf;
366 if (state->eof)
367 return (ARCHIVE_EOF);
368 total_decompressed = 0;
369 for (;;) {
370 if (state->stream.avail_in == 0) {
371 read_buf = state->stream.next_in;
372 ret = (a->client_reader)(&a->archive, a->client_data,
373 &read_buf);
374 state->stream.next_in = (void *)(uintptr_t)read_buf;
375 if (ret < 0) {
377 * TODO: Find a better way to handle
378 * this read failure.
380 goto fatal;
382 if (ret == 0 && total_decompressed == 0) {
383 archive_set_error(&a->archive, EIO,
384 "Premature end of %s compressed data",
385 a->archive.compression_name);
386 return (ARCHIVE_FATAL);
388 a->archive.raw_position += ret;
389 state->stream.avail_in = ret;
393 output = state->stream.next_out;
395 /* Decompress some data. */
396 ret = BZ2_bzDecompress(&(state->stream));
397 decompressed = state->stream.next_out - output;
399 /* Accumulate the total bytes of output. */
400 state->total_out += decompressed;
401 total_decompressed += decompressed;
403 switch (ret) {
404 case BZ_OK: /* Decompressor made some progress. */
405 if (decompressed > 0)
406 return (ARCHIVE_OK);
407 break;
408 case BZ_STREAM_END: /* Found end of stream. */
409 state->eof = 1;
410 return (ARCHIVE_OK);
411 default:
412 /* Any other return value is an error. */
413 goto fatal;
417 return (ARCHIVE_OK);
419 /* Return a fatal error. */
420 fatal:
421 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
422 "%s decompression failed", a->archive.compression_name);
423 return (ARCHIVE_FATAL);
426 #endif /* HAVE_BZLIB_H */