diff options
author | Ron Yorston <rmy@pobox.com> | 2018-11-02 14:14:31 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-11-02 14:14:51 +0100 |
commit | c339c7f7b393fbcd51b0f96df837baa1edad7fd8 (patch) | |
tree | 3fa49732a3426e0666ba732da7e4182db7dc66ca | |
parent | 0df289f427da6279e3ca198d14e90015c079af44 (diff) | |
download | busybox-w32-c339c7f7b393fbcd51b0f96df837baa1edad7fd8.tar.gz busybox-w32-c339c7f7b393fbcd51b0f96df837baa1edad7fd8.tar.bz2 busybox-w32-c339c7f7b393fbcd51b0f96df837baa1edad7fd8.zip |
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>
-rw-r--r-- | archival/libarchive/decompress_bunzip2.c | 38 | ||||
-rw-r--r-- | include/bb_archive.h | 7 | ||||
-rw-r--r-- | libbb/appletlib.c | 81 | ||||
-rw-r--r-- | 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 { | |||
107 | uint8_t selectors[32768]; /* nSelectors=15 bits */ | 107 | uint8_t selectors[32768]; /* nSelectors=15 bits */ |
108 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ | 108 | struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ |
109 | }; | 109 | }; |
110 | /* typedef struct bunzip_data bunzip_data; -- done in .h file */ | 110 | typedef struct bunzip_data bunzip_data; |
111 | 111 | ||
112 | 112 | ||
113 | /* Return the next nnn bits of input. All reads from the compressed input | 113 | /* 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) | |||
575 | in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. | 575 | in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0. |
576 | (Why? This allows to get rid of one local variable) | 576 | (Why? This allows to get rid of one local variable) |
577 | */ | 577 | */ |
578 | int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | 578 | static int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) |
579 | { | 579 | { |
580 | const uint32_t *dbuf; | 580 | const uint32_t *dbuf; |
581 | int pos, current, previous; | 581 | int pos, current, previous; |
@@ -699,7 +699,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len) | |||
699 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() | 699 | /* Because bunzip2 is used for help text unpacking, and because bb_show_usage() |
700 | should work for NOFORK applets too, we must be extremely careful to not leak | 700 | should work for NOFORK applets too, we must be extremely careful to not leak |
701 | any allocations! */ | 701 | any allocations! */ |
702 | int FAST_FUNC start_bunzip( | 702 | static int FAST_FUNC start_bunzip( |
703 | void *jmpbuf, | 703 | void *jmpbuf, |
704 | bunzip_data **bdp, | 704 | bunzip_data **bdp, |
705 | int in_fd, | 705 | int in_fd, |
@@ -759,7 +759,7 @@ int FAST_FUNC start_bunzip( | |||
759 | return RETVAL_OK; | 759 | return RETVAL_OK; |
760 | } | 760 | } |
761 | 761 | ||
762 | void FAST_FUNC dealloc_bunzip(bunzip_data *bd) | 762 | static void FAST_FUNC dealloc_bunzip(bunzip_data *bd) |
763 | { | 763 | { |
764 | free(bd->dbuf); | 764 | free(bd->dbuf); |
765 | free(bd); | 765 | free(bd); |
@@ -847,6 +847,36 @@ unpack_bz2_stream(transformer_state_t *xstate) | |||
847 | return i ? i : IF_DESKTOP(total_written) + 0; | 847 | return i ? i : IF_DESKTOP(total_written) + 0; |
848 | } | 848 | } |
849 | 849 | ||
850 | char* FAST_FUNC | ||
851 | unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) | ||
852 | { | ||
853 | char *outbuf = NULL; | ||
854 | bunzip_data *bd; | ||
855 | int i; | ||
856 | jmp_buf jmpbuf; | ||
857 | |||
858 | /* Setup for I/O error handling via longjmp */ | ||
859 | i = setjmp(jmpbuf); | ||
860 | if (i == 0) { | ||
861 | i = start_bunzip(&jmpbuf, | ||
862 | &bd, | ||
863 | /* src_fd: */ -1, | ||
864 | /* inbuf: */ packed, | ||
865 | /* len: */ packed_len | ||
866 | ); | ||
867 | } | ||
868 | /* read_bunzip can longjmp and end up here with i != 0 | ||
869 | * on read data errors! Not trivial */ | ||
870 | if (i == 0) { | ||
871 | /* Cannot use xmalloc: will leak bd in NOFORK case! */ | ||
872 | outbuf = malloc_or_warn(unpacked_len); | ||
873 | if (outbuf) | ||
874 | read_bunzip(bd, outbuf, unpacked_len); | ||
875 | } | ||
876 | dealloc_bunzip(bd); | ||
877 | return outbuf; | ||
878 | } | ||
879 | |||
850 | #ifdef TESTING | 880 | #ifdef TESTING |
851 | 881 | ||
852 | static char *const bunzip_errors[] = { | 882 | 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 | |||
214 | const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; | 214 | const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; |
215 | 215 | ||
216 | /* A bit of bunzip2 internals are exposed for compressed help support: */ | 216 | /* A bit of bunzip2 internals are exposed for compressed help support: */ |
217 | typedef struct bunzip_data bunzip_data; | 217 | char *unpack_bz2_data(const char *packed, int packed_len, int unpacked_len) FAST_FUNC; |
218 | int start_bunzip(void *, bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; | ||
219 | /* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes | ||
220 | * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */ | ||
221 | int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC; | ||
222 | void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; | ||
223 | 218 | ||
224 | /* Meaning and direction (input/output) of the fields are transformer-specific */ | 219 | /* Meaning and direction (input/output) of the fields are transformer-specific */ |
225 | typedef struct transformer_state_t { | 220 | 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; | |||
107 | 107 | ||
108 | static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; | 108 | static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; |
109 | # include "bb_archive.h" | 109 | # include "bb_archive.h" |
110 | static const char *unpack_usage_messages(void) | 110 | # define unpack_usage_messages() \ |
111 | { | 111 | unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE)) |
112 | char *outbuf = NULL; | ||
113 | bunzip_data *bd; | ||
114 | int i; | ||
115 | jmp_buf jmpbuf; | ||
116 | |||
117 | /* Setup for I/O error handling via longjmp */ | ||
118 | i = setjmp(jmpbuf); | ||
119 | if (i == 0) { | ||
120 | i = start_bunzip(&jmpbuf, | ||
121 | &bd, | ||
122 | /* src_fd: */ -1, | ||
123 | /* inbuf: */ packed_usage, | ||
124 | /* len: */ sizeof(packed_usage) | ||
125 | ); | ||
126 | } | ||
127 | /* read_bunzip can longjmp and end up here with i != 0 | ||
128 | * on read data errors! Not trivial */ | ||
129 | if (i == 0) { | ||
130 | /* Cannot use xmalloc: will leak bd in NOFORK case! */ | ||
131 | outbuf = malloc_or_warn(sizeof(UNPACKED_USAGE)); | ||
132 | if (outbuf) | ||
133 | read_bunzip(bd, outbuf, sizeof(UNPACKED_USAGE)); | ||
134 | } | ||
135 | dealloc_bunzip(bd); | ||
136 | return outbuf; | ||
137 | } | ||
138 | # define dealloc_usage_messages(s) free(s) | 112 | # define dealloc_usage_messages(s) free(s) |
139 | 113 | ||
140 | #else | 114 | #else |
@@ -152,21 +126,23 @@ void FAST_FUNC bb_show_usage(void) | |||
152 | /* Imagine that this applet is "true". Dont suck in printf! */ | 126 | /* Imagine that this applet is "true". Dont suck in printf! */ |
153 | const char *usage_string = unpack_usage_messages(); | 127 | const char *usage_string = unpack_usage_messages(); |
154 | 128 | ||
155 | if (*usage_string == '\b') { | 129 | if (usage_string) { |
156 | full_write2_str("No help available.\n\n"); | 130 | if (*usage_string == '\b') { |
157 | } else { | 131 | full_write2_str("No help available.\n\n"); |
158 | full_write2_str("Usage: "SINGLE_APPLET_STR" "); | 132 | } else { |
159 | full_write2_str(usage_string); | 133 | full_write2_str("Usage: "SINGLE_APPLET_STR" "); |
160 | full_write2_str("\n\n"); | 134 | full_write2_str(usage_string); |
135 | full_write2_str("\n\n"); | ||
136 | } | ||
137 | if (ENABLE_FEATURE_CLEAN_UP) | ||
138 | dealloc_usage_messages((char*)usage_string); | ||
161 | } | 139 | } |
162 | if (ENABLE_FEATURE_CLEAN_UP) | ||
163 | dealloc_usage_messages((char*)usage_string); | ||
164 | #else | 140 | #else |
165 | const char *p; | 141 | const char *p; |
166 | const char *usage_string = p = unpack_usage_messages(); | 142 | const char *usage_string = p = unpack_usage_messages(); |
167 | int ap = find_applet_by_name(applet_name); | 143 | int ap = find_applet_by_name(applet_name); |
168 | 144 | ||
169 | if (ap < 0) /* never happens, paranoia */ | 145 | if (ap < 0 || usage_string == NULL) |
170 | xfunc_die(); | 146 | xfunc_die(); |
171 | while (ap) { | 147 | while (ap) { |
172 | while (*p++) continue; | 148 | while (*p++) continue; |
@@ -986,38 +962,11 @@ find_script_by_name(const char *name) | |||
986 | return -0x10000; /* make it so that NUM_APPLETS + <error> is still < 0 */ | 962 | return -0x10000; /* make it so that NUM_APPLETS + <error> is still < 0 */ |
987 | } | 963 | } |
988 | 964 | ||
989 | static char * | ||
990 | unpack_scripts(void) | ||
991 | { | ||
992 | char *outbuf = NULL; | ||
993 | bunzip_data *bd; | ||
994 | int i; | ||
995 | jmp_buf jmpbuf; | ||
996 | |||
997 | /* Setup for I/O error handling via longjmp */ | ||
998 | i = setjmp(jmpbuf); | ||
999 | if (i == 0) { | ||
1000 | i = start_bunzip(&jmpbuf, | ||
1001 | &bd, | ||
1002 | /* src_fd: */ -1, | ||
1003 | /* inbuf: */ packed_scripts, | ||
1004 | /* len: */ sizeof(packed_scripts) | ||
1005 | ); | ||
1006 | } | ||
1007 | /* read_bunzip can longjmp and end up here with i != 0 | ||
1008 | * on read data errors! Not trivial */ | ||
1009 | if (i == 0) { | ||
1010 | outbuf = xmalloc(UNPACKED_SCRIPTS_LENGTH); | ||
1011 | read_bunzip(bd, outbuf, UNPACKED_SCRIPTS_LENGTH); | ||
1012 | } | ||
1013 | dealloc_bunzip(bd); | ||
1014 | return outbuf; | ||
1015 | } | ||
1016 | |||
1017 | char* FAST_FUNC | 965 | char* FAST_FUNC |
1018 | get_script_content(unsigned n) | 966 | get_script_content(unsigned n) |
1019 | { | 967 | { |
1020 | char *t = unpack_scripts(); | 968 | char *t = unpack_bz2_data(packed_scripts, sizeof(packed_scripts), |
969 | UNPACKED_SCRIPTS_LENGTH); | ||
1021 | if (t) { | 970 | if (t) { |
1022 | while (n != 0) { | 971 | while (n != 0) { |
1023 | while (*t++ != '\0') | 972 | 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; | |||
43 | int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | 43 | int bbconfig_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
44 | { | 44 | { |
45 | #if ENABLE_FEATURE_COMPRESS_BBCONFIG | 45 | #if ENABLE_FEATURE_COMPRESS_BBCONFIG |
46 | bunzip_data *bd; | 46 | const char *outbuf = unpack_bz2_data(bbconfig_config_bz2, |
47 | int i; | 47 | sizeof(bbconfig_config_bz2), sizeof(bbconfig_config)); |
48 | jmp_buf jmpbuf; | 48 | if (outbuf) { |
49 | 49 | full_write1_str(outbuf); | |
50 | /* Setup for I/O error handling via longjmp */ | ||
51 | i = setjmp(jmpbuf); | ||
52 | if (i == 0) { | ||
53 | i = start_bunzip(&jmpbuf, | ||
54 | &bd, | ||
55 | /* src_fd: */ -1, | ||
56 | /* inbuf: */ bbconfig_config_bz2, | ||
57 | /* len: */ sizeof(bbconfig_config_bz2) | ||
58 | ); | ||
59 | } | ||
60 | /* read_bunzip can longjmp and end up here with i != 0 | ||
61 | * on read data errors! Not trivial */ | ||
62 | if (i == 0) { | ||
63 | /* Cannot use xmalloc: will leak bd in NOFORK case! */ | ||
64 | char *outbuf = malloc_or_warn(sizeof(bbconfig_config)); | ||
65 | if (outbuf) { | ||
66 | read_bunzip(bd, outbuf, sizeof(bbconfig_config)); | ||
67 | full_write1_str(outbuf); | ||
68 | } | ||
69 | } | 50 | } |
70 | #else | 51 | #else |
71 | full_write1_str(bbconfig_config); | 52 | full_write1_str(bbconfig_config); |