diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-20 02:40:56 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-20 02:40:56 +0200 |
| commit | ba73cfd28464f9ef926dfd27e264215d4c4f8b1f (patch) | |
| tree | 1388876b477579cb6f43b4eb12b258b61bc8f010 | |
| parent | 91d7ee31f766a13595c1042d375f8374f2c3675f (diff) | |
| download | busybox-w32-ba73cfd28464f9ef926dfd27e264215d4c4f8b1f.tar.gz busybox-w32-ba73cfd28464f9ef926dfd27e264215d4c4f8b1f.tar.bz2 busybox-w32-ba73cfd28464f9ef926dfd27e264215d4c4f8b1f.zip | |
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>
| -rw-r--r-- | archival/libunarchive/decompress_unxz.c | 52 | ||||
| -rw-r--r-- | archival/libunarchive/unxz/xz.h | 139 | ||||
| -rw-r--r-- | archival/libunarchive/unxz/xz_dec_lzma2.c | 200 | ||||
| -rw-r--r-- | archival/libunarchive/unxz/xz_dec_stream.c | 17 | ||||
| -rw-r--r-- | archival/libunarchive/unxz/xz_private.h | 41 |
5 files changed, 270 insertions, 179 deletions
diff --git a/archival/libunarchive/decompress_unxz.c b/archival/libunarchive/decompress_unxz.c index 1302e29fb..800680fef 100644 --- a/archival/libunarchive/decompress_unxz.c +++ b/archival/libunarchive/decompress_unxz.c | |||
| @@ -12,10 +12,11 @@ | |||
| 12 | #include "libbb.h" | 12 | #include "libbb.h" |
| 13 | #include "unarchive.h" | 13 | #include "unarchive.h" |
| 14 | 14 | ||
| 15 | #define XZ_REALLOC_DICT_BUF(ptr, size) xrealloc(ptr, size) | ||
| 16 | #define XZ_FUNC FAST_FUNC | 15 | #define XZ_FUNC FAST_FUNC |
| 17 | #define XZ_EXTERN static | 16 | #define XZ_EXTERN static |
| 18 | 17 | ||
| 18 | #define XZ_DEC_DYNALLOC | ||
| 19 | |||
| 19 | /* Skip check (rather than fail) of unsupported hash functions */ | 20 | /* Skip check (rather than fail) of unsupported hash functions */ |
| 20 | #define XZ_DEC_ANY_CHECK 1 | 21 | #define XZ_DEC_ANY_CHECK 1 |
| 21 | 22 | ||
| @@ -40,15 +41,9 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) | |||
| 40 | #define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val)) | 41 | #define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val)) |
| 41 | #define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val)) | 42 | #define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val)) |
| 42 | 43 | ||
| 43 | #include "unxz/xz.h" | ||
| 44 | #include "unxz/xz_config.h" | ||
| 45 | |||
| 46 | #include "unxz/xz_dec_bcj.c" | 44 | #include "unxz/xz_dec_bcj.c" |
| 47 | #include "unxz/xz_dec_lzma2.c" | 45 | #include "unxz/xz_dec_lzma2.c" |
| 48 | #include "unxz/xz_dec_stream.c" | 46 | #include "unxz/xz_dec_stream.c" |
| 49 | #include "unxz/xz_lzma2.h" | ||
| 50 | #include "unxz/xz_private.h" | ||
| 51 | #include "unxz/xz_stream.h" | ||
| 52 | 47 | ||
| 53 | IF_DESKTOP(long long) int FAST_FUNC | 48 | IF_DESKTOP(long long) int FAST_FUNC |
| 54 | unpack_xz_stream(int src_fd, int dst_fd) | 49 | unpack_xz_stream(int src_fd, int dst_fd) |
| @@ -57,63 +52,50 @@ unpack_xz_stream(int src_fd, int dst_fd) | |||
| 57 | struct xz_dec *state; | 52 | struct xz_dec *state; |
| 58 | unsigned char *membuf; | 53 | unsigned char *membuf; |
| 59 | IF_DESKTOP(long long) int total = 0; | 54 | IF_DESKTOP(long long) int total = 0; |
| 60 | enum { | ||
| 61 | IN_SIZE = 4 * 1024, | ||
| 62 | OUT_SIZE = 60 * 1024, | ||
| 63 | }; | ||
| 64 | 55 | ||
| 65 | if (!crc32_table) | 56 | if (!crc32_table) |
| 66 | crc32_table = crc32_filltable(NULL, /*endian:*/ 0); | 57 | crc32_table = crc32_filltable(NULL, /*endian:*/ 0); |
| 67 | 58 | ||
| 68 | membuf = xmalloc(IN_SIZE + OUT_SIZE); | 59 | membuf = xmalloc(2 * BUFSIZ); |
| 69 | memset(&iobuf, 0, sizeof(iobuf)); | 60 | memset(&iobuf, 0, sizeof(iobuf)); |
| 70 | iobuf.in = membuf; | 61 | iobuf.in = membuf; |
| 71 | iobuf.out = membuf + IN_SIZE; | 62 | iobuf.out = membuf + BUFSIZ; |
| 72 | iobuf.out_size = OUT_SIZE; | 63 | iobuf.out_size = BUFSIZ; |
| 73 | 64 | ||
| 74 | state = xz_dec_init(64*1024); /* initial dict of 64k */ | 65 | /* Limit memory usage to about 64 MiB. */ |
| 66 | state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024); | ||
| 75 | 67 | ||
| 76 | while (1) { | 68 | while (1) { |
| 77 | enum xz_ret r; | 69 | enum xz_ret r; |
| 78 | int insz, rd, outpos; | ||
| 79 | 70 | ||
| 80 | iobuf.in_size -= iobuf.in_pos; | 71 | if (iobuf.in_pos == iobuf.in_size) { |
| 81 | insz = iobuf.in_size; | 72 | int rd = safe_read(src_fd, membuf, BUFSIZ); |
| 82 | if (insz) | ||
| 83 | memmove(membuf, membuf + iobuf.in_pos, insz); | ||
| 84 | iobuf.in_pos = 0; | ||
| 85 | rd = IN_SIZE - insz; | ||
| 86 | if (rd) { | ||
| 87 | rd = safe_read(src_fd, membuf + insz, rd); | ||
| 88 | if (rd < 0) { | 73 | if (rd < 0) { |
| 89 | bb_error_msg(bb_msg_read_error); | 74 | bb_error_msg(bb_msg_read_error); |
| 90 | total = -1; | 75 | total = -1; |
| 91 | break; | 76 | break; |
| 92 | } | 77 | } |
| 93 | iobuf.in_size = insz + rd; | 78 | iobuf.in_size = rd; |
| 79 | iobuf.in_pos = 0; | ||
| 94 | } | 80 | } |
| 95 | // bb_error_msg(">in pos:%d size:%d out pos:%d size:%d", | 81 | // bb_error_msg(">in pos:%d size:%d out pos:%d size:%d", |
| 96 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size); | 82 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size); |
| 97 | r = xz_dec_run(state, &iobuf); | 83 | r = xz_dec_run(state, &iobuf); |
| 98 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", | 84 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", |
| 99 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r); | 85 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r); |
| 100 | outpos = iobuf.out_pos; | 86 | if (iobuf.out_pos) { |
| 101 | if (outpos) { | 87 | xwrite(dst_fd, iobuf.out, iobuf.out_pos); |
| 102 | xwrite(dst_fd, iobuf.out, outpos); | 88 | IF_DESKTOP(total += iobuf.out_pos;) |
| 103 | IF_DESKTOP(total += outpos;) | 89 | iobuf.out_pos = 0; |
| 104 | } | 90 | } |
| 105 | if (r == XZ_STREAM_END | 91 | if (r == XZ_STREAM_END) { |
| 106 | /* this happens even with well-formed files: */ | ||
| 107 | || (r == XZ_BUF_ERROR && insz == 0 && outpos == 0) | ||
| 108 | ) { | ||
| 109 | break; | 92 | break; |
| 110 | } | 93 | } |
| 111 | if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) { | 94 | if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) { |
| 112 | bb_error_msg("corrupted data"); | 95 | bb_error_msg("corrupted or unsupported data"); |
| 113 | total = -1; | 96 | total = -1; |
| 114 | break; | 97 | break; |
| 115 | } | 98 | } |
| 116 | iobuf.out_pos = 0; | ||
| 117 | } | 99 | } |
| 118 | xz_dec_end(state); | 100 | xz_dec_end(state); |
| 119 | free(membuf); | 101 | free(membuf); |
diff --git a/archival/libunarchive/unxz/xz.h b/archival/libunarchive/unxz/xz.h index eb82706b9..c6c071c4a 100644 --- a/archival/libunarchive/unxz/xz.h +++ b/archival/libunarchive/unxz/xz.h | |||
| @@ -30,9 +30,42 @@ | |||
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| 32 | /** | 32 | /** |
| 33 | * enum xz_mode - Operation mode | ||
| 34 | * | ||
| 35 | * @XZ_SINGLE: Single-call mode. This uses less RAM than | ||
| 36 | * than multi-call modes, because the LZMA2 | ||
| 37 | * dictionary doesn't need to be allocated as | ||
| 38 | * part of the decoder state. All required data | ||
| 39 | * structures are allocated at initialization, | ||
| 40 | * so xz_dec_run() cannot return XZ_MEM_ERROR. | ||
| 41 | * @XZ_PREALLOC: Multi-call mode with preallocated LZMA2 | ||
| 42 | * dictionary buffer. All data structures are | ||
| 43 | * allocated at initialization, so xz_dec_run() | ||
| 44 | * cannot return XZ_MEM_ERROR. | ||
| 45 | * @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is | ||
| 46 | * allocated once the required size has been | ||
| 47 | * parsed from the stream headers. If the | ||
| 48 | * allocation fails, xz_dec_run() will return | ||
| 49 | * XZ_MEM_ERROR. | ||
| 50 | * | ||
| 51 | * It is possible to enable support only for a subset of the above | ||
| 52 | * modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC, | ||
| 53 | * or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled | ||
| 54 | * with support for all operation modes, but the preboot code may | ||
| 55 | * be built with fewer features to minimize code size. | ||
| 56 | */ | ||
| 57 | enum xz_mode { | ||
| 58 | XZ_SINGLE, | ||
| 59 | XZ_PREALLOC, | ||
| 60 | XZ_DYNALLOC | ||
| 61 | }; | ||
| 62 | |||
| 63 | /** | ||
| 33 | * enum xz_ret - Return codes | 64 | * enum xz_ret - Return codes |
| 34 | * @XZ_OK: Everything is OK so far. More input or more | 65 | * @XZ_OK: Everything is OK so far. More input or more |
| 35 | * output space is required to continue. | 66 | * output space is required to continue. This |
| 67 | * return code is possible only in multi-call mode | ||
| 68 | * (XZ_PREALLOC or XZ_DYNALLOC). | ||
| 36 | * @XZ_STREAM_END: Operation finished successfully. | 69 | * @XZ_STREAM_END: Operation finished successfully. |
| 37 | * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding | 70 | * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding |
| 38 | * is still possible in multi-call mode by simply | 71 | * is still possible in multi-call mode by simply |
| @@ -42,8 +75,17 @@ | |||
| 42 | * which is not used in the kernel. Unsupported | 75 | * which is not used in the kernel. Unsupported |
| 43 | * check types return XZ_OPTIONS_ERROR if | 76 | * check types return XZ_OPTIONS_ERROR if |
| 44 | * XZ_DEC_ANY_CHECK was not defined at build time. | 77 | * XZ_DEC_ANY_CHECK was not defined at build time. |
| 45 | * @XZ_MEMLIMIT_ERROR: Not enough memory was preallocated at decoder | 78 | * @XZ_MEM_ERROR: Allocating memory failed. This return code is |
| 46 | * initialization time. | 79 | * possible only if the decoder was initialized |
| 80 | * with XZ_DYNALLOC. The amount of memory that was | ||
| 81 | * tried to be allocated was no more than the | ||
| 82 | * dict_max argument given to xz_dec_init(). | ||
| 83 | * @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than | ||
| 84 | * allowed by the dict_max argument given to | ||
| 85 | * xz_dec_init(). This return value is possible | ||
| 86 | * only in multi-call mode (XZ_PREALLOC or | ||
| 87 | * XZ_DYNALLOC); the single-call mode (XZ_SINGLE) | ||
| 88 | * ignores the dict_max argument. | ||
| 47 | * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic | 89 | * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic |
| 48 | * bytes). | 90 | * bytes). |
| 49 | * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested | 91 | * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested |
| @@ -72,6 +114,7 @@ enum xz_ret { | |||
| 72 | XZ_OK, | 114 | XZ_OK, |
| 73 | XZ_STREAM_END, | 115 | XZ_STREAM_END, |
| 74 | XZ_UNSUPPORTED_CHECK, | 116 | XZ_UNSUPPORTED_CHECK, |
| 117 | XZ_MEM_ERROR, | ||
| 75 | XZ_MEMLIMIT_ERROR, | 118 | XZ_MEMLIMIT_ERROR, |
| 76 | XZ_FORMAT_ERROR, | 119 | XZ_FORMAT_ERROR, |
| 77 | XZ_OPTIONS_ERROR, | 120 | XZ_OPTIONS_ERROR, |
| @@ -112,61 +155,67 @@ struct xz_dec; | |||
| 112 | 155 | ||
| 113 | /** | 156 | /** |
| 114 | * xz_dec_init() - Allocate and initialize a XZ decoder state | 157 | * xz_dec_init() - Allocate and initialize a XZ decoder state |
| 158 | * @mode: Operation mode | ||
| 115 | * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for | 159 | * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for |
| 116 | * multi-call decoding, or special value of zero to indicate | 160 | * multi-call decoding. This is ignored in single-call mode |
| 117 | * single-call decoding mode. | 161 | * (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes |
| 118 | * | 162 | * or 2^n + 2^(n-1) bytes (the latter sizes are less common |
| 119 | * If dict_max > 0, the decoder is initialized to work in multi-call mode. | 163 | * in practice), so other values for dict_max don't make sense. |
| 120 | * dict_max number of bytes of memory is preallocated for the LZMA2 | 164 | * In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB, |
| 121 | * dictionary. This way there is no risk that xz_dec_run() could run out | 165 | * 512 KiB, and 1 MiB are probably the only reasonable values, |
| 122 | * of memory, since xz_dec_run() will never allocate any memory. Instead, | 166 | * except for kernel and initramfs images where a bigger |
| 123 | * if the preallocated dictionary is too small for decoding the given input | 167 | * dictionary can be fine and useful. |
| 124 | * stream, xz_dec_run() will return XZ_MEMLIMIT_ERROR. Thus, it is important | 168 | * |
| 125 | * to know what kind of data will be decoded to avoid allocating excessive | 169 | * Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at |
| 126 | * amount of memory for the dictionary. | 170 | * once. The caller must provide enough output space or the decoding will |
| 127 | * | 171 | * fail. The output space is used as the dictionary buffer, which is why |
| 128 | * LZMA2 dictionary is always 2^n bytes or 2^n + 2^(n-1) bytes (the latter | 172 | * there is no need to allocate the dictionary as part of the decoder's |
| 129 | * sizes are less common in practice). In the kernel, dictionary sizes of | 173 | * internal state. |
| 130 | * 64 KiB, 128 KiB, 256 KiB, 512 KiB, and 1 MiB are probably the only | ||
| 131 | * reasonable values. | ||
| 132 | * | ||
| 133 | * If dict_max == 0, the decoder is initialized to work in single-call mode. | ||
| 134 | * In single-call mode, xz_dec_run() decodes the whole stream at once. The | ||
| 135 | * caller must provide enough output space or the decoding will fail. The | ||
| 136 | * output space is used as the dictionary buffer, which is why there is | ||
| 137 | * no need to allocate the dictionary as part of the decoder's internal | ||
| 138 | * state. | ||
| 139 | * | 174 | * |
| 140 | * Because the output buffer is used as the workspace, streams encoded using | 175 | * Because the output buffer is used as the workspace, streams encoded using |
| 141 | * a big dictionary are not a problem in single-call. It is enough that the | 176 | * a big dictionary are not a problem in single-call mode. It is enough that |
| 142 | * output buffer is big enough to hold the actual uncompressed data; it | 177 | * the output buffer is big enough to hold the actual uncompressed data; it |
| 143 | * can be smaller than the dictionary size stored in the stream headers. | 178 | * can be smaller than the dictionary size stored in the stream headers. |
| 144 | * | 179 | * |
| 180 | * Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes | ||
| 181 | * of memory is preallocated for the LZMA2 dictionary. This way there is no | ||
| 182 | * risk that xz_dec_run() could run out of memory, since xz_dec_run() will | ||
| 183 | * never allocate any memory. Instead, if the preallocated dictionary is too | ||
| 184 | * small for decoding the given input stream, xz_dec_run() will return | ||
| 185 | * XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be | ||
| 186 | * decoded to avoid allocating excessive amount of memory for the dictionary. | ||
| 187 | * | ||
| 188 | * Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC): | ||
| 189 | * dict_max specifies the maximum allowed dictionary size that xz_dec_run() | ||
| 190 | * may allocate once it has parsed the dictionary size from the stream | ||
| 191 | * headers. This way excessive allocations can be avoided while still | ||
| 192 | * limiting the maximum memory usage to a sane value to prevent running the | ||
| 193 | * system out of memory when decompressing streams from untrusted sources. | ||
| 194 | * | ||
| 145 | * On success, xz_dec_init() returns a pointer to struct xz_dec, which is | 195 | * On success, xz_dec_init() returns a pointer to struct xz_dec, which is |
| 146 | * ready to be used with xz_dec_run(). On error, xz_dec_init() returns NULL. | 196 | * ready to be used with xz_dec_run(). If memory allocation fails, |
| 197 | * xz_dec_init() returns NULL. | ||
| 147 | */ | 198 | */ |
| 148 | XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(uint32_t dict_max); | 199 | XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init( |
| 200 | enum xz_mode mode, uint32_t dict_max); | ||
| 149 | 201 | ||
| 150 | /** | 202 | /** |
| 151 | * xz_dec_run() - Run the XZ decoder | 203 | * xz_dec_run() - Run the XZ decoder |
| 152 | * @s: Decoder state allocated using xz_dec_init() | 204 | * @s: Decoder state allocated using xz_dec_init() |
| 153 | * @b: Input and output buffers | 205 | * @b: Input and output buffers |
| 154 | * | 206 | * |
| 155 | * In multi-call mode, this function may return any of the values listed in | 207 | * The possible return values depend on build options and operation mode. |
| 156 | * enum xz_ret. | 208 | * See enum xz_ret for details. |
| 157 | * | 209 | * |
| 158 | * In single-call mode, this function never returns XZ_OK. If an error occurs | 210 | * NOTE: If an error occurs in single-call mode (return value is not |
| 159 | * in single-call mode (return value is not XZ_STREAM_END), b->in_pos and | 211 | * XZ_STREAM_END), b->in_pos and b->out_pos are not modified, and the |
| 160 | * b->out_pos are not modified, and the contents of the output buffer from | 212 | * contents of the output buffer from b->out[b->out_pos] onward are |
| 161 | * b->out[b->out_pos] onward are undefined. | 213 | * undefined. This is true even after XZ_BUF_ERROR, because with some filter |
| 162 | * | 214 | * chains, there may be a second pass over the output buffer, and this pass |
| 163 | * NOTE: In single-call mode, the contents of the output buffer are undefined | 215 | * cannot be properly done if the output buffer is truncated. Thus, you |
| 164 | * also after XZ_BUF_ERROR. This is because with some filter chains, there | 216 | * cannot give the single-call decoder a too small buffer and then expect to |
| 165 | * may be a second pass over the output buffer, and this pass cannot be | 217 | * get that amount valid data from the beginning of the stream. You must use |
| 166 | * properly done if the output buffer is truncated. Thus, you cannot give | 218 | * the multi-call decoder if you don't want to uncompress the whole stream. |
| 167 | * the single-call decoder a too small buffer and then expect to get that | ||
| 168 | * amount valid data from the beginning of the stream. You must use the | ||
| 169 | * multi-call decoder if you don't want to uncompress the whole stream. | ||
| 170 | */ | 219 | */ |
| 171 | XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b); | 220 | XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b); |
| 172 | 221 | ||
diff --git a/archival/libunarchive/unxz/xz_dec_lzma2.c b/archival/libunarchive/unxz/xz_dec_lzma2.c index 37de6fc32..da71cb4d4 100644 --- a/archival/libunarchive/unxz/xz_dec_lzma2.c +++ b/archival/libunarchive/unxz/xz_dec_lzma2.c | |||
| @@ -34,7 +34,8 @@ | |||
| 34 | * | 34 | * |
| 35 | * In multi-call mode, also these are true: | 35 | * In multi-call mode, also these are true: |
| 36 | * end == size | 36 | * end == size |
| 37 | * size <= allocated | 37 | * size <= size_max |
| 38 | * allocated <= size | ||
| 38 | * | 39 | * |
| 39 | * Most of these variables are size_t to support single-call mode, | 40 | * Most of these variables are size_t to support single-call mode, |
| 40 | * in which the dictionary variables address the actual output | 41 | * in which the dictionary variables address the actual output |
| @@ -74,11 +75,20 @@ struct dictionary { | |||
| 74 | uint32_t size; | 75 | uint32_t size; |
| 75 | 76 | ||
| 76 | /* | 77 | /* |
| 77 | * Amount of memory allocated for the dictionary. A special | 78 | * Maximum allowed dictionary size in multi-call mode. |
| 78 | * value of zero indicates that we are in single-call mode, | 79 | * This is ignored in single-call mode. |
| 79 | * where the output buffer works as the dictionary. | 80 | */ |
| 81 | uint32_t size_max; | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Amount of memory currently allocated for the dictionary. | ||
| 85 | * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC, | ||
| 86 | * size_max is always the same as the allocated size.) | ||
| 80 | */ | 87 | */ |
| 81 | uint32_t allocated; | 88 | uint32_t allocated; |
| 89 | |||
| 90 | /* Operation mode */ | ||
| 91 | enum xz_mode mode; | ||
| 82 | }; | 92 | }; |
| 83 | 93 | ||
| 84 | /* Range decoder */ | 94 | /* Range decoder */ |
| @@ -120,31 +130,31 @@ struct lzma_len_dec { | |||
| 120 | }; | 130 | }; |
| 121 | 131 | ||
| 122 | struct lzma_dec { | 132 | struct lzma_dec { |
| 123 | /* | ||
| 124 | * LZMA properties or related bit masks (number of literal | ||
| 125 | * context bits, a mask dervied from the number of literal | ||
| 126 | * position bits, and a mask dervied from the number | ||
| 127 | * position bits) | ||
| 128 | */ | ||
| 129 | uint32_t lc; | ||
| 130 | uint32_t literal_pos_mask; /* (1 << lp) - 1 */ | ||
| 131 | uint32_t pos_mask; /* (1 << pb) - 1 */ | ||
| 132 | |||
| 133 | /* Types of the most recently seen LZMA symbols */ | ||
| 134 | enum lzma_state state; | ||
| 135 | |||
| 136 | /* Distances of latest four matches */ | 133 | /* Distances of latest four matches */ |
| 137 | uint32_t rep0; | 134 | uint32_t rep0; |
| 138 | uint32_t rep1; | 135 | uint32_t rep1; |
| 139 | uint32_t rep2; | 136 | uint32_t rep2; |
| 140 | uint32_t rep3; | 137 | uint32_t rep3; |
| 141 | 138 | ||
| 139 | /* Types of the most recently seen LZMA symbols */ | ||
| 140 | enum lzma_state state; | ||
| 141 | |||
| 142 | /* | 142 | /* |
| 143 | * Length of a match. This is updated so that dict_repeat can | 143 | * Length of a match. This is updated so that dict_repeat can |
| 144 | * be called again to finish repeating the whole match. | 144 | * be called again to finish repeating the whole match. |
| 145 | */ | 145 | */ |
| 146 | uint32_t len; | 146 | uint32_t len; |
| 147 | 147 | ||
| 148 | /* | ||
| 149 | * LZMA properties or related bit masks (number of literal | ||
| 150 | * context bits, a mask dervied from the number of literal | ||
| 151 | * position bits, and a mask dervied from the number | ||
| 152 | * position bits) | ||
| 153 | */ | ||
| 154 | uint32_t lc; | ||
| 155 | uint32_t literal_pos_mask; /* (1 << lp) - 1 */ | ||
| 156 | uint32_t pos_mask; /* (1 << pb) - 1 */ | ||
| 157 | |||
| 148 | /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ | 158 | /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ |
| 149 | uint16_t is_match[STATES][POS_STATES_MAX]; | 159 | uint16_t is_match[STATES][POS_STATES_MAX]; |
| 150 | 160 | ||
| @@ -201,49 +211,59 @@ struct lzma_dec { | |||
| 201 | uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; | 211 | uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; |
| 202 | }; | 212 | }; |
| 203 | 213 | ||
| 214 | struct lzma2_dec { | ||
| 215 | /* Position in xz_dec_lzma2_run(). */ | ||
| 216 | enum lzma2_seq { | ||
| 217 | SEQ_CONTROL, | ||
| 218 | SEQ_UNCOMPRESSED_1, | ||
| 219 | SEQ_UNCOMPRESSED_2, | ||
| 220 | SEQ_COMPRESSED_0, | ||
| 221 | SEQ_COMPRESSED_1, | ||
| 222 | SEQ_PROPERTIES, | ||
| 223 | SEQ_LZMA_PREPARE, | ||
| 224 | SEQ_LZMA_RUN, | ||
| 225 | SEQ_COPY | ||
| 226 | } sequence; | ||
| 227 | |||
| 228 | /* Next position after decoding the compressed size of the chunk. */ | ||
| 229 | enum lzma2_seq next_sequence; | ||
| 230 | |||
| 231 | /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ | ||
| 232 | uint32_t uncompressed; | ||
| 233 | |||
| 234 | /* | ||
| 235 | * Compressed size of LZMA chunk or compressed/uncompressed | ||
| 236 | * size of uncompressed chunk (64 KiB at maximum) | ||
| 237 | */ | ||
| 238 | uint32_t compressed; | ||
| 239 | |||
| 240 | /* | ||
| 241 | * True if dictionary reset is needed. This is false before | ||
| 242 | * the first chunk (LZMA or uncompressed). | ||
| 243 | */ | ||
| 244 | bool need_dict_reset; | ||
| 245 | |||
| 246 | /* | ||
| 247 | * True if new LZMA properties are needed. This is false | ||
| 248 | * before the first LZMA chunk. | ||
| 249 | */ | ||
| 250 | bool need_props; | ||
| 251 | }; | ||
| 252 | |||
| 204 | struct xz_dec_lzma2 { | 253 | struct xz_dec_lzma2 { |
| 205 | /* LZMA2 */ | 254 | /* |
| 206 | struct { | 255 | * The order below is important on x86 to reduce code size and |
| 207 | /* Position in xz_dec_lzma2_run(). */ | 256 | * it shouldn't hurt on other platforms. Everything up to and |
| 208 | enum lzma2_seq { | 257 | * including lzma.pos_mask are in the first 128 bytes on x86-32, |
| 209 | SEQ_CONTROL, | 258 | * which allows using smaller instructions to access those |
| 210 | SEQ_UNCOMPRESSED_1, | 259 | * variables. On x86-64, fewer variables fit into the first 128 |
| 211 | SEQ_UNCOMPRESSED_2, | 260 | * bytes, but this is still the best order without sacrificing |
| 212 | SEQ_COMPRESSED_0, | 261 | * the readability by splitting the structures. |
| 213 | SEQ_COMPRESSED_1, | 262 | */ |
| 214 | SEQ_PROPERTIES, | 263 | struct rc_dec rc; |
| 215 | SEQ_LZMA_PREPARE, | 264 | struct dictionary dict; |
| 216 | SEQ_LZMA_RUN, | 265 | struct lzma2_dec lzma2; |
| 217 | SEQ_COPY | 266 | struct lzma_dec lzma; |
| 218 | } sequence; | ||
| 219 | |||
| 220 | /* | ||
| 221 | * Next position after decoding the compressed size of | ||
| 222 | * the chunk. | ||
| 223 | */ | ||
| 224 | enum lzma2_seq next_sequence; | ||
| 225 | |||
| 226 | /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ | ||
| 227 | uint32_t uncompressed; | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Compressed size of LZMA chunk or compressed/uncompressed | ||
| 231 | * size of uncompressed chunk (64 KiB at maximum) | ||
| 232 | */ | ||
| 233 | uint32_t compressed; | ||
| 234 | |||
| 235 | /* | ||
| 236 | * True if dictionary reset is needed. This is false before | ||
| 237 | * the first chunk (LZMA or uncompressed). | ||
| 238 | */ | ||
| 239 | bool need_dict_reset; | ||
| 240 | |||
| 241 | /* | ||
| 242 | * True if new LZMA properties are needed. This is false | ||
| 243 | * before the first LZMA chunk. | ||
| 244 | */ | ||
| 245 | bool need_props; | ||
| 246 | } lzma2; | ||
| 247 | 267 | ||
| 248 | /* | 268 | /* |
| 249 | * Temporary buffer which holds small number of input bytes between | 269 | * Temporary buffer which holds small number of input bytes between |
| @@ -253,10 +273,6 @@ struct xz_dec_lzma2 { | |||
| 253 | uint32_t size; | 273 | uint32_t size; |
| 254 | uint8_t buf[3 * LZMA_IN_REQUIRED]; | 274 | uint8_t buf[3 * LZMA_IN_REQUIRED]; |
| 255 | } temp; | 275 | } temp; |
| 256 | |||
| 257 | struct dictionary dict; | ||
| 258 | struct rc_dec rc; | ||
| 259 | struct lzma_dec lzma; | ||
| 260 | }; | 276 | }; |
| 261 | 277 | ||
| 262 | /************** | 278 | /************** |
| @@ -269,7 +285,7 @@ struct xz_dec_lzma2 { | |||
| 269 | */ | 285 | */ |
| 270 | static void XZ_FUNC dict_reset(struct dictionary *dict, struct xz_buf *b) | 286 | static void XZ_FUNC dict_reset(struct dictionary *dict, struct xz_buf *b) |
| 271 | { | 287 | { |
| 272 | if (dict->allocated == 0) { | 288 | if (DEC_IS_SINGLE(dict->mode)) { |
| 273 | dict->buf = b->out + b->out_pos; | 289 | dict->buf = b->out + b->out_pos; |
| 274 | dict->end = b->out_size - b->out_pos; | 290 | dict->end = b->out_size - b->out_pos; |
| 275 | } | 291 | } |
| @@ -379,7 +395,7 @@ static void XZ_FUNC dict_uncompressed( | |||
| 379 | if (dict->full < dict->pos) | 395 | if (dict->full < dict->pos) |
| 380 | dict->full = dict->pos; | 396 | dict->full = dict->pos; |
| 381 | 397 | ||
| 382 | if (dict->allocated != 0) { | 398 | if (DEC_IS_MULTI(dict->mode)) { |
| 383 | if (dict->pos == dict->end) | 399 | if (dict->pos == dict->end) |
| 384 | dict->pos = 0; | 400 | dict->pos = 0; |
| 385 | 401 | ||
| @@ -404,7 +420,7 @@ static uint32_t XZ_FUNC dict_flush(struct dictionary *dict, struct xz_buf *b) | |||
| 404 | { | 420 | { |
| 405 | size_t copy_size = dict->pos - dict->start; | 421 | size_t copy_size = dict->pos - dict->start; |
| 406 | 422 | ||
| 407 | if (dict->allocated != 0) { | 423 | if (DEC_IS_MULTI(dict->mode)) { |
| 408 | if (dict->pos == dict->end) | 424 | if (dict->pos == dict->end) |
| 409 | dict->pos = 0; | 425 | dict->pos = 0; |
| 410 | 426 | ||
| @@ -422,7 +438,7 @@ static uint32_t XZ_FUNC dict_flush(struct dictionary *dict, struct xz_buf *b) | |||
| 422 | *****************/ | 438 | *****************/ |
| 423 | 439 | ||
| 424 | /* Reset the range decoder. */ | 440 | /* Reset the range decoder. */ |
| 425 | static __always_inline void XZ_FUNC rc_reset(struct rc_dec *rc) | 441 | static void XZ_FUNC rc_reset(struct rc_dec *rc) |
| 426 | { | 442 | { |
| 427 | rc->range = (uint32_t)-1; | 443 | rc->range = (uint32_t)-1; |
| 428 | rc->code = 0; | 444 | rc->code = 0; |
| @@ -1088,28 +1104,27 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | |||
| 1088 | return XZ_OK; | 1104 | return XZ_OK; |
| 1089 | } | 1105 | } |
| 1090 | 1106 | ||
| 1091 | XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(uint32_t dict_max) | 1107 | XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create( |
| 1108 | enum xz_mode mode, uint32_t dict_max) | ||
| 1092 | { | 1109 | { |
| 1093 | struct xz_dec_lzma2 *s; | 1110 | struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL); |
| 1094 | |||
| 1095 | /* Maximum supported dictionary by this implementation is 3 GiB. */ | ||
| 1096 | if (dict_max > ((uint32_t)3 << 30)) | ||
| 1097 | return NULL; | ||
| 1098 | |||
| 1099 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
| 1100 | if (s == NULL) | 1111 | if (s == NULL) |
| 1101 | return NULL; | 1112 | return NULL; |
| 1102 | 1113 | ||
| 1103 | if (dict_max > 0) { | 1114 | s->dict.mode = mode; |
| 1115 | s->dict.size_max = dict_max; | ||
| 1116 | |||
| 1117 | if (DEC_IS_PREALLOC(mode)) { | ||
| 1104 | s->dict.buf = vmalloc(dict_max); | 1118 | s->dict.buf = vmalloc(dict_max); |
| 1105 | if (s->dict.buf == NULL) { | 1119 | if (s->dict.buf == NULL) { |
| 1106 | kfree(s); | 1120 | kfree(s); |
| 1107 | return NULL; | 1121 | return NULL; |
| 1108 | } | 1122 | } |
| 1123 | } else if (DEC_IS_DYNALLOC(mode)) { | ||
| 1124 | s->dict.buf = NULL; | ||
| 1125 | s->dict.allocated = 0; | ||
| 1109 | } | 1126 | } |
| 1110 | 1127 | ||
| 1111 | s->dict.allocated = dict_max; | ||
| 1112 | |||
| 1113 | return s; | 1128 | return s; |
| 1114 | } | 1129 | } |
| 1115 | 1130 | ||
| @@ -1123,18 +1138,23 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_reset( | |||
| 1123 | s->dict.size = 2 + (props & 1); | 1138 | s->dict.size = 2 + (props & 1); |
| 1124 | s->dict.size <<= (props >> 1) + 11; | 1139 | s->dict.size <<= (props >> 1) + 11; |
| 1125 | 1140 | ||
| 1126 | if (s->dict.allocated > 0 && s->dict.allocated < s->dict.size) { | 1141 | if (DEC_IS_MULTI(s->dict.mode)) { |
| 1127 | #ifdef XZ_REALLOC_DICT_BUF | 1142 | if (s->dict.size > s->dict.size_max) |
| 1128 | s->dict.buf = XZ_REALLOC_DICT_BUF(s->dict.buf, s->dict.size); | 1143 | return XZ_MEMLIMIT_ERROR; |
| 1129 | if (!s->dict.buf) | ||
| 1130 | return XZ_MEMLIMIT_ERROR; | ||
| 1131 | s->dict.allocated = s->dict.size; | ||
| 1132 | #else | ||
| 1133 | return XZ_MEMLIMIT_ERROR; | ||
| 1134 | #endif | ||
| 1135 | } | ||
| 1136 | 1144 | ||
| 1137 | s->dict.end = s->dict.size; | 1145 | s->dict.end = s->dict.size; |
| 1146 | |||
| 1147 | if (DEC_IS_DYNALLOC(s->dict.mode)) { | ||
| 1148 | if (s->dict.allocated < s->dict.size) { | ||
| 1149 | vfree(s->dict.buf); | ||
| 1150 | s->dict.buf = vmalloc(s->dict.size); | ||
| 1151 | if (s->dict.buf == NULL) { | ||
| 1152 | s->dict.allocated = 0; | ||
| 1153 | return XZ_MEM_ERROR; | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | } | ||
| 1138 | 1158 | ||
| 1139 | s->lzma.len = 0; | 1159 | s->lzma.len = 0; |
| 1140 | 1160 | ||
| @@ -1148,7 +1168,7 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_reset( | |||
| 1148 | 1168 | ||
| 1149 | XZ_EXTERN void XZ_FUNC xz_dec_lzma2_end(struct xz_dec_lzma2 *s) | 1169 | XZ_EXTERN void XZ_FUNC xz_dec_lzma2_end(struct xz_dec_lzma2 *s) |
| 1150 | { | 1170 | { |
| 1151 | if (s->dict.allocated > 0) | 1171 | if (DEC_IS_MULTI(s->dict.mode)) |
| 1152 | vfree(s->dict.buf); | 1172 | vfree(s->dict.buf); |
| 1153 | 1173 | ||
| 1154 | kfree(s); | 1174 | kfree(s); |
diff --git a/archival/libunarchive/unxz/xz_dec_stream.c b/archival/libunarchive/unxz/xz_dec_stream.c index 21db283fb..bdcbf1ba3 100644 --- a/archival/libunarchive/unxz/xz_dec_stream.c +++ b/archival/libunarchive/unxz/xz_dec_stream.c | |||
| @@ -48,8 +48,8 @@ struct xz_dec { | |||
| 48 | /* Type of the integrity check calculated from uncompressed data */ | 48 | /* Type of the integrity check calculated from uncompressed data */ |
| 49 | enum xz_check check_type; | 49 | enum xz_check check_type; |
| 50 | 50 | ||
| 51 | /* True if we are operating in single-call mode. */ | 51 | /* Operation mode */ |
| 52 | bool single_call; | 52 | enum xz_mode mode; |
| 53 | 53 | ||
| 54 | /* | 54 | /* |
| 55 | * True if the next call to xz_dec_run() is allowed to return | 55 | * 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) | |||
| 737 | size_t out_start; | 737 | size_t out_start; |
| 738 | enum xz_ret ret; | 738 | enum xz_ret ret; |
| 739 | 739 | ||
| 740 | if (s->single_call) | 740 | if (DEC_IS_SINGLE(s->mode)) |
| 741 | xz_dec_reset(s); | 741 | xz_dec_reset(s); |
| 742 | 742 | ||
| 743 | in_start = b->in_pos; | 743 | in_start = b->in_pos; |
| 744 | out_start = b->out_pos; | 744 | out_start = b->out_pos; |
| 745 | ret = dec_main(s, b); | 745 | ret = dec_main(s, b); |
| 746 | 746 | ||
| 747 | if (s->single_call) { | 747 | if (DEC_IS_SINGLE(s->mode)) { |
| 748 | if (ret == XZ_OK) | 748 | if (ret == XZ_OK) |
| 749 | ret = b->in_pos == b->in_size | 749 | ret = b->in_pos == b->in_size |
| 750 | ? XZ_DATA_ERROR : XZ_BUF_ERROR; | 750 | ? 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) | |||
| 767 | return ret; | 767 | return ret; |
| 768 | } | 768 | } |
| 769 | 769 | ||
| 770 | XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(uint32_t dict_max) | 770 | XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init( |
| 771 | enum xz_mode mode, uint32_t dict_max) | ||
| 771 | { | 772 | { |
| 772 | struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); | 773 | struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); |
| 773 | if (s == NULL) | 774 | if (s == NULL) |
| 774 | return NULL; | 775 | return NULL; |
| 775 | 776 | ||
| 776 | s->single_call = dict_max == 0; | 777 | s->mode = mode; |
| 777 | 778 | ||
| 778 | #ifdef XZ_DEC_BCJ | 779 | #ifdef XZ_DEC_BCJ |
| 779 | s->bcj = xz_dec_bcj_create(s->single_call); | 780 | s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode)); |
| 780 | if (s->bcj == NULL) | 781 | if (s->bcj == NULL) |
| 781 | goto error_bcj; | 782 | goto error_bcj; |
| 782 | #endif | 783 | #endif |
| 783 | 784 | ||
| 784 | s->lzma2 = xz_dec_lzma2_create(dict_max); | 785 | s->lzma2 = xz_dec_lzma2_create(mode, dict_max); |
| 785 | if (s->lzma2 == NULL) | 786 | if (s->lzma2 == NULL) |
| 786 | goto error_lzma2; | 787 | goto error_lzma2; |
| 787 | 788 | ||
diff --git a/archival/libunarchive/unxz/xz_private.h b/archival/libunarchive/unxz/xz_private.h index f4e0b4010..145649a83 100644 --- a/archival/libunarchive/unxz/xz_private.h +++ b/archival/libunarchive/unxz/xz_private.h | |||
| @@ -53,6 +53,45 @@ | |||
| 53 | # include "xz_config.h" | 53 | # include "xz_config.h" |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| 56 | /* If no specific decoding mode is requested, enable support for all modes. */ | ||
| 57 | #if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \ | ||
| 58 | && !defined(XZ_DEC_DYNALLOC) | ||
| 59 | # define XZ_DEC_SINGLE | ||
| 60 | # define XZ_DEC_PREALLOC | ||
| 61 | # define XZ_DEC_DYNALLOC | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /* | ||
| 65 | * The DEC_IS_foo(mode) macros are used in "if" statements. If only some | ||
| 66 | * of the supported modes are enabled, these macros will evaluate to true or | ||
| 67 | * false at compile time and thus allow the compiler to omit unneeded code. | ||
| 68 | */ | ||
| 69 | #ifdef XZ_DEC_SINGLE | ||
| 70 | # define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE) | ||
| 71 | #else | ||
| 72 | # define DEC_IS_SINGLE(mode) (false) | ||
| 73 | #endif | ||
| 74 | |||
| 75 | #ifdef XZ_DEC_PREALLOC | ||
| 76 | # define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC) | ||
| 77 | #else | ||
| 78 | # define DEC_IS_PREALLOC(mode) (false) | ||
| 79 | #endif | ||
| 80 | |||
| 81 | #ifdef XZ_DEC_DYNALLOC | ||
| 82 | # define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC) | ||
| 83 | #else | ||
| 84 | # define DEC_IS_DYNALLOC(mode) (false) | ||
| 85 | #endif | ||
| 86 | |||
| 87 | #if !defined(XZ_DEC_SINGLE) | ||
| 88 | # define DEC_IS_MULTI(mode) (true) | ||
| 89 | #elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC) | ||
| 90 | # define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE) | ||
| 91 | #else | ||
| 92 | # define DEC_IS_MULTI(mode) (false) | ||
| 93 | #endif | ||
| 94 | |||
| 56 | /* | 95 | /* |
| 57 | * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. | 96 | * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. |
| 58 | * XZ_DEC_BCJ is used to enable generic support for BCJ decoders. | 97 | * XZ_DEC_BCJ is used to enable generic support for BCJ decoders. |
| @@ -71,7 +110,7 @@ | |||
| 71 | * before calling xz_dec_lzma2_run(). | 110 | * before calling xz_dec_lzma2_run(). |
| 72 | */ | 111 | */ |
| 73 | XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create( | 112 | XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create( |
| 74 | uint32_t dict_max); | 113 | enum xz_mode mode, uint32_t dict_max); |
| 75 | 114 | ||
| 76 | /* | 115 | /* |
| 77 | * Decode the LZMA2 properties (one byte) and reset the decoder. Return | 116 | * Decode the LZMA2 properties (one byte) and reset the decoder. Return |
