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>
This commit is contained in:
		
				
					committed by
					
						 Denys Vlasenko
						Denys Vlasenko
					
				
			
			
				
	
			
			
			
						parent
						
							0df289f427
						
					
				
				
					commit
					c339c7f7b3
				
			| @@ -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[] = { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user