From c339c7f7b393fbcd51b0f96df837baa1edad7fd8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 2 Nov 2018 14:14:31 +0100 Subject: [PATCH] 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 Signed-off-by: Denys Vlasenko --- 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..6f2c49fbc 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; } +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..561dd0c9d 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; +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 + 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..fe02516a8 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);