*: refactor handling of archived files. "tar f file.tar.lzma" now works too.

function                                             old     new   delta
unpack_Z_stream                                        -    1229   +1229
open_zipped                                            -     176    +176
unpack_bz2_stream_prime                                -      60     +60
tar_main                                             642     677     +35
find_main                                            406     418     +12
sv_main                                             1222    1233     +11
decode_format_string                                 829     837      +8
cmp_main                                             641     649      +8
popstring                                            134     140      +6
filter_accept_list_reassign                          120     125      +5
parse_and_put_prompt                                 800     804      +4
passwd_main                                         1053    1049      -4
make_new_name_gunzip                                 119     114      -5
rpm_main                                            1688    1670     -18
prepare                                              302     283     -19
xmalloc_open_zipped_read_close                       135      61     -74
uncompress                                          1229       -   -1229
------------------------------------------------------------------------------
(add/remove: 3/1 grow/shrink: 8/5 up/down: 1554/-1349)        Total: 205 bytes

diff --git a/archival/libunarchive/Kbuild b/archival/libunarchive/Kbuild
index 468a7e8..364f917 100644
--- a/archival/libunarchive/Kbuild
+++ b/archival/libunarchive/Kbuild
@@ -32,36 +32,20 @@
 	get_header_tar.o \
 	filter_accept_list_reassign.o
 
-lib-$(CONFIG_RPM)                       += open_transformer.o
-lib-$(CONFIG_FEATURE_TAR_BZIP2)         += open_transformer.o
-lib-$(CONFIG_FEATURE_TAR_LZMA)          += open_transformer.o
-lib-$(CONFIG_FEATURE_TAR_GZIP)          += open_transformer.o
-lib-$(CONFIG_FEATURE_TAR_COMPRESS)      += open_transformer.o
-lib-$(CONFIG_FEATURE_DEB_TAR_GZ)        += open_transformer.o
-lib-$(CONFIG_FEATURE_DEB_TAR_BZ2)       += open_transformer.o
-lib-$(CONFIG_FEATURE_DEB_TAR_LZMA)      += open_transformer.o
-
-lib-$(CONFIG_FEATURE_MODPROBE_SMALL_ZIPPED) += open_transformer.o decompress_unzip.o decompress_bunzip2.o
-
 lib-$(CONFIG_AR)                        += get_header_ar.o unpack_ar_archive.o
 lib-$(CONFIG_BUNZIP2)                   += decompress_bunzip2.o
 lib-$(CONFIG_UNLZMA)                    += decompress_unlzma.o
 lib-$(CONFIG_CPIO)                      += get_header_cpio.o
 lib-$(CONFIG_DPKG)                      += $(DPKG_FILES)
 lib-$(CONFIG_DPKG_DEB)                  += $(DPKG_FILES)
-lib-$(CONFIG_FEATURE_DEB_TAR_GZ)        += decompress_unzip.o get_header_tar_gz.o
-lib-$(CONFIG_FEATURE_DEB_TAR_BZ2)       += decompress_bunzip2.o get_header_tar_bz2.o
-lib-$(CONFIG_FEATURE_DEB_TAR_LZMA)      += decompress_unlzma.o get_header_tar_lzma.o
 lib-$(CONFIG_GUNZIP)                    += decompress_unzip.o
-lib-$(CONFIG_FEATURE_GUNZIP_UNCOMPRESS) += decompress_uncompress.o
 lib-$(CONFIG_RPM2CPIO)                  += decompress_unzip.o get_header_cpio.o
-lib-$(CONFIG_RPM)                       += decompress_unzip.o get_header_cpio.o
-lib-$(CONFIG_FEATURE_RPM_BZ2)           += decompress_bunzip2.o
+lib-$(CONFIG_RPM)                       += open_transformer.o decompress_unzip.o get_header_cpio.o
 lib-$(CONFIG_TAR)                       += get_header_tar.o
