diff options
author | Ron Yorston <rmy@pobox.com> | 2013-03-19 11:18:39 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2013-03-19 11:18:39 +0000 |
commit | 63d2c5fead323df5f4250ed544d0bc03527c8936 (patch) | |
tree | 660979b139a4bc4b143c08843cb7efbc69bdcb4d /archival | |
parent | 27fc2d535588728ac3ca69337271471fb6fe3ee9 (diff) | |
parent | a42f530e034b673726a91ea5d8202254e677f066 (diff) | |
download | busybox-w32-63d2c5fead323df5f4250ed544d0bc03527c8936.tar.gz busybox-w32-63d2c5fead323df5f4250ed544d0bc03527c8936.tar.bz2 busybox-w32-63d2c5fead323df5f4250ed544d0bc03527c8936.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'archival')
-rw-r--r-- | archival/bbunzip.c | 77 | ||||
-rw-r--r-- | archival/libarchive/data_extract_all.c | 15 | ||||
-rw-r--r-- | archival/libarchive/decompress_unlzma.c | 29 | ||||
-rw-r--r-- | archival/libarchive/decompress_unxz.c | 47 | ||||
-rw-r--r-- | archival/libarchive/open_transformer.c | 11 | ||||
-rw-r--r-- | archival/libarchive/unxz/README | 6 | ||||
-rw-r--r-- | archival/libarchive/unxz/xz.h | 17 | ||||
-rw-r--r-- | archival/libarchive/unxz/xz_dec_bcj.c | 34 | ||||
-rw-r--r-- | archival/libarchive/unxz/xz_dec_lzma2.c | 7 | ||||
-rw-r--r-- | archival/libarchive/unxz/xz_stream.h | 11 | ||||
-rw-r--r-- | archival/lzop.c | 32 | ||||
-rw-r--r-- | archival/rpm.c | 305 |
12 files changed, 345 insertions, 246 deletions
diff --git a/archival/bbunzip.c b/archival/bbunzip.c index 66a046052..f77ac8383 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c | |||
@@ -7,13 +7,16 @@ | |||
7 | #include "libbb.h" | 7 | #include "libbb.h" |
8 | #include "bb_archive.h" | 8 | #include "bb_archive.h" |
9 | 9 | ||
10 | /* Note: must be kept in sync with archival/lzop.c */ | ||
10 | enum { | 11 | enum { |
11 | OPT_STDOUT = 1 << 0, | 12 | OPT_STDOUT = 1 << 0, |
12 | OPT_FORCE = 1 << 1, | 13 | OPT_FORCE = 1 << 1, |
13 | /* only some decompressors: */ | 14 | /* only some decompressors: */ |
14 | OPT_VERBOSE = 1 << 2, | 15 | OPT_VERBOSE = 1 << 2, |
15 | OPT_DECOMPRESS = 1 << 3, | 16 | OPT_QUIET = 1 << 3, |
16 | OPT_TEST = 1 << 4, | 17 | OPT_DECOMPRESS = 1 << 4, |
18 | OPT_TEST = 1 << 5, | ||
19 | SEAMLESS_MAGIC = (1 << 31) * SEAMLESS_COMPRESSION, | ||
17 | }; | 20 | }; |
18 | 21 | ||
19 | static | 22 | static |
@@ -39,7 +42,7 @@ int FAST_FUNC bbunpack(char **argv, | |||
39 | ) | 42 | ) |
40 | { | 43 | { |
41 | struct stat stat_buf; | 44 | struct stat stat_buf; |
42 | IF_DESKTOP(long long) int status; | 45 | IF_DESKTOP(long long) int status = 0; |
43 | char *filename, *new_name; | 46 | char *filename, *new_name; |
44 | smallint exitcode = 0; | 47 | smallint exitcode = 0; |
45 | transformer_aux_data_t aux; | 48 | transformer_aux_data_t aux; |
@@ -54,13 +57,27 @@ int FAST_FUNC bbunpack(char **argv, | |||
54 | 57 | ||
55 | /* Open src */ | 58 | /* Open src */ |
56 | if (filename) { | 59 | if (filename) { |
57 | if (stat(filename, &stat_buf) != 0) { | 60 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
58 | bb_simple_perror_msg(filename); | 61 | if (stat(filename, &stat_buf) != 0) { |
62 | err_name: | ||
63 | bb_simple_perror_msg(filename); | ||
59 | err: | 64 | err: |
60 | exitcode = 1; | 65 | exitcode = 1; |
61 | goto free_name; | 66 | goto free_name; |
67 | } | ||
68 | if (open_to_or_warn(STDIN_FILENO, filename, O_RDONLY, 0)) | ||
69 | goto err; | ||
70 | } else { | ||
71 | /* "clever zcat" with FILE */ | ||
72 | int fd = open_zipped(filename); | ||
73 | if (fd < 0) | ||
74 | goto err_name; | ||
75 | xmove_fd(fd, STDIN_FILENO); | ||
62 | } | 76 | } |
63 | if (open_to_or_warn(STDIN_FILENO, filename, O_RDONLY, 0)) | 77 | } else |
78 | if (option_mask32 & SEAMLESS_MAGIC) { | ||
79 | /* "clever zcat" on stdin */ | ||
80 | if (setup_unzip_on_fd(STDIN_FILENO, /*fail_if_not_detected*/ 0)) | ||
64 | goto err; | 81 | goto err; |
65 | } | 82 | } |
66 | 83 | ||
@@ -68,7 +85,7 @@ int FAST_FUNC bbunpack(char **argv, | |||
68 | if (option_mask32 & (OPT_STDOUT|OPT_TEST)) { | 85 | if (option_mask32 & (OPT_STDOUT|OPT_TEST)) { |
69 | if (option_mask32 & OPT_TEST) | 86 | if (option_mask32 & OPT_TEST) |
70 | if (open_to_or_warn(STDOUT_FILENO, bb_dev_null, O_WRONLY, 0)) | 87 | if (open_to_or_warn(STDOUT_FILENO, bb_dev_null, O_WRONLY, 0)) |
71 | goto err; | 88 | xfunc_die(); |
72 | filename = NULL; | 89 | filename = NULL; |
73 | } | 90 | } |
74 | 91 | ||
@@ -93,16 +110,22 @@ int FAST_FUNC bbunpack(char **argv, | |||
93 | } | 110 | } |
94 | 111 | ||
95 | /* Check that the input is sane */ | 112 | /* Check that the input is sane */ |
96 | if (isatty(STDIN_FILENO) && (option_mask32 & OPT_FORCE) == 0) { | 113 | if (!(option_mask32 & OPT_FORCE) && isatty(STDIN_FILENO)) { |
97 | bb_error_msg_and_die("compressed data not read from terminal, " | 114 | bb_error_msg_and_die("compressed data not read from terminal, " |
98 | "use -f to force it"); | 115 | "use -f to force it"); |
99 | } | 116 | } |
100 | 117 | ||
101 | init_transformer_aux_data(&aux); | 118 | if (!(option_mask32 & SEAMLESS_MAGIC)) { |
102 | aux.check_signature = 1; | 119 | init_transformer_aux_data(&aux); |
103 | status = unpacker(&aux); | 120 | aux.check_signature = 1; |
104 | if (status < 0) | 121 | status = unpacker(&aux); |
105 | exitcode = 1; | 122 | if (status < 0) |
123 | exitcode = 1; | ||
124 | } else { | ||
125 | if (bb_copyfd_eof(STDIN_FILENO, STDOUT_FILENO) < 0) | ||
126 | /* Disk full, tty closed, etc. No point in continuing */ | ||
127 | xfunc_die(); | ||
128 | } | ||
106 | 129 | ||
107 | if (!(option_mask32 & OPT_STDOUT)) | 130 | if (!(option_mask32 & OPT_STDOUT)) |
108 | xclose(STDOUT_FILENO); /* with error check! */ | 131 | xclose(STDOUT_FILENO); /* with error check! */ |
@@ -243,7 +266,7 @@ int uncompress_main(int argc UNUSED_PARAM, char **argv) | |||
243 | //usage: "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" | 266 | //usage: "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" |
244 | //usage: | 267 | //usage: |
245 | //usage:#define zcat_trivial_usage | 268 | //usage:#define zcat_trivial_usage |
246 | //usage: "FILE" | 269 | //usage: "[FILE]..." |
247 | //usage:#define zcat_full_usage "\n\n" | 270 | //usage:#define zcat_full_usage "\n\n" |
248 | //usage: "Decompress to stdout" | 271 | //usage: "Decompress to stdout" |
249 | 272 | ||
@@ -294,11 +317,15 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(transformer_aux_data_t *aux) | |||
294 | int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 317 | int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
295 | int gunzip_main(int argc UNUSED_PARAM, char **argv) | 318 | int gunzip_main(int argc UNUSED_PARAM, char **argv) |
296 | { | 319 | { |
297 | getopt32(argv, "cfvdtn"); | 320 | getopt32(argv, "cfvqdtn"); |
298 | argv += optind; | 321 | argv += optind; |
299 | /* if called as zcat */ | 322 | |
323 | /* If called as zcat... | ||
324 | * Normally, "zcat" is just "gunzip -c". | ||
325 | * But if seamless magic is enabled, then we are much more clever. | ||
326 | */ | ||
300 | if (applet_name[1] == 'c') | 327 | if (applet_name[1] == 'c') |
301 | option_mask32 |= OPT_STDOUT; | 328 | option_mask32 |= OPT_STDOUT | SEAMLESS_MAGIC; |
302 | 329 | ||
303 | return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); | 330 | return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); |
304 | } | 331 | } |
@@ -318,7 +345,7 @@ int gunzip_main(int argc UNUSED_PARAM, char **argv) | |||
318 | //usage: "\n -c Write to stdout" | 345 | //usage: "\n -c Write to stdout" |
319 | //usage: "\n -f Force" | 346 | //usage: "\n -f Force" |
320 | //usage:#define bzcat_trivial_usage | 347 | //usage:#define bzcat_trivial_usage |
321 | //usage: "FILE" | 348 | //usage: "[FILE]..." |
322 | //usage:#define bzcat_full_usage "\n\n" | 349 | //usage:#define bzcat_full_usage "\n\n" |
323 | //usage: "Decompress to stdout" | 350 | //usage: "Decompress to stdout" |
324 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) | 351 | //applet:IF_BUNZIP2(APPLET(bunzip2, BB_DIR_USR_BIN, BB_SUID_DROP)) |
@@ -332,7 +359,7 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(transformer_aux_data_t *aux) | |||
332 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 359 | int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
333 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) | 360 | int bunzip2_main(int argc UNUSED_PARAM, char **argv) |
334 | { | 361 | { |
335 | getopt32(argv, "cfvdt"); | 362 | getopt32(argv, "cfvqdt"); |
336 | argv += optind; | 363 | argv += optind; |
337 | if (applet_name[2] == 'c') /* bzcat */ | 364 | if (applet_name[2] == 'c') /* bzcat */ |
338 | option_mask32 |= OPT_STDOUT; | 365 | option_mask32 |= OPT_STDOUT; |
@@ -367,7 +394,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
367 | //usage: "\n -f Force" | 394 | //usage: "\n -f Force" |
368 | //usage: | 395 | //usage: |
369 | //usage:#define lzcat_trivial_usage | 396 | //usage:#define lzcat_trivial_usage |
370 | //usage: "FILE" | 397 | //usage: "[FILE]..." |
371 | //usage:#define lzcat_full_usage "\n\n" | 398 | //usage:#define lzcat_full_usage "\n\n" |
372 | //usage: "Decompress to stdout" | 399 | //usage: "Decompress to stdout" |
373 | //usage: | 400 | //usage: |
@@ -387,7 +414,7 @@ int bunzip2_main(int argc UNUSED_PARAM, char **argv) | |||
387 | //usage: "\n -f Force" | 414 | //usage: "\n -f Force" |
388 | //usage: | 415 | //usage: |
389 | //usage:#define xzcat_trivial_usage | 416 | //usage:#define xzcat_trivial_usage |
390 | //usage: "FILE" | 417 | //usage: "[FILE]..." |
391 | //usage:#define xzcat_full_usage "\n\n" | 418 | //usage:#define xzcat_full_usage "\n\n" |
392 | //usage: "Decompress to stdout" | 419 | //usage: "Decompress to stdout" |
393 | 420 | ||
@@ -400,7 +427,7 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(transformer_aux_data_t *aux) | |||
400 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 427 | int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
401 | int unlzma_main(int argc UNUSED_PARAM, char **argv) | 428 | int unlzma_main(int argc UNUSED_PARAM, char **argv) |
402 | { | 429 | { |
403 | IF_LZMA(int opts =) getopt32(argv, "cfvdt"); | 430 | IF_LZMA(int opts =) getopt32(argv, "cfvqdt"); |
404 | # if ENABLE_LZMA | 431 | # if ENABLE_LZMA |
405 | /* lzma without -d or -t? */ | 432 | /* lzma without -d or -t? */ |
406 | if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) | 433 | if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) |
@@ -425,7 +452,7 @@ IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(transformer_aux_data_t *aux) | |||
425 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 452 | int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
426 | int unxz_main(int argc UNUSED_PARAM, char **argv) | 453 | int unxz_main(int argc UNUSED_PARAM, char **argv) |
427 | { | 454 | { |
428 | IF_XZ(int opts =) getopt32(argv, "cfvdt"); | 455 | IF_XZ(int opts =) getopt32(argv, "cfvqdt"); |
429 | # if ENABLE_XZ | 456 | # if ENABLE_XZ |
430 | /* xz without -d or -t? */ | 457 | /* xz without -d or -t? */ |
431 | if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) | 458 | if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) |
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 3f67b835f..45776dcbe 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
@@ -106,15 +106,28 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
106 | switch (file_header->mode & S_IFMT) { | 106 | switch (file_header->mode & S_IFMT) { |
107 | case S_IFREG: { | 107 | case S_IFREG: { |
108 | /* Regular file */ | 108 | /* Regular file */ |
109 | char *dst_name; | ||
109 | int flags = O_WRONLY | O_CREAT | O_EXCL; | 110 | int flags = O_WRONLY | O_CREAT | O_EXCL; |
110 | if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) | 111 | if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) |
111 | flags = O_WRONLY | O_CREAT | O_TRUNC; | 112 | flags = O_WRONLY | O_CREAT | O_TRUNC; |
112 | dst_fd = xopen3(file_header->name, | 113 | dst_name = file_header->name; |
114 | #ifdef ARCHIVE_REPLACE_VIA_RENAME | ||
115 | if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) | ||
116 | /* rpm-style temp file name */ | ||
117 | dst_name = xasprintf("%s;%x", dst_name, (int)getpid()); | ||
118 | #endif | ||
119 | dst_fd = xopen3(dst_name, | ||
113 | flags, | 120 | flags, |
114 | file_header->mode | 121 | file_header->mode |
115 | ); | 122 | ); |
116 | bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); | 123 | bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); |
117 | close(dst_fd); | 124 | close(dst_fd); |
125 | #ifdef ARCHIVE_REPLACE_VIA_RENAME | ||
126 | if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) { | ||
127 | xrename(dst_name, file_header->name); | ||
128 | free(dst_name); | ||
129 | } | ||
130 | #endif | ||
118 | break; | 131 | break; |
119 | } | 132 | } |
120 | case S_IFDIR: | 133 | case S_IFDIR: |
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c index cfde8ea56..ca32bd82c 100644 --- a/archival/libarchive/decompress_unlzma.c +++ b/archival/libarchive/decompress_unlzma.c | |||
@@ -45,16 +45,16 @@ typedef struct { | |||
45 | #define RC_MODEL_TOTAL_BITS 11 | 45 | #define RC_MODEL_TOTAL_BITS 11 |
46 | 46 | ||
47 | 47 | ||
48 | /* Called twice: once at startup (LZMA_FAST only) and once in rc_normalize() */ | 48 | /* Called once in rc_do_normalize() */ |
49 | static size_inline void rc_read(rc_t *rc) | 49 | static void rc_read(rc_t *rc) |
50 | { | 50 | { |
51 | int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE); | 51 | int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE); |
52 | //TODO: return -1 instead | 52 | //TODO: return -1 instead |
53 | //This will make unlzma delete broken unpacked file on unpack errors | 53 | //This will make unlzma delete broken unpacked file on unpack errors |
54 | if (buffer_size <= 0) | 54 | if (buffer_size <= 0) |
55 | bb_error_msg_and_die("unexpected EOF"); | 55 | bb_error_msg_and_die("unexpected EOF"); |
56 | rc->ptr = RC_BUFFER; | ||
57 | rc->buffer_end = RC_BUFFER + buffer_size; | 56 | rc->buffer_end = RC_BUFFER + buffer_size; |
57 | rc->ptr = RC_BUFFER; | ||
58 | } | 58 | } |
59 | 59 | ||
60 | /* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */ | 60 | /* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */ |
@@ -65,6 +65,12 @@ static void rc_do_normalize(rc_t *rc) | |||
65 | rc->range <<= 8; | 65 | rc->range <<= 8; |
66 | rc->code = (rc->code << 8) | *rc->ptr++; | 66 | rc->code = (rc->code << 8) | *rc->ptr++; |
67 | } | 67 | } |
68 | static ALWAYS_INLINE void rc_normalize(rc_t *rc) | ||
69 | { | ||
70 | if (rc->range < (1 << RC_TOP_BITS)) { | ||
71 | rc_do_normalize(rc); | ||
72 | } | ||
73 | } | ||
68 | 74 | ||
69 | /* Called once */ | 75 | /* Called once */ |
70 | static ALWAYS_INLINE rc_t* rc_init(int fd) /*, int buffer_size) */ | 76 | static ALWAYS_INLINE rc_t* rc_init(int fd) /*, int buffer_size) */ |
@@ -78,15 +84,9 @@ static ALWAYS_INLINE rc_t* rc_init(int fd) /*, int buffer_size) */ | |||
78 | /* rc->ptr = rc->buffer_end; */ | 84 | /* rc->ptr = rc->buffer_end; */ |
79 | 85 | ||
80 | for (i = 0; i < 5; i++) { | 86 | for (i = 0; i < 5; i++) { |
81 | #if ENABLE_FEATURE_LZMA_FAST | ||
82 | if (rc->ptr >= rc->buffer_end) | ||
83 | rc_read(rc); | ||
84 | rc->code = (rc->code << 8) | *rc->ptr++; | ||
85 | #else | ||
86 | rc_do_normalize(rc); | 87 | rc_do_normalize(rc); |
87 | #endif | ||
88 | } | 88 | } |
89 | rc->range = 0xFFFFFFFF; | 89 | rc->range = 0xffffffff; |
90 | return rc; | 90 | return rc; |
91 | } | 91 | } |
92 | 92 | ||
@@ -96,13 +96,6 @@ static ALWAYS_INLINE void rc_free(rc_t *rc) | |||
96 | free(rc); | 96 | free(rc); |
97 | } | 97 | } |
98 | 98 | ||
99 | static ALWAYS_INLINE void rc_normalize(rc_t *rc) | ||
100 | { | ||
101 | if (rc->range < (1 << RC_TOP_BITS)) { | ||
102 | rc_do_normalize(rc); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | /* rc_is_bit_1 is called 9 times */ | 99 | /* rc_is_bit_1 is called 9 times */ |
107 | static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p) | 100 | static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p) |
108 | { | 101 | { |
@@ -120,7 +113,7 @@ static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p) | |||
120 | } | 113 | } |
121 | 114 | ||
122 | /* Called 4 times in unlzma loop */ | 115 | /* Called 4 times in unlzma loop */ |
123 | static speed_inline int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol) | 116 | static ALWAYS_INLINE int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol) |
124 | { | 117 | { |
125 | int ret = rc_is_bit_1(rc, p); | 118 | int ret = rc_is_bit_1(rc, p); |
126 | *symbol = *symbol * 2 + ret; | 119 | *symbol = *symbol * 2 + ret; |
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 79b48a152..986b7b191 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c | |||
@@ -30,8 +30,8 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) | |||
30 | /* We use arch-optimized unaligned accessors */ | 30 | /* We use arch-optimized unaligned accessors */ |
31 | #define get_unaligned_le32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_LE32(v); }) | 31 | #define get_unaligned_le32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_LE32(v); }) |
32 | #define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); }) | 32 | #define get_unaligned_be32(buf) ({ uint32_t v; move_from_unaligned32(v, buf); SWAP_BE32(v); }) |
33 | #define put_unaligned_le32(val, buf) move_to_unaligned16(buf, SWAP_LE32(val)) | 33 | #define put_unaligned_le32(val, buf) move_to_unaligned32(buf, SWAP_LE32(val)) |
34 | #define put_unaligned_be32(val, buf) move_to_unaligned16(buf, SWAP_BE32(val)) | 34 | #define put_unaligned_be32(val, buf) move_to_unaligned32(buf, SWAP_BE32(val)) |
35 | 35 | ||
36 | #include "unxz/xz_dec_bcj.c" | 36 | #include "unxz/xz_dec_bcj.c" |
37 | #include "unxz/xz_dec_lzma2.c" | 37 | #include "unxz/xz_dec_lzma2.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 | ||
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index f2edc2a2b..841e9dce9 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c | |||
@@ -35,6 +35,7 @@ void check_errors_in_children(int signo) | |||
35 | if (!signo) { | 35 | if (!signo) { |
36 | /* block waiting for any child */ | 36 | /* block waiting for any child */ |
37 | if (wait(&status) < 0) | 37 | if (wait(&status) < 0) |
38 | //FIXME: check EINTR? | ||
38 | return; /* probably there are no children */ | 39 | return; /* probably there are no children */ |
39 | goto check_status; | 40 | goto check_status; |
40 | } | 41 | } |
@@ -42,14 +43,18 @@ void check_errors_in_children(int signo) | |||
42 | /* Wait for any child without blocking */ | 43 | /* Wait for any child without blocking */ |
43 | for (;;) { | 44 | for (;;) { |
44 | if (wait_any_nohang(&status) < 0) | 45 | if (wait_any_nohang(&status) < 0) |
46 | //FIXME: check EINTR? | ||
45 | /* wait failed?! I'm confused... */ | 47 | /* wait failed?! I'm confused... */ |
46 | return; | 48 | return; |
47 | check_status: | 49 | check_status: |
48 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0) | 50 | /*if (WIFEXITED(status) && WEXITSTATUS(status) == 0)*/ |
51 | /* On Linux, the above can be checked simply as: */ | ||
52 | if (status == 0) | ||
49 | /* this child exited with 0 */ | 53 | /* this child exited with 0 */ |
50 | continue; | 54 | continue; |
51 | /* Cannot happen? | 55 | /* Cannot happen: |
52 | if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; */ | 56 | if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; |
57 | */ | ||
53 | bb_got_signal = 1; | 58 | bb_got_signal = 1; |
54 | } | 59 | } |
55 | } | 60 | } |
diff --git a/archival/libarchive/unxz/README b/archival/libarchive/unxz/README index c5972f6b8..a84912035 100644 --- a/archival/libarchive/unxz/README +++ b/archival/libarchive/unxz/README | |||
@@ -7,7 +7,7 @@ XZ Embedded | |||
7 | 7 | ||
8 | XZ Embedded was written for use in the Linux kernel, but the code can | 8 | XZ Embedded was written for use in the Linux kernel, but the code can |
9 | be easily used in other environments too, including regular userspace | 9 | be easily used in other environments too, including regular userspace |
10 | applications. | 10 | applications. See userspace/xzminidec.c for an example program. |
11 | 11 | ||
12 | This README contains information that is useful only when the copy | 12 | This README contains information that is useful only when the copy |
13 | of XZ Embedded isn't part of the Linux kernel tree. You should also | 13 | of XZ Embedded isn't part of the Linux kernel tree. You should also |
@@ -55,7 +55,7 @@ Compiler requirements | |||
55 | code is modified not to support large files, which needs some more | 55 | code is modified not to support large files, which needs some more |
56 | care than just using 32-bit integer instead of 64-bit). | 56 | care than just using 32-bit integer instead of 64-bit). |
57 | 57 | ||
58 | If you use GCC, try to use a recent version. For example, on x86, | 58 | If you use GCC, try to use a recent version. For example, on x86-32, |
59 | xz_dec_lzma2.c compiled with GCC 3.3.6 is 15-25 % slower than when | 59 | xz_dec_lzma2.c compiled with GCC 3.3.6 is 15-25 % slower than when |
60 | compiled with GCC 4.3.3. | 60 | compiled with GCC 4.3.3. |
61 | 61 | ||
@@ -93,7 +93,7 @@ BCJ filter support | |||
93 | them always #defined doesn't hurt either. | 93 | them always #defined doesn't hurt either. |
94 | 94 | ||
95 | #define Instruction set BCJ filter endianness | 95 | #define Instruction set BCJ filter endianness |
96 | XZ_DEC_X86 x86 or x86-64 Little endian only | 96 | XZ_DEC_X86 x86-32 or x86-64 Little endian only |
97 | XZ_DEC_POWERPC PowerPC Big endian only | 97 | XZ_DEC_POWERPC PowerPC Big endian only |
98 | XZ_DEC_IA64 Itanium (IA-64) Big or little endian | 98 | XZ_DEC_IA64 Itanium (IA-64) Big or little endian |
99 | XZ_DEC_ARM ARM Little endian only | 99 | XZ_DEC_ARM ARM Little endian only |
diff --git a/archival/libarchive/unxz/xz.h b/archival/libarchive/unxz/xz.h index c6c071c4a..e0b22db56 100644 --- a/archival/libarchive/unxz/xz.h +++ b/archival/libarchive/unxz/xz.h | |||
@@ -19,6 +19,10 @@ | |||
19 | # include <stdint.h> | 19 | # include <stdint.h> |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #ifdef __cplusplus | ||
23 | extern "C" { | ||
24 | #endif | ||
25 | |||
22 | /* In Linux, this is used to make extern functions static when needed. */ | 26 | /* In Linux, this is used to make extern functions static when needed. */ |
23 | #ifndef XZ_EXTERN | 27 | #ifndef XZ_EXTERN |
24 | # define XZ_EXTERN extern | 28 | # define XZ_EXTERN extern |
@@ -70,7 +74,7 @@ enum xz_mode { | |||
70 | * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding | 74 | * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding |
71 | * is still possible in multi-call mode by simply | 75 | * is still possible in multi-call mode by simply |
72 | * calling xz_dec_run() again. | 76 | * calling xz_dec_run() again. |
73 | * NOTE: This return value is used only if | 77 | * Note that this return value is used only if |
74 | * XZ_DEC_ANY_CHECK was defined at build time, | 78 | * XZ_DEC_ANY_CHECK was defined at build time, |
75 | * which is not used in the kernel. Unsupported | 79 | * which is not used in the kernel. Unsupported |
76 | * check types return XZ_OPTIONS_ERROR if | 80 | * check types return XZ_OPTIONS_ERROR if |
@@ -105,7 +109,7 @@ enum xz_mode { | |||
105 | * stream that is truncated or otherwise corrupt. | 109 | * stream that is truncated or otherwise corrupt. |
106 | * | 110 | * |
107 | * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer | 111 | * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer |
108 | * is too small, or the compressed input is corrupt in a way that makes the | 112 | * is too small or the compressed input is corrupt in a way that makes the |
109 | * decoder produce more output than the caller expected. When it is | 113 | * decoder produce more output than the caller expected. When it is |
110 | * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR | 114 | * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR |
111 | * is used instead of XZ_BUF_ERROR. | 115 | * is used instead of XZ_BUF_ERROR. |
@@ -207,8 +211,8 @@ XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init( | |||
207 | * The possible return values depend on build options and operation mode. | 211 | * The possible return values depend on build options and operation mode. |
208 | * See enum xz_ret for details. | 212 | * See enum xz_ret for details. |
209 | * | 213 | * |
210 | * NOTE: If an error occurs in single-call mode (return value is not | 214 | * Note that if an error occurs in single-call mode (return value is not |
211 | * XZ_STREAM_END), b->in_pos and b->out_pos are not modified, and the | 215 | * XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the |
212 | * contents of the output buffer from b->out[b->out_pos] onward are | 216 | * contents of the output buffer from b->out[b->out_pos] onward are |
213 | * undefined. This is true even after XZ_BUF_ERROR, because with some filter | 217 | * undefined. This is true even after XZ_BUF_ERROR, because with some filter |
214 | * chains, there may be a second pass over the output buffer, and this pass | 218 | * chains, there may be a second pass over the output buffer, and this pass |
@@ -268,4 +272,9 @@ XZ_EXTERN void XZ_FUNC xz_crc32_init(void); | |||
268 | XZ_EXTERN uint32_t XZ_FUNC xz_crc32( | 272 | XZ_EXTERN uint32_t XZ_FUNC xz_crc32( |
269 | const uint8_t *buf, size_t size, uint32_t crc); | 273 | const uint8_t *buf, size_t size, uint32_t crc); |
270 | #endif | 274 | #endif |
275 | |||
276 | #ifdef __cplusplus | ||
277 | } | ||
278 | #endif | ||
279 | |||
271 | #endif | 280 | #endif |
diff --git a/archival/libarchive/unxz/xz_dec_bcj.c b/archival/libarchive/unxz/xz_dec_bcj.c index 09162b51f..e0f913a94 100644 --- a/archival/libarchive/unxz/xz_dec_bcj.c +++ b/archival/libarchive/unxz/xz_dec_bcj.c | |||
@@ -77,10 +77,13 @@ struct xz_dec_bcj { | |||
77 | 77 | ||
78 | #ifdef XZ_DEC_X86 | 78 | #ifdef XZ_DEC_X86 |
79 | /* | 79 | /* |
80 | * This is macro used to test the most significant byte of a memory address | 80 | * This is used to test the most significant byte of a memory address |
81 | * in an x86 instruction. | 81 | * in an x86 instruction. |
82 | */ | 82 | */ |
83 | #define bcj_x86_test_msbyte(b) ((b) == 0x00 || (b) == 0xFF) | 83 | static inline int bcj_x86_test_msbyte(uint8_t b) |
84 | { | ||
85 | return b == 0x00 || b == 0xFF; | ||
86 | } | ||
84 | 87 | ||
85 | static noinline_for_stack size_t XZ_FUNC bcj_x86( | 88 | static noinline_for_stack size_t XZ_FUNC bcj_x86( |
86 | struct xz_dec_bcj *s, uint8_t *buf, size_t size) | 89 | struct xz_dec_bcj *s, uint8_t *buf, size_t size) |
@@ -443,8 +446,12 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s, | |||
443 | * next filter in the chain. Apply the BCJ filter on the new data | 446 | * next filter in the chain. Apply the BCJ filter on the new data |
444 | * in the output buffer. If everything cannot be filtered, copy it | 447 | * in the output buffer. If everything cannot be filtered, copy it |
445 | * to temp and rewind the output buffer position accordingly. | 448 | * to temp and rewind the output buffer position accordingly. |
449 | * | ||
450 | * This needs to be always run when temp.size == 0 to handle a special | ||
451 | * case where the output buffer is full and the next filter has no | ||
452 | * more output coming but hasn't returned XZ_STREAM_END yet. | ||
446 | */ | 453 | */ |
447 | if (s->temp.size < b->out_size - b->out_pos) { | 454 | if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) { |
448 | out_start = b->out_pos; | 455 | out_start = b->out_pos; |
449 | memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); | 456 | memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size); |
450 | b->out_pos += s->temp.size; | 457 | b->out_pos += s->temp.size; |
@@ -467,16 +474,25 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s, | |||
467 | s->temp.size = b->out_pos - out_start; | 474 | s->temp.size = b->out_pos - out_start; |
468 | b->out_pos -= s->temp.size; | 475 | b->out_pos -= s->temp.size; |
469 | memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); | 476 | memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size); |
477 | |||
478 | /* | ||
479 | * If there wasn't enough input to the next filter to fill | ||
480 | * the output buffer with unfiltered data, there's no point | ||
481 | * to try decoding more data to temp. | ||
482 | */ | ||
483 | if (b->out_pos + s->temp.size < b->out_size) | ||
484 | return XZ_OK; | ||
470 | } | 485 | } |
471 | 486 | ||
472 | /* | 487 | /* |
473 | * If we have unfiltered data in temp, try to fill by decoding more | 488 | * We have unfiltered data in temp. If the output buffer isn't full |
474 | * data from the next filter. Apply the BCJ filter on temp. Then we | 489 | * yet, try to fill the temp buffer by decoding more data from the |
475 | * hopefully can fill the actual output buffer by copying filtered | 490 | * next filter. Apply the BCJ filter on temp. Then we hopefully can |
476 | * data from temp. A mix of filtered and unfiltered data may be left | 491 | * fill the actual output buffer by copying filtered data from temp. |
477 | * in temp; it will be taken care on the next call to this function. | 492 | * A mix of filtered and unfiltered data may be left in temp; it will |
493 | * be taken care on the next call to this function. | ||
478 | */ | 494 | */ |
479 | if (s->temp.size > 0) { | 495 | if (b->out_pos < b->out_size) { |
480 | /* Make b->out{,_pos,_size} temporarily point to s->temp. */ | 496 | /* Make b->out{,_pos,_size} temporarily point to s->temp. */ |
481 | s->out = b->out; | 497 | s->out = b->out; |
482 | s->out_pos = b->out_pos; | 498 | s->out_pos = b->out_pos; |
diff --git a/archival/libarchive/unxz/xz_dec_lzma2.c b/archival/libarchive/unxz/xz_dec_lzma2.c index da71cb4d4..3c2dc88b7 100644 --- a/archival/libarchive/unxz/xz_dec_lzma2.c +++ b/archival/libarchive/unxz/xz_dec_lzma2.c | |||
@@ -407,7 +407,6 @@ static void XZ_FUNC dict_uncompressed( | |||
407 | 407 | ||
408 | b->out_pos += copy_size; | 408 | b->out_pos += copy_size; |
409 | b->in_pos += copy_size; | 409 | b->in_pos += copy_size; |
410 | |||
411 | } | 410 | } |
412 | } | 411 | } |
413 | 412 | ||
@@ -972,6 +971,9 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | |||
972 | */ | 971 | */ |
973 | tmp = b->in[b->in_pos++]; | 972 | tmp = b->in[b->in_pos++]; |
974 | 973 | ||
974 | if (tmp == 0x00) | ||
975 | return XZ_STREAM_END; | ||
976 | |||
975 | if (tmp >= 0xE0 || tmp == 0x01) { | 977 | if (tmp >= 0xE0 || tmp == 0x01) { |
976 | s->lzma2.need_props = true; | 978 | s->lzma2.need_props = true; |
977 | s->lzma2.need_dict_reset = false; | 979 | s->lzma2.need_dict_reset = false; |
@@ -1004,9 +1006,6 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( | |||
1004 | lzma_reset(s); | 1006 | lzma_reset(s); |
1005 | } | 1007 | } |
1006 | } else { | 1008 | } else { |
1007 | if (tmp == 0x00) | ||
1008 | return XZ_STREAM_END; | ||
1009 | |||
1010 | if (tmp > 0x02) | 1009 | if (tmp > 0x02) |
1011 | return XZ_DATA_ERROR; | 1010 | return XZ_DATA_ERROR; |
1012 | 1011 | ||
diff --git a/archival/libarchive/unxz/xz_stream.h b/archival/libarchive/unxz/xz_stream.h index 36f2a7cbf..66cb5a705 100644 --- a/archival/libarchive/unxz/xz_stream.h +++ b/archival/libarchive/unxz/xz_stream.h | |||
@@ -25,15 +25,20 @@ | |||
25 | 25 | ||
26 | #define STREAM_HEADER_SIZE 12 | 26 | #define STREAM_HEADER_SIZE 12 |
27 | 27 | ||
28 | #define HEADER_MAGIC "\3757zXZ\0" | 28 | #define HEADER_MAGIC "\3757zXZ" |
29 | #define HEADER_MAGIC_SIZE 6 | 29 | #define HEADER_MAGIC_SIZE 6 |
30 | 30 | ||
31 | #define FOOTER_MAGIC "YZ" | 31 | #define FOOTER_MAGIC "YZ" |
32 | #define FOOTER_MAGIC_SIZE 2 | 32 | #define FOOTER_MAGIC_SIZE 2 |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Variable-length integer can hold a 63-bit unsigned integer, or a special | 35 | * Variable-length integer can hold a 63-bit unsigned integer or a special |
36 | * value to indicate that the value is unknown. | 36 | * value indicating that the value is unknown. |
37 | * | ||
38 | * Experimental: vli_type can be defined to uint32_t to save a few bytes | ||
39 | * in code size (no effect on speed). Doing so limits the uncompressed and | ||
40 | * compressed size of the file to less than 256 MiB and may also weaken | ||
41 | * error detection slightly. | ||
37 | */ | 42 | */ |
38 | typedef uint64_t vli_type; | 43 | typedef uint64_t vli_type; |
39 | 44 | ||
diff --git a/archival/lzop.c b/archival/lzop.c index 56003d421..9b42e5fd3 100644 --- a/archival/lzop.c +++ b/archival/lzop.c | |||
@@ -436,25 +436,27 @@ struct globals { | |||
436 | //#define LZOP_VERSION_STRING "1.01" | 436 | //#define LZOP_VERSION_STRING "1.01" |
437 | //#define LZOP_VERSION_DATE "Apr 27th 2003" | 437 | //#define LZOP_VERSION_DATE "Apr 27th 2003" |
438 | 438 | ||
439 | #define OPTION_STRING "cfvdt123456789CF" | 439 | #define OPTION_STRING "cfvqdt123456789CF" |
440 | 440 | ||
441 | /* Note: must be kept in sync with archival/bbunzip.c */ | ||
441 | enum { | 442 | enum { |
442 | OPT_STDOUT = (1 << 0), | 443 | OPT_STDOUT = (1 << 0), |
443 | OPT_FORCE = (1 << 1), | 444 | OPT_FORCE = (1 << 1), |
444 | OPT_VERBOSE = (1 << 2), | 445 | OPT_VERBOSE = (1 << 2), |
445 | OPT_DECOMPRESS = (1 << 3), | 446 | OPT_QUIET = (1 << 3), |
446 | OPT_TEST = (1 << 4), | 447 | OPT_DECOMPRESS = (1 << 4), |
447 | OPT_1 = (1 << 5), | 448 | OPT_TEST = (1 << 5), |
448 | OPT_2 = (1 << 6), | 449 | OPT_1 = (1 << 6), |
449 | OPT_3 = (1 << 7), | 450 | OPT_2 = (1 << 7), |
450 | OPT_4 = (1 << 8), | 451 | OPT_3 = (1 << 8), |
451 | OPT_5 = (1 << 9), | 452 | OPT_4 = (1 << 9), |
452 | OPT_6 = (1 << 10), | 453 | OPT_5 = (1 << 10), |
453 | OPT_789 = (7 << 11), | 454 | OPT_6 = (1 << 11), |
454 | OPT_7 = (1 << 11), | 455 | OPT_789 = (7 << 12), |
455 | OPT_8 = (1 << 12), | 456 | OPT_7 = (1 << 13), |
456 | OPT_C = (1 << 14), | 457 | OPT_8 = (1 << 14), |
457 | OPT_F = (1 << 15), | 458 | OPT_C = (1 << 15), |
459 | OPT_F = (1 << 16), | ||
458 | }; | 460 | }; |
459 | 461 | ||
460 | /**********************************************************************/ | 462 | /**********************************************************************/ |
@@ -1093,7 +1095,7 @@ int lzop_main(int argc UNUSED_PARAM, char **argv) | |||
1093 | if (applet_name[4] == 'c') | 1095 | if (applet_name[4] == 'c') |
1094 | option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS); | 1096 | option_mask32 |= (OPT_STDOUT | OPT_DECOMPRESS); |
1095 | /* unlzop? */ | 1097 | /* unlzop? */ |
1096 | if (applet_name[0] == 'u') | 1098 | if (applet_name[4] == 'o') |
1097 | option_mask32 |= OPT_DECOMPRESS; | 1099 | option_mask32 |= OPT_DECOMPRESS; |
1098 | 1100 | ||
1099 | global_crc32_table = crc32_filltable(NULL, 0); | 1101 | global_crc32_table = crc32_filltable(NULL, 0); |
diff --git a/archival/rpm.c b/archival/rpm.c index 6757a6ceb..86ba4dca4 100644 --- a/archival/rpm.c +++ b/archival/rpm.c | |||
@@ -14,10 +14,10 @@ | |||
14 | //usage: "\nCommands:" | 14 | //usage: "\nCommands:" |
15 | //usage: "\n -i Install package" | 15 | //usage: "\n -i Install package" |
16 | //usage: "\n -qp Query package" | 16 | //usage: "\n -qp Query package" |
17 | //usage: "\n -i Show information" | 17 | //usage: "\n -qpi Show information" |
18 | //usage: "\n -l List contents" | 18 | //usage: "\n -qpl List contents" |
19 | //usage: "\n -d List documents" | 19 | //usage: "\n -qpd List documents" |
20 | //usage: "\n -c List config files" | 20 | //usage: "\n -qpc List config files" |
21 | 21 | ||
22 | #include "libbb.h" | 22 | #include "libbb.h" |
23 | #include "bb_archive.h" | 23 | #include "bb_archive.h" |
@@ -79,136 +79,13 @@ typedef struct { | |||
79 | uint32_t count; /* 4 byte count */ | 79 | uint32_t count; /* 4 byte count */ |
80 | } rpm_index; | 80 | } rpm_index; |
81 | 81 | ||
82 | static void *map; | 82 | struct globals { |
83 | static rpm_index **mytags; | 83 | void *map; |
84 | static int tagcount; | 84 | rpm_index **mytags; |
85 | 85 | int tagcount; | |
86 | static void extract_cpio(int fd, const char *source_rpm); | 86 | } FIX_ALIASING; |
87 | static rpm_index **rpm_gettags(int fd, int *num_tags); | 87 | #define G (*(struct globals*)&bb_common_bufsiz1) |
88 | static int bsearch_rpmtag(const void *key, const void *item); | 88 | #define INIT_G() do { } while (0) |
89 | static char *rpm_getstr(int tag, int itemindex); | ||
90 | static int rpm_getint(int tag, int itemindex); | ||
91 | static int rpm_getcount(int tag); | ||
92 | static void fileaction_dobackup(char *filename, int fileref); | ||
93 | static void fileaction_setowngrp(char *filename, int fileref); | ||
94 | static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)); | ||
95 | |||
96 | int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
97 | int rpm_main(int argc, char **argv) | ||
98 | { | ||
99 | int opt = 0, func = 0, rpm_fd, offset; | ||
100 | const int pagesize = getpagesize(); | ||
101 | |||
102 | while ((opt = getopt(argc, argv, "iqpldc")) != -1) { | ||
103 | switch (opt) { | ||
104 | case 'i': /* First arg: Install mode, with q: Information */ | ||
105 | if (!func) func = rpm_install; | ||
106 | else func |= rpm_query_info; | ||
107 | break; | ||
108 | case 'q': /* First arg: Query mode */ | ||
109 | if (func) bb_show_usage(); | ||
110 | func = rpm_query; | ||
111 | break; | ||
112 | case 'p': /* Query a package */ | ||
113 | func |= rpm_query_package; | ||
114 | break; | ||
115 | case 'l': /* List files in a package */ | ||
116 | func |= rpm_query_list; | ||
117 | break; | ||
118 | case 'd': /* List doc files in a package (implies list) */ | ||
119 | func |= rpm_query_list; | ||
120 | func |= rpm_query_list_doc; | ||
121 | break; | ||
122 | case 'c': /* List config files in a package (implies list) */ | ||
123 | func |= rpm_query_list; | ||
124 | func |= rpm_query_list_config; | ||
125 | break; | ||
126 | default: | ||
127 | bb_show_usage(); | ||
128 | } | ||
129 | } | ||
130 | argv += optind; | ||
131 | //argc -= optind; | ||
132 | if (!argv[0]) { | ||
133 | bb_show_usage(); | ||
134 | } | ||
135 | |||
136 | while (*argv) { | ||
137 | const char *source_rpm; | ||
138 | |||
139 | rpm_fd = xopen(*argv++, O_RDONLY); | ||
140 | mytags = rpm_gettags(rpm_fd, &tagcount); | ||
141 | if (!mytags) | ||
142 | bb_error_msg_and_die("error reading rpm header"); | ||
143 | offset = xlseek(rpm_fd, 0, SEEK_CUR); | ||
144 | /* Mimimum is one page */ | ||
145 | map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); | ||
146 | |||
147 | source_rpm = rpm_getstr(TAG_SOURCERPM, 0); | ||
148 | |||
149 | if (func & rpm_install) { | ||
150 | /* Backup any config files */ | ||
151 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); | ||
152 | /* Extact the archive */ | ||
153 | extract_cpio(rpm_fd, source_rpm); | ||
154 | /* Set the correct file uid/gid's */ | ||
155 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); | ||
156 | } | ||
157 | else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) { | ||
158 | if (!(func & (rpm_query_info|rpm_query_list))) { | ||
159 | /* If just a straight query, just give package name */ | ||
160 | printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0)); | ||
161 | } | ||
162 | if (func & rpm_query_info) { | ||
163 | /* Do the nice printout */ | ||
164 | time_t bdate_time; | ||
165 | struct tm *bdate_ptm; | ||
166 | char bdatestring[50]; | ||
167 | const char *p; | ||
168 | |||
169 | p = rpm_getstr(TAG_PREFIXS, 0); | ||
170 | if (!p) p = "(not relocateable)"; | ||
171 | printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p); | ||
172 | p = rpm_getstr(TAG_VENDOR, 0); | ||
173 | if (!p) p = "(none)"; | ||
174 | printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p); | ||
175 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); | ||
176 | bdate_ptm = localtime(&bdate_time); | ||
177 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); | ||
178 | printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); | ||
179 | printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); | ||
180 | printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm); | ||
181 | printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); | ||
182 | printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); | ||
183 | printf("Summary : %s\n", rpm_getstr(TAG_SUMMARY, 0)); | ||
184 | printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0)); | ||
185 | } | ||
186 | if (func & rpm_query_list) { | ||
187 | int count, it, flags; | ||
188 | count = rpm_getcount(TAG_BASENAMES); | ||
189 | for (it = 0; it < count; it++) { | ||
190 | flags = rpm_getint(TAG_FILEFLAGS, it); | ||
191 | switch (func & (rpm_query_list_doc|rpm_query_list_config)) { | ||
192 | case rpm_query_list_doc: | ||
193 | if (!(flags & RPMFILE_DOC)) continue; | ||
194 | break; | ||
195 | case rpm_query_list_config: | ||
196 | if (!(flags & RPMFILE_CONFIG)) continue; | ||
197 | break; | ||
198 | case rpm_query_list_doc|rpm_query_list_config: | ||
199 | if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue; | ||
200 | break; | ||
201 | } | ||
202 | printf("%s%s\n", | ||
203 | rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)), | ||
204 | rpm_getstr(TAG_BASENAMES, it)); | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | free(mytags); | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | 89 | ||
213 | static void extract_cpio(int fd, const char *source_rpm) | 90 | static void extract_cpio(int fd, const char *source_rpm) |
214 | { | 91 | { |
@@ -231,8 +108,8 @@ static void extract_cpio(int fd, const char *source_rpm) | |||
231 | /* compat: overwrite existing files. | 108 | /* compat: overwrite existing files. |
232 | * try "rpm -i foo.src.rpm" few times in a row - | 109 | * try "rpm -i foo.src.rpm" few times in a row - |
233 | * standard rpm will not complain. | 110 | * standard rpm will not complain. |
234 | * (TODO? real rpm creates "file;1234" and then renames it) */ | 111 | */ |
235 | | ARCHIVE_UNLINK_OLD; | 112 | | ARCHIVE_REPLACE_VIA_RENAME; |
236 | archive_handle->src_fd = fd; | 113 | archive_handle->src_fd = fd; |
237 | /*archive_handle->offset = 0; - init_handle() did it */ | 114 | /*archive_handle->offset = 0; - init_handle() did it */ |
238 | 115 | ||
@@ -294,7 +171,7 @@ static int bsearch_rpmtag(const void *key, const void *item) | |||
294 | static int rpm_getcount(int tag) | 171 | static int rpm_getcount(int tag) |
295 | { | 172 | { |
296 | rpm_index **found; | 173 | rpm_index **found; |
297 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 174 | found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
298 | if (!found) | 175 | if (!found) |
299 | return 0; | 176 | return 0; |
300 | return found[0]->count; | 177 | return found[0]->count; |
@@ -303,7 +180,7 @@ static int rpm_getcount(int tag) | |||
303 | static char *rpm_getstr(int tag, int itemindex) | 180 | static char *rpm_getstr(int tag, int itemindex) |
304 | { | 181 | { |
305 | rpm_index **found; | 182 | rpm_index **found; |
306 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 183 | found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
307 | if (!found || itemindex >= found[0]->count) | 184 | if (!found || itemindex >= found[0]->count) |
308 | return NULL; | 185 | return NULL; |
309 | if (found[0]->type == RPM_STRING_TYPE | 186 | if (found[0]->type == RPM_STRING_TYPE |
@@ -311,7 +188,7 @@ static char *rpm_getstr(int tag, int itemindex) | |||
311 | || found[0]->type == RPM_STRING_ARRAY_TYPE | 188 | || found[0]->type == RPM_STRING_ARRAY_TYPE |
312 | ) { | 189 | ) { |
313 | int n; | 190 | int n; |
314 | char *tmpstr = (char *) map + found[0]->offset; | 191 | char *tmpstr = (char *) G.map + found[0]->offset; |
315 | for (n = 0; n < itemindex; n++) | 192 | for (n = 0; n < itemindex; n++) |
316 | tmpstr = tmpstr + strlen(tmpstr) + 1; | 193 | tmpstr = tmpstr + strlen(tmpstr) + 1; |
317 | return tmpstr; | 194 | return tmpstr; |
@@ -322,32 +199,25 @@ static char *rpm_getstr(int tag, int itemindex) | |||
322 | static int rpm_getint(int tag, int itemindex) | 199 | static int rpm_getint(int tag, int itemindex) |
323 | { | 200 | { |
324 | rpm_index **found; | 201 | rpm_index **found; |
325 | int *tmpint; /* NB: using int8_t* would be easier to code */ | 202 | char *tmpint; |
326 | 203 | ||
327 | /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... | 204 | /* gcc throws warnings here when sizeof(void*)!=sizeof(int) ... |
328 | * it's ok to ignore it because tag won't be used as a pointer */ | 205 | * it's ok to ignore it because tag won't be used as a pointer */ |
329 | found = bsearch(&tag, mytags, tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); | 206 | found = bsearch(&tag, G.mytags, G.tagcount, sizeof(struct rpmtag *), bsearch_rpmtag); |
330 | if (!found || itemindex >= found[0]->count) | 207 | if (!found || itemindex >= found[0]->count) |
331 | return -1; | 208 | return -1; |
332 | 209 | ||
333 | tmpint = (int *) ((char *) map + found[0]->offset); | 210 | tmpint = (char *) G.map + found[0]->offset; |
334 | |||
335 | if (found[0]->type == RPM_INT32_TYPE) { | 211 | if (found[0]->type == RPM_INT32_TYPE) { |
336 | tmpint = (int *) ((char *) tmpint + itemindex*4); | 212 | tmpint += itemindex*4; |
337 | /*return ntohl(*tmpint);*/ | ||
338 | /* int can be != int32_t */ | ||
339 | return ntohl(*(int32_t*)tmpint); | 213 | return ntohl(*(int32_t*)tmpint); |
340 | } | 214 | } |
341 | if (found[0]->type == RPM_INT16_TYPE) { | 215 | if (found[0]->type == RPM_INT16_TYPE) { |
342 | tmpint = (int *) ((char *) tmpint + itemindex*2); | 216 | tmpint += itemindex*2; |
343 | /* ??? read int, and THEN ntohs() it?? */ | ||
344 | /*return ntohs(*tmpint);*/ | ||
345 | return ntohs(*(int16_t*)tmpint); | 217 | return ntohs(*(int16_t*)tmpint); |
346 | } | 218 | } |
347 | if (found[0]->type == RPM_INT8_TYPE) { | 219 | if (found[0]->type == RPM_INT8_TYPE) { |
348 | tmpint = (int *) ((char *) tmpint + itemindex); | 220 | tmpint += itemindex; |
349 | /* ??? why we don't read byte here??? */ | ||
350 | /*return ntohs(*tmpint);*/ | ||
351 | return *(int8_t*)tmpint; | 221 | return *(int8_t*)tmpint; |
352 | } | 222 | } |
353 | return -1; | 223 | return -1; |
@@ -392,3 +262,134 @@ static void loop_through_files(int filetag, void (*fileaction)(char *filename, i | |||
392 | free(filename); | 262 | free(filename); |
393 | } | 263 | } |
394 | } | 264 | } |
265 | |||
266 | int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
267 | int rpm_main(int argc, char **argv) | ||
268 | { | ||
269 | int opt, func = 0; | ||
270 | const unsigned pagesize = getpagesize(); | ||
271 | |||
272 | while ((opt = getopt(argc, argv, "iqpldc")) != -1) { | ||
273 | switch (opt) { | ||
274 | case 'i': /* First arg: Install mode, with q: Information */ | ||
275 | if (!func) func = rpm_install; | ||
276 | else func |= rpm_query_info; | ||
277 | break; | ||
278 | case 'q': /* First arg: Query mode */ | ||
279 | if (func) bb_show_usage(); | ||
280 | func = rpm_query; | ||
281 | break; | ||
282 | case 'p': /* Query a package */ | ||
283 | func |= rpm_query_package; | ||
284 | break; | ||
285 | case 'l': /* List files in a package */ | ||
286 | func |= rpm_query_list; | ||
287 | break; | ||
288 | case 'd': /* List doc files in a package (implies list) */ | ||
289 | func |= rpm_query_list; | ||
290 | func |= rpm_query_list_doc; | ||
291 | break; | ||
292 | case 'c': /* List config files in a package (implies list) */ | ||
293 | func |= rpm_query_list; | ||
294 | func |= rpm_query_list_config; | ||
295 | break; | ||
296 | default: | ||
297 | bb_show_usage(); | ||
298 | } | ||
299 | } | ||
300 | argv += optind; | ||
301 | //argc -= optind; | ||
302 | if (!argv[0]) { | ||
303 | bb_show_usage(); | ||
304 | } | ||
305 | |||
306 | while (*argv) { | ||
307 | int rpm_fd; | ||
308 | unsigned mapsize; | ||
309 | const char *source_rpm; | ||
310 | |||
311 | rpm_fd = xopen(*argv++, O_RDONLY); | ||
312 | G.mytags = rpm_gettags(rpm_fd, &G.tagcount); | ||
313 | if (!G.mytags) | ||
314 | bb_error_msg_and_die("error reading rpm header"); | ||
315 | mapsize = xlseek(rpm_fd, 0, SEEK_CUR); | ||
316 | mapsize = (mapsize + pagesize) & -(int)pagesize; | ||
317 | /* Some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */ | ||
318 | G.map = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); | ||
319 | //FIXME: error check? | ||
320 | |||
321 | source_rpm = rpm_getstr(TAG_SOURCERPM, 0); | ||
322 | |||
323 | if (func & rpm_install) { | ||
324 | /* Backup any config files */ | ||
325 | loop_through_files(TAG_BASENAMES, fileaction_dobackup); | ||
326 | /* Extact the archive */ | ||
327 | extract_cpio(rpm_fd, source_rpm); | ||
328 | /* Set the correct file uid/gid's */ | ||
329 | loop_through_files(TAG_BASENAMES, fileaction_setowngrp); | ||
330 | } | ||
331 | else if ((func & (rpm_query|rpm_query_package)) == (rpm_query|rpm_query_package)) { | ||
332 | if (!(func & (rpm_query_info|rpm_query_list))) { | ||
333 | /* If just a straight query, just give package name */ | ||
334 | printf("%s-%s-%s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_RELEASE, 0)); | ||
335 | } | ||
336 | if (func & rpm_query_info) { | ||
337 | /* Do the nice printout */ | ||
338 | time_t bdate_time; | ||
339 | struct tm *bdate_ptm; | ||
340 | char bdatestring[50]; | ||
341 | const char *p; | ||
342 | |||
343 | printf("%-12s: %s\n", "Name" , rpm_getstr(TAG_NAME, 0)); | ||
344 | /* TODO compat: add "Epoch" here */ | ||
345 | printf("%-12s: %s\n", "Version" , rpm_getstr(TAG_VERSION, 0)); | ||
346 | printf("%-12s: %s\n", "Release" , rpm_getstr(TAG_RELEASE, 0)); | ||
347 | /* add "Architecture" */ | ||
348 | printf("%-12s: %s\n", "Install Date", "(not installed)"); | ||
349 | printf("%-12s: %s\n", "Group" , rpm_getstr(TAG_GROUP, 0)); | ||
350 | printf("%-12s: %d\n", "Size" , rpm_getint(TAG_SIZE, 0)); | ||
351 | printf("%-12s: %s\n", "License" , rpm_getstr(TAG_LICENSE, 0)); | ||
352 | /* add "Signature" */ | ||
353 | printf("%-12s: %s\n", "Source RPM" , source_rpm ? source_rpm : "(none)"); | ||
354 | bdate_time = rpm_getint(TAG_BUILDTIME, 0); | ||
355 | bdate_ptm = localtime(&bdate_time); | ||
356 | strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); | ||
357 | printf("%-12s: %s\n", "Build Date" , bdatestring); | ||
358 | printf("%-12s: %s\n", "Build Host" , rpm_getstr(TAG_BUILDHOST, 0)); | ||
359 | p = rpm_getstr(TAG_PREFIXS, 0); | ||
360 | printf("%-12s: %s\n", "Relocations" , p ? p : "(not relocatable)"); | ||
361 | /* add "Packager" */ | ||
362 | p = rpm_getstr(TAG_VENDOR, 0); | ||
363 | printf("%-12s: %s\n", "Vendor" , p ? p : "(none)"); | ||
364 | printf("%-12s: %s\n", "URL" , rpm_getstr(TAG_URL, 0)); | ||
365 | printf("%-12s: %s\n", "Summary" , rpm_getstr(TAG_SUMMARY, 0)); | ||
366 | printf("Description :\n%s\n", rpm_getstr(TAG_DESCRIPTION, 0)); | ||
367 | } | ||
368 | if (func & rpm_query_list) { | ||
369 | int count, it, flags; | ||
370 | count = rpm_getcount(TAG_BASENAMES); | ||
371 | for (it = 0; it < count; it++) { | ||
372 | flags = rpm_getint(TAG_FILEFLAGS, it); | ||
373 | switch (func & (rpm_query_list_doc|rpm_query_list_config)) { | ||
374 | case rpm_query_list_doc: | ||
375 | if (!(flags & RPMFILE_DOC)) continue; | ||
376 | break; | ||
377 | case rpm_query_list_config: | ||
378 | if (!(flags & RPMFILE_CONFIG)) continue; | ||
379 | break; | ||
380 | case rpm_query_list_doc|rpm_query_list_config: | ||
381 | if (!(flags & (RPMFILE_CONFIG|RPMFILE_DOC))) continue; | ||
382 | break; | ||
383 | } | ||
384 | printf("%s%s\n", | ||
385 | rpm_getstr(TAG_DIRNAMES, rpm_getint(TAG_DIRINDEXES, it)), | ||
386 | rpm_getstr(TAG_BASENAMES, it)); | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | munmap(G.map, mapsize); | ||
391 | free(G.mytags); | ||
392 | close(rpm_fd); | ||
393 | } | ||
394 | return 0; | ||
395 | } | ||