1228753Smm/*-
2231200Smm * Copyright (c) 2003-2010 Tim Kientzle
3232153Smm * Copyright (c) 2009-2012 Michihiro NAKAJIMA
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
29228753Smm__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_xz.c 201108 2009-12-28 03:28:21Z kientzle $");
30228753Smm
31228753Smm#ifdef HAVE_ERRNO_H
32228753Smm#include <errno.h>
33228753Smm#endif
34228753Smm#ifdef HAVE_STDLIB_H
35228753Smm#include <stdlib.h>
36228753Smm#endif
37228753Smm#ifdef HAVE_STRING_H
38228753Smm#include <string.h>
39228753Smm#endif
40228753Smm#include <time.h>
41228753Smm#ifdef HAVE_LZMA_H
42228753Smm#include <lzma.h>
43228753Smm#endif
44228753Smm
45228753Smm#include "archive.h"
46231200Smm#include "archive_endian.h"
47228753Smm#include "archive_private.h"
48228753Smm#include "archive_write_private.h"
49228753Smm
50231200Smm#if ARCHIVE_VERSION_NUMBER < 4000000
51228753Smmint
52231200Smmarchive_write_set_compression_lzip(struct archive *a)
53231200Smm{
54231200Smm	__archive_write_filters_free(a);
55231200Smm	return (archive_write_add_filter_lzip(a));
56231200Smm}
57231200Smm
58231200Smmint
59231200Smmarchive_write_set_compression_lzma(struct archive *a)
60231200Smm{
61231200Smm	__archive_write_filters_free(a);
62231200Smm	return (archive_write_add_filter_lzma(a));
63231200Smm}
64231200Smm
65231200Smmint
66228753Smmarchive_write_set_compression_xz(struct archive *a)
67228753Smm{
68231200Smm	__archive_write_filters_free(a);
69231200Smm	return (archive_write_add_filter_xz(a));
70231200Smm}
71231200Smm
72231200Smm#endif
73231200Smm
74231200Smm#ifndef HAVE_LZMA_H
75231200Smmint
76231200Smmarchive_write_add_filter_xz(struct archive *a)
77231200Smm{
78228753Smm	archive_set_error(a, ARCHIVE_ERRNO_MISC,
79228753Smm	    "xz compression not supported on this platform");
80228753Smm	return (ARCHIVE_FATAL);
81228753Smm}
82228753Smm
83228753Smmint
84231200Smmarchive_write_add_filter_lzma(struct archive *a)
85228753Smm{
86228753Smm	archive_set_error(a, ARCHIVE_ERRNO_MISC,
87228753Smm	    "lzma compression not supported on this platform");
88228753Smm	return (ARCHIVE_FATAL);
89228753Smm}
90231200Smm
91231200Smmint
92231200Smmarchive_write_add_filter_lzip(struct archive *a)
93231200Smm{
94231200Smm	archive_set_error(a, ARCHIVE_ERRNO_MISC,
95231200Smm	    "lzma compression not supported on this platform");
96231200Smm	return (ARCHIVE_FATAL);
97231200Smm}
98228753Smm#else
99228753Smm/* Don't compile this if we don't have liblzma. */
100228753Smm
101228753Smmstruct private_data {
102231200Smm	int		 compression_level;
103228753Smm	lzma_stream	 stream;
104228753Smm	lzma_filter	 lzmafilters[2];
105228753Smm	lzma_options_lzma lzma_opt;
106228753Smm	int64_t		 total_in;
107228753Smm	unsigned char	*compressed;
108228753Smm	size_t		 compressed_buffer_size;
109231200Smm	int64_t		 total_out;
110231200Smm	/* the CRC32 value of uncompressed data for lzip */
111231200Smm	uint32_t	 crc32;
112228753Smm};
113228753Smm
114231200Smmstatic int	archive_compressor_xz_options(struct archive_write_filter *,
115228753Smm		    const char *, const char *);
116231200Smmstatic int	archive_compressor_xz_open(struct archive_write_filter *);
117231200Smmstatic int	archive_compressor_xz_write(struct archive_write_filter *,
118228753Smm		    const void *, size_t);
119231200Smmstatic int	archive_compressor_xz_close(struct archive_write_filter *);
120231200Smmstatic int	archive_compressor_xz_free(struct archive_write_filter *);
121231200Smmstatic int	drive_compressor(struct archive_write_filter *,
122231200Smm		    struct private_data *, int finishing);
123228753Smm
124231200Smmstruct option_value {
125231200Smm	uint32_t dict_size;
126231200Smm	uint32_t nice_len;
127231200Smm	lzma_match_finder mf;
128231200Smm};
129231200Smmstatic const struct option_value option_values[] = {
130231200Smm	{ 1 << 16, 32, LZMA_MF_HC3},
131231200Smm	{ 1 << 20, 32, LZMA_MF_HC3},
132231200Smm	{ 3 << 19, 32, LZMA_MF_HC4},
133231200Smm	{ 1 << 21, 32, LZMA_MF_BT4},
134231200Smm	{ 3 << 20, 32, LZMA_MF_BT4},
135231200Smm	{ 1 << 22, 32, LZMA_MF_BT4},
136231200Smm	{ 1 << 23, 64, LZMA_MF_BT4},
137231200Smm	{ 1 << 24, 64, LZMA_MF_BT4},
138231200Smm	{ 3 << 23, 64, LZMA_MF_BT4},
139231200Smm	{ 1 << 25, 64, LZMA_MF_BT4}
140231200Smm};
141228753Smm
142231200Smmstatic int
143231200Smmcommon_setup(struct archive_write_filter *f)
144228753Smm{
145231200Smm	struct private_data *data;
146231200Smm	struct archive_write *a = (struct archive_write *)f->archive;
147231200Smm	data = calloc(1, sizeof(*data));
148231200Smm	if (data == NULL) {
149228753Smm		archive_set_error(&a->archive, ENOMEM, "Out of memory");
150228753Smm		return (ARCHIVE_FATAL);
151228753Smm	}
152231200Smm	f->data = data;
153231200Smm	data->compression_level = LZMA_PRESET_DEFAULT;
154231200Smm	f->open = &archive_compressor_xz_open;
155231200Smm	f->close = archive_compressor_xz_close;
156231200Smm	f->free = archive_compressor_xz_free;
157231200Smm	f->options = &archive_compressor_xz_options;
158228753Smm	return (ARCHIVE_OK);
159228753Smm}
160228753Smm
161231200Smm/*
162231200Smm * Add an xz compression filter to this write handle.
163231200Smm */
164231200Smmint
165231200Smmarchive_write_add_filter_xz(struct archive *_a)
166231200Smm{
167231200Smm	struct archive_write_filter *f;
168231200Smm	int r;
169231200Smm
170231200Smm	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
171231200Smm	    ARCHIVE_STATE_NEW, "archive_write_add_filter_xz");
172231200Smm	f = __archive_write_allocate_filter(_a);
173231200Smm	r = common_setup(f);
174231200Smm	if (r == ARCHIVE_OK) {
175248616Smm		f->code = ARCHIVE_FILTER_XZ;
176231200Smm		f->name = "xz";
177231200Smm	}
178231200Smm	return (r);
179231200Smm}
180231200Smm
181228753Smm/* LZMA is handled identically, we just need a different compression
182228753Smm * code set.  (The liblzma setup looks at the code to determine
183228753Smm * the one place that XZ and LZMA require different handling.) */
184228753Smmint
185231200Smmarchive_write_add_filter_lzma(struct archive *_a)
186228753Smm{
187231200Smm	struct archive_write_filter *f;
188231200Smm	int r;
189231200Smm
190231200Smm	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
191231200Smm	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lzma");
192231200Smm	f = __archive_write_allocate_filter(_a);
193231200Smm	r = common_setup(f);
194231200Smm	if (r == ARCHIVE_OK) {
195248616Smm		f->code = ARCHIVE_FILTER_LZMA;
196231200Smm		f->name = "lzma";
197231200Smm	}
198231200Smm	return (r);
199228753Smm}
200228753Smm
201231200Smmint
202231200Smmarchive_write_add_filter_lzip(struct archive *_a)
203231200Smm{
204231200Smm	struct archive_write_filter *f;
205231200Smm	int r;
206231200Smm
207231200Smm	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
208231200Smm	    ARCHIVE_STATE_NEW, "archive_write_add_filter_lzip");
209231200Smm	f = __archive_write_allocate_filter(_a);
210231200Smm	r = common_setup(f);
211231200Smm	if (r == ARCHIVE_OK) {
212248616Smm		f->code = ARCHIVE_FILTER_LZIP;
213231200Smm		f->name = "lzip";
214231200Smm	}
215231200Smm	return (r);
216231200Smm}
217231200Smm
218228753Smmstatic int
219231200Smmarchive_compressor_xz_init_stream(struct archive_write_filter *f,
220231200Smm    struct private_data *data)
221228753Smm{
222228753Smm	static const lzma_stream lzma_stream_init_data = LZMA_STREAM_INIT;
223228753Smm	int ret;
224228753Smm
225231200Smm	data->stream = lzma_stream_init_data;
226231200Smm	data->stream.next_out = data->compressed;
227231200Smm	data->stream.avail_out = data->compressed_buffer_size;
228248616Smm	if (f->code == ARCHIVE_FILTER_XZ)
229231200Smm		ret = lzma_stream_encoder(&(data->stream),
230231200Smm		    data->lzmafilters, LZMA_CHECK_CRC64);
231248616Smm	else if (f->code == ARCHIVE_FILTER_LZMA)
232231200Smm		ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt);
233248616Smm	else {	/* ARCHIVE_FILTER_LZIP */
234231200Smm		int dict_size = data->lzma_opt.dict_size;
235231200Smm		int ds, log2dic, wedges;
236231200Smm
237231200Smm		/* Calculate a coded dictionary size */
238231200Smm		if (dict_size < (1 << 12) || dict_size > (1 << 27)) {
239231200Smm			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
240231200Smm			    "Unacceptable dictionary dize for lzip: %d",
241231200Smm			    dict_size);
242231200Smm			return (ARCHIVE_FATAL);
243231200Smm		}
244231200Smm		for (log2dic = 27; log2dic >= 12; log2dic--) {
245231200Smm			if (dict_size & (1 << log2dic))
246231200Smm				break;
247231200Smm		}
248231200Smm		if (dict_size > (1 << log2dic)) {
249231200Smm			log2dic++;
250231200Smm			wedges =
251231200Smm			    ((1 << log2dic) - dict_size) / (1 << (log2dic - 4));
252231200Smm		} else
253231200Smm			wedges = 0;
254231200Smm		ds = ((wedges << 5) & 0xe0) | (log2dic & 0x1f);
255231200Smm
256231200Smm		data->crc32 = 0;
257231200Smm		/* Make a header */
258231200Smm		data->compressed[0] = 0x4C;
259231200Smm		data->compressed[1] = 0x5A;
260231200Smm		data->compressed[2] = 0x49;
261231200Smm		data->compressed[3] = 0x50;
262231200Smm		data->compressed[4] = 1;/* Version */
263231200Smm		data->compressed[5] = (unsigned char)ds;
264231200Smm		data->stream.next_out += 6;
265231200Smm		data->stream.avail_out -= 6;
266231200Smm
267231200Smm		ret = lzma_raw_encoder(&(data->stream), data->lzmafilters);
268231200Smm	}
269228753Smm	if (ret == LZMA_OK)
270228753Smm		return (ARCHIVE_OK);
271228753Smm
272228753Smm	switch (ret) {
273228753Smm	case LZMA_MEM_ERROR:
274231200Smm		archive_set_error(f->archive, ENOMEM,
275228753Smm		    "Internal error initializing compression library: "
276228753Smm		    "Cannot allocate memory");
277228753Smm		break;
278228753Smm	default:
279231200Smm		archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
280228753Smm		    "Internal error initializing compression library: "
281228753Smm		    "It's a bug in liblzma");
282228753Smm		break;
283228753Smm	}
284228753Smm	return (ARCHIVE_FATAL);
285228753Smm}
286228753Smm
287228753Smm/*
288228753Smm * Setup callback.
289228753Smm */
290228753Smmstatic int
291231200Smmarchive_compressor_xz_open(struct archive_write_filter *f)
292228753Smm{
293231200Smm	struct private_data *data = f->data;
294228753Smm	int ret;
295228753Smm
296231200Smm	ret = __archive_write_open_filter(f->next_filter);
297231200Smm	if (ret != ARCHIVE_OK)
298231200Smm		return (ret);
299228753Smm
300231200Smm	if (data->compressed == NULL) {
301238856Smm		size_t bs = 65536, bpb;
302238856Smm		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
303238856Smm			/* Buffer size should be a multiple number of the of bytes
304238856Smm			 * per block for performance. */
305238856Smm			bpb = archive_write_get_bytes_per_block(f->archive);
306238856Smm			if (bpb > bs)
307238856Smm				bs = bpb;
308238856Smm			else if (bpb != 0)
309238856Smm				bs -= bs % bpb;
310238856Smm		}
311238856Smm		data->compressed_buffer_size = bs;
312231200Smm		data->compressed
313231200Smm		    = (unsigned char *)malloc(data->compressed_buffer_size);
314231200Smm		if (data->compressed == NULL) {
315231200Smm			archive_set_error(f->archive, ENOMEM,
316231200Smm			    "Can't allocate data for compression buffer");
317231200Smm			return (ARCHIVE_FATAL);
318231200Smm		}
319228753Smm	}
320228753Smm
321231200Smm	f->write = archive_compressor_xz_write;
322228753Smm
323228753Smm	/* Initialize compression library. */
324248616Smm	if (f->code == ARCHIVE_FILTER_LZIP) {
325231200Smm		const struct option_value *val =
326231200Smm		    &option_values[data->compression_level];
327231200Smm
328231200Smm		data->lzma_opt.dict_size = val->dict_size;
329231200Smm		data->lzma_opt.preset_dict = NULL;
330231200Smm		data->lzma_opt.preset_dict_size = 0;
331231200Smm		data->lzma_opt.lc = LZMA_LC_DEFAULT;
332231200Smm		data->lzma_opt.lp = LZMA_LP_DEFAULT;
333231200Smm		data->lzma_opt.pb = LZMA_PB_DEFAULT;
334231200Smm		data->lzma_opt.mode =
335231200Smm		    data->compression_level<= 2? LZMA_MODE_FAST:LZMA_MODE_NORMAL;
336231200Smm		data->lzma_opt.nice_len = val->nice_len;
337231200Smm		data->lzma_opt.mf = val->mf;
338231200Smm		data->lzma_opt.depth = 0;
339231200Smm		data->lzmafilters[0].id = LZMA_FILTER_LZMA1;
340231200Smm		data->lzmafilters[0].options = &data->lzma_opt;
341231200Smm		data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
342231200Smm	} else {
343231200Smm		if (lzma_lzma_preset(&data->lzma_opt, data->compression_level)) {
344231200Smm			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
345231200Smm			    "Internal error initializing compression library");
346231200Smm		}
347231200Smm		data->lzmafilters[0].id = LZMA_FILTER_LZMA2;
348231200Smm		data->lzmafilters[0].options = &data->lzma_opt;
349231200Smm		data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
350228753Smm	}
351231200Smm	ret = archive_compressor_xz_init_stream(f, data);
352228753Smm	if (ret == LZMA_OK) {
353231200Smm		f->data = data;
354228753Smm		return (0);
355228753Smm	}
356228753Smm	return (ARCHIVE_FATAL);
357228753Smm}
358228753Smm
359228753Smm/*
360228753Smm * Set write options.
361228753Smm */
362228753Smmstatic int
363231200Smmarchive_compressor_xz_options(struct archive_write_filter *f,
364231200Smm    const char *key, const char *value)
365228753Smm{
366231200Smm	struct private_data *data = (struct private_data *)f->data;
367228753Smm
368228753Smm	if (strcmp(key, "compression-level") == 0) {
369228753Smm		if (value == NULL || !(value[0] >= '0' && value[0] <= '9') ||
370228753Smm		    value[1] != '\0')
371228753Smm			return (ARCHIVE_WARN);
372231200Smm		data->compression_level = value[0] - '0';
373231200Smm		if (data->compression_level > 6)
374231200Smm			data->compression_level = 6;
375228753Smm		return (ARCHIVE_OK);
376228753Smm	}
377228753Smm
378232153Smm	/* Note: The "warn" return is just to inform the options
379232153Smm	 * supervisor that we didn't handle it.  It will generate
380232153Smm	 * a suitable error if no one used this option. */
381228753Smm	return (ARCHIVE_WARN);
382228753Smm}
383228753Smm
384228753Smm/*
385228753Smm * Write data to the compressed stream.
386228753Smm */
387228753Smmstatic int
388231200Smmarchive_compressor_xz_write(struct archive_write_filter *f,
389231200Smm    const void *buff, size_t length)
390228753Smm{
391231200Smm	struct private_data *data = (struct private_data *)f->data;
392228753Smm	int ret;
393228753Smm
394228753Smm	/* Update statistics */
395231200Smm	data->total_in += length;
396248616Smm	if (f->code == ARCHIVE_FILTER_LZIP)
397231200Smm		data->crc32 = lzma_crc32(buff, length, data->crc32);
398228753Smm
399228753Smm	/* Compress input data to output buffer */
400231200Smm	data->stream.next_in = buff;
401231200Smm	data->stream.avail_in = length;
402231200Smm	if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK)
403228753Smm		return (ret);
404228753Smm
405228753Smm	return (ARCHIVE_OK);
406228753Smm}
407228753Smm
408228753Smm
409228753Smm/*
410228753Smm * Finish the compression...
411228753Smm */
412228753Smmstatic int
413231200Smmarchive_compressor_xz_close(struct archive_write_filter *f)
414228753Smm{
415231200Smm	struct private_data *data = (struct private_data *)f->data;
416231200Smm	int ret, r1;
417228753Smm
418231200Smm	ret = drive_compressor(f, data, 1);
419231200Smm	if (ret == ARCHIVE_OK) {
420231200Smm		data->total_out +=
421231200Smm		    data->compressed_buffer_size - data->stream.avail_out;
422231200Smm		ret = __archive_write_filter(f->next_filter,
423231200Smm		    data->compressed,
424231200Smm		    data->compressed_buffer_size - data->stream.avail_out);
425248616Smm		if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) {
426231200Smm			archive_le32enc(data->compressed, data->crc32);
427231200Smm			archive_le64enc(data->compressed+4, data->total_in);
428231200Smm			archive_le64enc(data->compressed+12, data->total_out + 20);
429231200Smm			ret = __archive_write_filter(f->next_filter,
430231200Smm			    data->compressed, 20);
431228753Smm		}
432228753Smm	}
433231200Smm	lzma_end(&(data->stream));
434231200Smm	r1 = __archive_write_close_filter(f->next_filter);
435231200Smm	return (r1 < ret ? r1 : ret);
436228753Smm}
437228753Smm
438231200Smmstatic int
439231200Smmarchive_compressor_xz_free(struct archive_write_filter *f)
440231200Smm{
441231200Smm	struct private_data *data = (struct private_data *)f->data;
442231200Smm	free(data->compressed);
443231200Smm	free(data);
444231200Smm	f->data = NULL;
445231200Smm	return (ARCHIVE_OK);
446231200Smm}
447231200Smm
448228753Smm/*
449228753Smm * Utility function to push input data through compressor,
450228753Smm * writing full output blocks as necessary.
451228753Smm *
452228753Smm * Note that this handles both the regular write case (finishing ==
453228753Smm * false) and the end-of-archive case (finishing == true).
454228753Smm */
455228753Smmstatic int
456231200Smmdrive_compressor(struct archive_write_filter *f,
457231200Smm    struct private_data *data, int finishing)
458228753Smm{
459228753Smm	int ret;
460228753Smm
461228753Smm	for (;;) {
462231200Smm		if (data->stream.avail_out == 0) {
463231200Smm			data->total_out += data->compressed_buffer_size;
464231200Smm			ret = __archive_write_filter(f->next_filter,
465231200Smm			    data->compressed,
466231200Smm			    data->compressed_buffer_size);
467231200Smm			if (ret != ARCHIVE_OK)
468228753Smm				return (ARCHIVE_FATAL);
469231200Smm			data->stream.next_out = data->compressed;
470231200Smm			data->stream.avail_out = data->compressed_buffer_size;
471228753Smm		}
472228753Smm
473228753Smm		/* If there's nothing to do, we're done. */
474231200Smm		if (!finishing && data->stream.avail_in == 0)
475228753Smm			return (ARCHIVE_OK);
476228753Smm
477231200Smm		ret = lzma_code(&(data->stream),
478228753Smm		    finishing ? LZMA_FINISH : LZMA_RUN );
479228753Smm
480228753Smm		switch (ret) {
481228753Smm		case LZMA_OK:
482228753Smm			/* In non-finishing case, check if compressor
483228753Smm			 * consumed everything */
484231200Smm			if (!finishing && data->stream.avail_in == 0)
485228753Smm				return (ARCHIVE_OK);
486228753Smm			/* In finishing case, this return always means
487228753Smm			 * there's more work */
488228753Smm			break;
489228753Smm		case LZMA_STREAM_END:
490228753Smm			/* This return can only occur in finishing case. */
491228753Smm			if (finishing)
492228753Smm				return (ARCHIVE_OK);
493231200Smm			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
494228753Smm			    "lzma compression data error");
495228753Smm			return (ARCHIVE_FATAL);
496228753Smm		case LZMA_MEMLIMIT_ERROR:
497231200Smm			archive_set_error(f->archive, ENOMEM,
498228753Smm			    "lzma compression error: "
499228753Smm			    "%ju MiB would have been needed",
500231200Smm			    (uintmax_t)((lzma_memusage(&(data->stream))
501231200Smm				    + 1024 * 1024 -1)
502228753Smm				/ (1024 * 1024)));
503228753Smm			return (ARCHIVE_FATAL);
504228753Smm		default:
505228753Smm			/* Any other return value indicates an error. */
506231200Smm			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
507228753Smm			    "lzma compression failed:"
508228753Smm			    " lzma_code() call returned status %d",
509228753Smm			    ret);
510228753Smm			return (ARCHIVE_FATAL);
511228753Smm		}
512228753Smm	}
513228753Smm}
514228753Smm
515228753Smm#endif /* HAVE_LZMA_H */
516