libarchive: add a function to unpack embedded data

Similar code to unpack embedded data is used to decompress usage
messages, embedded scripts and the config file (in the non-default
bbconfig applet).

Moving this code to a common function reduces the size of the default
build and hides more of the internals of libarchive.

function                                             old     new   delta
unpack_bz2_data                                        -     135    +135
bb_show_usage                                        137     157     +20
get_script_content                                    32      47     +15
unpack_scripts                                       119       -    -119
unpack_usage_messages                                124       -    -124
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 2/0 up/down: 170/-243)          Total: -73 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
index 7ef4e03..6f2c49f 100644
--- a/archival/libarchive/decompress_bunzip2.c
+++ b/archival/libarchive/decompress_bunzip2.c
@@ -107,7 +107,7 @@
 	uint8_t selectors[32768];  /* nSelectors=15 bits */
 	struct group_data groups[MAX_GROUPS];  /* Huffman coding tables */
 };
-/* typedef struct bunzip_data bunzip_data; -- done in .h file */
+typedef struct bunzip_data bunzip_data;
 
 
 /* Return the next nnn bits of input.  All reads from the compressed input
@@ -575,7 +575,7 @@
    in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0.
    (Why? This allows to get rid of one local variable)
 */
-int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
+static int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
 {
 	const uint32_t *dbuf;
 	int pos, current, previous;
@@ -699,7 +699,7 @@
 /* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
    should work for NOFORK applets too, we must be extremely careful to not leak
    any allocations! */
-int FAST_FUNC start_bunzip(
+static int FAST_FUNC start_bunzip(
 		void *jmpbuf,
 		bunzip_data **bdp,
 		int in_fd,
@@ -759,7 +759,7 @@
 	return RETVAL_OK;
 }
 
-void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
+static void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
 {
 	free(bd->dbuf);
 	free(bd);
@@ -847,6 +847,36 @@
 	return i ? i : IF_DESKTOP(total_written) + 0;
 }
 
+char* FAST_FUNC
+unpack_bz2_data(const char *packed, int packed_len, int unpacked_len)
+{
+	char *outbuf = NULL;
+	bunzip_data *bd;
+	int i;
+	jmp_buf jmpbuf;
+
+	/* Setup for I/O error handling via longjmp */
+	i = setjmp(jmpbuf);
+	if (i == 0) {
+		i = start_bunzip(&jmpbuf,
+			&bd,
+			/* src_fd: */ -1,
+			/* inbuf:  */ packed,
+			/* len:    */ packed_len
+		);
+	}
+	/* read_bunzip can longjmp and end up here with i != 0
+	 * on read data errors! Not trivial */
+	if (i == 0) {
+		/* Cannot use xmalloc: will leak bd in NOFORK case! */
+		outbuf = malloc_or_warn(unpacked_len);
+		if (outbuf)
+			read_bunzip(bd, outbuf, unpacked_len);
+	}
+	dealloc_bunzip(bd);
+	return outbuf;
+}
+
 #ifdef TESTING
 
 static char *const bunzip_errors[] = {