*: 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/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))