libarchive: add capability to unpack to mem.buffer

The performance and number of processes for a "depmod -a" with gzipped
modules was abysmal. This patch adds a code path without fork,
benefiting all users of xmalloc_open_zipped_read_close.

"modinfo radeon.ko.gz", a single-file reader, got 30% faster.
"depmod -a", which used to fork over 800 times, got 20% faster.

Heavily based on a patch by Lauri Kasanen <curaga@operamail.com>

function                                             old     new   delta
setup_transformer_on_fd                                -     159    +159
transformer_write                                      -     122    +122
fork_transformer                                       -     112    +112
xmalloc_open_zipped_read_close                        63     118     +55
read_bunzip                                         1866    1896     +30
xtransformer_write                                     -      19     +19
unzip_main                                          2449    2462     +13
bbunpack                                             755     766     +11
unpack_lzma_stream                                  2717    2723      +6
unpack_xz_stream                                    2393    2397      +4
unpack_Z_stream                                     1173    1175      +2
inflate_unzip                                        111     105      -6
check_signature16                                     70      63      -7
unpack_bz2_stream                                    359     349     -10
unpack_unxz                                           12       -     -12
unpack_unlzma                                         12       -     -12
unpack_uncompress                                     12       -     -12
unpack_gunzip                                         12       -     -12
unpack_bunzip2                                        12       -     -12
open_transformer                                     106      92     -14
inflate_unzip_internal                              1945    1916     -29
unpack_gz_stream                                     693     655     -38
open_zipped                                           89      47     -42
setup_unzip_on_fd                                    142      53     -89
------------------------------------------------------------------------------
(add/remove: 4/5 grow/shrink: 7/8 up/down: 533/-295)          Total: 238 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
index ccedac4..c8622f9 100644
--- a/archival/libarchive/decompress_unlzma.c
+++ b/archival/libarchive/decompress_unlzma.c
@@ -206,7 +206,7 @@
 
 
 IF_DESKTOP(long long) int FAST_FUNC
-unpack_lzma_stream(transformer_state_t *xstate UNUSED_PARAM, int src_fd, int dst_fd)
+unpack_lzma_stream(transformer_state_t *xstate)
 {
 	IF_DESKTOP(long long total_written = 0;)
 	lzma_header_t header;
@@ -223,7 +223,7 @@
 	int state = 0;
 	uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
 
-	if (full_read(src_fd, &header, sizeof(header)) != sizeof(header)
+	if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header)
 	 || header.pos >= (9 * 5 * 5)
 	) {
 		bb_error_msg("bad lzma header");
@@ -258,7 +258,7 @@
 			p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
 	}
 
-	rc = rc_init(src_fd); /*, RC_BUFFER_SIZE); */
+	rc = rc_init(xstate->src_fd); /*, RC_BUFFER_SIZE); */
 
 	while (global_pos + buffer_pos < header.dst_size) {
 		int pos_state = (buffer_pos + global_pos) & pos_state_mask;
@@ -306,7 +306,7 @@
 			if (buffer_pos == header.dict_size) {
 				buffer_pos = 0;
 				global_pos += header.dict_size;
-				if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size)
+				if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size)
 					goto bad;
 				IF_DESKTOP(total_written += header.dict_size;)
 			}
@@ -440,7 +440,7 @@
 				if (buffer_pos == header.dict_size) {
 					buffer_pos = 0;
 					global_pos += header.dict_size;
-					if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size)
+					if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size)
 						goto bad;
 					IF_DESKTOP(total_written += header.dict_size;)
 				}
@@ -455,7 +455,7 @@
 	{
 		IF_NOT_DESKTOP(int total_written = 0; /* success */)
 		IF_DESKTOP(total_written += buffer_pos;)
-		if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) {
+		if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) {
  bad:
 			total_written = -1; /* failure */
 		}