summaryrefslogtreecommitdiff
path: root/archival/libarchive
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-23 12:12:03 +0000
committerRon Yorston <rmy@pobox.com>2012-03-23 12:12:03 +0000
commitb0f54743e36af163ae2530c381c485bb29df13dc (patch)
treecda4cfeaae6e47fe4f14c1b566092be4da9affc4 /archival/libarchive
parent40514a0309939f2446f0d4ed9600cad5de396e7f (diff)
parentba88826c66411affc1da3614742b454654f7298a (diff)
downloadbusybox-w32-b0f54743e36af163ae2530c381c485bb29df13dc.tar.gz
busybox-w32-b0f54743e36af163ae2530c381c485bb29df13dc.tar.bz2
busybox-w32-b0f54743e36af163ae2530c381c485bb29df13dc.zip
Merge branch 'busybox' into merge
Conflicts: Makefile.flags
Diffstat (limited to 'archival/libarchive')
-rw-r--r--archival/libarchive/Kbuild.src21
-rw-r--r--archival/libarchive/data_extract_all.c8
-rw-r--r--archival/libarchive/data_extract_to_command.c8
-rw-r--r--archival/libarchive/decompress_bunzip2.c18
-rw-r--r--archival/libarchive/decompress_gunzip.c (renamed from archival/libarchive/decompress_unzip.c)69
-rw-r--r--archival/libarchive/decompress_uncompress.c15
-rw-r--r--archival/libarchive/decompress_unlzma.c2
-rw-r--r--archival/libarchive/decompress_unxz.c12
-rw-r--r--archival/libarchive/get_header_tar.c100
-rw-r--r--archival/libarchive/get_header_tar_bz2.c2
-rw-r--r--archival/libarchive/get_header_tar_gz.c17
-rw-r--r--archival/libarchive/get_header_tar_lzma.c2
-rw-r--r--archival/libarchive/open_transformer.c193
13 files changed, 309 insertions, 158 deletions
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index b0bc4e5aa..39c18f264 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -28,10 +28,13 @@ COMMON_FILES:= \
28 init_handle.o 28 init_handle.o
29 29
30DPKG_FILES:= \ 30DPKG_FILES:= \
31 get_header_ar.o \
32 unpack_ar_archive.o \ 31 unpack_ar_archive.o \
32 filter_accept_list_reassign.o \
33 get_header_ar.o \
33 get_header_tar.o \ 34 get_header_tar.o \
34 filter_accept_list_reassign.o 35 get_header_tar_gz.o \
36 get_header_tar_bz2.o \
37 get_header_tar_lzma.o \
35 38
36INSERT 39INSERT
37 40
@@ -42,18 +45,18 @@ lib-$(CONFIG_UNXZ) += decompress_unxz.o
42lib-$(CONFIG_CPIO) += get_header_cpio.o 45lib-$(CONFIG_CPIO) += get_header_cpio.o
43lib-$(CONFIG_DPKG) += $(DPKG_FILES) 46lib-$(CONFIG_DPKG) += $(DPKG_FILES)
44lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) 47lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES)
45lib-$(CONFIG_GUNZIP) += decompress_unzip.o 48lib-$(CONFIG_GUNZIP) += decompress_gunzip.o
46lib-$(CONFIG_RPM2CPIO) += decompress_unzip.o get_header_cpio.o 49lib-$(CONFIG_RPM2CPIO) += decompress_gunzip.o get_header_cpio.o
47lib-$(CONFIG_RPM) += open_transformer.o decompress_unzip.o get_header_cpio.o 50lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o
48lib-$(CONFIG_TAR) += get_header_tar.o 51lib-$(CONFIG_TAR) += get_header_tar.o
49lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o 52lib-$(CONFIG_UNCOMPRESS) += decompress_uncompress.o
50lib-$(CONFIG_UNZIP) += decompress_unzip.o 53lib-$(CONFIG_UNZIP) += decompress_gunzip.o
51lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o 54lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
52lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o 55lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o
53lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o 56lib-$(CONFIG_FEATURE_SEAMLESS_Z) += open_transformer.o decompress_uncompress.o
54lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_unzip.o get_header_tar_gz.o 57lib-$(CONFIG_FEATURE_SEAMLESS_GZ) += open_transformer.o decompress_gunzip.o
55lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o get_header_tar_bz2.o 58lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2.o
56lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o 59lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o
57lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o 60lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
58lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o 61lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
59lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += decompress_bunzip2.o 62lib-$(CONFIG_FEATURE_COMPRESS_BBCONFIG) += decompress_bunzip2.o
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c
index f565e5471..3f67b835f 100644
--- a/archival/libarchive/data_extract_all.c
+++ b/archival/libarchive/data_extract_all.c
@@ -13,13 +13,13 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
13 int res; 13 int res;
14 14
15#if ENABLE_FEATURE_TAR_SELINUX 15#if ENABLE_FEATURE_TAR_SELINUX
16 char *sctx = archive_handle->tar__next_file_sctx; 16 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
17 if (!sctx) 17 if (!sctx)
18 sctx = archive_handle->tar__global_sctx; 18 sctx = archive_handle->tar__sctx[PAX_GLOBAL];
19 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ 19 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
20 setfscreatecon(sctx); 20 setfscreatecon(sctx);
21 free(archive_handle->tar__next_file_sctx); 21 free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
22 archive_handle->tar__next_file_sctx = NULL; 22 archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
23 } 23 }
24#endif 24#endif
25 25
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index cc2ff7798..a2ce33b51 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -64,13 +64,13 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
64 file_header_t *file_header = archive_handle->file_header; 64 file_header_t *file_header = archive_handle->file_header;
65 65
66#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */ 66#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
67 char *sctx = archive_handle->tar__next_file_sctx; 67 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
68 if (!sctx) 68 if (!sctx)
69 sctx = archive_handle->tar__global_sctx; 69 sctx = archive_handle->tar__sctx[PAX_GLOBAL];
70 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ 70 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
71 setfscreatecon(sctx); 71 setfscreatecon(sctx);
72 free(archive_handle->tar__next_file_sctx); 72 free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
73 archive_handle->tar__next_file_sctx = NULL; 73 archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
74 } 74 }
75#endif 75#endif
76 76
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
index c4640d489..dc252bb82 100644
--- a/archival/libarchive/decompress_bunzip2.c
+++ b/archival/libarchive/decompress_bunzip2.c
@@ -721,7 +721,7 @@ void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
721 721
722/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ 722/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */
723IF_DESKTOP(long long) int FAST_FUNC 723IF_DESKTOP(long long) int FAST_FUNC
724unpack_bz2_stream(int src_fd, int dst_fd) 724unpack_bz2_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
725{ 725{
726 IF_DESKTOP(long long total_written = 0;) 726 IF_DESKTOP(long long total_written = 0;)
727 bunzip_data *bd; 727 bunzip_data *bd;
@@ -729,6 +729,9 @@ unpack_bz2_stream(int src_fd, int dst_fd)
729 int i; 729 int i;
730 unsigned len; 730 unsigned len;
731 731
732 if (check_signature16(aux, src_fd, BZIP2_MAGIC))
733 return -1;
734
732 outbuf = xmalloc(IOBUF_SIZE); 735 outbuf = xmalloc(IOBUF_SIZE);
733 len = 0; 736 len = 0;
734 while (1) { /* "Process one BZ... stream" loop */ 737 while (1) { /* "Process one BZ... stream" loop */
@@ -794,17 +797,6 @@ unpack_bz2_stream(int src_fd, int dst_fd)
794 return i ? i : IF_DESKTOP(total_written) + 0; 797 return i ? i : IF_DESKTOP(total_written) + 0;
795} 798}
796 799
797IF_DESKTOP(long long) int FAST_FUNC
798unpack_bz2_stream_prime(int src_fd, int dst_fd)
799{
800 uint16_t magic2;
801 xread(src_fd, &magic2, 2);
802 if (magic2 != BZIP2_MAGIC) {
803 bb_error_msg_and_die("invalid magic");
804 }
805 return unpack_bz2_stream(src_fd, dst_fd);
806}
807
808#ifdef TESTING 800#ifdef TESTING
809 801
810static char *const bunzip_errors[] = { 802static char *const bunzip_errors[] = {
@@ -819,7 +811,7 @@ int main(int argc, char **argv)
819 int i; 811 int i;
820 char c; 812 char c;
821 813
822 int i = unpack_bz2_stream_prime(0, 1); 814 int i = unpack_bz2_stream(0, 1);
823 if (i < 0) 815 if (i < 0)
824 fprintf(stderr, "%s\n", bunzip_errors[-i]); 816 fprintf(stderr, "%s\n", bunzip_errors[-i]);
825 else if (read(STDIN_FILENO, &c, 1)) 817 else if (read(STDIN_FILENO, &c, 1))
diff --git a/archival/libarchive/decompress_unzip.c b/archival/libarchive/decompress_gunzip.c
index aa5d22d0a..2d5ab3eb3 100644
--- a/archival/libarchive/decompress_unzip.c
+++ b/archival/libarchive/decompress_gunzip.c
@@ -1034,22 +1034,22 @@ inflate_unzip_internal(STATE_PARAM int in, int out)
1034/* For unzip */ 1034/* For unzip */
1035 1035
1036IF_DESKTOP(long long) int FAST_FUNC 1036IF_DESKTOP(long long) int FAST_FUNC
1037inflate_unzip(inflate_unzip_result *res, off_t compr_size, int in, int out) 1037inflate_unzip(transformer_aux_data_t *aux, int in, int out)
1038{ 1038{
1039 IF_DESKTOP(long long) int n; 1039 IF_DESKTOP(long long) int n;
1040 DECLARE_STATE; 1040 DECLARE_STATE;
1041 1041
1042 ALLOC_STATE; 1042 ALLOC_STATE;
1043 1043
1044 to_read = compr_size; 1044 to_read = aux->bytes_in;
1045// bytebuffer_max = 0x8000; 1045// bytebuffer_max = 0x8000;
1046 bytebuffer_offset = 4; 1046 bytebuffer_offset = 4;
1047 bytebuffer = xmalloc(bytebuffer_max); 1047 bytebuffer = xmalloc(bytebuffer_max);
1048 n = inflate_unzip_internal(PASS_STATE in, out); 1048 n = inflate_unzip_internal(PASS_STATE in, out);
1049 free(bytebuffer); 1049 free(bytebuffer);
1050 1050
1051 res->crc = gunzip_crc; 1051 aux->crc32 = gunzip_crc;
1052 res->bytes_out = gunzip_bytes_out; 1052 aux->bytes_out = gunzip_bytes_out;
1053 DEALLOC_STATE; 1053 DEALLOC_STATE;
1054 return n; 1054 return n;
1055} 1055}
@@ -1107,7 +1107,7 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY)
1107 return res; 1107 return res;
1108} 1108}
1109 1109
1110static int check_header_gzip(STATE_PARAM unpack_info_t *info) 1110static int check_header_gzip(STATE_PARAM transformer_aux_data_t *aux)
1111{ 1111{
1112 union { 1112 union {
1113 unsigned char raw[8]; 1113 unsigned char raw[8];
@@ -1169,8 +1169,8 @@ static int check_header_gzip(STATE_PARAM unpack_info_t *info)
1169 } 1169 }
1170 } 1170 }
1171 1171
1172 if (info) 1172 if (aux)
1173 info->mtime = SWAP_LE32(header.formatted.mtime); 1173 aux->mtime = SWAP_LE32(header.formatted.mtime);
1174 1174
1175 /* Read the header checksum */ 1175 /* Read the header checksum */
1176 if (header.formatted.flags & 0x02) { 1176 if (header.formatted.flags & 0x02) {
@@ -1182,33 +1182,58 @@ 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(transformer_aux_data_t *aux, int src_fd, int dst_fd)
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#if !ENABLE_FEATURE_SEAMLESS_Z
1192 if (check_signature16(aux, src_fd, GZIP_MAGIC))
1193 return -1;
1194#else
1195 if (aux && aux->check_signature) {
1196 uint16_t magic2;
1197
1198 if (full_read(src_fd, &magic2, 2) != 2) {
1199 bad_magic:
1200 bb_error_msg("invalid magic");
1201 return -1;
1202 }
1203 if (magic2 == COMPRESS_MAGIC) {
1204 aux->check_signature = 0;
1205 return unpack_Z_stream(aux, src_fd, dst_fd);
1206 }
1207 if (magic2 != GZIP_MAGIC)
1208 goto bad_magic;
1209 }
1210#endif
1211
1212 total = 0;
1192 1213
1193 ALLOC_STATE; 1214 ALLOC_STATE;
1194 to_read = -1; 1215 to_read = -1;
1195// bytebuffer_max = 0x8000; 1216// bytebuffer_max = 0x8000;
1196 bytebuffer = xmalloc(bytebuffer_max); 1217 bytebuffer = xmalloc(bytebuffer_max);
1197 gunzip_src_fd = in; 1218 gunzip_src_fd = src_fd;
1198 1219
1199 again: 1220 again:
1200 if (!check_header_gzip(PASS_STATE info)) { 1221 if (!check_header_gzip(PASS_STATE aux)) {
1201 bb_error_msg("corrupted data"); 1222 bb_error_msg("corrupted data");
1202 n = -1; 1223 total = -1;
1203 goto ret; 1224 goto ret;
1204 } 1225 }
1205 n += inflate_unzip_internal(PASS_STATE in, out); 1226
1206 if (n < 0) 1227 n = inflate_unzip_internal(PASS_STATE src_fd, dst_fd);
1228 if (n < 0) {
1229 total = -1;
1207 goto ret; 1230 goto ret;
1231 }
1232 total += n;
1208 1233
1209 if (!top_up(PASS_STATE 8)) { 1234 if (!top_up(PASS_STATE 8)) {
1210 bb_error_msg("corrupted data"); 1235 bb_error_msg("corrupted data");
1211 n = -1; 1236 total = -1;
1212 goto ret; 1237 goto ret;
1213 } 1238 }
1214 1239
@@ -1216,7 +1241,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1216 v32 = buffer_read_le_u32(PASS_STATE_ONLY); 1241 v32 = buffer_read_le_u32(PASS_STATE_ONLY);
1217 if ((~gunzip_crc) != v32) { 1242 if ((~gunzip_crc) != v32) {
1218 bb_error_msg("crc error"); 1243 bb_error_msg("crc error");
1219 n = -1; 1244 total = -1;
1220 goto ret; 1245 goto ret;
1221 } 1246 }
1222 1247
@@ -1224,7 +1249,7 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1224 v32 = buffer_read_le_u32(PASS_STATE_ONLY); 1249 v32 = buffer_read_le_u32(PASS_STATE_ONLY);
1225 if ((uint32_t)gunzip_bytes_out != v32) { 1250 if ((uint32_t)gunzip_bytes_out != v32) {
1226 bb_error_msg("incorrect length"); 1251 bb_error_msg("incorrect length");
1227 n = -1; 1252 total = -1;
1228 } 1253 }
1229 1254
1230 if (!top_up(PASS_STATE 2)) 1255 if (!top_up(PASS_STATE 2))
@@ -1242,11 +1267,5 @@ unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
1242 ret: 1267 ret:
1243 free(bytebuffer); 1268 free(bytebuffer);
1244 DEALLOC_STATE; 1269 DEALLOC_STATE;
1245 return n; 1270 return total;
1246}
1247
1248IF_DESKTOP(long long) int FAST_FUNC
1249unpack_gz_stream(int in, int out)
1250{
1251 return unpack_gz_stream_with_info(in, out, NULL);
1252} 1271}
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c
index c6040d04b..e9bbfb9bd 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(transformer_aux_data_t *aux, 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;
@@ -103,16 +103,19 @@ unpack_Z_stream(int fd_in, int fd_out)
103 /* block compress mode -C compatible with 2.0 */ 103 /* block compress mode -C compatible with 2.0 */
104 int block_mode; /* = BLOCK_MODE; */ 104 int block_mode; /* = BLOCK_MODE; */
105 105
106 if (check_signature16(aux, src_fd, COMPRESS_MAGIC))
107 return -1;
108
106 inbuf = xzalloc(IBUFSIZ + 64); 109 inbuf = xzalloc(IBUFSIZ + 64);
107 outbuf = xzalloc(OBUFSIZ + 2048); 110 outbuf = xzalloc(OBUFSIZ + 2048);
108 htab = xzalloc(HSIZE); /* wsn't zeroed out before, maybe can xmalloc? */ 111 htab = xzalloc(HSIZE); /* wasn't zeroed out before, maybe can xmalloc? */
109 codetab = xzalloc(HSIZE * sizeof(codetab[0])); 112 codetab = xzalloc(HSIZE * sizeof(codetab[0]));
110 113
111 insize = 0; 114 insize = 0;
112 115
113 /* xread isn't good here, we have to return - caller may want 116 /* xread isn't good here, we have to return - caller may want
114 * to do some cleanup (e.g. delete incomplete unpacked file etc) */ 117 * to do some cleanup (e.g. delete incomplete unpacked file etc) */
115 if (full_read(fd_in, inbuf, 1) != 1) { 118 if (full_read(src_fd, inbuf, 1) != 1) {
116 bb_error_msg("short read"); 119 bb_error_msg("short read");
117 goto err; 120 goto err;
118 } 121 }
@@ -162,7 +165,7 @@ unpack_Z_stream(int fd_in, int fd_out)
162 } 165 }
163 166
164 if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) { 167 if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
165 rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ); 168 rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ);
166 if (rsize < 0) 169 if (rsize < 0)
167 bb_error_msg_and_die(bb_msg_read_error); 170 bb_error_msg_and_die(bb_msg_read_error);
168 insize += rsize; 171 insize += rsize;
@@ -268,7 +271,7 @@ unpack_Z_stream(int fd_in, int fd_out)
268 } 271 }
269 272
270 if (outpos >= OBUFSIZ) { 273 if (outpos >= OBUFSIZ) {
271 xwrite(fd_out, outbuf, outpos); 274 xwrite(dst_fd, outbuf, outpos);
272 IF_DESKTOP(total_written += outpos;) 275 IF_DESKTOP(total_written += outpos;)
273 outpos = 0; 276 outpos = 0;
274 } 277 }
@@ -296,7 +299,7 @@ unpack_Z_stream(int fd_in, int fd_out)
296 } while (rsize > 0); 299 } while (rsize > 0);
297 300
298 if (outpos > 0) { 301 if (outpos > 0) {
299 xwrite(fd_out, outbuf, outpos); 302 xwrite(dst_fd, outbuf, outpos);
300 IF_DESKTOP(total_written += outpos;) 303 IF_DESKTOP(total_written += outpos;)
301 } 304 }
302 305
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
index 3631b50cc..cfde8ea56 100644
--- a/archival/libarchive/decompress_unlzma.c
+++ b/archival/libarchive/decompress_unlzma.c
@@ -213,7 +213,7 @@ enum {
213 213
214 214
215IF_DESKTOP(long long) int FAST_FUNC 215IF_DESKTOP(long long) int FAST_FUNC
216unpack_lzma_stream(int src_fd, int dst_fd) 216unpack_lzma_stream(transformer_aux_data_t *aux UNUSED_PARAM, int src_fd, int dst_fd)
217{ 217{
218 IF_DESKTOP(long long total_written = 0;) 218 IF_DESKTOP(long long total_written = 0;)
219 lzma_header_t header; 219 lzma_header_t header;
diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c
index 3e5d4edca..79b48a152 100644
--- a/archival/libarchive/decompress_unxz.c
+++ b/archival/libarchive/decompress_unxz.c
@@ -38,7 +38,7 @@ static uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
38#include "unxz/xz_dec_stream.c" 38#include "unxz/xz_dec_stream.c"
39 39
40IF_DESKTOP(long long) int FAST_FUNC 40IF_DESKTOP(long long) int FAST_FUNC
41unpack_xz_stream(int src_fd, int dst_fd) 41unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
42{ 42{
43 struct xz_buf iobuf; 43 struct xz_buf iobuf;
44 struct xz_dec *state; 44 struct xz_dec *state;
@@ -49,13 +49,17 @@ unpack_xz_stream(int src_fd, int dst_fd)
49 global_crc32_table = crc32_filltable(NULL, /*endian:*/ 0); 49 global_crc32_table = crc32_filltable(NULL, /*endian:*/ 0);
50 50
51 memset(&iobuf, 0, sizeof(iobuf)); 51 memset(&iobuf, 0, sizeof(iobuf));
52 /* Preload XZ file signature */ 52 membuf = xmalloc(2 * BUFSIZ);
53 membuf = (void*) strcpy(xmalloc(2 * BUFSIZ), HEADER_MAGIC);
54 iobuf.in = membuf; 53 iobuf.in = membuf;
55 iobuf.in_size = HEADER_MAGIC_SIZE;
56 iobuf.out = membuf + BUFSIZ; 54 iobuf.out = membuf + BUFSIZ;
57 iobuf.out_size = BUFSIZ; 55 iobuf.out_size = BUFSIZ;
58 56
57 if (!aux || aux->check_signature == 0) {
58 /* Preload XZ file signature */
59 strcpy((char*)membuf, HEADER_MAGIC);
60 iobuf.in_size = HEADER_MAGIC_SIZE;
61 } /* else: let xz code read & check it */
62
59 /* Limit memory usage to about 64 MiB. */ 63 /* Limit memory usage to about 64 MiB. */
60 state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024); 64 state = xz_dec_init(XZ_DYNALLOC, 64*1024*1024);
61 65
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index a63c0fb01..80a709144 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -90,23 +90,20 @@ static unsigned long long getOctal(char *str, int len)
90} 90}
91#define GET_OCTAL(a) getOctal((a), sizeof(a)) 91#define GET_OCTAL(a) getOctal((a), sizeof(a))
92 92
93#if ENABLE_FEATURE_TAR_SELINUX 93/* "global" is 0 or 1 */
94/* Scan a PAX header for SELinux contexts, via "RHT.security.selinux" keyword. 94static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int global)
95 * This is what Red Hat's patched version of tar uses.
96 */
97# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
98static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, unsigned sz)
99{ 95{
100 char *buf, *p; 96 char *buf, *p;
101 char *result; 97 unsigned blk_sz;
98
99 blk_sz = (sz + 511) & (~511);
100 p = buf = xmalloc(blk_sz + 1);
101 xread(archive_handle->src_fd, buf, blk_sz);
102 archive_handle->offset += blk_sz;
102 103
103 p = buf = xmalloc(sz + 1);
104 /* prevent bb_strtou from running off the buffer */ 104 /* prevent bb_strtou from running off the buffer */
105 buf[sz] = '\0'; 105 buf[sz] = '\0';
106 xread(archive_handle->src_fd, buf, sz);
107 archive_handle->offset += sz;
108 106
109 result = NULL;
110 while (sz != 0) { 107 while (sz != 0) {
111 char *end, *value; 108 char *end, *value;
112 unsigned len; 109 unsigned len;
@@ -133,19 +130,33 @@ static char *get_selinux_sctx_from_pax_hdr(archive_handle_t *archive_handle, uns
133 * (we do not bother to check that it *was* a newline) 130 * (we do not bother to check that it *was* a newline)
134 */ 131 */
135 p[-1] = '\0'; 132 p[-1] = '\0';
136 /* Is it selinux security context? */
137 value = end + 1; 133 value = end + 1;
134
135#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
136 if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) {
137 value += sizeof("path=") - 1;
138 free(archive_handle->tar__longname);
139 archive_handle->tar__longname = xstrdup(value);
140 continue;
141 }
142#endif
143
144#if ENABLE_FEATURE_TAR_SELINUX
145 /* Scan for SELinux contexts, via "RHT.security.selinux" keyword.
146 * This is what Red Hat's patched version of tar uses.
147 */
148# define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux"
138 if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) { 149 if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) {
139 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; 150 value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1;
140 result = xstrdup(value); 151 free(archive_handle->tar__sctx[global]);
141 break; 152 archive_handle->tar__sctx[global] = xstrdup(value);
153 continue;
142 } 154 }
155#endif
143 } 156 }
144 157
145 free(buf); 158 free(buf);
146 return result;
147} 159}
148#endif
149 160
150char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) 161char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
151{ 162{
@@ -224,43 +235,18 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
224 || memcmp(tar.magic, "\0\0\0\0", 5) != 0) 235 || memcmp(tar.magic, "\0\0\0\0", 5) != 0)
225 ) { 236 ) {
226#if ENABLE_FEATURE_TAR_AUTODETECT 237#if ENABLE_FEATURE_TAR_AUTODETECT
227 char FAST_FUNC (*get_header_ptr)(archive_handle_t *);
228 uint16_t magic2;
229
230 autodetect: 238 autodetect:
231 magic2 = *(bb__aliased_uint16_t*)tar.name;
232 /* tar gz/bz autodetect: check for gz/bz2 magic.
233 * If we see the magic, and it is the very first block,
234 * we can switch to get_header_tar_gz/bz2/lzma().
235 * Needs seekable fd. I wish recv(MSG_PEEK) works
236 * on any fd... */
237# if ENABLE_FEATURE_SEAMLESS_GZ
238 if (magic2 == GZIP_MAGIC) {
239 get_header_ptr = get_header_tar_gz;
240 } else
241# endif
242# if ENABLE_FEATURE_SEAMLESS_BZ2
243 if (magic2 == BZIP2_MAGIC
244 && tar.name[2] == 'h' && isdigit(tar.name[3])
245 ) { /* bzip2 */
246 get_header_ptr = get_header_tar_bz2;
247 } else
248# endif
249# if ENABLE_FEATURE_SEAMLESS_XZ
250 //TODO: if (magic2 == XZ_MAGIC1)...
251 //else
252# endif
253 goto err;
254 /* Two different causes for lseek() != 0: 239 /* Two different causes for lseek() != 0:
255 * unseekable fd (would like to support that too, but...), 240 * unseekable fd (would like to support that too, but...),
256 * or not first block (false positive, it's not .gz/.bz2!) */ 241 * or not first block (false positive, it's not .gz/.bz2!) */
257 if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0) 242 if (lseek(archive_handle->src_fd, -i, SEEK_CUR) != 0)
258 goto err; 243 goto err;
259 while (get_header_ptr(archive_handle) == EXIT_SUCCESS) 244 if (setup_unzip_on_fd(archive_handle->src_fd, /*fail_if_not_detected:*/ 0) != 0)
260 continue;
261 return EXIT_FAILURE;
262 err: 245 err:
263#endif /* FEATURE_TAR_AUTODETECT */ 246 bb_error_msg_and_die("invalid tar magic");
247 archive_handle->offset = 0;
248 goto again_after_align;
249#endif
264 bb_error_msg_and_die("invalid tar magic"); 250 bb_error_msg_and_die("invalid tar magic");
265 } 251 }
266 252
@@ -418,12 +404,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
418 case 'S': /* Sparse file */ 404 case 'S': /* Sparse file */
419 case 'V': /* Volume header */ 405 case 'V': /* Volume header */
420#endif 406#endif
421#if !ENABLE_FEATURE_TAR_SELINUX
422 case 'g': /* pax global header */ 407 case 'g': /* pax global header */
423 case 'x': /* pax extended header */ 408 case 'x': { /* pax extended header */
424#else 409 if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
410 goto skip_ext_hdr;
411 process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g'));
412 goto again_after_align;
413 }
425 skip_ext_hdr: 414 skip_ext_hdr:
426#endif
427 { 415 {
428 off_t sz; 416 off_t sz;
429 bb_error_msg("warning: skipping header '%c'", tar.typeflag); 417 bb_error_msg("warning: skipping header '%c'", tar.typeflag);
@@ -435,18 +423,6 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
435 /* return get_header_tar(archive_handle); */ 423 /* return get_header_tar(archive_handle); */
436 goto again_after_align; 424 goto again_after_align;
437 } 425 }
438#if ENABLE_FEATURE_TAR_SELINUX
439 case 'g': /* pax global header */
440 case 'x': { /* pax extended header */
441 char **pp;
442 if ((uoff_t)file_header->size > 0xfffff) /* paranoia */
443 goto skip_ext_hdr;
444 pp = (tar.typeflag == 'g') ? &archive_handle->tar__global_sctx : &archive_handle->tar__next_file_sctx;
445 free(*pp);
446 *pp = get_selinux_sctx_from_pax_hdr(archive_handle, file_header->size);
447 goto again;
448 }
449#endif
450 default: 426 default:
451 bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag); 427 bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
452 } 428 }
diff --git a/archival/libarchive/get_header_tar_bz2.c b/archival/libarchive/get_header_tar_bz2.c
index e012dec3b..0ee00df53 100644
--- a/archival/libarchive/get_header_tar_bz2.c
+++ b/archival/libarchive/get_header_tar_bz2.c
@@ -11,7 +11,7 @@ char FAST_FUNC get_header_tar_bz2(archive_handle_t *archive_handle)
11 /* Can't lseek over pipes */ 11 /* Can't lseek over pipes */
12 archive_handle->seek = seek_by_read; 12 archive_handle->seek = seek_by_read;
13 13
14 open_transformer(archive_handle->src_fd, unpack_bz2_stream_prime, "bunzip2"); 14 open_transformer_with_sig(archive_handle->src_fd, unpack_bz2_stream, "bunzip2");
15 archive_handle->offset = 0; 15 archive_handle->offset = 0;
16 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 16 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
17 continue; 17 continue;
diff --git a/archival/libarchive/get_header_tar_gz.c b/archival/libarchive/get_header_tar_gz.c
index b9679b0bd..03284342b 100644
--- a/archival/libarchive/get_header_tar_gz.c
+++ b/archival/libarchive/get_header_tar_gz.c
@@ -8,25 +8,10 @@
8 8
9char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle) 9char FAST_FUNC get_header_tar_gz(archive_handle_t *archive_handle)
10{ 10{
11#if BB_MMU
12 uint16_t magic;
13#endif
14
15 /* Can't lseek over pipes */ 11 /* Can't lseek over pipes */
16 archive_handle->seek = seek_by_read; 12 archive_handle->seek = seek_by_read;
17 13
18 /* Check gzip magic only if open_transformer will invoke unpack_gz_stream (MMU case). 14 open_transformer_with_sig(archive_handle->src_fd, unpack_gz_stream, "gunzip");
19 * Otherwise, it will invoke an external helper "gunzip -cf" (NOMMU case) which will
20 * need the header. */
21#if BB_MMU
22 xread(archive_handle->src_fd, &magic, 2);
23 /* Can skip this check, but error message will be less clear */
24 if (magic != GZIP_MAGIC) {
25 bb_error_msg_and_die("invalid gzip magic");
26 }
27#endif
28
29 open_transformer(archive_handle->src_fd, unpack_gz_stream, "gunzip");
30 archive_handle->offset = 0; 15 archive_handle->offset = 0;
31 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 16 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
32 continue; 17 continue;
diff --git a/archival/libarchive/get_header_tar_lzma.c b/archival/libarchive/get_header_tar_lzma.c
index 666700729..d565a217d 100644
--- a/archival/libarchive/get_header_tar_lzma.c
+++ b/archival/libarchive/get_header_tar_lzma.c
@@ -14,7 +14,7 @@ char FAST_FUNC get_header_tar_lzma(archive_handle_t *archive_handle)
14 /* Can't lseek over pipes */ 14 /* Can't lseek over pipes */
15 archive_handle->seek = seek_by_read; 15 archive_handle->seek = seek_by_read;
16 16
17 open_transformer(archive_handle->src_fd, unpack_lzma_stream, "unlzma"); 17 open_transformer_with_sig(archive_handle->src_fd, unpack_lzma_stream, "unlzma");
18 archive_handle->offset = 0; 18 archive_handle->offset = 0;
19 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 19 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
20 continue; 20 continue;
diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c
index aa8c1021c..f2edc2a2b 100644
--- a/archival/libarchive/open_transformer.c
+++ b/archival/libarchive/open_transformer.c
@@ -6,14 +6,64 @@
6#include "libbb.h" 6#include "libbb.h"
7#include "bb_archive.h" 7#include "bb_archive.h"
8 8
9void FAST_FUNC init_transformer_aux_data(transformer_aux_data_t *aux)
10{
11 memset(aux, 0, sizeof(*aux));
12}
13
14int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16)
15{
16 if (aux && aux->check_signature) {
17 uint16_t magic2;
18 if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) {
19 bb_error_msg("invalid magic");
20#if 0 /* possible future extension */
21 if (aux->check_signature > 1)
22 xfunc_die();
23#endif
24 return -1;
25 }
26 }
27 return 0;
28}
29
30#if !ENABLE_PLATFORM_MINGW32
31void check_errors_in_children(int signo)
32{
33 int status;
34
35 if (!signo) {
36 /* block waiting for any child */
37 if (wait(&status) < 0)
38 return; /* probably there are no children */
39 goto check_status;
40 }
41
42 /* Wait for any child without blocking */
43 for (;;) {
44 if (wait_any_nohang(&status) < 0)
45 /* wait failed?! I'm confused... */
46 return;
47 check_status:
48 if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
49 /* this child exited with 0 */
50 continue;
51 /* Cannot happen?
52 if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; */
53 bb_got_signal = 1;
54 }
55}
56#endif
57
9/* transformer(), more than meets the eye */ 58/* transformer(), more than meets the eye */
10/* 59#if BB_MMU
11 * On MMU machine, the transform_prog is removed by macro magic
12 * in include/archive.h. On NOMMU, transformer is removed.
13 */
14void FAST_FUNC open_transformer(int fd, 60void FAST_FUNC open_transformer(int fd,
15 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(int src_fd, int dst_fd), 61 int check_signature,
16 const char *transform_prog) 62 IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd)
63)
64#else
65void FAST_FUNC open_transformer(int fd, const char *transform_prog)
66#endif
17{ 67{
18 struct fd_pair fd_pipe; 68 struct fd_pair fd_pipe;
19 int pid; 69 int pid;
@@ -25,13 +75,18 @@ void FAST_FUNC open_transformer(int fd,
25 close(fd_pipe.rd); /* we don't want to read from the parent */ 75 close(fd_pipe.rd); /* we don't want to read from the parent */
26 // FIXME: error check? 76 // FIXME: error check?
27#if BB_MMU 77#if BB_MMU
28 transformer(fd, fd_pipe.wr); 78 {
29 if (ENABLE_FEATURE_CLEAN_UP) { 79 transformer_aux_data_t aux;
30 close(fd_pipe.wr); /* send EOF */ 80 init_transformer_aux_data(&aux);
31 close(fd); 81 aux.check_signature = check_signature;
82 transformer(&aux, fd, fd_pipe.wr);
83 if (ENABLE_FEATURE_CLEAN_UP) {
84 close(fd_pipe.wr); /* send EOF */
85 close(fd);
86 }
87 /* must be _exit! bug was actually seen here */
88 _exit(EXIT_SUCCESS);
32 } 89 }
33 /* must be _exit! bug was actually seen here */
34 _exit(EXIT_SUCCESS);
35#else 90#else
36 { 91 {
37 char *argv[4]; 92 char *argv[4];
@@ -52,3 +107,117 @@ void FAST_FUNC open_transformer(int fd,
52 close(fd_pipe.wr); /* don't want to write to the child */ 107 close(fd_pipe.wr); /* don't want to write to the child */
53 xmove_fd(fd_pipe.rd, fd); 108 xmove_fd(fd_pipe.rd, fd);
54} 109}
110
111
112#if SEAMLESS_COMPRESSION
113
114/* Used by e.g. rpm which gives us a fd without filename,
115 * thus we can't guess the format from filename's extension.
116 */
117int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_detected)
118{
119 union {
120 uint8_t b[4];
121 uint16_t b16[2];
122 uint32_t b32[1];
123 } magic;
124 int offset = -2;
125 USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
126 USE_FOR_NOMMU(const char *xformer_prog;)
127
128 /* .gz and .bz2 both have 2-byte signature, and their
129 * unpack_XXX_stream wants this header skipped. */
130 xread(fd, magic.b16, sizeof(magic.b16[0]));
131 if (ENABLE_FEATURE_SEAMLESS_GZ
132 && magic.b16[0] == GZIP_MAGIC
133 ) {
134 USE_FOR_MMU(xformer = unpack_gz_stream;)
135 USE_FOR_NOMMU(xformer_prog = "gunzip";)
136 goto found_magic;
137 }
138 if (ENABLE_FEATURE_SEAMLESS_BZ2
139 && magic.b16[0] == BZIP2_MAGIC
140 ) {
141 USE_FOR_MMU(xformer = unpack_bz2_stream;)
142 USE_FOR_NOMMU(xformer_prog = "bunzip2";)
143 goto found_magic;
144 }
145 if (ENABLE_FEATURE_SEAMLESS_XZ
146 && magic.b16[0] == XZ_MAGIC1
147 ) {
148 offset = -6;
149 xread(fd, magic.b32, sizeof(magic.b32[0]));
150 if (magic.b32[0] == XZ_MAGIC2) {
151 USE_FOR_MMU(xformer = unpack_xz_stream;)
152 USE_FOR_NOMMU(xformer_prog = "unxz";)
153 goto found_magic;
154 }
155 }
156
157 /* No known magic seen */
158 if (fail_if_not_detected)
159 bb_error_msg_and_die("no gzip"
160 IF_FEATURE_SEAMLESS_BZ2("/bzip2")
161 IF_FEATURE_SEAMLESS_XZ("/xz")
162 " magic");
163 xlseek(fd, offset, SEEK_CUR);
164 return 1;
165
166 found_magic:
167# if BB_MMU
168 open_transformer_with_no_sig(fd, xformer);
169# else
170 /* NOMMU version of open_transformer execs
171 * an external unzipper that wants
172 * file position at the start of the file */
173 xlseek(fd, offset, SEEK_CUR);
174 open_transformer_with_sig(fd, xformer, xformer_prog);
175# endif
176 return 0;
177}
178
179int FAST_FUNC open_zipped(const char *fname)
180{
181 char *sfx;
182 int fd;
183
184 fd = open(fname, O_RDONLY);
185 if (fd < 0)
186 return fd;
187
188 sfx = strrchr(fname, '.');
189 if (sfx) {
190 sfx++;
191 if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
192 /* .lzma has no header/signature, just trust it */
193 open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma");
194 else
195 if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
196 || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
197 || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
198 ) {
199 setup_unzip_on_fd(fd, /*fail_if_not_detected:*/ 1);
200 }
201 }
202
203 return fd;
204}
205
206#endif /* SEAMLESS_COMPRESSION */
207
208void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
209{
210 int fd;
211 char *image;
212
213 fd = open_zipped(fname);
214 if (fd < 0)
215 return NULL;
216
217 image = xmalloc_read(fd, maxsz_p);
218 if (!image)
219 bb_perror_msg("read error from '%s'", fname);
220 close(fd);
221
222 return image;
223}