aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-05-30 04:18:13 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-05-30 04:18:13 +0200
commit6948f210ed443f8153e0ba751e77bec8a0c6c8d4 (patch)
tree134443f225a788cbb4fda7b4713ee2bc535fb126
parentfb6c76cb6eaade5693b7e99c33846c902689f1db (diff)
downloadbusybox-w32-6948f210ed443f8153e0ba751e77bec8a0c6c8d4.tar.gz
busybox-w32-6948f210ed443f8153e0ba751e77bec8a0c6c8d4.tar.bz2
busybox-w32-6948f210ed443f8153e0ba751e77bec8a0c6c8d4.zip
*: teach tar et. al. to understand .xz by heart
function old new delta unpack_xz_stream - 4126 +4126 setup_unzip_on_fd 80 150 +70 open_zipped 113 131 +18 unpack_unxz 5 12 +7 send_tree 360 353 -7 unpack_xz_stream_stdin 3953 - -3953 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 3/1 up/down: 4221/-3960) Total: 261 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/bbunzip.c2
-rw-r--r--archival/libunarchive/decompress_unxz.c9
-rw-r--r--include/libbb.h2
-rw-r--r--include/unarchive.h5
-rw-r--r--libbb/read.c53
5 files changed, 46 insertions, 25 deletions
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index 1c8d0ab55..86adb6e24 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -374,7 +374,7 @@ char* make_new_name_unxz(char *filename)
374static 374static
375IF_DESKTOP(long long) int unpack_unxz(unpack_info_t *info UNUSED_PARAM) 375IF_DESKTOP(long long) int unpack_unxz(unpack_info_t *info UNUSED_PARAM)
376{ 376{
377 return unpack_xz_stream_stdin(); 377 return unpack_xz_stream(STDIN_FILENO, STDOUT_FILENO);
378} 378}
379int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 379int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
380int unxz_main(int argc UNUSED_PARAM, char **argv) 380int unxz_main(int argc UNUSED_PARAM, char **argv)
diff --git a/archival/libunarchive/decompress_unxz.c b/archival/libunarchive/decompress_unxz.c
index 0ae789160..9edc2461a 100644
--- a/archival/libunarchive/decompress_unxz.c
+++ b/archival/libunarchive/decompress_unxz.c
@@ -3,7 +3,7 @@
3 * by Lasse Collin <lasse.collin@tukaani.org> 3 * by Lasse Collin <lasse.collin@tukaani.org>
4 * and Igor Pavlov <http://7-zip.org/> 4 * and Igor Pavlov <http://7-zip.org/>
5 * 5 *
6 * See README file in unxzbz/ directory for more information. 6 * See README file in unxz/ directory for more information.
7 * 7 *
8 * This file is: 8 * This file is:
9 * Copyright (C) 2010 Denys Vlasenko <vda.linux@googlemail.com> 9 * Copyright (C) 2010 Denys Vlasenko <vda.linux@googlemail.com>
@@ -48,7 +48,7 @@ static uint32_t xz_crc32(uint32_t *crc32_table,
48#include "unxz/xz_stream.h" 48#include "unxz/xz_stream.h"
49 49
50IF_DESKTOP(long long) int FAST_FUNC 50IF_DESKTOP(long long) int FAST_FUNC
51unpack_xz_stream_stdin(void) 51unpack_xz_stream(int src_fd, int dst_fd)
52{ 52{
53 struct xz_buf iobuf; 53 struct xz_buf iobuf;
54 struct xz_dec *state; 54 struct xz_dec *state;
@@ -79,7 +79,7 @@ unpack_xz_stream_stdin(void)
79 iobuf.in_pos = 0; 79 iobuf.in_pos = 0;
80 rd = IN_SIZE - insz; 80 rd = IN_SIZE - insz;
81 if (rd) { 81 if (rd) {
82 rd = safe_read(STDIN_FILENO, membuf + insz, rd); 82 rd = safe_read(src_fd, membuf + insz, rd);
83 if (rd < 0) { 83 if (rd < 0) {
84 bb_error_msg("read error"); 84 bb_error_msg("read error");
85 total = -1; 85 total = -1;
@@ -94,10 +94,11 @@ unpack_xz_stream_stdin(void)
94// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r); 94// iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r);
95 outpos = iobuf.out_pos; 95 outpos = iobuf.out_pos;
96 if (outpos) { 96 if (outpos) {
97 xwrite(STDOUT_FILENO, iobuf.out, outpos); 97 xwrite(dst_fd, iobuf.out, outpos);
98 IF_DESKTOP(total += outpos;) 98 IF_DESKTOP(total += outpos;)
99 } 99 }
100 if (r == XZ_STREAM_END 100 if (r == XZ_STREAM_END
101 /* this happens even with well-formed files: */
101 || (r == XZ_BUF_ERROR && insz == 0 && outpos == 0) 102 || (r == XZ_BUF_ERROR && insz == 0 && outpos == 0)
102 ) { 103 ) {
103 break; 104 break;
diff --git a/include/libbb.h b/include/libbb.h
index 2f67c7f72..326179b97 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -656,7 +656,7 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST
656 || ENABLE_FEATURE_SEAMLESS_BZ2 \ 656 || ENABLE_FEATURE_SEAMLESS_BZ2 \
657 || ENABLE_FEATURE_SEAMLESS_GZ \ 657 || ENABLE_FEATURE_SEAMLESS_GZ \
658 /* || ENABLE_FEATURE_SEAMLESS_Z */ 658 /* || ENABLE_FEATURE_SEAMLESS_Z */
659extern int setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) FAST_FUNC; 659extern void setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) FAST_FUNC;
660#else 660#else
661# define setup_unzip_on_fd(...) ((void)0) 661# define setup_unzip_on_fd(...) ((void)0)
662#endif 662#endif
diff --git a/include/unarchive.h b/include/unarchive.h
index 14cd98e24..783a943b6 100644
--- a/include/unarchive.h
+++ b/include/unarchive.h
@@ -143,14 +143,15 @@ typedef struct inflate_unzip_result {
143} inflate_unzip_result; 143} inflate_unzip_result;
144 144
145IF_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, off_t compr_size, int src_fd, int dst_fd) FAST_FUNC; 145IF_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, off_t compr_size, int src_fd, int dst_fd) FAST_FUNC;
146IF_DESKTOP(long long) int unpack_xz_stream_stdin(void) FAST_FUNC; 146/* xz unpacker takes .xz stream from offset 0 */
147IF_DESKTOP(long long) int unpack_xz_stream(int src_fd, int dst_fd) FAST_FUNC;
147/* lzma unpacker takes .lzma stream from offset 0 */ 148/* lzma unpacker takes .lzma stream from offset 0 */
148IF_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd) FAST_FUNC; 149IF_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd) FAST_FUNC;
149/* the rest wants 2 first bytes already skipped by the caller */ 150/* the rest wants 2 first bytes already skipped by the caller */
150IF_DESKTOP(long long) int unpack_bz2_stream(int src_fd, int dst_fd) FAST_FUNC; 151IF_DESKTOP(long long) int unpack_bz2_stream(int src_fd, int dst_fd) FAST_FUNC;
151IF_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd) FAST_FUNC; 152IF_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd) FAST_FUNC;
152IF_DESKTOP(long long) int unpack_gz_stream_with_info(int src_fd, int dst_fd, unpack_info_t *info) FAST_FUNC; 153IF_DESKTOP(long long) int unpack_gz_stream_with_info(int src_fd, int dst_fd, unpack_info_t *info) FAST_FUNC;
153IF_DESKTOP(long long) int unpack_Z_stream(int fd_in, int fd_out) FAST_FUNC; 154IF_DESKTOP(long long) int unpack_Z_stream(int src_fd, int dst_fd) FAST_FUNC;
154/* wrapper which checks first two bytes to be "BZ" */ 155/* wrapper which checks first two bytes to be "BZ" */
155IF_DESKTOP(long long) int unpack_bz2_stream_prime(int src_fd, int dst_fd) FAST_FUNC; 156IF_DESKTOP(long long) int unpack_bz2_stream_prime(int src_fd, int dst_fd) FAST_FUNC;
156 157
diff --git a/libbb/read.c b/libbb/read.c
index f3af144f0..cd6bbeb13 100644
--- a/libbb/read.c
+++ b/libbb/read.c
@@ -305,22 +305,26 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p)
305 return buf; 305 return buf;
306} 306}
307 307
308/* Used by e.g. rpm which gives us a fd without filename,
309 * thus we can't guess the format from filename's extension.
310 */
308#if ZIPPED 311#if ZIPPED
309int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) 312void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/)
310{ 313{
311 const int fail_if_not_detected = 1; 314 const int fail_if_not_detected = 1;
312 unsigned char magic[2]; 315 unsigned char magic[8];
313#if BB_MMU 316 int offset = -2;
317# if BB_MMU
314 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); 318 IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd);
315 enum { xformer_prog = 0 }; 319 enum { xformer_prog = 0 };
316#else 320# else
317 enum { xformer = 0 }; 321 enum { xformer = 0 };
318 const char *xformer_prog; 322 const char *xformer_prog;
319#endif 323# endif
320 324
321 /* .gz and .bz2 both have 2-byte signature, and their 325 /* .gz and .bz2 both have 2-byte signature, and their
322 * unpack_XXX_stream wants this header skipped. */ 326 * unpack_XXX_stream wants this header skipped. */
323 xread(fd, &magic, 2); 327 xread(fd, magic, 2);
324 if (ENABLE_FEATURE_SEAMLESS_GZ 328 if (ENABLE_FEATURE_SEAMLESS_GZ
325 && magic[0] == 0x1f && magic[1] == 0x8b 329 && magic[0] == 0x1f && magic[1] == 0x8b
326 ) { 330 ) {
@@ -341,28 +345,41 @@ int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/)
341# endif 345# endif
342 goto found_magic; 346 goto found_magic;
343 } 347 }
344// TODO: xz format support. rpm adopted it, "rpm -i FILE.rpm" badly needs this. 348 if (ENABLE_FEATURE_SEAMLESS_XZ
345// Signature: 0xFD, '7', 'z', 'X', 'Z', 0x00 349 && magic[0] == 0xfd && magic[1] == '7'
346// More info at: http://tukaani.org/xz/xz-file-format.txt 350 ) {
351 /* .xz signature: 0xfd, '7', 'z', 'X', 'Z', 0x00 */
352 /* More info at: http://tukaani.org/xz/xz-file-format.txt */
353 offset = -6;
354 xread(fd, magic + 2, 4);
355 if (strcmp((char*)magic + 2, "zXZ") == 0) {
356# if BB_MMU
357 xformer = unpack_xz_stream;
358# else
359 xformer_prog = "unxz";
360# endif
361 xlseek(fd, offset, SEEK_CUR);
362 goto found_magic;
363 }
364 }
347 365
348 /* No known magic seen */ 366 /* No known magic seen */
349 if (fail_if_not_detected) 367 if (fail_if_not_detected)
350 bb_error_msg_and_die("no gzip" 368 bb_error_msg_and_die("no gzip"
351 IF_FEATURE_SEAMLESS_BZ2("/bzip2") 369 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
370 IF_FEATURE_SEAMLESS_XZ("/xz")
352 " magic"); 371 " magic");
353 xlseek(fd, -2, SEEK_CUR); 372 xlseek(fd, offset, SEEK_CUR);
354 return fd; 373 return;
355 374
356 found_magic: 375 found_magic:
357# if !BB_MMU 376# if !BB_MMU
358 /* NOMMU version of open_transformer execs 377 /* NOMMU version of open_transformer execs
359 * an external unzipper that wants 378 * an external unzipper that wants
360 * file position at the start of the file */ 379 * file position at the start of the file */
361 xlseek(fd, -2, SEEK_CUR); 380 xlseek(fd, offset, SEEK_CUR);
362# endif 381# endif
363 open_transformer(fd, xformer, xformer_prog); 382 open_transformer(fd, xformer, xformer_prog);
364
365 return fd;
366} 383}
367#endif /* ZIPPED */ 384#endif /* ZIPPED */
368 385
@@ -380,12 +397,14 @@ int FAST_FUNC open_zipped(const char *fname)
380 397
381 sfx = strrchr(fname, '.'); 398 sfx = strrchr(fname, '.');
382 if (sfx) { 399 if (sfx) {
383 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, ".lzma") == 0) 400 sfx++;
401 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
384 /* .lzma has no header/signature, just trust it */ 402 /* .lzma has no header/signature, just trust it */
385 open_transformer(fd, unpack_lzma_stream, "unlzma"); 403 open_transformer(fd, unpack_lzma_stream, "unlzma");
386 else 404 else
387 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0) 405 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
388 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0) 406 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
407 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
389 ) { 408 ) {
390 setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); 409 setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/);
391 } 410 }