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$");
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 defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
52struct private_data {
53	bz_stream	 stream;
54	char		*out_block;
55	size_t		 out_block_size;
56	char		 valid; /* True = decompressor is initialized */
57	char		 eof; /* True = found end of compressed data. */
58};
59
60/* Bzip2 filter */
61static ssize_t	bzip2_filter_read(struct archive_read_filter *, const void **);
62static int	bzip2_filter_close(struct archive_read_filter *);
63#endif
64
65/*
66 * Note that we can detect bzip2 archives even if we can't decompress
67 * them.  (In fact, we like detecting them because we can give better
68 * error messages.)  So the bid framework here gets compiled even
69 * if bzlib is unavailable.
70 */
71static int	bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
72static int	bzip2_reader_init(struct archive_read_filter *);
73static int	bzip2_reader_free(struct archive_read_filter_bidder *);
74
75#if ARCHIVE_VERSION_NUMBER < 4000000
76/* Deprecated; remove in libarchive 4.0 */
77int
78archive_read_support_compression_bzip2(struct archive *a)
79{
80	return archive_read_support_filter_bzip2(a);
81}
82#endif
83
84int
85archive_read_support_filter_bzip2(struct archive *_a)
86{
87	struct archive_read *a = (struct archive_read *)_a;
88	struct archive_read_filter_bidder *reader;
89
90	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
91	    ARCHIVE_STATE_NEW, "archive_read_support_filter_bzip2");
92
93	if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
94		return (ARCHIVE_FATAL);
95
96	reader->data = NULL;
97	reader->name = "bzip2";
98	reader->bid = bzip2_reader_bid;
99	reader->init = bzip2_reader_init;
100	reader->options = NULL;
101	reader->free = bzip2_reader_free;
102#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
103	return (ARCHIVE_OK);
104#else
105	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
106	    "Using external bzip2 program");
107	return (ARCHIVE_WARN);
108#endif
109}
110
111static int
112bzip2_reader_free(struct archive_read_filter_bidder *self){
113	(void)self; /* UNUSED */
114	return (ARCHIVE_OK);
115}
116
117/*
118 * Test whether we can handle this data.
119 *
120 * This logic returns zero if any part of the signature fails.  It
121 * also tries to Do The Right Thing if a very short buffer prevents us
122 * from verifying as much as we would like.
123 */
124static int
125bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter)
126{
127	const unsigned char *buffer;
128	ssize_t avail;
129	int bits_checked;
130
131	(void)self; /* UNUSED */
132
133	/* Minimal bzip2 archive is 14 bytes. */
134	buffer = __archive_read_filter_ahead(filter, 14, &avail);
135	if (buffer == NULL)
136		return (0);
137
138	/* First three bytes must be "BZh" */
139	bits_checked = 0;
140	if (memcmp(buffer, "BZh", 3) != 0)
141		return (0);
142	bits_checked += 24;
143
144	/* Next follows a compression flag which must be an ASCII digit. */
145	if (buffer[3] < '1' || buffer[3] > '9')
146		return (0);
147	bits_checked += 5;
148
149	/* After BZh[1-9], there must be either a data block
150	 * which begins with 0x314159265359 or an end-of-data
151	 * marker of 0x177245385090. */
152	if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0)
153		bits_checked += 48;
154	else if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", 6) == 0)
155		bits_checked += 48;
156	else
157		return (0);
158
159	return (bits_checked);
160}
161
162#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
163
164/*
165 * If we don't have the library on this system, we can't actually do the
166 * decompression.  We can, however, still detect compressed archives
167 * and emit a useful message.
168 */
169static int
170bzip2_reader_init(struct archive_read_filter *self)
171{
172	int r;
173
174	r = __archive_read_program(self, "bzip2 -d");
175	/* Note: We set the format here even if __archive_read_program()
176	 * above fails.  We do, after all, know what the format is
177	 * even if we weren't able to read it. */
178	self->code = ARCHIVE_FILTER_BZIP2;
179	self->name = "bzip2";
180	return (r);
181}
182
183
184#else
185
186/*
187 * Setup the callbacks.
188 */
189static int
190bzip2_reader_init(struct archive_read_filter *self)
191{
192	static const size_t out_block_size = 64 * 1024;
193	void *out_block;
194	struct private_data *state;
195
196	self->code = ARCHIVE_FILTER_BZIP2;
197	self->name = "bzip2";
198
199	state = (struct private_data *)calloc(sizeof(*state), 1);
200	out_block = (unsigned char *)malloc(out_block_size);
201	if (state == NULL || out_block == NULL) {
202		archive_set_error(&self->archive->archive, ENOMEM,
203		    "Can't allocate data for bzip2 decompression");
204		free(out_block);
205		free(state);
206		return (ARCHIVE_FATAL);
207	}
208
209	self->data = state;
210	state->out_block_size = out_block_size;
211	state->out_block = out_block;
212	self->read = bzip2_filter_read;
213	self->skip = NULL; /* not supported */
214	self->close = bzip2_filter_close;
215
216	return (ARCHIVE_OK);
217}
218
219/*
220 * Return the next block of decompressed data.
221 */
222static ssize_t
223bzip2_filter_read(struct archive_read_filter *self, const void **p)
224{
225	struct private_data *state;
226	size_t decompressed;
227	const char *read_buf;
228	ssize_t ret;
229
230	state = (struct private_data *)self->data;
231
232	if (state->eof) {
233		*p = NULL;
234		return (0);
235	}
236
237	/* Empty our output buffer. */
238	state->stream.next_out = state->out_block;
239	state->stream.avail_out = state->out_block_size;
240
241	/* Try to fill the output buffer. */
242	for (;;) {
243		if (!state->valid) {
244			if (bzip2_reader_bid(self->bidder, self->upstream) == 0) {
245				state->eof = 1;
246				*p = state->out_block;
247				decompressed = state->stream.next_out
248				    - state->out_block;
249				return (decompressed);
250			}
251			/* Initialize compression library. */
252			ret = BZ2_bzDecompressInit(&(state->stream),
253					   0 /* library verbosity */,
254					   0 /* don't use low-mem algorithm */);
255
256			/* If init fails, try low-memory algorithm instead. */
257			if (ret == BZ_MEM_ERROR)
258				ret = BZ2_bzDecompressInit(&(state->stream),
259					   0 /* library verbosity */,
260					   1 /* do use low-mem algo */);
261
262			if (ret != BZ_OK) {
263				const char *detail = NULL;
264				int err = ARCHIVE_ERRNO_MISC;
265				switch (ret) {
266				case BZ_PARAM_ERROR:
267					detail = "invalid setup parameter";
268					break;
269				case BZ_MEM_ERROR:
270					err = ENOMEM;
271					detail = "out of memory";
272					break;
273				case BZ_CONFIG_ERROR:
274					detail = "mis-compiled library";
275					break;
276				}
277				archive_set_error(&self->archive->archive, err,
278				    "Internal error initializing decompressor%s%s",
279				    detail == NULL ? "" : ": ",
280				    detail);
281				return (ARCHIVE_FATAL);
282			}
283			state->valid = 1;
284		}
285
286		/* stream.next_in is really const, but bzlib
287		 * doesn't declare it so. <sigh> */
288		read_buf =
289		    __archive_read_filter_ahead(self->upstream, 1, &ret);
290		if (read_buf == NULL) {
291			archive_set_error(&self->archive->archive,
292			    ARCHIVE_ERRNO_MISC,
293			    "truncated bzip2 input");
294			return (ARCHIVE_FATAL);
295		}
296		state->stream.next_in = (char *)(uintptr_t)read_buf;
297		state->stream.avail_in = ret;
298		/* There is no more data, return whatever we have. */
299		if (ret == 0) {
300			state->eof = 1;
301			*p = state->out_block;
302			decompressed = state->stream.next_out
303			    - state->out_block;
304			return (decompressed);
305		}
306
307		/* Decompress as much as we can in one pass. */
308		ret = BZ2_bzDecompress(&(state->stream));
309		__archive_read_filter_consume(self->upstream,
310		    state->stream.next_in - read_buf);
311
312		switch (ret) {
313		case BZ_STREAM_END: /* Found end of stream. */
314			switch (BZ2_bzDecompressEnd(&(state->stream))) {
315			case BZ_OK:
316				break;
317			default:
318				archive_set_error(&(self->archive->archive),
319					  ARCHIVE_ERRNO_MISC,
320					  "Failed to clean up decompressor");
321				return (ARCHIVE_FATAL);
322			}
323			state->valid = 0;
324			/* FALLTHROUGH */
325		case BZ_OK: /* Decompressor made some progress. */
326			/* If we filled our buffer, update stats and return. */
327			if (state->stream.avail_out == 0) {
328				*p = state->out_block;
329				decompressed = state->stream.next_out
330				    - state->out_block;
331				return (decompressed);
332			}
333			break;
334		default: /* Return an error. */
335			archive_set_error(&self->archive->archive,
336			    ARCHIVE_ERRNO_MISC, "bzip decompression failed");
337			return (ARCHIVE_FATAL);
338		}
339	}
340}
341
342/*
343 * Clean up the decompressor.
344 */
345static int
346bzip2_filter_close(struct archive_read_filter *self)
347{
348	struct private_data *state;
349	int ret = ARCHIVE_OK;
350
351	state = (struct private_data *)self->data;
352
353	if (state->valid) {
354		switch (BZ2_bzDecompressEnd(&state->stream)) {
355		case BZ_OK:
356			break;
357		default:
358			archive_set_error(&self->archive->archive,
359					  ARCHIVE_ERRNO_MISC,
360					  "Failed to clean up decompressor");
361			ret = ARCHIVE_FATAL;
362		}
363		state->valid = 0;
364	}
365
366	free(state->out_block);
367	free(state);
368	return (ret);
369}
370
371#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
372