File unzip-optional-support-for-bzip2-and-lzma.patch of Package busybox.20467

From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon Jan 9 10:58:37 2017 +0100
Subject: unzip: optional support for bzip2 and lzma
Patch-mainline: 2a0867a5ed277e4c3cf4c5e17e539d225286ef07
Git-repo: https://git.busybox.net/busybox
Git-commit: 7f09b0d73e4f94bf027f44cb33cb452f6ede1810
References: 

function                                             old     new   delta
unzip_main                                          2376    2476    +100
bbunpack                                             750     745      -5

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Egbert Eich <eich@suse.de>
---
 archival/bbunzip.c             |  2 +-
 archival/libarchive/Kbuild.src |  2 +
 archival/unzip.c               | 93 ++++++++++++++++++++++++++----------------
 3 files changed, 61 insertions(+), 36 deletions(-)
diff --git a/archival/bbunzip.c b/archival/bbunzip.c
index 60a837e22..6c2d2c6d8 100644
--- a/archival/bbunzip.c
+++ b/archival/bbunzip.c
@@ -127,7 +127,7 @@ int FAST_FUNC bbunpack(char **argv,
 
 		if (!(option_mask32 & SEAMLESS_MAGIC)) {
 			init_transformer_state(&xstate);
-			xstate.signature_skipped = 0;
+			/*xstate.signature_skipped = 0; - already is */
 			/*xstate.src_fd = STDIN_FILENO; - already is */
 			xstate.dst_fd = STDOUT_FILENO;
 			status = unpacker(&xstate);
diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src
index ad5c5c42d..84117fa85 100644
--- a/archival/libarchive/Kbuild.src
+++ b/archival/libarchive/Kbuild.src
@@ -53,9 +53,11 @@ lib-$(CONFIG_LZOPCAT)                   += lzo1x_1.o lzo1x_1o.o lzo1x_d.o
 lib-$(CONFIG_LZOP_COMPR_HIGH)           += lzo1x_9x.o
 lib-$(CONFIG_BUNZIP2)                   += open_transformer.o decompress_bunzip2.o
 lib-$(CONFIG_BZCAT)                     += open_transformer.o decompress_bunzip2.o
+lib-$(CONFIG_FEATURE_UNZIP_BZIP2)       += open_transformer.o decompress_bunzip2.o
 lib-$(CONFIG_UNLZMA)                    += open_transformer.o decompress_unlzma.o
 lib-$(CONFIG_LZCAT)                     += open_transformer.o decompress_unlzma.o
 lib-$(CONFIG_LZMA)                      += open_transformer.o decompress_unlzma.o
+lib-$(CONFIG_FEATURE_UNZIP_LZMA)        += open_transformer.o decompress_unlzma.o
 lib-$(CONFIG_UNXZ)                      += open_transformer.o decompress_unxz.o
 lib-$(CONFIG_XZCAT)                     += open_transformer.o decompress_unxz.o
 lib-$(CONFIG_XZ)                        += open_transformer.o decompress_unxz.o
diff --git a/archival/unzip.c b/archival/unzip.c
index caef7ce8c..48fde4813 100644
--- a/archival/unzip.c
+++ b/archival/unzip.c
@@ -34,6 +34,18 @@
 //config:	  ZIP files without deleted/updated files, SFX archves etc,
 //config:	  you can reduce code size by unselecting this option.
 //config:	  To support less trivial ZIPs, say Y.
+//config:
+//config:config FEATURE_UNZIP_BZIP2
+//config:	bool "Support compression method 12 (bzip2)"
+//config:	default y
+//config:	depends on FEATURE_UNZIP_CDF && DESKTOP
+// FEATURE_UNZIP_CDF is needed, otherwise we can't find start of next file
+// DESKTOP is needed to get back uncompressed length
+//config:
+//config:config FEATURE_UNZIP_LZMA
+//config:	bool "Support compression method 14 (lzma)"
+//config:	default y
+//config:	depends on FEATURE_UNZIP_CDF && DESKTOP
 
 //applet:IF_UNZIP(APPLET(unzip, BB_DIR_USR_BIN, BB_SUID_DROP))
 //kbuild:lib-$(CONFIG_UNZIP) += unzip.o
@@ -319,32 +331,57 @@ static void unzip_create_leading_dirs(const char *fn)
 
 static void unzip_extract(zip_header_t *zip, int dst_fd)
 {
+	transformer_state_t xstate;
+
 	if (zip->fmt.method == 0) {
 		/* Method 0 - stored (not compressed) */
 		off_t size = zip->fmt.ucmpsize;
 		if (size)
 			bb_copyfd_exact_size(zip_fd, dst_fd, size);
-	} else {
+		return;
+	}
+
+	init_transformer_state(&xstate);
+	xstate.bytes_in = zip->fmt.cmpsize;
+	xstate.src_fd = zip_fd;
+	xstate.dst_fd = dst_fd;
+	if (zip->fmt.method == 8) {
 		/* Method 8 - inflate */
-		transformer_state_t xstate;
-		init_transformer_state(&xstate);
-		xstate.bytes_in = zip->fmt.cmpsize;
-		xstate.src_fd = zip_fd;
-		xstate.dst_fd = dst_fd;
 		if (inflate_unzip(&xstate) < 0)
 			bb_error_msg_and_die("inflate error");
 		/* Validate decompression - crc */
 		if (zip->fmt.crc32 != (xstate.crc32 ^ 0xffffffffL)) {
 			bb_error_msg_and_die("crc error");
 		}
-		/* Validate decompression - size */
-		if (zip->fmt.ucmpsize != xstate.bytes_out) {
-			/* Don't die. Who knows, maybe len calculation
-			 * was botched somewhere. After all, crc matched! */
-			bb_error_msg("bad length");
-		}
 	}
-	/* TODO? method 12: bzip2, method 14: LZMA */
+#if ENABLE_FEATURE_UNZIP_BZIP2
+	else if (zip->fmt.method == 12) {
+		/* Tested. Unpacker reads too much, but we use CDF
+		 * and will seek to the correct beginning of next file.
+		 */
+		xstate.bytes_out = unpack_bz2_stream(&xstate);
+		if (xstate.bytes_out < 0)
+			bb_error_msg_and_die("inflate error");
+	}
+#endif
+#if ENABLE_FEATURE_UNZIP_LZMA
+	else if (zip->fmt.method == 14) {
+		/* Not tested yet */
+		xstate.bytes_out = unpack_lzma_stream(&xstate);
+		if (xstate.bytes_out < 0)
+			bb_error_msg_and_die("inflate error");
+	}
+#endif
+	else {
+		bb_error_msg_and_die("unsupported method %u", zip->fmt.method);
+	}
+
+	/* Validate decompression - size */
+	if (zip->fmt.ucmpsize != xstate.bytes_out) {
+		/* Don't die. Who knows, maybe len calculation
+		 * was botched somewhere. After all, crc matched! */
+		bb_error_msg("bad length");
+	}
 }
 
 static void my_fgets80(char *buf80)
@@ -609,12 +646,6 @@ int unzip_main(int argc, char **argv)
 
 			xread(zip_fd, zip.raw, ZIP_HEADER_LEN);
 			FIX_ENDIANNESS_ZIP(zip);
-			if ((zip.fmt.method != 0)
-			 && (zip.fmt.method != 8)
-			) {
-				/* TODO? method 12: bzip2, method 14: LZMA */
-				bb_error_msg_and_die("unsupported method %d", zip.fmt.method);
-			}
 			if (zip.fmt.zip_flags & SWAP_LE16(0x0009)) {
 				bb_error_msg_and_die("zip flags 1 and 8 are not supported");
 			}
@@ -704,7 +735,11 @@ int unzip_main(int argc, char **argv)
 						dtbuf,
 						dst_fn);
 				} else {
-					unsigned long percents = zip.fmt.ucmpsize - zip.fmt.cmpsize;
+					char method6[7];
+					unsigned long percents;
+
+					sprintf(method6, "%6u", zip.fmt.method);
+					percents = zip.fmt.ucmpsize - zip.fmt.cmpsize;
 					if ((int32_t)percents < 0)
 						percents = 0; /* happens if ucmpsize < cmpsize */
 					percents = percents * 100;
@@ -714,21 +749,9 @@ int unzip_main(int argc, char **argv)
 					//      "--------  ------  ------- ---- ---------- ----- --------  ----"
 					printf(      "%8u  %s"        "%9u%4u%% " "%s "         "%08x  "  "%s\n",
 						(unsigned)zip.fmt.ucmpsize,
-						zip.fmt.method == 0 ? "Stored" : "Defl:N", /* Defl is method 8 */
-/* TODO: show other methods?
- *  1 - Shrunk
- *  2 - Reduced with compression factor 1
- *  3 - Reduced with compression factor 2
- *  4 - Reduced with compression factor 3
- *  5 - Reduced with compression factor 4
- *  6 - Imploded
- *  7 - Reserved for Tokenizing compression algorithm
- *  9 - Deflate64
- * 10 - PKWARE Data Compression Library Imploding
- * 11 - Reserved by PKWARE
- * 12 - BZIP2
- * 14 - LZMA
- */
+						zip.fmt.method == 0 ? "Stored"
+						: zip.fmt.method == 8 ? "Defl:N"
+						: method6,
 						(unsigned)zip.fmt.cmpsize,
 						(unsigned)percents,
 						dtbuf,
openSUSE Build Service is sponsored by