X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Flibunarchive%2Fdecompress_unlzma.c;h=15a0275b4732fc6739681c9c769c6e65c0028077;hb=dcbd51dd2874164b693fc7133a07714c8ea14234;hp=0fb1249cba6e8c5f9e43b7b3883cdf02148695fd;hpb=63fc1a9e08fabfc8ba96bad80731673ef40bf5cb;p=oweals%2Fbusybox.git diff --git a/archival/libunarchive/decompress_unlzma.c b/archival/libunarchive/decompress_unlzma.c index 0fb1249cb..15a0275b4 100644 --- a/archival/libunarchive/decompress_unlzma.c +++ b/archival/libunarchive/decompress_unlzma.c @@ -22,15 +22,23 @@ typedef struct { int fd; uint8_t *ptr; - uint8_t *buffer; + +/* Was keeping rc on stack in unlzma and separately allocating buffer, + * but with "buffer 'attached to' allocated rc" code is smaller: */ + /* uint8_t *buffer; */ +#define RC_BUFFER ((uint8_t*)(rc+1)) + uint8_t *buffer_end; - int buffer_size; + +/* Had provisions for variable buffer, but we don't need it here */ + /* int buffer_size; */ +#define RC_BUFFER_SIZE 0x10000 + uint32_t code; uint32_t range; uint32_t bound; } rc_t; - #define RC_TOP_BITS 24 #define RC_MOVE_BITS 5 #define RC_MODEL_TOTAL_BITS 11 @@ -39,22 +47,24 @@ typedef struct { /* Called twice: once at startup and once in rc_normalize() */ static void rc_read(rc_t * rc) { - rc->buffer_size = read(rc->fd, rc->buffer, rc->buffer_size); - if (rc->buffer_size <= 0) + int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE); + if (buffer_size <= 0) bb_error_msg_and_die("unexpected EOF"); - rc->ptr = rc->buffer; - rc->buffer_end = rc->buffer + rc->buffer_size; + rc->ptr = RC_BUFFER; + rc->buffer_end = RC_BUFFER + buffer_size; } /* Called once */ -static void rc_init(rc_t * rc, int fd, int buffer_size) +static rc_t* rc_init(int fd) /*, int buffer_size) */ { int i; + rc_t* rc; + + rc = xmalloc(sizeof(rc_t) + RC_BUFFER_SIZE); rc->fd = fd; - rc->buffer = xmalloc(buffer_size); - rc->buffer_size = buffer_size; - rc->buffer_end = rc->buffer + rc->buffer_size; + /* rc->buffer_size = buffer_size; */ + rc->buffer_end = RC_BUFFER + RC_BUFFER_SIZE; rc->ptr = rc->buffer_end; rc->code = 0; @@ -64,13 +74,14 @@ static void rc_init(rc_t * rc, int fd, int buffer_size) rc_read(rc); rc->code = (rc->code << 8) | *rc->ptr++; } + return rc; } -/* Called once. TODO: bb_maybe_free() */ +/* Called once */ static ATTRIBUTE_ALWAYS_INLINE void rc_free(rc_t * rc) { if (ENABLE_FEATURE_CLEAN_UP) - free(rc->buffer); + free(rc); } /* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */ @@ -163,57 +174,63 @@ typedef struct { } __attribute__ ((packed)) lzma_header_t; -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LZMA_NUM_POS_BITS_MAX 4 - -#define LZMA_LEN_NUM_LOW_BITS 3 -#define LZMA_LEN_NUM_MID_BITS 3 -#define LZMA_LEN_NUM_HIGH_BITS 8 - -#define LZMA_LEN_CHOICE 0 -#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) -#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) -#define LZMA_LEN_MID (LZMA_LEN_LOW \ - + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) -#define LZMA_LEN_HIGH (LZMA_LEN_MID \ - +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) -#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) - -#define LZMA_NUM_STATES 12 -#define LZMA_NUM_LIT_STATES 7 - -#define LZMA_START_POS_MODEL_INDEX 4 -#define LZMA_END_POS_MODEL_INDEX 14 -#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) - -#define LZMA_NUM_POS_SLOT_BITS 6 -#define LZMA_NUM_LEN_TO_POS_STATES 4 - -#define LZMA_NUM_ALIGN_BITS 4 - -#define LZMA_MATCH_MIN_LEN 2 - -#define LZMA_IS_MATCH 0 -#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES <> 1)), + + LZMA_NUM_POS_SLOT_BITS = 6, + LZMA_NUM_LEN_TO_POS_STATES = 4, + + LZMA_NUM_ALIGN_BITS = 4, + + LZMA_MATCH_MIN_LEN = 2, + + LZMA_IS_MATCH = 0, + LZMA_IS_REP = (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)), + LZMA_IS_REP_G0 = (LZMA_IS_REP + LZMA_NUM_STATES), + LZMA_IS_REP_G1 = (LZMA_IS_REP_G0 + LZMA_NUM_STATES), + LZMA_IS_REP_G2 = (LZMA_IS_REP_G1 + LZMA_NUM_STATES), + LZMA_IS_REP_0_LONG = (LZMA_IS_REP_G2 + LZMA_NUM_STATES), + LZMA_POS_SLOT = (LZMA_IS_REP_0_LONG \ + + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)), + LZMA_SPEC_POS = (LZMA_POS_SLOT \ + + (LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)), + LZMA_ALIGN = (LZMA_SPEC_POS \ + + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX), + LZMA_LEN_CODER = (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)), + LZMA_REP_LEN_CODER = (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS), + LZMA_LITERAL = (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS), +}; + + +USE_DESKTOP(long long) int +unlzma(int src_fd, int dst_fd) { + USE_DESKTOP(long long total_written = 0;) lzma_header_t header; int lc, pb, lp; uint32_t pos_state_mask; @@ -224,7 +241,7 @@ int unlzma(int src_fd, int dst_fd) uint16_t *prob_lit; int num_bits; int num_probs; - rc_t rc; + rc_t *rc; int i, mi; uint8_t *buffer; uint8_t previous_byte = 0; @@ -233,8 +250,7 @@ int unlzma(int src_fd, int dst_fd) int state = 0; uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; - if (read(src_fd, &header, sizeof(header)) != sizeof(header)) - bb_error_msg_and_die("can't read header"); + xread(src_fd, &header, sizeof(header)); if (header.pos >= (9 * 5 * 5)) bb_error_msg_and_die("bad header"); @@ -259,16 +275,16 @@ int unlzma(int src_fd, int dst_fd) for (i = 0; i < num_probs; i++) p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; - rc_init(&rc, src_fd, 0x10000); + rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */ while (global_pos + buffer_pos < header.dst_size) { int pos_state = (buffer_pos + global_pos) & pos_state_mask; prob = p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state; - if (rc_is_bit_0(&rc, prob)) { + if (rc_is_bit_0(rc, prob)) { mi = 1; - rc_update_bit_0(&rc, prob); + rc_update_bit_0(rc, prob); prob = (p + LZMA_LITERAL + (LZMA_LIT_SIZE * ((((buffer_pos + global_pos) & literal_pos_mask) << lc) + (previous_byte >> (8 - lc))))); @@ -286,7 +302,7 @@ int unlzma(int src_fd, int dst_fd) match_byte <<= 1; bit = match_byte & 0x100; prob_lit = prob + 0x100 + bit + mi; - if (rc_get_bit(&rc, prob_lit, &mi)) { + if (rc_get_bit(rc, prob_lit, &mi)) { if (!bit) break; } else { @@ -297,7 +313,7 @@ int unlzma(int src_fd, int dst_fd) } while (mi < 0x100) { prob_lit = prob + mi; - rc_get_bit(&rc, prob_lit, &mi); + rc_get_bit(rc, prob_lit, &mi); } previous_byte = (uint8_t) mi; @@ -305,7 +321,9 @@ int unlzma(int src_fd, int dst_fd) if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - write(dst_fd, buffer, header.dict_size); + if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size) + goto bad; + USE_DESKTOP(total_written += header.dict_size;) } if (state < 4) state = 0; @@ -317,24 +335,24 @@ int unlzma(int src_fd, int dst_fd) int offset; uint16_t *prob_len; - rc_update_bit_1(&rc, prob); + rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP + state; - if (rc_is_bit_0(&rc, prob)) { - rc_update_bit_0(&rc, prob); + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); rep3 = rep2; rep2 = rep1; rep1 = rep0; state = state < LZMA_NUM_LIT_STATES ? 0 : 3; prob = p + LZMA_LEN_CODER; } else { - rc_update_bit_1(&rc, prob); + rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP_G0 + state; - if (rc_is_bit_0(&rc, prob)) { - rc_update_bit_0(&rc, prob); + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); prob = (p + LZMA_IS_REP_0_LONG + (state << LZMA_NUM_POS_BITS_MAX) + pos_state); - if (rc_is_bit_0(&rc, prob)) { - rc_update_bit_0(&rc, prob); + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); state = state < LZMA_NUM_LIT_STATES ? 9 : 11; pos = buffer_pos - rep0; @@ -345,28 +363,30 @@ int unlzma(int src_fd, int dst_fd) if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - write(dst_fd, buffer, header.dict_size); + if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size) + goto bad; + USE_DESKTOP(total_written += header.dict_size;) } continue; } else { - rc_update_bit_1(&rc, prob); + rc_update_bit_1(rc, prob); } } else { uint32_t distance; - rc_update_bit_1(&rc, prob); + rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP_G1 + state; - if (rc_is_bit_0(&rc, prob)) { - rc_update_bit_0(&rc, prob); + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); distance = rep1; } else { - rc_update_bit_1(&rc, prob); + rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP_G2 + state; - if (rc_is_bit_0(&rc, prob)) { - rc_update_bit_0(&rc, prob); + if (rc_is_bit_0(rc, prob)) { + rc_update_bit_0(rc, prob); distance = rep2; } else { - rc_update_bit_1(&rc, prob); + rc_update_bit_1(rc, prob); distance = rep3; rep3 = rep2; } @@ -380,30 +400,30 @@ int unlzma(int src_fd, int dst_fd) } prob_len = prob + LZMA_LEN_CHOICE; - if (rc_is_bit_0(&rc, prob_len)) { - rc_update_bit_0(&rc, prob_len); + if (rc_is_bit_0(rc, prob_len)) { + rc_update_bit_0(rc, prob_len); prob_len = (prob + LZMA_LEN_LOW + (pos_state << LZMA_LEN_NUM_LOW_BITS)); offset = 0; num_bits = LZMA_LEN_NUM_LOW_BITS; } else { - rc_update_bit_1(&rc, prob_len); + rc_update_bit_1(rc, prob_len); prob_len = prob + LZMA_LEN_CHOICE_2; - if (rc_is_bit_0(&rc, prob_len)) { - rc_update_bit_0(&rc, prob_len); + if (rc_is_bit_0(rc, prob_len)) { + rc_update_bit_0(rc, prob_len); prob_len = (prob + LZMA_LEN_MID + (pos_state << LZMA_LEN_NUM_MID_BITS)); offset = 1 << LZMA_LEN_NUM_LOW_BITS; num_bits = LZMA_LEN_NUM_MID_BITS; } else { - rc_update_bit_1(&rc, prob_len); + rc_update_bit_1(rc, prob_len); prob_len = prob + LZMA_LEN_HIGH; offset = ((1 << LZMA_LEN_NUM_LOW_BITS) + (1 << LZMA_LEN_NUM_MID_BITS)); num_bits = LZMA_LEN_NUM_HIGH_BITS; } } - rc_bit_tree_decode(&rc, prob_len, num_bits, &len); + rc_bit_tree_decode(rc, prob_len, num_bits, &len); len += offset; if (state < 4) { @@ -416,7 +436,7 @@ int unlzma(int src_fd, int dst_fd) LZMA_NUM_LEN_TO_POS_STATES ? len : LZMA_NUM_LEN_TO_POS_STATES - 1) << LZMA_NUM_POS_SLOT_BITS); - rc_bit_tree_decode(&rc, prob, LZMA_NUM_POS_SLOT_BITS, + rc_bit_tree_decode(rc, prob, LZMA_NUM_POS_SLOT_BITS, &pos_slot); if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { num_bits = (pos_slot >> 1) - 1; @@ -427,7 +447,7 @@ int unlzma(int src_fd, int dst_fd) } else { num_bits -= LZMA_NUM_ALIGN_BITS; while (num_bits--) - rep0 = (rep0 << 1) | rc_direct_bit(&rc); + rep0 = (rep0 << 1) | rc_direct_bit(rc); prob = p + LZMA_ALIGN; rep0 <<= LZMA_NUM_ALIGN_BITS; num_bits = LZMA_NUM_ALIGN_BITS; @@ -435,7 +455,7 @@ int unlzma(int src_fd, int dst_fd) i = 1; mi = 1; while (num_bits--) { - if (rc_get_bit(&rc, prob + mi, &mi)) + if (rc_get_bit(rc, prob + mi, &mi)) rep0 |= i; i <<= 1; } @@ -456,15 +476,22 @@ int unlzma(int src_fd, int dst_fd) if (buffer_pos == header.dict_size) { buffer_pos = 0; global_pos += header.dict_size; - write(dst_fd, buffer, header.dict_size); + if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size) + goto bad; + USE_DESKTOP(total_written += header.dict_size;) } len--; } while (len != 0 && buffer_pos < header.dst_size); } } - write(dst_fd, buffer, buffer_pos); - rc_free(&rc); - return 0; -} + if (full_write(dst_fd, buffer, buffer_pos) != buffer_pos) { + bad: + rc_free(rc); + return -1; + } + rc_free(rc); + USE_DESKTOP(total_written += buffer_pos;) + return USE_DESKTOP(total_written) + 0; +}