1228753Smm/*-
2228753Smm * Copyright (c) 2009 Michihiro NAKAJIMA
3228753Smm * Copyright (c) 2003-2008 Tim Kientzle and Miklos Vajna
4228753Smm * All rights reserved.
5228753Smm *
6228753Smm * Redistribution and use in source and binary forms, with or without
7228753Smm * modification, are permitted provided that the following conditions
8228753Smm * are met:
9228753Smm * 1. Redistributions of source code must retain the above copyright
10228753Smm *    notice, this list of conditions and the following disclaimer.
11228753Smm * 2. Redistributions in binary form must reproduce the above copyright
12228753Smm *    notice, this list of conditions and the following disclaimer in the
13228753Smm *    documentation and/or other materials provided with the distribution.
14228753Smm *
15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25228753Smm */
26228753Smm
27228753Smm#include "archive_platform.h"
28228753Smm
29229592Smm__FBSDID("$FreeBSD$");
30228753Smm
31228753Smm#ifdef HAVE_ERRNO_H
32228753Smm#include <errno.h>
33228753Smm#endif
34228753Smm#include <stdio.h>
35228753Smm#ifdef HAVE_STDLIB_H
36228753Smm#include <stdlib.h>
37228753Smm#endif
38228753Smm#ifdef HAVE_STRING_H
39228753Smm#include <string.h>
40228753Smm#endif
41228753Smm#ifdef HAVE_UNISTD_H
42228753Smm#include <unistd.h>
43228753Smm#endif
44228753Smm#if HAVE_LZMA_H
45228753Smm#include <lzma.h>
46228753Smm#elif HAVE_LZMADEC_H
47228753Smm#include <lzmadec.h>
48228753Smm#endif
49228753Smm
50228753Smm#include "archive.h"
51228753Smm#include "archive_endian.h"
52228753Smm#include "archive_private.h"
53228753Smm#include "archive_read_private.h"
54228753Smm
55228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA
56228753Smm
57228753Smmstruct private_data {
58228753Smm	lzma_stream	 stream;
59228753Smm	unsigned char	*out_block;
60228753Smm	size_t		 out_block_size;
61228753Smm	int64_t		 total_out;
62228753Smm	char		 eof; /* True = found end of compressed data. */
63228753Smm};
64228753Smm
65228753Smm/* Combined lzma/xz filter */
66228753Smmstatic ssize_t	xz_filter_read(struct archive_read_filter *, const void **);
67228753Smmstatic int	xz_filter_close(struct archive_read_filter *);
68228753Smmstatic int	xz_lzma_bidder_init(struct archive_read_filter *);
69228753Smm
70228753Smm#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
71228753Smm
72228753Smmstruct private_data {
73228753Smm	lzmadec_stream	 stream;
74228753Smm	unsigned char	*out_block;
75228753Smm	size_t		 out_block_size;
76228753Smm	int64_t		 total_out;
77228753Smm	char		 eof; /* True = found end of compressed data. */
78228753Smm};
79228753Smm
80228753Smm/* Lzma-only filter */
81228753Smmstatic ssize_t	lzma_filter_read(struct archive_read_filter *, const void **);
82228753Smmstatic int	lzma_filter_close(struct archive_read_filter *);
83228753Smm#endif
84228753Smm
85228753Smm/*
86228753Smm * Note that we can detect xz and lzma compressed files even if we
87228753Smm * can't decompress them.  (In fact, we like detecting them because we
88228753Smm * can give better error messages.)  So the bid framework here gets
89228753Smm * compiled even if no lzma library is available.
90228753Smm */
91228753Smmstatic int	xz_bidder_bid(struct archive_read_filter_bidder *,
92228753Smm		    struct archive_read_filter *);
93228753Smmstatic int	xz_bidder_init(struct archive_read_filter *);
94228753Smmstatic int	lzma_bidder_bid(struct archive_read_filter_bidder *,
95228753Smm		    struct archive_read_filter *);
96228753Smmstatic int	lzma_bidder_init(struct archive_read_filter *);
97228753Smm
98228753Smmint
99228753Smmarchive_read_support_compression_xz(struct archive *_a)
100228753Smm{
101228753Smm	struct archive_read *a = (struct archive_read *)_a;
102228753Smm	struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a);
103228753Smm
104228753Smm	archive_clear_error(_a);
105228753Smm	if (bidder == NULL)
106228753Smm		return (ARCHIVE_FATAL);
107228753Smm
108228753Smm	bidder->data = NULL;
109228753Smm	bidder->bid = xz_bidder_bid;
110228753Smm	bidder->init = xz_bidder_init;
111228753Smm	bidder->options = NULL;
112228753Smm	bidder->free = NULL;
113228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA
114228753Smm	return (ARCHIVE_OK);
115228753Smm#else
116228753Smm	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
117228753Smm	    "Using external unxz program for xz decompression");
118228753Smm	return (ARCHIVE_WARN);
119228753Smm#endif
120228753Smm}
121228753Smm
122228753Smmint
123228753Smmarchive_read_support_compression_lzma(struct archive *_a)
124228753Smm{
125228753Smm	struct archive_read *a = (struct archive_read *)_a;
126228753Smm	struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a);
127228753Smm
128228753Smm	archive_clear_error(_a);
129228753Smm	if (bidder == NULL)
130228753Smm		return (ARCHIVE_FATAL);
131228753Smm
132228753Smm	bidder->data = NULL;
133228753Smm	bidder->bid = lzma_bidder_bid;
134228753Smm	bidder->init = lzma_bidder_init;
135228753Smm	bidder->options = NULL;
136228753Smm	bidder->free = NULL;
137228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA
138228753Smm	return (ARCHIVE_OK);
139228753Smm#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
140228753Smm	return (ARCHIVE_OK);
141228753Smm#else
142228753Smm	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
143228753Smm	    "Using external unlzma program for lzma decompression");
144228753Smm	return (ARCHIVE_WARN);
145228753Smm#endif
146228753Smm}
147228753Smm
148228753Smm/*
149228753Smm * Test whether we can handle this data.
150228753Smm */
151228753Smmstatic int
152228753Smmxz_bidder_bid(struct archive_read_filter_bidder *self,
153228753Smm    struct archive_read_filter *filter)
154228753Smm{
155228753Smm	const unsigned char *buffer;
156228753Smm	ssize_t avail;
157228753Smm	int bits_checked;
158228753Smm
159228753Smm	(void)self; /* UNUSED */
160228753Smm
161228753Smm	buffer = __archive_read_filter_ahead(filter, 6, &avail);
162228753Smm	if (buffer == NULL)
163228753Smm		return (0);
164228753Smm
165228753Smm	/*
166228753Smm	 * Verify Header Magic Bytes : FD 37 7A 58 5A 00
167228753Smm	 */
168228753Smm	bits_checked = 0;
169228753Smm	if (buffer[0] != 0xFD)
170228753Smm		return (0);
171228753Smm	bits_checked += 8;
172228753Smm	if (buffer[1] != 0x37)
173228753Smm		return (0);
174228753Smm	bits_checked += 8;
175228753Smm	if (buffer[2] != 0x7A)
176228753Smm		return (0);
177228753Smm	bits_checked += 8;
178228753Smm	if (buffer[3] != 0x58)
179228753Smm		return (0);
180228753Smm	bits_checked += 8;
181228753Smm	if (buffer[4] != 0x5A)
182228753Smm		return (0);
183228753Smm	bits_checked += 8;
184228753Smm	if (buffer[5] != 0x00)
185228753Smm		return (0);
186228753Smm	bits_checked += 8;
187228753Smm
188228753Smm	return (bits_checked);
189228753Smm}
190228753Smm
191228753Smm/*
192228753Smm * Test whether we can handle this data.
193228753Smm *
194228753Smm * <sigh> LZMA has a rather poor file signature.  Zeros do not
195228753Smm * make good signature bytes as a rule, and the only non-zero byte
196228753Smm * here is an ASCII character.  For example, an uncompressed tar
197228753Smm * archive whose first file is ']' would satisfy this check.  It may
198228753Smm * be necessary to exclude LZMA from compression_all() because of
199228753Smm * this.  Clients of libarchive would then have to explicitly enable
200228753Smm * LZMA checking instead of (or in addition to) compression_all() when
201228753Smm * they have other evidence (file name, command-line option) to go on.
202228753Smm */
203228753Smmstatic int
204228753Smmlzma_bidder_bid(struct archive_read_filter_bidder *self,
205228753Smm    struct archive_read_filter *filter)
206228753Smm{
207228753Smm	const unsigned char *buffer;
208228753Smm	ssize_t avail;
209228753Smm	uint32_t dicsize;
210228753Smm	uint64_t uncompressed_size;
211228753Smm	int bits_checked;
212228753Smm
213228753Smm	(void)self; /* UNUSED */
214228753Smm
215228753Smm	buffer = __archive_read_filter_ahead(filter, 14, &avail);
216228753Smm	if (buffer == NULL)
217228753Smm		return (0);
218228753Smm
219228753Smm	/* First byte of raw LZMA stream is commonly 0x5d.
220228753Smm	 * The first byte is a special number, which consists of
221228753Smm	 * three parameters of LZMA compression, a number of literal
222228753Smm	 * context bits(which is from 0 to 8, default is 3), a number
223228753Smm	 * of literal pos bits(which is from 0 to 4, default is 0),
224228753Smm	 * a number of pos bits(which is from 0 to 4, default is 2).
225228753Smm	 * The first byte is made by
226228753Smm	 * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit,
227228753Smm	 * and so the default value in this field is
228228753Smm	 * (2 * 5 + 0) * 9 + 3 = 0x5d.
229228753Smm	 * lzma of LZMA SDK has options to change those parameters.
230228753Smm	 * It means a range of this field is from 0 to 224. And lzma of
231228753Smm	 * XZ Utils with option -e records 0x5e in this field. */
232228753Smm	/* NOTE: If this checking of the first byte increases false
233228753Smm	 * recognition, we should allow only 0x5d and 0x5e for the first
234228753Smm	 * byte of LZMA stream. */
235228753Smm	bits_checked = 0;
236228753Smm	if (buffer[0] > (4 * 5 + 4) * 9 + 8)
237228753Smm		return (0);
238228753Smm	/* Most likely value in the first byte of LZMA stream. */
239228753Smm	if (buffer[0] == 0x5d || buffer[0] == 0x5e)
240228753Smm		bits_checked += 8;
241228753Smm
242228753Smm	/* Sixth through fourteenth bytes are uncompressed size,
243228753Smm	 * stored in little-endian order. `-1' means uncompressed
244228753Smm	 * size is unknown and lzma of XZ Utils always records `-1'
245228753Smm	 * in this field. */
246228753Smm	uncompressed_size = archive_le64dec(buffer+5);
247228753Smm	if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1))
248228753Smm		bits_checked += 64;
249228753Smm
250228753Smm	/* Second through fifth bytes are dictionary size, stored in
251228753Smm	 * little-endian order. The minimum dictionary size is
252228753Smm	 * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
253228753Smm	 * -d12 and the maxinam dictionary size is 1 << 27(128MiB)
254228753Smm	 * which the one uses with option -d27.
255228753Smm	 * NOTE: A comment of LZMA SDK source code says this dictionary
256228753Smm	 * range is from 1 << 12 to 1 << 30. */
257228753Smm	dicsize = archive_le32dec(buffer+1);
258228753Smm	switch (dicsize) {
259228753Smm	case 0x00001000:/* lzma of LZMA SDK option -d12. */
260228753Smm	case 0x00002000:/* lzma of LZMA SDK option -d13. */
261228753Smm	case 0x00004000:/* lzma of LZMA SDK option -d14. */
262228753Smm	case 0x00008000:/* lzma of LZMA SDK option -d15. */
263228753Smm	case 0x00010000:/* lzma of XZ Utils option -0 and -1.
264228753Smm			 * lzma of LZMA SDK option -d16. */
265228753Smm	case 0x00020000:/* lzma of LZMA SDK option -d17. */
266228753Smm	case 0x00040000:/* lzma of LZMA SDK option -d18. */
267228753Smm	case 0x00080000:/* lzma of XZ Utils option -2.
268228753Smm			 * lzma of LZMA SDK option -d19. */
269228753Smm	case 0x00100000:/* lzma of XZ Utils option -3.
270228753Smm			 * lzma of LZMA SDK option -d20. */
271228753Smm	case 0x00200000:/* lzma of XZ Utils option -4.
272228753Smm			 * lzma of LZMA SDK option -d21. */
273228753Smm	case 0x00400000:/* lzma of XZ Utils option -5.
274228753Smm			 * lzma of LZMA SDK option -d22. */
275228753Smm	case 0x00800000:/* lzma of XZ Utils option -6.
276228753Smm			 * lzma of LZMA SDK option -d23. */
277228753Smm	case 0x01000000:/* lzma of XZ Utils option -7.
278228753Smm			 * lzma of LZMA SDK option -d24. */
279228753Smm	case 0x02000000:/* lzma of XZ Utils option -8.
280228753Smm			 * lzma of LZMA SDK option -d25. */
281228753Smm	case 0x04000000:/* lzma of XZ Utils option -9.
282228753Smm			 * lzma of LZMA SDK option -d26. */
283228753Smm	case 0x08000000:/* lzma of LZMA SDK option -d27. */
284228753Smm		bits_checked += 32;
285228753Smm		break;
286228753Smm	default:
287228753Smm		/* If a memory usage for encoding was not enough on
288228753Smm		 * the platform where LZMA stream was made, lzma of
289228753Smm		 * XZ Utils automatically decreased the dictionary
290228753Smm		 * size to enough memory for encoding by 1Mi bytes
291228753Smm		 * (1 << 20).*/
292228753Smm		if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 &&
293228753Smm		    (dicsize & ((1 << 20)-1)) == 0 &&
294228753Smm		    bits_checked == 8 + 64) {
295228753Smm			bits_checked += 32;
296228753Smm			break;
297228753Smm		}
298228753Smm		/* Otherwise dictionary size is unlikely. But it is
299228753Smm		 * possible that someone makes lzma stream with
300228753Smm		 * liblzma/LZMA SDK in one's dictionary size. */
301228753Smm		return (0);
302228753Smm	}
303228753Smm
304228753Smm	/* TODO: The above test is still very weak.  It would be
305228753Smm	 * good to do better. */
306228753Smm
307228753Smm	return (bits_checked);
308228753Smm}
309228753Smm
310228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA
311228753Smm
312228753Smm/*
313228753Smm * liblzma 4.999.7 and later support both lzma and xz streams.
314228753Smm */
315228753Smmstatic int
316228753Smmxz_bidder_init(struct archive_read_filter *self)
317228753Smm{
318228753Smm	self->code = ARCHIVE_COMPRESSION_XZ;
319228753Smm	self->name = "xz";
320228753Smm	return (xz_lzma_bidder_init(self));
321228753Smm}
322228753Smm
323228753Smmstatic int
324228753Smmlzma_bidder_init(struct archive_read_filter *self)
325228753Smm{
326228753Smm	self->code = ARCHIVE_COMPRESSION_LZMA;
327228753Smm	self->name = "lzma";
328228753Smm	return (xz_lzma_bidder_init(self));
329228753Smm}
330228753Smm
331228753Smm/*
332228753Smm * Setup the callbacks.
333228753Smm */
334228753Smmstatic int
335228753Smmxz_lzma_bidder_init(struct archive_read_filter *self)
336228753Smm{
337228753Smm	static const size_t out_block_size = 64 * 1024;
338228753Smm	void *out_block;
339228753Smm	struct private_data *state;
340228753Smm	int ret;
341228753Smm
342228753Smm	state = (struct private_data *)calloc(sizeof(*state), 1);
343228753Smm	out_block = (unsigned char *)malloc(out_block_size);
344228753Smm	if (state == NULL || out_block == NULL) {
345228753Smm		archive_set_error(&self->archive->archive, ENOMEM,
346228753Smm		    "Can't allocate data for xz decompression");
347228753Smm		free(out_block);
348228753Smm		free(state);
349228753Smm		return (ARCHIVE_FATAL);
350228753Smm	}
351228753Smm
352228753Smm	self->data = state;
353228753Smm	state->out_block_size = out_block_size;
354228753Smm	state->out_block = out_block;
355228753Smm	self->read = xz_filter_read;
356228753Smm	self->skip = NULL; /* not supported */
357228753Smm	self->close = xz_filter_close;
358228753Smm
359228753Smm	state->stream.avail_in = 0;
360228753Smm
361228753Smm	state->stream.next_out = state->out_block;
362228753Smm	state->stream.avail_out = state->out_block_size;
363228753Smm
364228753Smm	/* Initialize compression library.
365228753Smm	 * TODO: I don't know what value is best for memlimit.
366228753Smm	 *       maybe, it needs to check memory size which
367228753Smm	 *       running system has.
368228753Smm	 */
369228753Smm	if (self->code == ARCHIVE_COMPRESSION_XZ)
370228753Smm		ret = lzma_stream_decoder(&(state->stream),
371228753Smm		    (1U << 30),/* memlimit */
372228753Smm		    LZMA_CONCATENATED);
373228753Smm	else
374228753Smm		ret = lzma_alone_decoder(&(state->stream),
375228753Smm		    (1U << 30));/* memlimit */
376228753Smm
377228753Smm	if (ret == LZMA_OK)
378228753Smm		return (ARCHIVE_OK);
379228753Smm
380228753Smm	/* Library setup failed: Choose an error message and clean up. */
381228753Smm	switch (ret) {
382228753Smm	case LZMA_MEM_ERROR:
383228753Smm		archive_set_error(&self->archive->archive, ENOMEM,
384228753Smm		    "Internal error initializing compression library: "
385228753Smm		    "Cannot allocate memory");
386228753Smm		break;
387228753Smm	case LZMA_OPTIONS_ERROR:
388228753Smm		archive_set_error(&self->archive->archive,
389228753Smm		    ARCHIVE_ERRNO_MISC,
390228753Smm		    "Internal error initializing compression library: "
391228753Smm		    "Invalid or unsupported options");
392228753Smm		break;
393228753Smm	default:
394228753Smm		archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
395228753Smm		    "Internal error initializing lzma library");
396228753Smm		break;
397228753Smm	}
398228753Smm
399228753Smm	free(state->out_block);
400228753Smm	free(state);
401228753Smm	self->data = NULL;
402228753Smm	return (ARCHIVE_FATAL);
403228753Smm}
404228753Smm
405228753Smm/*
406228753Smm * Return the next block of decompressed data.
407228753Smm */
408228753Smmstatic ssize_t
409228753Smmxz_filter_read(struct archive_read_filter *self, const void **p)
410228753Smm{
411228753Smm	struct private_data *state;
412228753Smm	size_t decompressed;
413228753Smm	ssize_t avail_in;
414228753Smm	int ret;
415228753Smm
416228753Smm	state = (struct private_data *)self->data;
417228753Smm
418228753Smm	/* Empty our output buffer. */
419228753Smm	state->stream.next_out = state->out_block;
420228753Smm	state->stream.avail_out = state->out_block_size;
421228753Smm
422228753Smm	/* Try to fill the output buffer. */
423228753Smm	while (state->stream.avail_out > 0 && !state->eof) {
424228753Smm		state->stream.next_in =
425228753Smm		    __archive_read_filter_ahead(self->upstream, 1, &avail_in);
426228753Smm		if (state->stream.next_in == NULL && avail_in < 0)
427228753Smm			return (ARCHIVE_FATAL);
428228753Smm		state->stream.avail_in = avail_in;
429228753Smm
430228753Smm		/* Decompress as much as we can in one pass. */
431228753Smm		ret = lzma_code(&(state->stream),
432228753Smm		    (state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN);
433228753Smm		switch (ret) {
434228753Smm		case LZMA_STREAM_END: /* Found end of stream. */
435228753Smm			state->eof = 1;
436228753Smm			/* FALL THROUGH */
437228753Smm		case LZMA_OK: /* Decompressor made some progress. */
438228753Smm			__archive_read_filter_consume(self->upstream,
439228753Smm			    avail_in - state->stream.avail_in);
440228753Smm			break;
441228753Smm		case LZMA_MEM_ERROR:
442228753Smm			archive_set_error(&self->archive->archive, ENOMEM,
443228753Smm			    "Lzma library error: Cannot allocate memory");
444228753Smm			return (ARCHIVE_FATAL);
445228753Smm		case LZMA_MEMLIMIT_ERROR:
446228753Smm			archive_set_error(&self->archive->archive, ENOMEM,
447228753Smm			    "Lzma library error: Out of memory");
448228753Smm			return (ARCHIVE_FATAL);
449228753Smm		case LZMA_FORMAT_ERROR:
450228753Smm			archive_set_error(&self->archive->archive,
451228753Smm			    ARCHIVE_ERRNO_MISC,
452228753Smm			    "Lzma library error: format not recognized");
453228753Smm			return (ARCHIVE_FATAL);
454228753Smm		case LZMA_OPTIONS_ERROR:
455228753Smm			archive_set_error(&self->archive->archive,
456228753Smm			    ARCHIVE_ERRNO_MISC,
457228753Smm			    "Lzma library error: Invalid options");
458228753Smm			return (ARCHIVE_FATAL);
459228753Smm		case LZMA_DATA_ERROR:
460228753Smm			archive_set_error(&self->archive->archive,
461228753Smm			    ARCHIVE_ERRNO_MISC,
462228753Smm			    "Lzma library error: Corrupted input data");
463228753Smm			return (ARCHIVE_FATAL);
464228753Smm		case LZMA_BUF_ERROR:
465228753Smm			archive_set_error(&self->archive->archive,
466228753Smm			    ARCHIVE_ERRNO_MISC,
467228753Smm			    "Lzma library error:  No progress is possible");
468228753Smm			return (ARCHIVE_FATAL);
469228753Smm		default:
470228753Smm			/* Return an error. */
471228753Smm			archive_set_error(&self->archive->archive,
472228753Smm			    ARCHIVE_ERRNO_MISC,
473228753Smm			    "Lzma decompression failed:  Unknown error");
474228753Smm			return (ARCHIVE_FATAL);
475228753Smm		}
476228753Smm	}
477228753Smm
478228753Smm	decompressed = state->stream.next_out - state->out_block;
479228753Smm	state->total_out += decompressed;
480228753Smm	if (decompressed == 0)
481228753Smm		*p = NULL;
482228753Smm	else
483228753Smm		*p = state->out_block;
484228753Smm	return (decompressed);
485228753Smm}
486228753Smm
487228753Smm/*
488228753Smm * Clean up the decompressor.
489228753Smm */
490228753Smmstatic int
491228753Smmxz_filter_close(struct archive_read_filter *self)
492228753Smm{
493228753Smm	struct private_data *state;
494228753Smm
495228753Smm	state = (struct private_data *)self->data;
496228753Smm	lzma_end(&(state->stream));
497228753Smm	free(state->out_block);
498228753Smm	free(state);
499228753Smm	return (ARCHIVE_OK);
500228753Smm}
501228753Smm
502228753Smm#else
503228753Smm
504228753Smm#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
505228753Smm
506228753Smm/*
507228753Smm * If we have the older liblzmadec library, then we can handle
508228753Smm * LZMA streams but not XZ streams.
509228753Smm */
510228753Smm
511228753Smm/*
512228753Smm * Setup the callbacks.
513228753Smm */
514228753Smmstatic int
515228753Smmlzma_bidder_init(struct archive_read_filter *self)
516228753Smm{
517228753Smm	static const size_t out_block_size = 64 * 1024;
518228753Smm	void *out_block;
519228753Smm	struct private_data *state;
520228753Smm	ssize_t ret, avail_in;
521228753Smm
522228753Smm	self->code = ARCHIVE_COMPRESSION_LZMA;
523228753Smm	self->name = "lzma";
524228753Smm
525228753Smm	state = (struct private_data *)calloc(sizeof(*state), 1);
526228753Smm	out_block = (unsigned char *)malloc(out_block_size);
527228753Smm	if (state == NULL || out_block == NULL) {
528228753Smm		archive_set_error(&self->archive->archive, ENOMEM,
529228753Smm		    "Can't allocate data for lzma decompression");
530228753Smm		free(out_block);
531228753Smm		free(state);
532228753Smm		return (ARCHIVE_FATAL);
533228753Smm	}
534228753Smm
535228753Smm	self->data = state;
536228753Smm	state->out_block_size = out_block_size;
537228753Smm	state->out_block = out_block;
538228753Smm	self->read = lzma_filter_read;
539228753Smm	self->skip = NULL; /* not supported */
540228753Smm	self->close = lzma_filter_close;
541228753Smm
542228753Smm	/* Prime the lzma library with 18 bytes of input. */
543228753Smm	state->stream.next_in = (unsigned char *)(uintptr_t)
544228753Smm	    __archive_read_filter_ahead(self->upstream, 18, &avail_in);
545228753Smm	if (state->stream.next_in == NULL)
546228753Smm		return (ARCHIVE_FATAL);
547228753Smm	state->stream.avail_in = avail_in;
548228753Smm	state->stream.next_out = state->out_block;
549228753Smm	state->stream.avail_out = state->out_block_size;
550228753Smm
551228753Smm	/* Initialize compression library. */
552228753Smm	ret = lzmadec_init(&(state->stream));
553228753Smm	__archive_read_filter_consume(self->upstream,
554228753Smm	    avail_in - state->stream.avail_in);
555228753Smm	if (ret == LZMADEC_OK)
556228753Smm		return (ARCHIVE_OK);
557228753Smm
558228753Smm	/* Library setup failed: Clean up. */
559228753Smm	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
560228753Smm	    "Internal error initializing lzma library");
561228753Smm
562228753Smm	/* Override the error message if we know what really went wrong. */
563228753Smm	switch (ret) {
564228753Smm	case LZMADEC_HEADER_ERROR:
565228753Smm		archive_set_error(&self->archive->archive,
566228753Smm		    ARCHIVE_ERRNO_MISC,
567228753Smm		    "Internal error initializing compression library: "
568228753Smm		    "invalid header");
569228753Smm		break;
570228753Smm	case LZMADEC_MEM_ERROR:
571228753Smm		archive_set_error(&self->archive->archive, ENOMEM,
572228753Smm		    "Internal error initializing compression library: "
573228753Smm		    "out of memory");
574228753Smm		break;
575228753Smm	}
576228753Smm
577228753Smm	free(state->out_block);
578228753Smm	free(state);
579228753Smm	self->data = NULL;
580228753Smm	return (ARCHIVE_FATAL);
581228753Smm}
582228753Smm
583228753Smm/*
584228753Smm * Return the next block of decompressed data.
585228753Smm */
586228753Smmstatic ssize_t
587228753Smmlzma_filter_read(struct archive_read_filter *self, const void **p)
588228753Smm{
589228753Smm	struct private_data *state;
590228753Smm	size_t decompressed;
591228753Smm	ssize_t avail_in, ret;
592228753Smm
593228753Smm	state = (struct private_data *)self->data;
594228753Smm
595228753Smm	/* Empty our output buffer. */
596228753Smm	state->stream.next_out = state->out_block;
597228753Smm	state->stream.avail_out = state->out_block_size;
598228753Smm
599228753Smm	/* Try to fill the output buffer. */
600228753Smm	while (state->stream.avail_out > 0 && !state->eof) {
601228753Smm		state->stream.next_in = (unsigned char *)(uintptr_t)
602228753Smm		    __archive_read_filter_ahead(self->upstream, 1, &avail_in);
603228753Smm		if (state->stream.next_in == NULL && avail_in < 0)
604228753Smm			return (ARCHIVE_FATAL);
605228753Smm		state->stream.avail_in = avail_in;
606228753Smm
607228753Smm		/* Decompress as much as we can in one pass. */
608228753Smm		ret = lzmadec_decode(&(state->stream), avail_in == 0);
609228753Smm		switch (ret) {
610228753Smm		case LZMADEC_STREAM_END: /* Found end of stream. */
611228753Smm			state->eof = 1;
612228753Smm			/* FALL THROUGH */
613228753Smm		case LZMADEC_OK: /* Decompressor made some progress. */
614228753Smm			__archive_read_filter_consume(self->upstream,
615228753Smm			    avail_in - state->stream.avail_in);
616228753Smm			break;
617228753Smm		case LZMADEC_BUF_ERROR: /* Insufficient input data? */
618228753Smm			archive_set_error(&self->archive->archive,
619228753Smm			    ARCHIVE_ERRNO_MISC,
620228753Smm			    "Insufficient compressed data");
621228753Smm			return (ARCHIVE_FATAL);
622228753Smm		default:
623228753Smm			/* Return an error. */
624228753Smm			archive_set_error(&self->archive->archive,
625228753Smm			    ARCHIVE_ERRNO_MISC,
626228753Smm			    "Lzma decompression failed");
627228753Smm			return (ARCHIVE_FATAL);
628228753Smm		}
629228753Smm	}
630228753Smm
631228753Smm	decompressed = state->stream.next_out - state->out_block;
632228753Smm	state->total_out += decompressed;
633228753Smm	if (decompressed == 0)
634228753Smm		*p = NULL;
635228753Smm	else
636228753Smm		*p = state->out_block;
637228753Smm	return (decompressed);
638228753Smm}
639228753Smm
640228753Smm/*
641228753Smm * Clean up the decompressor.
642228753Smm */
643228753Smmstatic int
644228753Smmlzma_filter_close(struct archive_read_filter *self)
645228753Smm{
646228753Smm	struct private_data *state;
647228753Smm	int ret;
648228753Smm
649228753Smm	state = (struct private_data *)self->data;
650228753Smm	ret = ARCHIVE_OK;
651228753Smm	switch (lzmadec_end(&(state->stream))) {
652228753Smm	case LZMADEC_OK:
653228753Smm		break;
654228753Smm	default:
655228753Smm		archive_set_error(&(self->archive->archive),
656228753Smm		    ARCHIVE_ERRNO_MISC,
657228753Smm		    "Failed to clean up %s compressor",
658228753Smm		    self->archive->archive.compression_name);
659228753Smm		ret = ARCHIVE_FATAL;
660228753Smm	}
661228753Smm
662228753Smm	free(state->out_block);
663228753Smm	free(state);
664228753Smm	return (ret);
665228753Smm}
666228753Smm
667228753Smm#else
668228753Smm
669228753Smm/*
670228753Smm *
671228753Smm * If we have no suitable library on this system, we can't actually do
672228753Smm * the decompression.  We can, however, still detect compressed
673228753Smm * archives and emit a useful message.
674228753Smm *
675228753Smm */
676228753Smmstatic int
677228753Smmlzma_bidder_init(struct archive_read_filter *self)
678228753Smm{
679228753Smm	int r;
680228753Smm
681228753Smm	r = __archive_read_program(self, "unlzma");
682228753Smm	/* Note: We set the format here even if __archive_read_program()
683228753Smm	 * above fails.  We do, after all, know what the format is
684228753Smm	 * even if we weren't able to read it. */
685228753Smm	self->code = ARCHIVE_COMPRESSION_LZMA;
686228753Smm	self->name = "lzma";
687228753Smm	return (r);
688228753Smm}
689228753Smm
690228753Smm#endif /* HAVE_LZMADEC_H */
691228753Smm
692228753Smm
693228753Smmstatic int
694228753Smmxz_bidder_init(struct archive_read_filter *self)
695228753Smm{
696228753Smm	int r;
697228753Smm
698228753Smm	r = __archive_read_program(self, "unxz");
699228753Smm	/* Note: We set the format here even if __archive_read_program()
700228753Smm	 * above fails.  We do, after all, know what the format is
701228753Smm	 * even if we weren't able to read it. */
702228753Smm	self->code = ARCHIVE_COMPRESSION_XZ;
703228753Smm	self->name = "xz";
704228753Smm	return (r);
705228753Smm}
706228753Smm
707228753Smm
708228753Smm#endif /* HAVE_LZMA_H */
709