aboutsummaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
Diffstat (limited to 'archival')
-rw-r--r--archival/libarchive/decompress_uncompress.c12
-rw-r--r--archival/libarchive/decompress_unzip.c26
-rw-r--r--archival/libarchive/open_transformer.c140
3 files changed, 161 insertions, 17 deletions
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c
index c6040d04b..289f9e233 100644
--- a/archival/libarchive/decompress_uncompress.c
+++ b/archival/libarchive/decompress_uncompress.c
@@ -73,7 +73,7 @@
73 */ 73 */
74 74
75IF_DESKTOP(long long) int FAST_FUNC 75IF_DESKTOP(long long) int FAST_FUNC
76unpack_Z_stream(int fd_in, int fd_out) 76unpack_Z_stream(int src_fd, int dst_fd)
77{ 77{
78 IF_DESKTOP(long long total_written = 0;) 78 IF_DESKTOP(long long total_written = 0;)
79 IF_DESKTOP(long long) int retval = -1; 79 IF_DESKTOP(long long) int retval = -1;
@@ -105,14 +105,14 @@ unpack_Z_stream(int fd_in, int fd_out)
105 105
106 inbuf = xzalloc(IBUFSIZ + 64); 106 inbuf = xzalloc(IBUFSIZ + 64);
107 outbuf = xzalloc(OBUFSIZ + 2048); 107 outbuf = xzalloc(OBUFSIZ + 2048);
108 htab = xzalloc(HSIZE); /* wsn't zeroed out before, maybe can xmalloc? */ 108 htab = xzalloc(HSIZE); /* wasn't zeroed out before, maybe can xmalloc? */
109 codetab = xzalloc(HSIZE * sizeof(codetab[0])); 109 codetab = xzalloc(HSIZE * sizeof(codetab[0]));
110 110
111 insize = 0; 111 insize = 0;
112 112
113 /* xread isn't good here, we have to return - caller may want 113 /* xread isn't good here, we have to return - caller may want
114 * to do some cleanup (e.g. delete incomplete unpacked file etc) */ 114 * to do some cleanup (e.g. delete incomplete unpacked file etc) */
115 if (full_read(fd_in, inbuf, 1) != 1) { 115 if (full_read(src_fd, inbuf, 1) != 1) {
116 bb_error_msg("short read"); 116 bb_error_msg("short read");
117 goto err; 117 goto err;
118 } 118 }
@@ -162,7 +162,7 @@ unpack_Z_stream(int fd_in, int fd_out)
162 } 162 }
163 163
164 if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { 164 if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
165 rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ); 165 rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ);
166 if (rsize < 0) 166 if (rsize < 0)
167 bb_error_msg_and_die(bb_msg_read_error); 167 bb_error_msg_and_die(bb_msg_read_error);
168 insize += rsize; 168 insize += rsize;
@@ -268,7 +268,7 @@ unpack_Z_stream(int fd_in, int fd_out)
268 } 268 }
269 269
270 if (outpos >= OBUFSIZ) { 270 if (outpos >= OBUFSIZ) {
271 xwrite(fd_out, outbuf, outpos); 271 xwrite(dst_fd, outbuf, outpos);
272 IF_DESKTOP(total_written += outpos;) 272 IF_DESKTOP(total_written += outpos;)
273 outpos = 0; 273 outpos = 0;
274 } 274 }
@@ -296,7 +296,7 @@ unpack_Z_stream(int fd_in, int fd_out)
296 } while (rsize > 0); 296 } while (rsize > 0);
297 297
298 if (outpos > 0) { 298 if (outpos > 0) {
299 xwrite(fd_out, outbuf, outpos); 299 xwrite(dst_fd, outbuf, outpos);
300 IF_DESKTOP(total_written += outpos;) 300 IF_DESKTOP(total_written += outpos;)
301 } 301 }
302 302
diff --git a/archival/libarchive/decompress_unzip.c b/archival/libarchive/decompress_unzip.c
index aa5d22d0a..50873e3f6 100644
--- a/archival/libarchive/decompress_unzip.c
+++ b/archival/libarchive/decompress_unzip.c
@@ -1182,33 +1182,37 @@ static int check_header_gzip(STATE_PARAM unpack_info_t *info)
1182} 1182}
1183 1183
1184IF_DESKTOP(long long) int FAST_FUNC 1184IF_DESKTOP(long long) int FAST_FUNC
1185unpack_gz_stream_with_info(int in, int out, unpack_info_t *info) 1185unpack_gz_stream_with_info(int src_fd, int dst_fd, unpack_info_t *info)
1186{ 1186{
1187 uint32_t v32; 1187 uint32_t v32;
1188 IF_DESKTOP(long long) int n; 1188 IF_DESKTOP(long long) int total, n;
1189 DECLARE_STATE; 1189 DECLARE_STATE;
1190 1190
1191 n = 0; 1191 total = 0;
1192 1192
1193 ALLOC_STATE; 1193 ALLOC_STATE;
1194 to_read = -1; 1194 to_read = -1;
1195// bytebuffer_max = 0x8000; 1195// bytebuffer_max = 0x8000;
1196 bytebuffer = xmalloc(bytebuffer_max); 1196 bytebuffer = xmalloc(bytebuffer_max);
1197 gunzip_src_fd = in; 1197 gunzip_src_fd = src_fd;
1198 1198
1199 again: 1199 again:
1200 if (!check_header_gzip(PASS_STATE info)) { 1200 if (!check_header_gzip(PASS_STATE info)) {
1201 bb_error_msg("corrupted data"); 1201 bb_error_msg("corrupted data");
1202 n = -1; 1202 total = -1;
1203 goto ret; 1203 goto ret;
1204 } 1204 }
1205 n += inflate_unzip_internal(PASS_STATE in, out); 1205
1206 if (n < 0) 1206 n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd);
1207 if (n < 0) {
1208 total = -1;
1207 goto ret; 1209 goto ret;
1210 }
1211 total += n;
1208 1212
1209 if (!top_up(PASS_STATE 8)) { 1213 if (!top_up(PASS_STATE 8)) {
1210 bb_error_msg("corrupted data"); 1214 bb_error_msg("corrupted data");
1211 n = -1; 1215 total = -1;
1212 goto ret; 1216 goto ret;
1213 } 1217 }
1214 1218
@@ -1216,7 +1220,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1216 v32 = buffer_read_le_u32(PASS_STATE_ONLY); 1220 v32 = buffer_read_le_u32(PASS_STATE_ONLY);
1217 if ((~gunzip_crc) != v32) { 1221 if ((~gunzip_crc) != v32) {
1218 bb_error_msg("crc error"); 1222 bb_error_msg("crc error");
1219 n = -1; 1223 total = -1;
1220 goto ret; 1224 goto ret;
1221 } 1225 }
1222 1226
@@ -1224,7 +1228,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1224 v32 = buffer_read_le_u32(PASS_STATE_ONLY); 1228 v32 = buffer_read_le_u32(PASS_STATE_ONLY);
1225 if ((uint32_t)gunzip_bytes_out != v32) { 1229 if ((uint32_t)gunzip_bytes_out != v32) {
1226 bb_error_msg("incorrect length"); 1230 bb_error_msg("incorrect length");
1227 n = -1; 1231 total = -1;
1228 } 1232 }
1229 1233
1230 if (!top_up(PASS_STATE 2)) 1234 if (!top_up(PASS_STATE 2))
@@ -1242,7 +1246,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1242 ret: 1246 ret:
1243 free(bytebuffer); 1247 free(bytebuffer);
1244 DEALLOC_STATE; 1248 DEALLOC_STATE;
1245 return n; 1249 return total;
1246} 1250}
1247 1251
1248IF_DESKTOP(long long) int FAST_FUNC 1252IF_DESKTOP(long long) int FAST_FUNC
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index aa8c1021c..743ffee02 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -6,6 +6,16 @@
6#include "libbb.h" 6#include "libbb.h"
7#include "bb_archive.h" 7#include "bb_archive.h"
8 8
9#define ZIPPED (ENABLE_FEATURE_SEAMLESS_LZMA \
10 || ENABLE_FEATURE_SEAMLESS_BZ2 \
11 || ENABLE_FEATURE_SEAMLESS_GZ \
12 /* || ENABLE_FEATURE_SEAMLESS_Z */ \
13)
14
15#if ZIPPED
16# include "bb_archive.h"
17#endif
18
9/* transformer(), more than meets the eye */ 19/* transformer(), more than meets the eye */
10/* 20/*
11 * On MMU machine, the transform_prog is removed by macro magic 21 * On MMU machine, the transform_prog is removed by macro magic
@@ -52,3 +62,133 @@ void FAST_FUNC open_transformer(int fd,
52 close(fd_pipe.wr); /* don't want to write to the child */ 62 close(fd_pipe.wr); /* don't want to write to the child */
53 xmove_fd(fd_pipe.rd, fd); 63 xmove_fd(fd_pipe.rd, fd);
54} 64}
65
66
67/* Used by e.g. rpm which gives us a fd without filename,
68 * thus we can't guess the format from filename's extension.
69 */
70#if ZIPPED
71void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/)
72{
73 const int fail_if_not_detected = 1;
74 union {
75 uint8_t b[4];
76 uint16_t b16[2];
77 uint32_t b32[1];
78 } magic;
79 int offset = -2;
80# if BB_MMU
81 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd);
82 enum { xformer_prog = 0 };
83# else
84 enum { xformer = 0 };
85 const char *xformer_prog;
86# endif
87
88 /* .gz and .bz2 both have 2-byte signature, and their
89 * unpack_XXX_stream wants this header skipped. */
90 xread(fd, magic.b16, sizeof(magic.b16[0]));
91 if (ENABLE_FEATURE_SEAMLESS_GZ
92 && magic.b16[0] == GZIP_MAGIC
93 ) {
94# if BB_MMU
95 xformer = unpack_gz_stream;
96# else
97 xformer_prog = "gunzip";
98# endif
99 goto found_magic;
100 }
101 if (ENABLE_FEATURE_SEAMLESS_BZ2
102 && magic.b16[0] == BZIP2_MAGIC
103 ) {
104# if BB_MMU
105 xformer = unpack_bz2_stream;
106# else
107 xformer_prog = "bunzip2";
108# endif
109 goto found_magic;
110 }
111 if (ENABLE_FEATURE_SEAMLESS_XZ
112 && magic.b16[0] == XZ_MAGIC1
113 ) {
114 offset = -6;
115 xread(fd, magic.b32, sizeof(magic.b32[0]));
116 if (magic.b32[0] == XZ_MAGIC2) {
117# if BB_MMU
118 xformer = unpack_xz_stream;
119 /* unpack_xz_stream wants fd at position 6, no need to seek */
120 //xlseek(fd, offset, SEEK_CUR);
121# else
122 xformer_prog = "unxz";
123# endif
124 goto found_magic;
125 }
126 }
127
128 /* No known magic seen */
129 if (fail_if_not_detected)
130 bb_error_msg_and_die("no gzip"
131 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
132 IF_FEATURE_SEAMLESS_XZ("/xz")
133 " magic");
134 xlseek(fd, offset, SEEK_CUR);
135 return;
136
137 found_magic:
138# if !BB_MMU
139 /* NOMMU version of open_transformer execs
140 * an external unzipper that wants
141 * file position at the start of the file */
142 xlseek(fd, offset, SEEK_CUR);
143# endif
144 open_transformer(fd, xformer, xformer_prog);
145}
146#endif /* ZIPPED */
147
148int FAST_FUNC open_zipped(const char *fname)
149{
150#if !ZIPPED
151 return open(fname, O_RDONLY);
152#else
153 char *sfx;
154 int fd;
155
156 fd = open(fname, O_RDONLY);
157 if (fd < 0)
158 return fd;
159
160 sfx = strrchr(fname, '.');
161 if (sfx) {
162 sfx++;
163 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
164 /* .lzma has no header/signature, just trust it */
165 open_transformer(fd, unpack_lzma_stream, "unlzma");
166 else
167 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
168 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
169 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
170 ) {
171 setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/);
172 }
173 }
174
175 return fd;
176#endif
177}
178
179void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
180{
181 int fd;
182 char *image;
183
184 fd = open_zipped(fname);
185 if (fd < 0)
186 return NULL;
187
188 image = xmalloc_read(fd, maxsz_p);
189 if (!image)
190 bb_perror_msg("read error from '%s'", fname);
191 close(fd);
192
193 return image;
194}