diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2013-02-27 17:26:40 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-02-27 17:26:40 +0100 |
commit | 380c8a0763462692eef8d00df4872a561ff7aa7b (patch) | |
tree | e336c964ef716563e2115b1a5bfb11d4e75e883f | |
parent | 433757413f55986681f29ab1335e514e9f0c8423 (diff) | |
download | busybox-w32-380c8a0763462692eef8d00df4872a561ff7aa7b.tar.gz busybox-w32-380c8a0763462692eef8d00df4872a561ff7aa7b.tar.bz2 busybox-w32-380c8a0763462692eef8d00df4872a561ff7aa7b.zip |
xz: support concatenated .xz streams
function old new delta
xz_dec_reset - 77 +77
unpack_xz_stream 2402 2397 -5
Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/libarchive/decompress_unxz.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 79b48a152..e9ddd3709 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c | |||
@@ -40,6 +40,7 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) | |||
40 | IF_DESKTOP(long long) int FAST_FUNC | 40 | IF_DESKTOP(long long) int FAST_FUNC |
41 | unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | 41 | unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) |
42 | { | 42 | { |
43 | enum xz_ret xz_result; | ||
43 | struct xz_buf iobuf; | 44 | struct xz_buf iobuf; |
44 | struct xz_dec *state; | 45 | struct xz_dec *state; |
45 | unsigned char *membuf; | 46 | unsigned char *membuf; |
@@ -63,9 +64,8 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
63 | /* Limit memory usage to about 64 MiB. */ | 64 | /* Limit memory usage to about 64 MiB. */ |
64 | state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024); | 65 | state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024); |
65 | 66 | ||
67 | xz_result = X_OK; | ||
66 | while (1) { | 68 | while (1) { |
67 | enum xz_ret r; | ||
68 | |||
69 | if (iobuf.in_pos == iobuf.in_size) { | 69 | if (iobuf.in_pos == iobuf.in_size) { |
70 | int rd = safe_read(src_fd, membuf, BUFSIZ); | 70 | int rd = safe_read(src_fd, membuf, BUFSIZ); |
71 | if (rd < 0) { | 71 | if (rd < 0) { |
@@ -73,28 +73,57 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd) | |||
73 | total = -1; | 73 | total = -1; |
74 | break; | 74 | break; |
75 | } | 75 | } |
76 | if (rd == 0 && xz_result == XZ_STREAM_END) | ||
77 | break; | ||
76 | iobuf.in_size = rd; | 78 | iobuf.in_size = rd; |
77 | iobuf.in_pos = 0; | 79 | iobuf.in_pos = 0; |
78 | } | 80 | } |
81 | if (xz_result == XZ_STREAM_END) { | ||
82 | /* | ||
83 | * Try to start decoding next concatenated stream. | ||
84 | * Stream padding must always be a multiple of four | ||
85 | * bytes to preserve four-byte alignment. To keep the | ||
86 | * code slightly smaller, we aren't as strict here as | ||
87 | * the .xz spec requires. We just skip all zero-bytes | ||
88 | * without checking the alignment and thus can accept | ||
89 | * files that aren't valid, e.g. the XZ utils test | ||
90 | * files bad-0pad-empty.xz and bad-0catpad-empty.xz. | ||
91 | */ | ||
92 | do { | ||
93 | if (membuf[iobuf.in_pos] != 0) { | ||
94 | xz_dec_reset(state); | ||
95 | goto do_run; | ||
96 | } | ||
97 | iobuf.in_pos++; | ||
98 | } while (iobuf.in_pos < iobuf.in_size); | ||
99 | } | ||
100 | do_run: | ||
79 | // bb_error_msg(">in pos:%d size:%d out pos:%d size:%d", | 101 | // bb_error_msg(">in pos:%d size:%d out pos:%d size:%d", |
80 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size); | 102 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size); |
81 | r = xz_dec_run(state, &iobuf); | 103 | xz_result = xz_dec_run(state, &iobuf); |
82 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", | 104 | // bb_error_msg("<in pos:%d size:%d out pos:%d size:%d r:%d", |
83 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r); | 105 | // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, xz_result); |
84 | if (iobuf.out_pos) { | 106 | if (iobuf.out_pos) { |
85 | xwrite(dst_fd, iobuf.out, iobuf.out_pos); | 107 | xwrite(dst_fd, iobuf.out, iobuf.out_pos); |
86 | IF_DESKTOP(total += iobuf.out_pos;) | 108 | IF_DESKTOP(total += iobuf.out_pos;) |
87 | iobuf.out_pos = 0; | 109 | iobuf.out_pos = 0; |
88 | } | 110 | } |
89 | if (r == XZ_STREAM_END) { | 111 | if (xz_result == XZ_STREAM_END) { |
90 | break; | 112 | /* |
113 | * Can just "break;" here, if not for concatenated | ||
114 | * .xz streams. | ||
115 | * Checking for padding may require buffer | ||
116 | * replenishment. Can't do it here. | ||
117 | */ | ||
118 | continue; | ||
91 | } | 119 | } |
92 | if (r != XZ_OK && r != XZ_UNSUPPORTED_CHECK) { | 120 | if (xz_result != XZ_OK && xz_result != XZ_UNSUPPORTED_CHECK) { |
93 | bb_error_msg("corrupted data"); | 121 | bb_error_msg("corrupted data"); |
94 | total = -1; | 122 | total = -1; |
95 | break; | 123 | break; |
96 | } | 124 | } |
97 | } | 125 | } |
126 | |||
98 | xz_dec_end(state); | 127 | xz_dec_end(state); |
99 | free(membuf); | 128 | free(membuf); |
100 | 129 | ||