unxz: update from XZ embedded git
function old new delta rc_reset - 21 +21 unpack_xz_stream 2342 2357 +15 lzma_reset 102 64 -38 lzma_len 506 443 -63 xz_dec_lzma2_run 1438 1374 -64 xz_dec_reset 73 - -73 lzma_main 2517 2183 -334 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/4 up/down: 36/-572) Total: -536 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
91d7ee31f7
commit
ba73cfd284
@ -12,10 +12,11 @@
|
|||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
#include "unarchive.h"
|
#include "unarchive.h"
|
||||||
|
|
||||||
#define XZ_REALLOC_DICT_BUF(ptr, size) xrealloc(ptr, size)
|
|
||||||
#define XZ_FUNC FAST_FUNC
|
#define XZ_FUNC FAST_FUNC
|
||||||
#define XZ_EXTERN static
|
#define XZ_EXTERN static
|
||||||
|
|
||||||
|
#define XZ_DEC_DYNALLOC
|
||||||
|
|
||||||
/* Skip check (rather than fail) of unsupported hash functions */
|
/* Skip check (rather than fail) of unsupported hash functions */
|
||||||
#define XZ_DEC_ANY_CHECK 1
|
#define XZ_DEC_ANY_CHECK 1
|
||||||
|
|
||||||
@ -40,15 +41,9 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
|
|||||||
#define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val))
|
#define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val))
|
||||||
#define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val))
|
#define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val))
|
||||||
|
|
||||||
#include "unxz/xz.h"
|
|
||||||
#include "unxz/xz_config.h"
|
|
||||||
|
|
||||||
#include "unxz/xz_dec_bcj.c"
|
#include "unxz/xz_dec_bcj.c"
|
||||||
#include "unxz/xz_dec_lzma2.c"
|
#include "unxz/xz_dec_lzma2.c"
|
||||||
#include "unxz/xz_dec_stream.c"
|
#include "unxz/xz_dec_stream.c"
|
||||||
#include "unxz/xz_lzma2.h"
|
|
||||||
#include "unxz/xz_private.h"
|
|
||||||
#include "unxz/xz_stream.h"
|
|
||||||
|
|
||||||
IF_DESKTOP(long long) int FAST_FUNC
|
IF_DESKTOP(long long) int FAST_FUNC
|
||||||
unpack_xz_stream(int src_fd, int dst_fd)
|
unpack_xz_stream(int src_fd, int dst_fd)
|
||||||
@ -57,63 +52,50 @@ unpack_xz_stream(int src_fd, int dst_fd)
|
|||||||
struct xz_dec *state;
|
struct xz_dec *state;
|
||||||
unsigned char *membuf;
|
unsigned char *membuf;
|
||||||
IF_DESKTOP(long long) int total = 0;
|
IF_DESKTOP(long long) int total = 0;
|
||||||
enum {
|
|
||||||
IN_SIZE = 4 * 1024,
|
|
||||||
OUT_SIZE = 60 * 1024,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!crc32_table)
|
if (!crc32_table)
|
||||||
crc32_table = crc32_filltable(NULL, /*endian:*/ 0);
|
crc32_table = crc32_filltable(NULL, /*endian:*/ 0);
|
||||||
|
|
||||||
membuf = xmalloc(IN_SIZE + OUT_SIZE);
|
membuf = xmalloc(2 * BUFSIZ);
|
||||||
memset(&iobuf, 0, sizeof(iobuf));
|
memset(&iobuf, 0, sizeof(iobuf));
|
||||||
iobuf.in = membuf;
|
iobuf.in = membuf;
|
||||||
iobuf.out = membuf + IN_SIZE;
|
iobuf.out = membuf + BUFSIZ;
|
||||||
iobuf.out_size = OUT_SIZE;
|
iobuf.out_size = BUFSIZ;
|
||||||
|
|
||||||
state = xz_dec_init(64*1024); /* initial dict of 64k */
|
/* Limit memory usage to about 64 MiB. */
|
||||||
|
state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
enum xz_ret r;
|
enum xz_ret r;
|
||||||
int insz, rd, outpos;
|
|
||||||
|
|
||||||
iobuf.in_size -= iobuf.in_pos;
|
if (iobuf.in_pos == iobuf.in_size) {
|
||||||
insz = iobuf.in_size;
|
int rd = safe_read(src_fd, membuf, BUFSIZ);
|
||||||
if (insz)
|
|
||||||
memmove(membuf, membuf + iobuf.in_pos, insz);
|
|
||||||
iobuf.in_pos = 0;
|
|
||||||
rd = IN_SIZE - insz;
|
|
||||||
if (rd) {
|
|
||||||
rd = safe_read(src_fd, membuf + insz, rd);
|
|
||||||
if (rd < 0) {
|
if (rd < 0) {
|
||||||
bb_error_msg(bb_msg_read_error);
|
bb_error_msg(bb_msg_read_error);
|
||||||
total = -1;
|
total = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iobuf.in_size = insz + rd;
|
iobuf.in_size = rd;
|
||||||
|
iobuf.in_pos = 0;
|
||||||
}
|
}
|
||||||
// bb_error_msg(">in pos:%d size:%d out pos:%d size:%d",
|
// bb_error_msg(">in pos:%d size:%d out pos:%d size:%d",
|
||||||
// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size);
|
// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size);
|
||||||
r = xz_dec_run(state, &iobuf);
|
r = xz_dec_run(state, &iobuf);
|
||||||
// bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d",
|
// bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d",
|
||||||
// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r);
|
// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r);
|
||||||
outpos = iobuf.out_pos;
|
if (iobuf.out_pos) {
|
||||||
if (outpos) {
|
xwrite(dst_fd, iobuf.out, iobuf.out_pos);
|
||||||
xwrite(dst_fd, iobuf.out, outpos);
|
IF_DESKTOP(total += iobuf.out_pos;)
|
||||||
IF_DESKTOP(total += outpos;)
|
iobuf.out_pos = 0;
|
||||||
}
|
}
|
||||||
if (r == XZ_STREAM_END
|
if (r == XZ_STREAM_END) {
|
||||||
/* this happens even with well-formed files: */
|
|
||||||
|| (r == XZ_BUF_ERROR && insz == 0 && outpos == 0)
|
|
||||||
) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) {
|
if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) {
|
||||||
bb_error_msg("corrupted data");
|
bb_error_msg("corrupted or unsupported data");
|
||||||
total = -1;
|
total = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iobuf.out_pos = 0;
|
|
||||||
}
|
}
|
||||||
xz_dec_end(state);
|
xz_dec_end(state);
|
||||||
free(membuf);
|
free(membuf);
|
||||||
|
@ -29,10 +29,43 @@
|
|||||||
# define XZ_FUNC
|
# define XZ_FUNC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum xz_mode - Operation mode
|
||||||
|
*
|
||||||
|
* @XZ_SINGLE: Single-call mode. This uses less RAM than
|
||||||
|
* than multi-call modes, because the LZMA2
|
||||||
|
* dictionary doesn't need to be allocated as
|
||||||
|
* part of the decoder state. All required data
|
||||||
|
* structures are allocated at initialization,
|
||||||
|
* so xz_dec_run() cannot return XZ_MEM_ERROR.
|
||||||
|
* @XZ_PREALLOC: Multi-call mode with preallocated LZMA2
|
||||||
|
* dictionary buffer. All data structures are
|
||||||
|
* allocated at initialization, so xz_dec_run()
|
||||||
|
* cannot return XZ_MEM_ERROR.
|
||||||
|
* @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is
|
||||||
|
* allocated once the required size has been
|
||||||
|
* parsed from the stream headers. If the
|
||||||
|
* allocation fails, xz_dec_run() will return
|
||||||
|
* XZ_MEM_ERROR.
|
||||||
|
*
|
||||||
|
* It is possible to enable support only for a subset of the above
|
||||||
|
* modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC,
|
||||||
|
* or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled
|
||||||
|
* with support for all operation modes, but the preboot code may
|
||||||
|
* be built with fewer features to minimize code size.
|
||||||
|
*/
|
||||||
|
enum xz_mode {
|
||||||
|
XZ_SINGLE,
|
||||||
|
XZ_PREALLOC,
|
||||||
|
XZ_DYNALLOC
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum xz_ret - Return codes
|
* enum xz_ret - Return codes
|
||||||
* @XZ_OK: Everything is OK so far. More input or more
|
* @XZ_OK: Everything is OK so far. More input or more
|
||||||
* output space is required to continue.
|
* output space is required to continue. This
|
||||||
|
* return code is possible only in multi-call mode
|
||||||
|
* (XZ_PREALLOC or XZ_DYNALLOC).
|
||||||
* @XZ_STREAM_END: Operation finished successfully.
|
* @XZ_STREAM_END: Operation finished successfully.
|
||||||
* @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
|
* @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
|
||||||
* is still possible in multi-call mode by simply
|
* is still possible in multi-call mode by simply
|
||||||
@ -42,8 +75,17 @@
|
|||||||
* which is not used in the kernel. Unsupported
|
* which is not used in the kernel. Unsupported
|
||||||
* check types return XZ_OPTIONS_ERROR if
|
* check types return XZ_OPTIONS_ERROR if
|
||||||
* XZ_DEC_ANY_CHECK was not defined at build time.
|
* XZ_DEC_ANY_CHECK was not defined at build time.
|
||||||
* @XZ_MEMLIMIT_ERROR: Not enough memory was preallocated at decoder
|
* @XZ_MEM_ERROR: Allocating memory failed. This return code is
|
||||||
* initialization time.
|
* possible only if the decoder was initialized
|
||||||
|
* with XZ_DYNALLOC. The amount of memory that was
|
||||||
|
* tried to be allocated was no more than the
|
||||||
|
* dict_max argument given to xz_dec_init().
|
||||||
|
* @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than
|
||||||
|
* allowed by the dict_max argument given to
|
||||||
|
* xz_dec_init(). This return value is possible
|
||||||
|
* only in multi-call mode (XZ_PREALLOC or
|
||||||
|
* XZ_DYNALLOC); the single-call mode (XZ_SINGLE)
|
||||||
|
* ignores the dict_max argument.
|
||||||
* @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
|
* @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
|
||||||
* bytes).
|
* bytes).
|
||||||
* @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
|
* @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
|
||||||
@ -72,6 +114,7 @@ enum xz_ret {
|
|||||||
XZ_OK,
|
XZ_OK,
|
||||||
XZ_STREAM_END,
|
XZ_STREAM_END,
|
||||||
XZ_UNSUPPORTED_CHECK,
|
XZ_UNSUPPORTED_CHECK,
|
||||||
|
XZ_MEM_ERROR,
|
||||||
XZ_MEMLIMIT_ERROR,
|
XZ_MEMLIMIT_ERROR,
|
||||||
XZ_FORMAT_ERROR,
|
XZ_FORMAT_ERROR,
|
||||||
XZ_OPTIONS_ERROR,
|
XZ_OPTIONS_ERROR,
|
||||||
@ -112,61 +155,67 @@ struct xz_dec;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* xz_dec_init() - Allocate and initialize a XZ decoder state
|
* xz_dec_init() - Allocate and initialize a XZ decoder state
|
||||||
|
* @mode: Operation mode
|
||||||
* @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
|
* @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
|
||||||
* multi-call decoding, or special value of zero to indicate
|
* multi-call decoding. This is ignored in single-call mode
|
||||||
* single-call decoding mode.
|
* (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes
|
||||||
|
* or 2^n + 2^(n-1) bytes (the latter sizes are less common
|
||||||
|
* in practice), so other values for dict_max don't make sense.
|
||||||
|
* In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB,
|
||||||
|
* 512 KiB, and 1 MiB are probably the only reasonable values,
|
||||||
|
* except for kernel and initramfs images where a bigger
|
||||||
|
* dictionary can be fine and useful.
|
||||||
*
|
*
|
||||||
* If dict_max > 0, the decoder is initialized to work in multi-call mode.
|
* Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at
|
||||||
* dict_max number of bytes of memory is preallocated for the LZMA2
|
* once. The caller must provide enough output space or the decoding will
|
||||||
* dictionary. This way there is no risk that xz_dec_run() could run out
|
* fail. The output space is used as the dictionary buffer, which is why
|
||||||
* of memory, since xz_dec_run() will never allocate any memory. Instead,
|
* there is no need to allocate the dictionary as part of the decoder's
|
||||||
* if the preallocated dictionary is too small for decoding the given input
|
* internal state.
|
||||||
* stream, xz_dec_run() will return XZ_MEMLIMIT_ERROR. Thus, it is important
|
|
||||||
* to know what kind of data will be decoded to avoid allocating excessive
|
|
||||||
* amount of memory for the dictionary.
|
|
||||||
*
|
|
||||||
* LZMA2 dictionary is always 2^n bytes or 2^n + 2^(n-1) bytes (the latter
|
|
||||||
* sizes are less common in practice). In the kernel, dictionary sizes of
|
|
||||||
* 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB are probably the only
|
|
||||||
* reasonable values.
|
|
||||||
*
|
|
||||||
* If dict_max == 0, the decoder is initialized to work in single-call mode.
|
|
||||||
* In single-call mode, xz_dec_run() decodes the whole stream at once. The
|
|
||||||
* caller must provide enough output space or the decoding will fail. The
|
|
||||||
* output space is used as the dictionary buffer, which is why there is
|
|
||||||
* no need to allocate the dictionary as part of the decoder's internal
|
|
||||||
* state.
|
|
||||||
*
|
*
|
||||||
* Because the output buffer is used as the workspace, streams encoded using
|
* Because the output buffer is used as the workspace, streams encoded using
|
||||||
* a big dictionary are not a problem in single-call. It is enough that the
|
* a big dictionary are not a problem in single-call mode. It is enough that
|
||||||
* output buffer is big enough to hold the actual uncompressed data; it
|
* the output buffer is big enough to hold the actual uncompressed data; it
|
||||||
* can be smaller than the dictionary size stored in the stream headers.
|
* can be smaller than the dictionary size stored in the stream headers.
|
||||||
*
|
*
|
||||||
|
* Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes
|
||||||
|
* of memory is preallocated for the LZMA2 dictionary. This way there is no
|
||||||
|
* risk that xz_dec_run() could run out of memory, since xz_dec_run() will
|
||||||
|
* never allocate any memory. Instead, if the preallocated dictionary is too
|
||||||
|
* small for decoding the given input stream, xz_dec_run() will return
|
||||||
|
* XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be
|
||||||
|
* decoded to avoid allocating excessive amount of memory for the dictionary.
|
||||||
|
*
|
||||||
|
* Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC):
|
||||||
|
* dict_max specifies the maximum allowed dictionary size that xz_dec_run()
|
||||||
|
* may allocate once it has parsed the dictionary size from the stream
|
||||||
|
* headers. This way excessive allocations can be avoided while still
|
||||||
|
* limiting the maximum memory usage to a sane value to prevent running the
|
||||||
|
* system out of memory when decompressing streams from untrusted sources.
|
||||||
|
*
|
||||||
* On success, xz_dec_init() returns a pointer to struct xz_dec, which is
|
* On success, xz_dec_init() returns a pointer to struct xz_dec, which is
|
||||||
* ready to be used with xz_dec_run(). On error, xz_dec_init() returns NULL.
|
* ready to be used with xz_dec_run(). If memory allocation fails,
|
||||||
|
* xz_dec_init() returns NULL.
|
||||||
*/
|
*/
|
||||||
XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(uint32_t dict_max);
|
XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
|
||||||
|
enum xz_mode mode, uint32_t dict_max);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xz_dec_run() - Run the XZ decoder
|
* xz_dec_run() - Run the XZ decoder
|
||||||
* @s: Decoder state allocated using xz_dec_init()
|
* @s: Decoder state allocated using xz_dec_init()
|
||||||
* @b: Input and output buffers
|
* @b: Input and output buffers
|
||||||
*
|
*
|
||||||
* In multi-call mode, this function may return any of the values listed in
|
* The possible return values depend on build options and operation mode.
|
||||||
* enum xz_ret.
|
* See enum xz_ret for details.
|
||||||
*
|
*
|
||||||
* In single-call mode, this function never returns XZ_OK. If an error occurs
|
* NOTE: If an error occurs in single-call mode (return value is not
|
||||||
* in single-call mode (return value is not XZ_STREAM_END), b->in_pos and
|
* XZ_STREAM_END), b->in_pos and b->out_pos are not modified, and the
|
||||||
* b->out_pos are not modified, and the contents of the output buffer from
|
* contents of the output buffer from b->out[b->out_pos] onward are
|
||||||
* b->out[b->out_pos] onward are undefined.
|
* undefined. This is true even after XZ_BUF_ERROR, because with some filter
|
||||||
*
|
* chains, there may be a second pass over the output buffer, and this pass
|
||||||
* NOTE: In single-call mode, the contents of the output buffer are undefined
|
* cannot be properly done if the output buffer is truncated. Thus, you
|
||||||
* also after XZ_BUF_ERROR. This is because with some filter chains, there
|
* cannot give the single-call decoder a too small buffer and then expect to
|
||||||
* may be a second pass over the output buffer, and this pass cannot be
|
* get that amount valid data from the beginning of the stream. You must use
|
||||||
* properly done if the output buffer is truncated. Thus, you cannot give
|
* the multi-call decoder if you don't want to uncompress the whole stream.
|
||||||
* the single-call decoder a too small buffer and then expect to get that
|
|
||||||
* amount valid data from the beginning of the stream. You must use the
|
|
||||||
* multi-call decoder if you don't want to uncompress the whole stream.
|
|
||||||
*/
|
*/
|
||||||
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b);
|
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b);
|
||||||
|
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
*
|
*
|
||||||
* In multi-call mode, also these are true:
|
* In multi-call mode, also these are true:
|
||||||
* end == size
|
* end == size
|
||||||
* size <= allocated
|
* size <= size_max
|
||||||
|
* allocated <= size
|
||||||
*
|
*
|
||||||
* Most of these variables are size_t to support single-call mode,
|
* Most of these variables are size_t to support single-call mode,
|
||||||
* in which the dictionary variables address the actual output
|
* in which the dictionary variables address the actual output
|
||||||
@ -74,11 +75,20 @@ struct dictionary {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Amount of memory allocated for the dictionary. A special
|
* Maximum allowed dictionary size in multi-call mode.
|
||||||
* value of zero indicates that we are in single-call mode,
|
* This is ignored in single-call mode.
|
||||||
* where the output buffer works as the dictionary.
|
*/
|
||||||
|
uint32_t size_max;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Amount of memory currently allocated for the dictionary.
|
||||||
|
* This is used only with XZ_DYNALLOC. (With XZ_PREALLOC,
|
||||||
|
* size_max is always the same as the allocated size.)
|
||||||
*/
|
*/
|
||||||
uint32_t allocated;
|
uint32_t allocated;
|
||||||
|
|
||||||
|
/* Operation mode */
|
||||||
|
enum xz_mode mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Range decoder */
|
/* Range decoder */
|
||||||
@ -120,6 +130,21 @@ struct lzma_len_dec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct lzma_dec {
|
struct lzma_dec {
|
||||||
|
/* Distances of latest four matches */
|
||||||
|
uint32_t rep0;
|
||||||
|
uint32_t rep1;
|
||||||
|
uint32_t rep2;
|
||||||
|
uint32_t rep3;
|
||||||
|
|
||||||
|
/* Types of the most recently seen LZMA symbols */
|
||||||
|
enum lzma_state state;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Length of a match. This is updated so that dict_repeat can
|
||||||
|
* be called again to finish repeating the whole match.
|
||||||
|
*/
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LZMA properties or related bit masks (number of literal
|
* LZMA properties or related bit masks (number of literal
|
||||||
* context bits, a mask dervied from the number of literal
|
* context bits, a mask dervied from the number of literal
|
||||||
@ -130,21 +155,6 @@ struct lzma_dec {
|
|||||||
uint32_t literal_pos_mask; /* (1 << lp) - 1 */
|
uint32_t literal_pos_mask; /* (1 << lp) - 1 */
|
||||||
uint32_t pos_mask; /* (1 << pb) - 1 */
|
uint32_t pos_mask; /* (1 << pb) - 1 */
|
||||||
|
|
||||||
/* Types of the most recently seen LZMA symbols */
|
|
||||||
enum lzma_state state;
|
|
||||||
|
|
||||||
/* Distances of latest four matches */
|
|
||||||
uint32_t rep0;
|
|
||||||
uint32_t rep1;
|
|
||||||
uint32_t rep2;
|
|
||||||
uint32_t rep3;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Length of a match. This is updated so that dict_repeat can
|
|
||||||
* be called again to finish repeating the whole match.
|
|
||||||
*/
|
|
||||||
uint32_t len;
|
|
||||||
|
|
||||||
/* If 1, it's a match. Otherwise it's a single 8-bit literal. */
|
/* If 1, it's a match. Otherwise it's a single 8-bit literal. */
|
||||||
uint16_t is_match[STATES][POS_STATES_MAX];
|
uint16_t is_match[STATES][POS_STATES_MAX];
|
||||||
|
|
||||||
@ -201,49 +211,59 @@ struct lzma_dec {
|
|||||||
uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
|
uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct lzma2_dec {
|
||||||
|
/* Position in xz_dec_lzma2_run(). */
|
||||||
|
enum lzma2_seq {
|
||||||
|
SEQ_CONTROL,
|
||||||
|
SEQ_UNCOMPRESSED_1,
|
||||||
|
SEQ_UNCOMPRESSED_2,
|
||||||
|
SEQ_COMPRESSED_0,
|
||||||
|
SEQ_COMPRESSED_1,
|
||||||
|
SEQ_PROPERTIES,
|
||||||
|
SEQ_LZMA_PREPARE,
|
||||||
|
SEQ_LZMA_RUN,
|
||||||
|
SEQ_COPY
|
||||||
|
} sequence;
|
||||||
|
|
||||||
|
/* Next position after decoding the compressed size of the chunk. */
|
||||||
|
enum lzma2_seq next_sequence;
|
||||||
|
|
||||||
|
/* Uncompressed size of LZMA chunk (2 MiB at maximum) */
|
||||||
|
uint32_t uncompressed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compressed size of LZMA chunk or compressed/uncompressed
|
||||||
|
* size of uncompressed chunk (64 KiB at maximum)
|
||||||
|
*/
|
||||||
|
uint32_t compressed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* True if dictionary reset is needed. This is false before
|
||||||
|
* the first chunk (LZMA or uncompressed).
|
||||||
|
*/
|
||||||
|
bool need_dict_reset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* True if new LZMA properties are needed. This is false
|
||||||
|
* before the first LZMA chunk.
|
||||||
|
*/
|
||||||
|
bool need_props;
|
||||||
|
};
|
||||||
|
|
||||||
struct xz_dec_lzma2 {
|
struct xz_dec_lzma2 {
|
||||||
/* LZMA2 */
|
/*
|
||||||
struct {
|
* The order below is important on x86 to reduce code size and
|
||||||
/* Position in xz_dec_lzma2_run(). */
|
* it shouldn't hurt on other platforms. Everything up to and
|
||||||
enum lzma2_seq {
|
* including lzma.pos_mask are in the first 128 bytes on x86-32,
|
||||||
SEQ_CONTROL,
|
* which allows using smaller instructions to access those
|
||||||
SEQ_UNCOMPRESSED_1,
|
* variables. On x86-64, fewer variables fit into the first 128
|
||||||
SEQ_UNCOMPRESSED_2,
|
* bytes, but this is still the best order without sacrificing
|
||||||
SEQ_COMPRESSED_0,
|
* the readability by splitting the structures.
|
||||||
SEQ_COMPRESSED_1,
|
*/
|
||||||
SEQ_PROPERTIES,
|
struct rc_dec rc;
|
||||||
SEQ_LZMA_PREPARE,
|
struct dictionary dict;
|
||||||
SEQ_LZMA_RUN,
|
struct lzma2_dec lzma2;
|
||||||
SEQ_COPY
|
struct lzma_dec lzma;
|
||||||
} sequence;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Next position after decoding the compressed size of
|
|
||||||
* the chunk.
|
|
||||||
*/
|
|
||||||
enum lzma2_seq next_sequence;
|
|
||||||
|
|
||||||
/* Uncompressed size of LZMA chunk (2 MiB at maximum) */
|
|
||||||
uint32_t uncompressed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compressed size of LZMA chunk or compressed/uncompressed
|
|
||||||
* size of uncompressed chunk (64 KiB at maximum)
|
|
||||||
*/
|
|
||||||
uint32_t compressed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* True if dictionary reset is needed. This is false before
|
|
||||||
* the first chunk (LZMA or uncompressed).
|
|
||||||
*/
|
|
||||||
bool need_dict_reset;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* True if new LZMA properties are needed. This is false
|
|
||||||
* before the first LZMA chunk.
|
|
||||||
*/
|
|
||||||
bool need_props;
|
|
||||||
} lzma2;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Temporary buffer which holds small number of input bytes between
|
* Temporary buffer which holds small number of input bytes between
|
||||||
@ -253,10 +273,6 @@ struct xz_dec_lzma2 {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t buf[3 * LZMA_IN_REQUIRED];
|
uint8_t buf[3 * LZMA_IN_REQUIRED];
|
||||||
} temp;
|
} temp;
|
||||||
|
|
||||||
struct dictionary dict;
|
|
||||||
struct rc_dec rc;
|
|
||||||
struct lzma_dec lzma;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**************
|
/**************
|
||||||
@ -269,7 +285,7 @@ struct xz_dec_lzma2 {
|
|||||||
*/
|
*/
|
||||||
static void XZ_FUNC dict_reset(struct dictionary *dict, struct xz_buf *b)
|
static void XZ_FUNC dict_reset(struct dictionary *dict, struct xz_buf *b)
|
||||||
{
|
{
|
||||||
if (dict->allocated == 0) {
|
if (DEC_IS_SINGLE(dict->mode)) {
|
||||||
dict->buf = b->out + b->out_pos;
|
dict->buf = b->out + b->out_pos;
|
||||||
dict->end = b->out_size - b->out_pos;
|
dict->end = b->out_size - b->out_pos;
|
||||||
}
|
}
|
||||||
@ -379,7 +395,7 @@ static void XZ_FUNC dict_uncompressed(
|
|||||||
if (dict->full < dict->pos)
|
if (dict->full < dict->pos)
|
||||||
dict->full = dict->pos;
|
dict->full = dict->pos;
|
||||||
|
|
||||||
if (dict->allocated != 0) {
|
if (DEC_IS_MULTI(dict->mode)) {
|
||||||
if (dict->pos == dict->end)
|
if (dict->pos == dict->end)
|
||||||
dict->pos = 0;
|
dict->pos = 0;
|
||||||
|
|
||||||
@ -404,7 +420,7 @@ static uint32_t XZ_FUNC dict_flush(struct dictionary *dict, struct xz_buf *b)
|
|||||||
{
|
{
|
||||||
size_t copy_size = dict->pos - dict->start;
|
size_t copy_size = dict->pos - dict->start;
|
||||||
|
|
||||||
if (dict->allocated != 0) {
|
if (DEC_IS_MULTI(dict->mode)) {
|
||||||
if (dict->pos == dict->end)
|
if (dict->pos == dict->end)
|
||||||
dict->pos = 0;
|
dict->pos = 0;
|
||||||
|
|
||||||
@ -422,7 +438,7 @@ static uint32_t XZ_FUNC dict_flush(struct dictionary *dict, struct xz_buf *b)
|
|||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
/* Reset the range decoder. */
|
/* Reset the range decoder. */
|
||||||
static __always_inline void XZ_FUNC rc_reset(struct rc_dec *rc)
|
static void XZ_FUNC rc_reset(struct rc_dec *rc)
|
||||||
{
|
{
|
||||||
rc->range = (uint32_t)-1;
|
rc->range = (uint32_t)-1;
|
||||||
rc->code = 0;
|
rc->code = 0;
|
||||||
@ -1088,28 +1104,27 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run(
|
|||||||
return XZ_OK;
|
return XZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(uint32_t dict_max)
|
XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(
|
||||||
|
enum xz_mode mode, uint32_t dict_max)
|
||||||
{
|
{
|
||||||
struct xz_dec_lzma2 *s;
|
struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||||
|
|
||||||
/* Maximum supported dictionary by this implementation is 3 GiB. */
|
|
||||||
if (dict_max > ((uint32_t)3 << 30))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
s = kmalloc(sizeof(*s), GFP_KERNEL);
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (dict_max > 0) {
|
s->dict.mode = mode;
|
||||||
|
s->dict.size_max = dict_max;
|
||||||
|
|
||||||
|
if (DEC_IS_PREALLOC(mode)) {
|
||||||
s->dict.buf = vmalloc(dict_max);
|
s->dict.buf = vmalloc(dict_max);
|
||||||
if (s->dict.buf == NULL) {
|
if (s->dict.buf == NULL) {
|
||||||
kfree(s);
|
kfree(s);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
} else if (DEC_IS_DYNALLOC(mode)) {
|
||||||
|
s->dict.buf = NULL;
|
||||||
|
s->dict.allocated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->dict.allocated = dict_max;
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1123,18 +1138,23 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_reset(
|
|||||||
s->dict.size = 2 + (props & 1);
|
s->dict.size = 2 + (props & 1);
|
||||||
s->dict.size <<= (props >> 1) + 11;
|
s->dict.size <<= (props >> 1) + 11;
|
||||||
|
|
||||||
if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) {
|
if (DEC_IS_MULTI(s->dict.mode)) {
|
||||||
#ifdef XZ_REALLOC_DICT_BUF
|
if (s->dict.size > s->dict.size_max)
|
||||||
s->dict.buf = XZ_REALLOC_DICT_BUF(s->dict.buf, s->dict.size);
|
return XZ_MEMLIMIT_ERROR;
|
||||||
if (!s->dict.buf)
|
|
||||||
return XZ_MEMLIMIT_ERROR;
|
|
||||||
s->dict.allocated = s->dict.size;
|
|
||||||
#else
|
|
||||||
return XZ_MEMLIMIT_ERROR;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
s->dict.end = s->dict.size;
|
s->dict.end = s->dict.size;
|
||||||
|
|
||||||
|
if (DEC_IS_DYNALLOC(s->dict.mode)) {
|
||||||
|
if (s->dict.allocated < s->dict.size) {
|
||||||
|
vfree(s->dict.buf);
|
||||||
|
s->dict.buf = vmalloc(s->dict.size);
|
||||||
|
if (s->dict.buf == NULL) {
|
||||||
|
s->dict.allocated = 0;
|
||||||
|
return XZ_MEM_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s->lzma.len = 0;
|
s->lzma.len = 0;
|
||||||
|
|
||||||
@ -1148,7 +1168,7 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_reset(
|
|||||||
|
|
||||||
XZ_EXTERN void XZ_FUNC xz_dec_lzma2_end(struct xz_dec_lzma2 *s)
|
XZ_EXTERN void XZ_FUNC xz_dec_lzma2_end(struct xz_dec_lzma2 *s)
|
||||||
{
|
{
|
||||||
if (s->dict.allocated > 0)
|
if (DEC_IS_MULTI(s->dict.mode))
|
||||||
vfree(s->dict.buf);
|
vfree(s->dict.buf);
|
||||||
|
|
||||||
kfree(s);
|
kfree(s);
|
||||||
|
@ -48,8 +48,8 @@ struct xz_dec {
|
|||||||
/* Type of the integrity check calculated from uncompressed data */
|
/* Type of the integrity check calculated from uncompressed data */
|
||||||
enum xz_check check_type;
|
enum xz_check check_type;
|
||||||
|
|
||||||
/* True if we are operating in single-call mode. */
|
/* Operation mode */
|
||||||
bool single_call;
|
enum xz_mode mode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* True if the next call to xz_dec_run() is allowed to return
|
* True if the next call to xz_dec_run() is allowed to return
|
||||||
@ -737,14 +737,14 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b)
|
|||||||
size_t out_start;
|
size_t out_start;
|
||||||
enum xz_ret ret;
|
enum xz_ret ret;
|
||||||
|
|
||||||
if (s->single_call)
|
if (DEC_IS_SINGLE(s->mode))
|
||||||
xz_dec_reset(s);
|
xz_dec_reset(s);
|
||||||
|
|
||||||
in_start = b->in_pos;
|
in_start = b->in_pos;
|
||||||
out_start = b->out_pos;
|
out_start = b->out_pos;
|
||||||
ret = dec_main(s, b);
|
ret = dec_main(s, b);
|
||||||
|
|
||||||
if (s->single_call) {
|
if (DEC_IS_SINGLE(s->mode)) {
|
||||||
if (ret == XZ_OK)
|
if (ret == XZ_OK)
|
||||||
ret = b->in_pos == b->in_size
|
ret = b->in_pos == b->in_size
|
||||||
? XZ_DATA_ERROR : XZ_BUF_ERROR;
|
? XZ_DATA_ERROR : XZ_BUF_ERROR;
|
||||||
@ -767,21 +767,22 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(uint32_t dict_max)
|
XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
|
||||||
|
enum xz_mode mode, uint32_t dict_max)
|
||||||
{
|
{
|
||||||
struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
s->single_call = dict_max == 0;
|
s->mode = mode;
|
||||||
|
|
||||||
#ifdef XZ_DEC_BCJ
|
#ifdef XZ_DEC_BCJ
|
||||||
s->bcj = xz_dec_bcj_create(s->single_call);
|
s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
|
||||||
if (s->bcj == NULL)
|
if (s->bcj == NULL)
|
||||||
goto error_bcj;
|
goto error_bcj;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s->lzma2 = xz_dec_lzma2_create(dict_max);
|
s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
|
||||||
if (s->lzma2 == NULL)
|
if (s->lzma2 == NULL)
|
||||||
goto error_lzma2;
|
goto error_lzma2;
|
||||||
|
|
||||||
|
@ -53,6 +53,45 @@
|
|||||||
# include "xz_config.h"
|
# include "xz_config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If no specific decoding mode is requested, enable support for all modes. */
|
||||||
|
#if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \
|
||||||
|
&& !defined(XZ_DEC_DYNALLOC)
|
||||||
|
# define XZ_DEC_SINGLE
|
||||||
|
# define XZ_DEC_PREALLOC
|
||||||
|
# define XZ_DEC_DYNALLOC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The DEC_IS_foo(mode) macros are used in "if" statements. If only some
|
||||||
|
* of the supported modes are enabled, these macros will evaluate to true or
|
||||||
|
* false at compile time and thus allow the compiler to omit unneeded code.
|
||||||
|
*/
|
||||||
|
#ifdef XZ_DEC_SINGLE
|
||||||
|
# define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE)
|
||||||
|
#else
|
||||||
|
# define DEC_IS_SINGLE(mode) (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XZ_DEC_PREALLOC
|
||||||
|
# define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC)
|
||||||
|
#else
|
||||||
|
# define DEC_IS_PREALLOC(mode) (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XZ_DEC_DYNALLOC
|
||||||
|
# define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC)
|
||||||
|
#else
|
||||||
|
# define DEC_IS_DYNALLOC(mode) (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(XZ_DEC_SINGLE)
|
||||||
|
# define DEC_IS_MULTI(mode) (true)
|
||||||
|
#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC)
|
||||||
|
# define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE)
|
||||||
|
#else
|
||||||
|
# define DEC_IS_MULTI(mode) (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
|
* If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
|
||||||
* XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
|
* XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
|
||||||
@ -71,7 +110,7 @@
|
|||||||
* before calling xz_dec_lzma2_run().
|
* before calling xz_dec_lzma2_run().
|
||||||
*/
|
*/
|
||||||
XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(
|
XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(
|
||||||
uint32_t dict_max);
|
enum xz_mode mode, uint32_t dict_max);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decode the LZMA2 properties (one byte) and reset the decoder. Return
|
* Decode the LZMA2 properties (one byte) and reset the decoder. Return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user