xref: /freebsd/contrib/xz/src/liblzma/common/lzip_decoder.c (revision 3b35e7ee8de9b0260149a2b77e87a2b9c7a36244)
1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
2*3b35e7eeSXin LI 
373ed8e77SXin LI ///////////////////////////////////////////////////////////////////////////////
473ed8e77SXin LI //
573ed8e77SXin LI /// \file       lzip_decoder.c
673ed8e77SXin LI /// \brief      Decodes .lz (lzip) files
773ed8e77SXin LI //
873ed8e77SXin LI //  Author:     Michał Górny
973ed8e77SXin LI //              Lasse Collin
1073ed8e77SXin LI //
1173ed8e77SXin LI ///////////////////////////////////////////////////////////////////////////////
1273ed8e77SXin LI 
1373ed8e77SXin LI #include "lzip_decoder.h"
1473ed8e77SXin LI #include "lzma_decoder.h"
1573ed8e77SXin LI #include "check.h"
1673ed8e77SXin LI 
1773ed8e77SXin LI 
1873ed8e77SXin LI // .lz format version 0 lacks the 64-bit Member size field in the footer.
1973ed8e77SXin LI #define LZIP_V0_FOOTER_SIZE 12
2073ed8e77SXin LI #define LZIP_V1_FOOTER_SIZE 20
2173ed8e77SXin LI #define LZIP_FOOTER_SIZE_MAX LZIP_V1_FOOTER_SIZE
2273ed8e77SXin LI 
2373ed8e77SXin LI // lc/lp/pb are hardcoded in the .lz format.
2473ed8e77SXin LI #define LZIP_LC 3
2573ed8e77SXin LI #define LZIP_LP 0
2673ed8e77SXin LI #define LZIP_PB 2
2773ed8e77SXin LI 
2873ed8e77SXin LI 
2973ed8e77SXin LI typedef struct {
3073ed8e77SXin LI 	enum {
3173ed8e77SXin LI 		SEQ_ID_STRING,
3273ed8e77SXin LI 		SEQ_VERSION,
3373ed8e77SXin LI 		SEQ_DICT_SIZE,
3473ed8e77SXin LI 		SEQ_CODER_INIT,
3573ed8e77SXin LI 		SEQ_LZMA_STREAM,
3673ed8e77SXin LI 		SEQ_MEMBER_FOOTER,
3773ed8e77SXin LI 	} sequence;
3873ed8e77SXin LI 
3973ed8e77SXin LI 	/// .lz member format version
4073ed8e77SXin LI 	uint32_t version;
4173ed8e77SXin LI 
4273ed8e77SXin LI 	/// CRC32 of the uncompressed data in the .lz member
4373ed8e77SXin LI 	uint32_t crc32;
4473ed8e77SXin LI 
4573ed8e77SXin LI 	/// Uncompressed size of the .lz member
4673ed8e77SXin LI 	uint64_t uncompressed_size;
4773ed8e77SXin LI 
4873ed8e77SXin LI 	/// Compressed size of the .lz member
4973ed8e77SXin LI 	uint64_t member_size;
5073ed8e77SXin LI 
5173ed8e77SXin LI 	/// Memory usage limit
5273ed8e77SXin LI 	uint64_t memlimit;
5373ed8e77SXin LI 
5473ed8e77SXin LI 	/// Amount of memory actually needed
5573ed8e77SXin LI 	uint64_t memusage;
5673ed8e77SXin LI 
5773ed8e77SXin LI 	/// If true, LZMA_GET_CHECK is returned after decoding the header
5873ed8e77SXin LI 	/// fields. As all files use CRC32 this is redundant but it's
5973ed8e77SXin LI 	/// implemented anyway since the initialization functions supports
6073ed8e77SXin LI 	/// all other flags in addition to LZMA_TELL_ANY_CHECK.
6173ed8e77SXin LI 	bool tell_any_check;
6273ed8e77SXin LI 
6373ed8e77SXin LI 	/// If true, we won't calculate or verify the CRC32 of
6473ed8e77SXin LI 	/// the uncompressed data.
6573ed8e77SXin LI 	bool ignore_check;
6673ed8e77SXin LI 
6773ed8e77SXin LI 	/// If true, we will decode concatenated .lz members and stop if
6873ed8e77SXin LI 	/// non-.lz data is seen after at least one member has been
6973ed8e77SXin LI 	/// successfully decoded.
7073ed8e77SXin LI 	bool concatenated;
7173ed8e77SXin LI 
7273ed8e77SXin LI 	/// When decoding concatenated .lz members, this is true as long as
7373ed8e77SXin LI 	/// we are decoding the first .lz member. This is needed to avoid
7473ed8e77SXin LI 	/// incorrect LZMA_FORMAT_ERROR in case there is non-.lz data at
7573ed8e77SXin LI 	/// the end of the file.
7673ed8e77SXin LI 	bool first_member;
7773ed8e77SXin LI 
7873ed8e77SXin LI 	/// Reading position in the header and footer fields
7973ed8e77SXin LI 	size_t pos;
8073ed8e77SXin LI 
8173ed8e77SXin LI 	/// Buffer to hold the .lz footer fields
8273ed8e77SXin LI 	uint8_t buffer[LZIP_FOOTER_SIZE_MAX];
8373ed8e77SXin LI 
8473ed8e77SXin LI 	/// Options decoded from the .lz header that needed to initialize
8573ed8e77SXin LI 	/// the LZMA1 decoder.
8673ed8e77SXin LI 	lzma_options_lzma options;
8773ed8e77SXin LI 
8873ed8e77SXin LI 	/// LZMA1 decoder
8973ed8e77SXin LI 	lzma_next_coder lzma_decoder;
9073ed8e77SXin LI 
9173ed8e77SXin LI } lzma_lzip_coder;
9273ed8e77SXin LI 
9373ed8e77SXin LI 
9473ed8e77SXin LI static lzma_ret
9573ed8e77SXin LI lzip_decode(void *coder_ptr, const lzma_allocator *allocator,
9673ed8e77SXin LI 		const uint8_t *restrict in, size_t *restrict in_pos,
9773ed8e77SXin LI 		size_t in_size, uint8_t *restrict out,
9873ed8e77SXin LI 		size_t *restrict out_pos, size_t out_size, lzma_action action)
9973ed8e77SXin LI {
10073ed8e77SXin LI 	lzma_lzip_coder *coder = coder_ptr;
10173ed8e77SXin LI 
10273ed8e77SXin LI 	while (true)
10373ed8e77SXin LI 	switch (coder->sequence) {
10473ed8e77SXin LI 	case SEQ_ID_STRING: {
10573ed8e77SXin LI 		// The "ID string" or magic bytes are "LZIP" in US-ASCII.
10673ed8e77SXin LI 		const uint8_t lzip_id_string[4] = { 0x4C, 0x5A, 0x49, 0x50 };
10773ed8e77SXin LI 
10873ed8e77SXin LI 		while (coder->pos < sizeof(lzip_id_string)) {
10973ed8e77SXin LI 			if (*in_pos >= in_size) {
11073ed8e77SXin LI 				// If we are on the 2nd+ concatenated member
11173ed8e77SXin LI 				// and the input ends before we can read
11273ed8e77SXin LI 				// the magic bytes, we discard the bytes that
11373ed8e77SXin LI 				// were already read (up to 3) and finish.
11473ed8e77SXin LI 				// See the reasoning below.
11573ed8e77SXin LI 				return !coder->first_member
11673ed8e77SXin LI 						&& action == LZMA_FINISH
11773ed8e77SXin LI 					? LZMA_STREAM_END : LZMA_OK;
11873ed8e77SXin LI 			}
11973ed8e77SXin LI 
12073ed8e77SXin LI 			if (in[*in_pos] != lzip_id_string[coder->pos]) {
12173ed8e77SXin LI 				// The .lz format allows putting non-.lz data
12273ed8e77SXin LI 				// at the end of the file. If we have seen
12373ed8e77SXin LI 				// at least one valid .lz member already,
12473ed8e77SXin LI 				// then we won't consume the byte at *in_pos
12573ed8e77SXin LI 				// and will return LZMA_STREAM_END. This way
12673ed8e77SXin LI 				// apps can easily locate and read the non-.lz
12773ed8e77SXin LI 				// data after the .lz member(s).
12873ed8e77SXin LI 				//
12973ed8e77SXin LI 				// NOTE: If the first 1-3 bytes of the non-.lz
13073ed8e77SXin LI 				// data match the .lz ID string then the first
13173ed8e77SXin LI 				// 1-3 bytes of the junk will get ignored by
13273ed8e77SXin LI 				// us. If apps want to properly locate the
13373ed8e77SXin LI 				// trailing data they must ensure that the
13473ed8e77SXin LI 				// first byte of their custom data isn't the
13573ed8e77SXin LI 				// same as the first byte of .lz ID string.
13673ed8e77SXin LI 				// With the liblzma API we cannot rewind the
13773ed8e77SXin LI 				// input position across calls to lzma_code().
13873ed8e77SXin LI 				return !coder->first_member
13973ed8e77SXin LI 					? LZMA_STREAM_END : LZMA_FORMAT_ERROR;
14073ed8e77SXin LI 			}
14173ed8e77SXin LI 
14273ed8e77SXin LI 			++*in_pos;
14373ed8e77SXin LI 			++coder->pos;
14473ed8e77SXin LI 		}
14573ed8e77SXin LI 
14673ed8e77SXin LI 		coder->pos = 0;
14773ed8e77SXin LI 
14873ed8e77SXin LI 		coder->crc32 = 0;
14973ed8e77SXin LI 		coder->uncompressed_size = 0;
15073ed8e77SXin LI 		coder->member_size = sizeof(lzip_id_string);
15173ed8e77SXin LI 
15273ed8e77SXin LI 		coder->sequence = SEQ_VERSION;
15373ed8e77SXin LI 	}
15473ed8e77SXin LI 
15573ed8e77SXin LI 	// Fall through
15673ed8e77SXin LI 
15773ed8e77SXin LI 	case SEQ_VERSION:
15873ed8e77SXin LI 		if (*in_pos >= in_size)
15973ed8e77SXin LI 			return LZMA_OK;
16073ed8e77SXin LI 
16173ed8e77SXin LI 		coder->version = in[(*in_pos)++];
16273ed8e77SXin LI 
16373ed8e77SXin LI 		// We support version 0 and unextended version 1.
16473ed8e77SXin LI 		if (coder->version > 1)
16573ed8e77SXin LI 			return LZMA_OPTIONS_ERROR;
16673ed8e77SXin LI 
16773ed8e77SXin LI 		++coder->member_size;
16873ed8e77SXin LI 		coder->sequence = SEQ_DICT_SIZE;
16973ed8e77SXin LI 
17073ed8e77SXin LI 		// .lz versions 0 and 1 use CRC32 as the integrity check
17173ed8e77SXin LI 		// so if the application wanted to know that
17273ed8e77SXin LI 		// (LZMA_TELL_ANY_CHECK) we can tell it now.
17373ed8e77SXin LI 		if (coder->tell_any_check)
17473ed8e77SXin LI 			return LZMA_GET_CHECK;
17573ed8e77SXin LI 
17673ed8e77SXin LI 	// Fall through
17773ed8e77SXin LI 
17873ed8e77SXin LI 	case SEQ_DICT_SIZE: {
17973ed8e77SXin LI 		if (*in_pos >= in_size)
18073ed8e77SXin LI 			return LZMA_OK;
18173ed8e77SXin LI 
18273ed8e77SXin LI 		const uint32_t ds = in[(*in_pos)++];
18373ed8e77SXin LI 		++coder->member_size;
18473ed8e77SXin LI 
18573ed8e77SXin LI 		// The five lowest bits are for the base-2 logarithm of
18673ed8e77SXin LI 		// the dictionary size and the highest three bits are
18773ed8e77SXin LI 		// the fractional part (0/16 to 7/16) that will be
1881f3ced26SXin LI 		// subtracted to get the final value.
18973ed8e77SXin LI 		//
19073ed8e77SXin LI 		// For example, with 0xB5:
19173ed8e77SXin LI 		//     b2log = 21
19273ed8e77SXin LI 		//     fracnum = 5
19373ed8e77SXin LI 		//     dict_size = 2^21 - 2^21 * 5 / 16 = 1408 KiB
19473ed8e77SXin LI 		const uint32_t b2log = ds & 0x1F;
19573ed8e77SXin LI 		const uint32_t fracnum = ds >> 5;
19673ed8e77SXin LI 
19773ed8e77SXin LI 		// The format versions 0 and 1 allow dictionary size in the
19873ed8e77SXin LI 		// range [4 KiB, 512 MiB].
19973ed8e77SXin LI 		if (b2log < 12 || b2log > 29 || (b2log == 12 && fracnum > 0))
20073ed8e77SXin LI 			return LZMA_DATA_ERROR;
20173ed8e77SXin LI 
20273ed8e77SXin LI 		//   2^[b2log] - 2^[b2log] * [fracnum] / 16
20373ed8e77SXin LI 		// = 2^[b2log] - [fracnum] * 2^([b2log] - 4)
20473ed8e77SXin LI 		coder->options.dict_size = (UINT32_C(1) << b2log)
20573ed8e77SXin LI 				- (fracnum << (b2log - 4));
20673ed8e77SXin LI 
20773ed8e77SXin LI 		assert(coder->options.dict_size >= 4096);
20873ed8e77SXin LI 		assert(coder->options.dict_size <= (UINT32_C(512) << 20));
20973ed8e77SXin LI 
21073ed8e77SXin LI 		coder->options.preset_dict = NULL;
21173ed8e77SXin LI 		coder->options.lc = LZIP_LC;
21273ed8e77SXin LI 		coder->options.lp = LZIP_LP;
21373ed8e77SXin LI 		coder->options.pb = LZIP_PB;
21473ed8e77SXin LI 
21573ed8e77SXin LI 		// Calculate the memory usage.
21673ed8e77SXin LI 		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
21773ed8e77SXin LI 				+ LZMA_MEMUSAGE_BASE;
21873ed8e77SXin LI 
21973ed8e77SXin LI 		// Initialization is a separate step because if we return
22073ed8e77SXin LI 		// LZMA_MEMLIMIT_ERROR we need to be able to restart after
22173ed8e77SXin LI 		// the memlimit has been increased.
22273ed8e77SXin LI 		coder->sequence = SEQ_CODER_INIT;
22373ed8e77SXin LI 	}
22473ed8e77SXin LI 
22573ed8e77SXin LI 	// Fall through
22673ed8e77SXin LI 
22773ed8e77SXin LI 	case SEQ_CODER_INIT: {
22873ed8e77SXin LI 		if (coder->memusage > coder->memlimit)
22973ed8e77SXin LI 			return LZMA_MEMLIMIT_ERROR;
23073ed8e77SXin LI 
23173ed8e77SXin LI 		const lzma_filter_info filters[2] = {
23273ed8e77SXin LI 			{
23373ed8e77SXin LI 				.id = LZMA_FILTER_LZMA1,
23473ed8e77SXin LI 				.init = &lzma_lzma_decoder_init,
23573ed8e77SXin LI 				.options = &coder->options,
23673ed8e77SXin LI 			}, {
23773ed8e77SXin LI 				.init = NULL,
23873ed8e77SXin LI 			}
23973ed8e77SXin LI 		};
24073ed8e77SXin LI 
24173ed8e77SXin LI 		return_if_error(lzma_next_filter_init(&coder->lzma_decoder,
24273ed8e77SXin LI 				allocator, filters));
24373ed8e77SXin LI 
24473ed8e77SXin LI 		coder->crc32 = 0;
24573ed8e77SXin LI 		coder->sequence = SEQ_LZMA_STREAM;
24673ed8e77SXin LI 	}
24773ed8e77SXin LI 
24873ed8e77SXin LI 	// Fall through
24973ed8e77SXin LI 
25073ed8e77SXin LI 	case SEQ_LZMA_STREAM: {
25173ed8e77SXin LI 		const size_t in_start = *in_pos;
25273ed8e77SXin LI 		const size_t out_start = *out_pos;
25373ed8e77SXin LI 
25473ed8e77SXin LI 		const lzma_ret ret = coder->lzma_decoder.code(
25573ed8e77SXin LI 				coder->lzma_decoder.coder, allocator,
25673ed8e77SXin LI 				in, in_pos, in_size, out, out_pos, out_size,
25773ed8e77SXin LI 				action);
25873ed8e77SXin LI 
25973ed8e77SXin LI 		const size_t out_used = *out_pos - out_start;
26073ed8e77SXin LI 
26173ed8e77SXin LI 		coder->member_size += *in_pos - in_start;
26273ed8e77SXin LI 		coder->uncompressed_size += out_used;
26373ed8e77SXin LI 
264c917796cSXin LI 		// Don't update the CRC32 if the integrity check will be
265c917796cSXin LI 		// ignored or if there was no new output. The latter is
266c917796cSXin LI 		// important in case out == NULL to avoid null pointer + 0
267c917796cSXin LI 		// which is undefined behavior.
268c917796cSXin LI 		if (!coder->ignore_check && out_used > 0)
26973ed8e77SXin LI 			coder->crc32 = lzma_crc32(out + out_start, out_used,
27073ed8e77SXin LI 					coder->crc32);
27173ed8e77SXin LI 
27273ed8e77SXin LI 		if (ret != LZMA_STREAM_END)
27373ed8e77SXin LI 			return ret;
27473ed8e77SXin LI 
27573ed8e77SXin LI 		coder->sequence = SEQ_MEMBER_FOOTER;
27673ed8e77SXin LI 	}
27773ed8e77SXin LI 
27873ed8e77SXin LI 	// Fall through
27973ed8e77SXin LI 
28073ed8e77SXin LI 	case SEQ_MEMBER_FOOTER: {
28173ed8e77SXin LI 		// The footer of .lz version 0 lacks the Member size field.
28273ed8e77SXin LI 		// This is the only difference between version 0 and
28373ed8e77SXin LI 		// unextended version 1 formats.
28473ed8e77SXin LI 		const size_t footer_size = coder->version == 0
28573ed8e77SXin LI 				? LZIP_V0_FOOTER_SIZE
28673ed8e77SXin LI 				: LZIP_V1_FOOTER_SIZE;
28773ed8e77SXin LI 
28873ed8e77SXin LI 		// Copy the CRC32, Data size, and Member size fields to
28973ed8e77SXin LI 		// the internal buffer.
29073ed8e77SXin LI 		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
29173ed8e77SXin LI 				footer_size);
29273ed8e77SXin LI 
29373ed8e77SXin LI 		// Return if we didn't get the whole footer yet.
29473ed8e77SXin LI 		if (coder->pos < footer_size)
29573ed8e77SXin LI 			return LZMA_OK;
29673ed8e77SXin LI 
29773ed8e77SXin LI 		coder->pos = 0;
29873ed8e77SXin LI 		coder->member_size += footer_size;
29973ed8e77SXin LI 
30073ed8e77SXin LI 		// Check that the footer fields match the observed data.
30173ed8e77SXin LI 		if (!coder->ignore_check
30273ed8e77SXin LI 				&& coder->crc32 != read32le(&coder->buffer[0]))
30373ed8e77SXin LI 			return LZMA_DATA_ERROR;
30473ed8e77SXin LI 
30573ed8e77SXin LI 		if (coder->uncompressed_size != read64le(&coder->buffer[4]))
30673ed8e77SXin LI 			return LZMA_DATA_ERROR;
30773ed8e77SXin LI 
30873ed8e77SXin LI 		if (coder->version > 0) {
30973ed8e77SXin LI 			// .lz version 0 has no Member size field.
31073ed8e77SXin LI 			if (coder->member_size != read64le(&coder->buffer[12]))
31173ed8e77SXin LI 				return LZMA_DATA_ERROR;
31273ed8e77SXin LI 		}
31373ed8e77SXin LI 
31473ed8e77SXin LI 		// Decoding is finished if we weren't requested to decode
31573ed8e77SXin LI 		// more than one .lz member.
31673ed8e77SXin LI 		if (!coder->concatenated)
31773ed8e77SXin LI 			return LZMA_STREAM_END;
31873ed8e77SXin LI 
31973ed8e77SXin LI 		coder->first_member = false;
32073ed8e77SXin LI 		coder->sequence = SEQ_ID_STRING;
32173ed8e77SXin LI 		break;
32273ed8e77SXin LI 	}
32373ed8e77SXin LI 
32473ed8e77SXin LI 	default:
32573ed8e77SXin LI 		assert(0);
32673ed8e77SXin LI 		return LZMA_PROG_ERROR;
32773ed8e77SXin LI 	}
32873ed8e77SXin LI 
32973ed8e77SXin LI 	// Never reached
33073ed8e77SXin LI }
33173ed8e77SXin LI 
33273ed8e77SXin LI 
33373ed8e77SXin LI static void
33473ed8e77SXin LI lzip_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
33573ed8e77SXin LI {
33673ed8e77SXin LI 	lzma_lzip_coder *coder = coder_ptr;
33773ed8e77SXin LI 	lzma_next_end(&coder->lzma_decoder, allocator);
33873ed8e77SXin LI 	lzma_free(coder, allocator);
33973ed8e77SXin LI 	return;
34073ed8e77SXin LI }
34173ed8e77SXin LI 
34273ed8e77SXin LI 
34373ed8e77SXin LI static lzma_check
34473ed8e77SXin LI lzip_decoder_get_check(const void *coder_ptr lzma_attribute((__unused__)))
34573ed8e77SXin LI {
34673ed8e77SXin LI 	return LZMA_CHECK_CRC32;
34773ed8e77SXin LI }
34873ed8e77SXin LI 
34973ed8e77SXin LI 
35073ed8e77SXin LI static lzma_ret
35173ed8e77SXin LI lzip_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
35273ed8e77SXin LI 		uint64_t *old_memlimit, uint64_t new_memlimit)
35373ed8e77SXin LI {
35473ed8e77SXin LI 	lzma_lzip_coder *coder = coder_ptr;
35573ed8e77SXin LI 
35673ed8e77SXin LI 	*memusage = coder->memusage;
35773ed8e77SXin LI 	*old_memlimit = coder->memlimit;
35873ed8e77SXin LI 
35973ed8e77SXin LI 	if (new_memlimit != 0) {
36073ed8e77SXin LI 		if (new_memlimit < coder->memusage)
36173ed8e77SXin LI 			return LZMA_MEMLIMIT_ERROR;
36273ed8e77SXin LI 
36373ed8e77SXin LI 		coder->memlimit = new_memlimit;
36473ed8e77SXin LI 	}
36573ed8e77SXin LI 
36673ed8e77SXin LI 	return LZMA_OK;
36773ed8e77SXin LI }
36873ed8e77SXin LI 
36973ed8e77SXin LI 
37073ed8e77SXin LI extern lzma_ret
37173ed8e77SXin LI lzma_lzip_decoder_init(
37273ed8e77SXin LI 		lzma_next_coder *next, const lzma_allocator *allocator,
37373ed8e77SXin LI 		uint64_t memlimit, uint32_t flags)
37473ed8e77SXin LI {
37573ed8e77SXin LI 	lzma_next_coder_init(&lzma_lzip_decoder_init, next, allocator);
37673ed8e77SXin LI 
37773ed8e77SXin LI 	if (flags & ~LZMA_SUPPORTED_FLAGS)
37873ed8e77SXin LI 		return LZMA_OPTIONS_ERROR;
37973ed8e77SXin LI 
38073ed8e77SXin LI 	lzma_lzip_coder *coder = next->coder;
38173ed8e77SXin LI 	if (coder == NULL) {
38273ed8e77SXin LI 		coder = lzma_alloc(sizeof(lzma_lzip_coder), allocator);
38373ed8e77SXin LI 		if (coder == NULL)
38473ed8e77SXin LI 			return LZMA_MEM_ERROR;
38573ed8e77SXin LI 
38673ed8e77SXin LI 		next->coder = coder;
38773ed8e77SXin LI 		next->code = &lzip_decode;
38873ed8e77SXin LI 		next->end = &lzip_decoder_end;
38973ed8e77SXin LI 		next->get_check = &lzip_decoder_get_check;
39073ed8e77SXin LI 		next->memconfig = &lzip_decoder_memconfig;
39173ed8e77SXin LI 
39273ed8e77SXin LI 		coder->lzma_decoder = LZMA_NEXT_CODER_INIT;
39373ed8e77SXin LI 	}
39473ed8e77SXin LI 
39573ed8e77SXin LI 	coder->sequence = SEQ_ID_STRING;
39673ed8e77SXin LI 	coder->memlimit = my_max(1, memlimit);
39773ed8e77SXin LI 	coder->memusage = LZMA_MEMUSAGE_BASE;
39873ed8e77SXin LI 	coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
39973ed8e77SXin LI 	coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
40073ed8e77SXin LI 	coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
40173ed8e77SXin LI 	coder->first_member = true;
40273ed8e77SXin LI 	coder->pos = 0;
40373ed8e77SXin LI 
40473ed8e77SXin LI 	return LZMA_OK;
40573ed8e77SXin LI }
40673ed8e77SXin LI 
40773ed8e77SXin LI 
40873ed8e77SXin LI extern LZMA_API(lzma_ret)
40973ed8e77SXin LI lzma_lzip_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
41073ed8e77SXin LI {
41173ed8e77SXin LI 	lzma_next_strm_init(lzma_lzip_decoder_init, strm, memlimit, flags);
41273ed8e77SXin LI 
41373ed8e77SXin LI 	strm->internal->supported_actions[LZMA_RUN] = true;
41473ed8e77SXin LI 	strm->internal->supported_actions[LZMA_FINISH] = true;
41573ed8e77SXin LI 
41673ed8e77SXin LI 	return LZMA_OK;
41773ed8e77SXin LI }
418