-lib-$(CONFIG_FEATURE_TAR_BZIP2)         += decompress_bunzip2.o get_header_tar_bz2.o
-lib-$(CONFIG_FEATURE_TAR_LZMA)          += decompress_unlzma.o get_header_tar_lzma.o
-lib-$(CONFIG_FEATURE_TAR_GZIP)          += decompress_unzip.o get_header_tar_gz.o
-lib-$(CONFIG_FEATURE_TAR_COMPRESS)      += decompress_uncompress.o
 lib-$(CONFIG_UNCOMPRESS)                += decompress_uncompress.o
 lib-$(CONFIG_UNZIP)                     += decompress_unzip.o
+lib-$(CONFIG_FEATURE_SEAMLESS_Z)        += open_transformer.o decompress_uncompress.o
+lib-$(CONFIG_FEATURE_SEAMLESS_GZ)       += open_transformer.o decompress_unzip.o get_header_tar_gz.o
+lib-$(CONFIG_FEATURE_SEAMLESS_BZ2)      += open_transformer.o decompress_bunzip2.o get_header_tar_bz2.o
+lib-$(CONFIG_FEATURE_SEAMLESS_LZMA)     += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o
 lib-$(CONFIG_FEATURE_COMPRESS_USAGE)    += decompress_bunzip2.o
diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c
index 654dc28..b53720f 100644
--- a/archival/libunarchive/decompress_bunzip2.c
+++ b/archival/libunarchive/decompress_bunzip2.c
@@ -590,7 +590,8 @@
 	bunzip_data *bd;
 	unsigned i;
 	enum {
-		BZh0 = ('B' << 24) + ('Z' << 16) + ('h' << 8) + '0'
+		BZh0 = ('B' << 24) + ('Z' << 16) + ('h' << 8) + '0',
+		h0 = ('h' << 8) + '0',
 	};
 
 	/* Figure out how much data to allocate */
@@ -617,12 +618,18 @@
 	if (i) return i;
 
 	/* Ensure that file starts with "BZh['1'-'9']." */
