[PATCH] libarchive: add a function to unpack embedded data
Denys Vlasenko
vda.linux at googlemail.com
Fri Nov 2 13:19:23 UTC 2018
Applied, thanks!
On Fri, Nov 2, 2018 at 9:34 AM Ron Yorston <rmy at pobox.com> wrote:
>
> 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 at pobox.com>
> ---
> archival/libarchive/decompress_bunzip2.c | 38 +++++++++--
> include/bb_archive.h | 7 +-
> libbb/appletlib.c | 81 +++++-------------------
> miscutils/bbconfig.c | 27 ++------
> 4 files changed, 54 insertions(+), 99 deletions(-)
>
> diff --git a/archival/libarchive/decompress_bunzip2.c b/archival/libarchive/decompress_bunzip2.c
> index 7ef4e035f..3deb213a8 100644
> --- a/archival/libarchive/decompress_bunzip2.c
> +++ b/archival/libarchive/decompress_bunzip2.c
> @@ -107,7 +107,7 @@ struct bunzip_data {
> 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 @@ static int get_next_block(bunzip_data *bd)
> 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 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
> /* 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 @@ int FAST_FUNC start_bunzip(
> 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 @@ unpack_bz2_stream(transformer_state_t *xstate)
> return i ? i : IF_DESKTOP(total_written) + 0;
> }
>
> +const 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[] = {
> diff --git a/include/bb_archive.h b/include/bb_archive.h
> index d2022336b..0dbe17496 100644
> --- a/include/bb_archive.h
> +++ b/include/bb_archive.h
> @@ -214,12 +214,7 @@ const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_F
> const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC;
>
> /* A bit of bunzip2 internals are exposed for compressed help support: */
> -typedef struct bunzip_data bunzip_data;
> -int start_bunzip(void *, bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC;
> -/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
> - * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */
> -int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
> -void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
> +const char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC;
>
> /* Meaning and direction (input/output) of the fields are transformer-specific */
> typedef struct transformer_state_t {
> diff --git a/libbb/appletlib.c b/libbb/appletlib.c
> index d48b2ea60..6dfaf1f41 100644
> --- a/libbb/appletlib.c
> +++ b/libbb/appletlib.c
> @@ -107,34 +107,8 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
>
> static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
> # include "bb_archive.h"
> -static const char *unpack_usage_messages(void)
> -{
> - 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_usage,
> - /* len: */ sizeof(packed_usage)
> - );
> - }
> - /* 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(sizeof(UNPACKED_USAGE));
> - if (outbuf)
> - read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE));
> - }
> - dealloc_bunzip(bd);
> - return outbuf;
> -}
> +# define unpack_usage_messages() \
> + unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE))
> # define dealloc_usage_messages(s) free(s)
>
> #else
> @@ -152,21 +126,23 @@ void FAST_FUNC bb_show_usage(void)
> /* Imagine that this applet is "true". Dont suck in printf! */
> const char *usage_string = unpack_usage_messages();
>
> - if (*usage_string == '\b') {
> - full_write2_str("No help available.\n\n");
> - } else {
> - full_write2_str("Usage: "SINGLE_APPLET_STR" ");
> - full_write2_str(usage_string);
> - full_write2_str("\n\n");
> + if (usage_string) {
> + if (*usage_string == '\b') {
> + full_write2_str("No help available.\n\n");
> + } else {
> + full_write2_str("Usage: "SINGLE_APPLET_STR" ");
> + full_write2_str(usage_string);
> + full_write2_str("\n\n");
> + }
> + if (ENABLE_FEATURE_CLEAN_UP)
> + dealloc_usage_messages((char*)usage_string);
> }
> - if (ENABLE_FEATURE_CLEAN_UP)
> - dealloc_usage_messages((char*)usage_string);
> #else
> const char *p;
> const char *usage_string = p = unpack_usage_messages();
> int ap = find_applet_by_name(applet_name);
>
> - if (ap < 0) /* never happens, paranoia */
> + if (ap < 0 || usage_string == NULL)
> xfunc_die();
> while (ap) {
> while (*p++) continue;
> @@ -986,38 +962,11 @@ find_script_by_name(const char *name)
> return -0x10000; /* make it so that NUM_APPLETS + <error> is still < 0 */
> }
>
> -static char *
> -unpack_scripts(void)
> -{
> - 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_scripts,
> - /* len: */ sizeof(packed_scripts)
> - );
> - }
> - /* read_bunzip can longjmp and end up here with i != 0
> - * on read data errors! Not trivial */
> - if (i == 0) {
> - outbuf = xmalloc(UNPACKED_SCRIPTS_LENGTH);
> - read_bunzip(bd, outbuf, UNPACKED_SCRIPTS_LENGTH);
> - }
> - dealloc_bunzip(bd);
> - return outbuf;
> -}
> -
> char* FAST_FUNC
> get_script_content(unsigned n)
> {
> - char *t = unpack_scripts();
> + char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts),
> + UNPACKED_SCRIPTS_LENGTH);
> if (t) {
> while (n != 0) {
> while (*t++ != '\0')
> diff --git a/miscutils/bbconfig.c b/miscutils/bbconfig.c
> index 501349548..11698de94 100644
> --- a/miscutils/bbconfig.c
> +++ b/miscutils/bbconfig.c
> @@ -43,29 +43,10 @@ int bbconfig_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
> int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
> {
> #if ENABLE_FEATURE_COMPRESS_BBCONFIG
> - 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: */ bbconfig_config_bz2,
> - /* len: */ sizeof(bbconfig_config_bz2)
> - );
> - }
> - /* 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! */
> - char *outbuf = malloc_or_warn(sizeof(bbconfig_config));
> - if (outbuf) {
> - read_bunzip(bd, outbuf, sizeof(bbconfig_config));
> - full_write1_str(outbuf);
> - }
> + const char *outbuf = unpack_bz2_data(bbconfig_config_bz2,
> + sizeof(bbconfig_config_bz2), sizeof(bbconfig_config));
> + if (outbuf) {
> + full_write1_str(outbuf);
> }
> #else
> full_write1_str(bbconfig_config);
> --
> 2.19.1
>
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
More information about the busybox
mailing list