diff options
-rw-r--r-- | toys/pending/xzcat.c | 213 |
1 files changed, 44 insertions, 169 deletions
diff --git a/toys/pending/xzcat.c b/toys/pending/xzcat.c index 3bbb8230..42d5ba37 100644 --- a/toys/pending/xzcat.c +++ b/toys/pending/xzcat.c @@ -25,30 +25,16 @@ config XZCAT /** * 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. xzcat uses only XZ_DEC_DYNALLOC, - * so that is the default. + * xzcat uses only XZ_DEC_DYNALLOC, though xz-embedded supports + * XZ_DEC_SINGLE and XZ_DEC_PREALLOC */ enum xz_mode { - XZ_SINGLE, - XZ_PREALLOC, XZ_DYNALLOC }; @@ -158,25 +144,6 @@ struct xz_dec; * except for kernel and initramfs images where a bigger * dictionary can be fine and useful. * - * Single-call mode (XZ_SINGLE): 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 - * a big dictionary are not a problem in single-call mode. It is enough that - * 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. - * - * 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 @@ -435,43 +402,7 @@ static inline void put_unaligned_be32(uint32_t val, uint8_t *buf) # define get_le32 get_unaligned_le32 #endif - #define XZ_DEC_DYNALLOC -/* DYNALLOC is what we use, but we may want these later. -#define XZ_DEC_SINGLE -#define XZ_DEC_PREALLOC -*/ - -/* - * 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) (0) -#endif - -#ifdef XZ_DEC_PREALLOC -# define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC) -#else -# define DEC_IS_PREALLOC(mode) (0) -#endif - -#ifdef XZ_DEC_DYNALLOC -# define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC) -#else -# define DEC_IS_DYNALLOC(mode) (0) -#endif - -#if !defined(XZ_DEC_SINGLE) -# define DEC_IS_MULTI(mode) (1) -#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC) -# define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE) -#else -# define DEC_IS_MULTI(mode) (0) -#endif /* * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ. @@ -506,31 +437,6 @@ enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, struct xz_buf *b); -#ifdef XZ_DEC_BCJ -/* - * Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before - * calling xz_dec_bcj_run(). - */ -struct xz_dec_bcj *xz_dec_bcj_create(int single_call); - -/* - * Decode the Filter ID of a BCJ filter. This implementation doesn't - * support custom start offsets, so no decoding of Filter Properties - * is needed. Returns XZ_OK if the given Filter ID is supported. - * Otherwise XZ_OPTIONS_ERROR is returned. - */ -enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id); - -/* - * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is - * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run() - * must be called directly. - */ -enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, - struct xz_dec_lzma2 *lzma2, - struct xz_buf *b); -#endif - // END "xz_private.h" @@ -561,9 +467,6 @@ struct xz_dec_bcj { */ enum xz_ret ret; - /* True if we are operating in single-call mode. */ - int single_call; - /* * Absolute position relative to the beginning of the uncompressed * data (in a single .xz Block). We care only about the lowest 32 @@ -602,6 +505,23 @@ struct xz_dec_bcj { } temp; }; +/* + * Decode the Filter ID of a BCJ filter. This implementation doesn't + * support custom start offsets, so no decoding of Filter Properties + * is needed. Returns XZ_OK if the given Filter ID is supported. + * Otherwise XZ_OPTIONS_ERROR is returned. + */ +enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id); + +/* + * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is + * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run() + * must be called directly. + */ +enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, + struct xz_dec_lzma2 *lzma2, + struct xz_buf *b); + #ifdef XZ_DEC_X86 /* * This is used to test the most significant byte of a memory address @@ -980,7 +900,7 @@ enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, s->ret = xz_dec_lzma2_run(lzma2, b); if (s->ret != XZ_STREAM_END - && (s->ret != XZ_OK || s->single_call)) + && (s->ret != XZ_OK )) return s->ret; bcj_apply(s, b->out, &out_start, b->out_pos); @@ -1051,15 +971,6 @@ enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, return s->ret; } -struct xz_dec_bcj *xz_dec_bcj_create(int single_call) -{ - struct xz_dec_bcj *s = malloc(sizeof(*s)); - if (s != NULL) - s->single_call = single_call; - - return s; -} - enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id) { switch (id) { @@ -1578,11 +1489,6 @@ struct xz_dec_lzma2 { */ static void dict_reset(struct dictionary *dict, struct xz_buf *b) { - if (DEC_IS_SINGLE(dict->mode)) { - dict->buf = b->out + b->out_pos; - dict->end = b->out_size - b->out_pos; - } - dict->start = 0; dict->pos = 0; dict->limit = 0; @@ -1685,13 +1591,11 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, if (dict->full < dict->pos) dict->full = dict->pos; - if (DEC_IS_MULTI(dict->mode)) { - if (dict->pos == dict->end) - dict->pos = 0; + if (dict->pos == dict->end) + dict->pos = 0; - memcpy(b->out + b->out_pos, b->in + b->in_pos, - copy_size); - } + memcpy(b->out + b->out_pos, b->in + b->in_pos, + copy_size); dict->start = dict->pos; @@ -1709,13 +1613,11 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) { size_t copy_size = dict->pos - dict->start; - if (DEC_IS_MULTI(dict->mode)) { - if (dict->pos == dict->end) - dict->pos = 0; + if (dict->pos == dict->end) + dict->pos = 0; - memcpy(b->out + b->out_pos, dict->buf + dict->start, - copy_size); - } + memcpy(b->out + b->out_pos, dict->buf + dict->start, + copy_size); dict->start = dict->pos; b->out_pos += copy_size; @@ -2401,16 +2303,8 @@ struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, s->dict.mode = mode; s->dict.size_max = dict_max; - if (DEC_IS_PREALLOC(mode)) { - s->dict.buf = malloc(dict_max); - if (s->dict.buf == NULL) { - free(s); - return NULL; - } - } else if (DEC_IS_DYNALLOC(mode)) { - s->dict.buf = NULL; - s->dict.allocated = 0; - } + s->dict.buf = NULL; + s->dict.allocated = 0; return s; } @@ -2424,21 +2318,17 @@ enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) s->dict.size = 2 + (props & 1); s->dict.size <<= (props >> 1) + 11; - if (DEC_IS_MULTI(s->dict.mode)) { - if (s->dict.size > s->dict.size_max) - return XZ_MEMLIMIT_ERROR; + if (s->dict.size > s->dict.size_max) + return XZ_MEMLIMIT_ERROR; - 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) { - free(s->dict.buf); - s->dict.buf = malloc(s->dict.size); - if (s->dict.buf == NULL) { - s->dict.allocated = 0; - return XZ_MEM_ERROR; - } - } + if (s->dict.allocated < s->dict.size) { + free(s->dict.buf); + s->dict.buf = malloc(s->dict.size); + if (s->dict.buf == NULL) { + s->dict.allocated = 0; + return XZ_MEM_ERROR; } } @@ -3234,25 +3124,11 @@ enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) size_t out_start; enum xz_ret ret; - if (DEC_IS_SINGLE(s->mode)) - xz_dec_reset(s); - in_start = b->in_pos; out_start = b->out_pos; ret = dec_main(s, b); - if (DEC_IS_SINGLE(s->mode)) { - if (ret == XZ_OK) - ret = b->in_pos == b->in_size - ? XZ_DATA_ERROR : XZ_BUF_ERROR; - - if (ret != XZ_STREAM_END) { - b->in_pos = in_start; - b->out_pos = out_start; - } - - } else if (ret == XZ_OK && in_start == b->in_pos - && out_start == b->out_pos) { + if (ret == XZ_OK && in_start == b->in_pos && out_start == b->out_pos) { if (s->allow_buf_error) ret = XZ_BUF_ERROR; @@ -3267,14 +3143,14 @@ enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max) { struct xz_dec *s = malloc(sizeof(*s)); - if (s == NULL) + if (!s) return NULL; s->mode = mode; #ifdef XZ_DEC_BCJ - s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode)); - if (s->bcj == NULL) + s->bcj = malloc(sizeof(*s->bcj)); + if (!s->bcj) goto error_bcj; #endif @@ -3309,8 +3185,7 @@ void xz_dec_reset(struct xz_dec *s) void xz_dec_end(struct xz_dec *s) { if (s != NULL) { - if (DEC_IS_MULTI((s->lzma2)->dict.mode)) - free((s->lzma2)->dict.buf); + free((s->lzma2)->dict.buf); free(s->lzma2); #ifdef XZ_DEC_BCJ |