*: teach tar et. al. to understand .xz by heart
No binary (build failed)
—
(log yok)
| @@ -374,7 +374,7 @@ char* make_new_name_unxz(char *filename) | |
| static | |
| IF_DESKTOP(long long) int unpack_unxz(unpack_info_t *info UNUSED_PARAM) | |
| { | |
| - | return unpack_xz_stream_stdin(); |
| + | return unpack_xz_stream(STDIN_FILENO, STDOUT_FILENO); |
| } | |
| int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int unxz_main(int argc UNUSED_PARAM, char **argv) | |
| @@ -3,7 +3,7 @@ | |
| * by Lasse Collin <[email protected]> | |
| * and Igor Pavlov <http://7-zip.org/> | |
| * | |
| - | * See README file in unxzbz/ directory for more information. |
| + | * See README file in unxz/ directory for more information. |
| * | |
| * This file is: | |
| * Copyright (C) 2010 Denys Vlasenko <[email protected]> | |
| @@ -48,7 +48,7 @@ static uint32_t xz_crc32(uint32_t *crc32_table, | |
| #include "unxz/xz_stream.h" | |
| IF_DESKTOP(long long) int FAST_FUNC | |
| - | unpack_xz_stream_stdin(void) |
| + | unpack_xz_stream(int src_fd, int dst_fd) |
| { | |
| struct xz_buf iobuf; | |
| struct xz_dec *state; | |
| @@ -79,7 +79,7 @@ unpack_xz_stream_stdin(void) | |
| iobuf.in_pos = 0; | |
| rd = IN_SIZE - insz; | |
| if (rd) { | |
| - | rd = safe_read(STDIN_FILENO, membuf + insz, rd); |
| + | rd = safe_read(src_fd, membuf + insz, rd); |
| if (rd < 0) { | |
| bb_error_msg("read error"); | |
| total = -1; | |
| @@ -94,10 +94,11 @@ unpack_xz_stream_stdin(void) | |
| // iobuf.in_pos, iobuf.in_size, iobuf.out_pos, iobuf.out_size, r); | |
| outpos = iobuf.out_pos; | |
| if (outpos) { | |
| - | xwrite(STDOUT_FILENO, iobuf.out, outpos); |
| + | xwrite(dst_fd, iobuf.out, outpos); |
| IF_DESKTOP(total += outpos;) | |
| } | |
| if (r == XZ_STREAM_END | |
| + | /* this happens even with well-formed files: */ |
| || (r == XZ_BUF_ERROR && insz == 0 && outpos == 0) | |
| ) { | |
| break; | |
| @@ -656,7 +656,7 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST | |
| || ENABLE_FEATURE_SEAMLESS_BZ2 \ | |
| || ENABLE_FEATURE_SEAMLESS_GZ \ | |
| /* || ENABLE_FEATURE_SEAMLESS_Z */ | |
| - | extern int setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) FAST_FUNC; |
| + | extern void setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) FAST_FUNC; |
| #else | |
| # define setup_unzip_on_fd(...) ((void)0) | |
| #endif | |
| @@ -143,14 +143,15 @@ typedef struct inflate_unzip_result { | |
| } inflate_unzip_result; | |
| IF_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, off_t compr_size, int src_fd, int dst_fd) FAST_FUNC; | |
| - | IF_DESKTOP(long long) int unpack_xz_stream_stdin(void) FAST_FUNC; |
| + | /* xz unpacker takes .xz stream from offset 0 */ |
| + | IF_DESKTOP(long long) int unpack_xz_stream(int src_fd, int dst_fd) FAST_FUNC; |
| /* lzma unpacker takes .lzma stream from offset 0 */ | |
| IF_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd) FAST_FUNC; | |
| /* the rest wants 2 first bytes already skipped by the caller */ | |
| IF_DESKTOP(long long) int unpack_bz2_stream(int src_fd, int dst_fd) FAST_FUNC; | |
| IF_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd) FAST_FUNC; | |
| IF_DESKTOP(long long) int unpack_gz_stream_with_info(int src_fd, int dst_fd, unpack_info_t *info) FAST_FUNC; | |
| - | IF_DESKTOP(long long) int unpack_Z_stream(int fd_in, int fd_out) FAST_FUNC; |
| + | IF_DESKTOP(long long) int unpack_Z_stream(int src_fd, int dst_fd) FAST_FUNC; |
| /* wrapper which checks first two bytes to be "BZ" */ | |
| IF_DESKTOP(long long) int unpack_bz2_stream_prime(int src_fd, int dst_fd) FAST_FUNC; | |
| @@ -305,22 +305,26 @@ void* FAST_FUNC xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) | |
| return buf; | |
| } | |
| + | /* Used by e.g. rpm which gives us a fd without filename, |
| + | * thus we can't guess the format from filename's extension. |
| + | */ |
| #if ZIPPED | |
| - | int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) |
| + | void FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) |
| { | |
| const int fail_if_not_detected = 1; | |
| - | unsigned char magic[2]; |
| - | #if BB_MMU |
| + | unsigned char magic[8]; |
| + | int offset = -2; |
| + | # if BB_MMU |
| IF_DESKTOP(long long) int FAST_FUNC (*xformer)(int src_fd, int dst_fd); | |
| enum { xformer_prog = 0 }; | |
| - | #else |
| + | # else |
| enum { xformer = 0 }; | |
| const char *xformer_prog; | |
| - | #endif |
| + | # endif |
| /* .gz and .bz2 both have 2-byte signature, and their | |
| * unpack_XXX_stream wants this header skipped. */ | |
| - | xread(fd, &magic, 2); |
| + | xread(fd, magic, 2); |
| if (ENABLE_FEATURE_SEAMLESS_GZ | |
| && magic[0] == 0x1f && magic[1] == 0x8b | |
| ) { | |
| @@ -341,28 +345,41 @@ int FAST_FUNC setup_unzip_on_fd(int fd /*, int fail_if_not_detected*/) | |
| # endif | |
| goto found_magic; | |
| } | |
| - | // TODO: xz format support. rpm adopted it, "rpm -i FILE.rpm" badly needs this. |
| - | // Signature: 0xFD, '7', 'z', 'X', 'Z', 0x00 |
| - | // More info at: http://tukaani.org/xz/xz-file-format.txt |
| + | if (ENABLE_FEATURE_SEAMLESS_XZ |
| + | && magic[0] == 0xfd && magic[1] == '7' |
| + | ) { |
| + | /* .xz signature: 0xfd, '7', 'z', 'X', 'Z', 0x00 */ |
| + | /* More info at: http://tukaani.org/xz/xz-file-format.txt */ |
| + | offset = -6; |
| + | xread(fd, magic + 2, 4); |
| + | if (strcmp((char*)magic + 2, "zXZ") == 0) { |
| + | # if BB_MMU |
| + | xformer = unpack_xz_stream; |
| + | # else |
| + | xformer_prog = "unxz"; |
| + | # endif |
| + | xlseek(fd, offset, SEEK_CUR); |
| + | goto found_magic; |
| + | } |
| + | } |
| /* No known magic seen */ | |
| if (fail_if_not_detected) | |
| bb_error_msg_and_die("no gzip" | |
| IF_FEATURE_SEAMLESS_BZ2("/bzip2") | |
| + | IF_FEATURE_SEAMLESS_XZ("/xz") |
| " magic"); | |
| - | xlseek(fd, -2, SEEK_CUR); |
| - | return fd; |
| + | xlseek(fd, offset, SEEK_CUR); |
| + | return; |
| found_magic: | |
| # if !BB_MMU | |
| /* NOMMU version of open_transformer execs | |
| * an external unzipper that wants | |
| * file position at the start of the file */ | |
| - | xlseek(fd, -2, SEEK_CUR); |
| + | xlseek(fd, offset, SEEK_CUR); |
| # endif | |
| open_transformer(fd, xformer, xformer_prog); | |
| - | |
| - | return fd; |
| } | |
| #endif /* ZIPPED */ | |
| @@ -380,12 +397,14 @@ int FAST_FUNC open_zipped(const char *fname) | |
| sfx = strrchr(fname, '.'); | |
| if (sfx) { | |
| - | if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, ".lzma") == 0) |
| + | sfx++; |
| + | if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0) |
| /* .lzma has no header/signature, just trust it */ | |
| open_transformer(fd, unpack_lzma_stream, "unlzma"); | |
| else | |
| - | if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, ".gz") == 0) |
| - | || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, ".bz2") == 0) |
| + | if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0) |
| + | || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0) |
| + | || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0) |
| ) { | |
| setup_unzip_on_fd(fd /*, fail_if_not_detected: 1*/); | |
| } | |