-	i = get_bits(bd, 32);
-	if ((unsigned)(i - BZh0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA;
+	/* Update: now caller verifies 1st two bytes, makes .gz/.bz2
+	 * integration easier */
+	/* was: */
+	/* i = get_bits(bd, 32); */
+	/* if ((unsigned)(i - BZh0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA; */
+	i = get_bits(bd, 16);
+	if ((unsigned)(i - h0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA;
 
 	/* Fourth byte (ascii '1'-'9') indicates block size in units of 100k of
 	   uncompressed data.  Allocate intermediate buffer for block. */
-	bd->dbufSize = 100000 * (i - BZh0);
+	/* bd->dbufSize = 100000 * (i - BZh0); */
+	bd->dbufSize = 100000 * (i - h0);
 
 	/* Cannot use xmalloc - may leak bd in NOFORK case! */
 	bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(int));
@@ -682,6 +689,17 @@
 	return i ? i : USE_DESKTOP(total_written) + 0;
 }
 
+USE_DESKTOP(long long) int FAST_FUNC
+unpack_bz2_stream_prime(int src_fd, int dst_fd)
+{
+	unsigned char magic[2];
+	xread(src_fd, magic, 2);
+	if (magic[0] != 'B' || magic[1] != 'Z') {
+		bb_error_msg_and_die("invalid magic");
+	}
+	return unpack_bz2_stream(src_fd, dst_fd);
+}
+
 #ifdef TESTING
 
 static char *const bunzip_errors[] = {
@@ -693,9 +711,10 @@
 /* Dumb little test thing, decompress stdin to stdout */
 int main(int argc, char **argv)
 {
-	int i = unpack_bz2_stream(0, 1);
+	int i;
 	char c;
 
+	int i = unpack_bz2_stream_prime(0, 1);
 	if (i < 0)
 		fprintf(stderr, "%s\n", bunzip_errors[-i]);
 	else if (read(STDIN_FILENO, &c, 1))
diff --git a/archival/libunarchive/decompress_uncompress.c b/archival/libunarchive/decompress_uncompress.c
index 1615700..fe1491e 100644
--- a/archival/libunarchive/decompress_uncompress.c
+++ b/archival/libunarchive/decompress_uncompress.c
@@ -1,6 +1,4 @@
 /* vi: set sw=4 ts=4: */
-#include "libbb.h"
-
 /* uncompress for busybox -- (c) 2002 Robert Griebl
  *
  * based on the original compress42.c source
@@ -26,6 +24,10 @@
  *
  */
 
+#include "libbb.h"
+#include "unarchive.h"
+
+
 /* Default input buffer size */
 #define	IBUFSIZ	2048
 
@@ -71,7 +73,7 @@
  */
 
 USE_DESKTOP(long long) int FAST_FUNC
-uncompress(int fd_in, int fd_out)
+unpack_Z_stream(int fd_in, int fd_out)
 {
 	USE_DESKTOP(long long total_written = 0;)
 	USE_DESKTOP(long long) int retval = -1;
diff --git a/archival/libunarchive/filter_accept_list_reassign.c b/archival/libunarchive/filter_accept_list_reassign.c
index 4dbc2d1..f1de4e8 100644
--- a/archival/libunarchive/filter_accept_list_reassign.c
+++ b/archival/libunarchive/filter_accept_list_reassign.c
@@ -23,22 +23,25 @@
 
 		/* Find extension */
 		name_ptr = strrchr(archive_handle->file_header->name, '.');
+		if (!name_ptr)
+			return EXIT_FAILURE;
+		name_ptr++;
 
 		/* Modify the subarchive handler based on the extension */
-		if (ENABLE_FEATURE_DEB_TAR_GZ
-		 && strcmp(name_ptr, ".gz") == 0
+		if (ENABLE_FEATURE_SEAMLESS_GZ
+		 && strcmp(name_ptr, "gz") == 0
 		) {
 			archive_handle->action_data_subarchive = get_header_tar_gz;
 			return EXIT_SUCCESS;
 		}
-		if (ENABLE_FEATURE_DEB_TAR_BZ2
-		 && strcmp(name_ptr, ".bz2") == 0
+		if (ENABLE_FEATURE_SEAMLESS_BZ2
+		 && strcmp(name_ptr, "bz2") == 0
 		) {
 			archive_handle->action_data_subarchive = get_header_tar_bz2;
 			return EXIT_SUCCESS;
 		}
-		if (ENABLE_FEATURE_DEB_TAR_LZMA
-		 && strcmp(name_ptr, ".lzma") == 0
+		if (ENABLE_FEATURE_SEAMLESS_LZMA
+		 && strcmp(name_ptr, "lzma") == 0
 		) {
 			archive_handle->action_data_subarchive = get_header_tar_lzma;
 			return EXIT_SUCCESS;
diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c
index 5310f3f..bf0f92b 100644
--- a/archival/libunarchive/get_header_tar.c
+++ b/archival/libunarchive/get_header_tar.c
@@ -148,12 +148,12 @@
 		 * we can switch to get_header_tar_gz/bz2/lzma().
 		 * Needs seekable fd. I wish recv(MSG_PEEK) works
 		 * on any fd... */
-#if ENABLE_FEATURE_TAR_GZIP
+#if ENABLE_FEATURE_SEAMLESS_GZ
 		if (tar.name[0] == 0x1f && tar.name[1] == (char)0x8b) { /* gzip */
 			get_header_ptr = get_header_tar_gz;
 		} else
 #endif
-#if ENABLE_FEATURE_TAR_BZIP2
+#if ENABLE_FEATURE_SEAMLESS_BZ2
 		if (tar.name[0] == 'B' && tar.name[1] == 'Z'
 		 && tar.name[2] == 'h' && isdigit(tar.name[3])
 		) { /* bzip2 */
diff --git a/archival/libunarchive/get_header_tar_bz2.c b/archival/libunarchive/get_header_tar_bz2.c
index 035c10b..615bbba 100644
--- a/archival/libunarchive/get_header_tar_bz2.c
+++ b/archival/libunarchive/get_header_tar_bz2.c
@@ -11,7 +11,7 @@
 	/* Can't lseek over pipes */
 	archive_handle->seek = seek_by_read;
 
-	open_transformer(archive_handle->src_fd, unpack_bz2_stream, "bunzip2");
+	open_transformer(archive_handle->src_fd, unpack_bz2_stream_prime, "bunzip2");
 	archive_handle->offset = 0;
 	while (get_header_tar(archive_handle) == EXIT_SUCCESS)
 		continue;