safe_strtoXX interface proved to be a bit unconvenient.
Remove it, introduce saner bb_strtoXX. Saved ~350 bytes.
This commit is contained in:
		| @@ -49,6 +49,8 @@ typedef long arith_t; | ||||
| #define STRTOL(s, e, b) strtol(s, e, b) | ||||
| #endif | ||||
|  | ||||
| /* TODO: use bb_strtol[l]? It's easier to check for errors... */ | ||||
|  | ||||
| /* A value is.... */ | ||||
| struct valinfo { | ||||
| 	TYPE type;			/* Which kind. */ | ||||
|   | ||||
| @@ -44,38 +44,55 @@ static int print_formatted(char *format, int argc, char **argv); | ||||
| static void print_direc(char *start, size_t length, | ||||
| 			int field_width, int precision, char *argument); | ||||
|  | ||||
| typedef int (*converter)(char *arg, void *result); | ||||
| typedef void (*converter)(char *arg, void *result); | ||||
|  | ||||
| static void multiconvert(char *arg, void *result, converter convert) | ||||
| { | ||||
| 	char s[16]; | ||||
| 	if (*arg == '"' || *arg == '\'') { | ||||
| 		sprintf(s, "%d", (unsigned)arg[1]); | ||||
| 		sprintf(s, "%d", (unsigned char)arg[1]); | ||||
| 		arg = s; | ||||
| 	} | ||||
| 	if (convert(arg, result)) | ||||
| 	convert(arg, result); | ||||
| 	if (errno) /* Huh, looks strange... bug? */ | ||||
| 		fputs(arg, stderr); | ||||
| } | ||||
|  | ||||
| static void conv_strtoul(char *arg, void *result) | ||||
| { | ||||
| 	*(unsigned long*)result = bb_strtoul(arg, NULL, 10); | ||||
| } | ||||
| static void conv_strtol(char *arg, void *result) | ||||
| { | ||||
| 	*(long*)result = bb_strtol(arg, NULL, 10); | ||||
| } | ||||
| static void conv_strtod(char *arg, void *result) | ||||
| { | ||||
| 	char *end; | ||||
| 	/* Well, this one allows leading whitespace... so what */ | ||||
| 	/* What I like much less is that "-" is accepted too! :( */ | ||||
| 	*(double*)result = strtod(arg, &end); | ||||
| 	if (end[0]) errno = ERANGE; | ||||
| } | ||||
|  | ||||
| static unsigned long my_xstrtoul(char *arg) | ||||
| { | ||||
| 	unsigned long result; | ||||
|  | ||||
| 	multiconvert(arg, &result, (converter)safe_strtoul); | ||||
| 	multiconvert(arg, &result, conv_strtoul); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static long my_xstrtol(char *arg) | ||||
| { | ||||
| 	long result; | ||||
| 	multiconvert(arg, &result, (converter)safe_strtol); | ||||
| 	multiconvert(arg, &result, conv_strtol); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| static double my_xstrtod(char *arg) | ||||
| { | ||||
| 	double result; | ||||
| 	multiconvert(arg, &result, (converter)safe_strtod); | ||||
| 	multiconvert(arg, &result, conv_strtod); | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -673,7 +673,7 @@ static void show_stats(ext2_filsys fs) | ||||
| static int set_os(struct ext2_super_block *sb, char *os) | ||||
| { | ||||
| 	if (isdigit (*os)) { | ||||
| 		sb->s_creator_os = atoi (os); | ||||
| 		sb->s_creator_os = atoi(os); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| @@ -790,7 +790,7 @@ static __u32 ok_features[3] = { | ||||
|  | ||||
| static int PRS(int argc, char *argv[]) | ||||
| { | ||||
| 	int		b, c; | ||||
| 	int		c; | ||||
| 	int		size; | ||||
| 	char *		tmp; | ||||
| 	int		blocksize = 0; | ||||
| @@ -848,54 +848,32 @@ static int PRS(int argc, char *argv[]) | ||||
| 		    "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) { | ||||
| 		switch (c) { | ||||
| 		case 'b': | ||||
| 			if (safe_strtoi(optarg, &blocksize)) | ||||
| 				goto BLOCKSIZE_ERROR; | ||||
| 			b = (blocksize > 0) ? blocksize : -blocksize; | ||||
| 			if (b < EXT2_MIN_BLOCK_SIZE || | ||||
| 			    b > EXT2_MAX_BLOCK_SIZE) { | ||||
| BLOCKSIZE_ERROR: | ||||
| 				bb_error_msg_and_die("invalid block size - %s", optarg); | ||||
| 			} | ||||
| 			blocksize = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE); | ||||
| 			mke2fs_warning_msg((blocksize > 4096), | ||||
| 				"blocksize %d not usable on most systems", | ||||
| 				blocksize); | ||||
| 			if (blocksize > 0) | ||||
| 				param.s_log_block_size = | ||||
| 					int_log2(blocksize >> | ||||
| 						 EXT2_MIN_BLOCK_LOG_SIZE); | ||||
| 			param.s_log_block_size = | ||||
| 				int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); | ||||
| 			break; | ||||
| 		case 'c':	/* Check for bad blocks */ | ||||
| 		case 't':	/* deprecated */ | ||||
| 			cflag++; | ||||
| 			break; | ||||
| 		case 'f': | ||||
| 			if (safe_strtoi(optarg, &size) || size < EXT2_MIN_BLOCK_SIZE || size > EXT2_MAX_BLOCK_SIZE ){ | ||||
| 				bb_error_msg_and_die("invalid fragment size - %s", optarg); | ||||
| 			} | ||||
| 			size = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE); | ||||
| 			param.s_log_frag_size = | ||||
| 				int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); | ||||
| 			mke2fs_warning_msg(1, "fragments not supported. Ignoring -f option"); | ||||
| 			break; | ||||
| 		case 'g': | ||||
| 			{ | ||||
| 			    int foo; | ||||
| 			    if (safe_strtoi(optarg, &foo)) { | ||||
| 				bb_error_msg_and_die("Illegal number for blocks per group"); | ||||
| 			    } | ||||
| 			    param.s_blocks_per_group = foo; | ||||
| 			} | ||||
| 			param.s_blocks_per_group = xatou32(optarg); | ||||
| 			if ((param.s_blocks_per_group % 8) != 0) { | ||||
| 				bb_error_msg_and_die("blocks per group must be multiple of 8"); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'i': | ||||
| 			if (safe_strtoi(optarg, &inode_ratio) | ||||
| 				|| inode_ratio < EXT2_MIN_BLOCK_SIZE | ||||
| 				|| inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024) { | ||||
| 				bb_error_msg_and_die("invalid inode ratio %s (min %d/max %d)", | ||||
| 					optarg, EXT2_MIN_BLOCK_SIZE, | ||||
| 					EXT2_MAX_BLOCK_SIZE); | ||||
| 				} | ||||
| 			/* Huh? is "* 1024" correct? */ | ||||
| 			inode_ratio = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE * 1024); | ||||
| 			break; | ||||
| 		case 'J': | ||||
| 			parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg); | ||||
| @@ -910,9 +888,7 @@ BLOCKSIZE_ERROR: | ||||
| 			bad_blocks_filename = optarg; | ||||
| 			break; | ||||
| 		case 'm': | ||||
| 			if (safe_strtoi(optarg, &reserved_ratio) || reserved_ratio > 50 ) { | ||||
| 				bb_error_msg_and_die("invalid reserved blocks percent - %s", optarg); | ||||
| 			} | ||||
| 			reserved_ratio = xatou_range(optarg, 0, 50); | ||||
| 			break; | ||||
| 		case 'n': | ||||
| 			noaction++; | ||||
| @@ -921,7 +897,7 @@ BLOCKSIZE_ERROR: | ||||
| 			creator_os = optarg; | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			param.s_rev_level = atoi(optarg); | ||||
| 			param.s_rev_level = xatoi_u(optarg); | ||||
| 			if (param.s_rev_level == EXT2_GOOD_OLD_REV) { | ||||
| 				param.s_feature_incompat = 0; | ||||
| 				param.s_feature_compat = 0; | ||||
| @@ -929,7 +905,7 @@ BLOCKSIZE_ERROR: | ||||
| 			} | ||||
| 			break; | ||||
| 		case 's':	/* deprecated */ | ||||
| 			if (atoi(optarg)) | ||||
| 			if (xatou(optarg)) | ||||
| 				param.s_feature_ro_compat |= | ||||
| 					EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; | ||||
| 			else | ||||
| @@ -938,13 +914,11 @@ BLOCKSIZE_ERROR: | ||||
| 			break; | ||||
| #ifdef EXT2_DYNAMIC_REV | ||||
| 		case 'I': | ||||
| 			if (safe_strtoi(optarg, &inode_size)) { | ||||
| 				bb_error_msg_and_die("invalid inode size - %s", optarg); | ||||
| 			} | ||||
| 			inode_size = xatoi_u(optarg); | ||||
| 			break; | ||||
| #endif | ||||
| 		case 'N': | ||||
| 			num_inodes = atoi(optarg); | ||||
| 			num_inodes = xatoi_u(optarg); | ||||
| 			break; | ||||
| 		case 'v': | ||||
| 			quiet = 0; | ||||
|   | ||||
| @@ -54,7 +54,8 @@ static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag; | ||||
| static time_t last_check_time; | ||||
| static int print_label; | ||||
| static int max_mount_count, mount_count, mount_flags; | ||||
| static unsigned long interval, reserved_ratio, reserved_blocks; | ||||
| static unsigned long interval, reserved_blocks; | ||||
| static unsigned reserved_ratio; | ||||
| static unsigned long resgid, resuid; | ||||
| static unsigned short errors; | ||||
| static int open_flag; | ||||
| @@ -410,19 +411,14 @@ static void parse_tune2fs_options(int argc, char **argv) | ||||
| 		switch (c) | ||||
| 		{ | ||||
| 			case 'c': | ||||
| 				if (safe_strtoi(optarg, &max_mount_count) ||  max_mount_count > 16000) { | ||||
| 					goto MOUNTS_COUNT_ERROR; | ||||
| 				} | ||||
| 				max_mount_count = xatou_range(optarg, 0, 16000); | ||||
| 				if (max_mount_count == 0) | ||||
| 					max_mount_count = -1; | ||||
| 				c_flag = 1; | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| 			case 'C': | ||||
| 				if (safe_strtoi(optarg, &mount_count) || mount_count > 16000) { | ||||
| MOUNTS_COUNT_ERROR: | ||||
| 					bb_error_msg_and_die("bad mounts count - %s", optarg); | ||||
| 				} | ||||
| 				mount_count = xatou_range(optarg, 0, 16000); | ||||
| 				C_flag = 1; | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| @@ -443,13 +439,14 @@ MOUNTS_COUNT_ERROR: | ||||
| 				f_flag = 1; | ||||
| 				break; | ||||
| 			case 'g': | ||||
| 				if (safe_strtoul(optarg, &resgid)) | ||||
| 				resgid = bb_strtoul(optarg, NULL, 10); | ||||
| 				if (errno) | ||||
| 					resgid = bb_xgetgrnam(optarg); | ||||
| 				g_flag = 1; | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| 			case 'i': | ||||
| 				interval = strtoul (optarg, &tmp, 0); | ||||
| 				interval = strtoul(optarg, &tmp, 0); | ||||
| 				switch (*tmp) { | ||||
| 				case 's': | ||||
| 					tmp++; | ||||
| @@ -497,9 +494,7 @@ MOUNTS_COUNT_ERROR: | ||||
| 					EXT2_FLAG_JOURNAL_DEV_OK; | ||||
| 				break; | ||||
| 			case 'm': | ||||
| 				if(safe_strtoul(optarg, &reserved_ratio) || reserved_ratio > 50) { | ||||
| 					bb_error_msg_and_die("bad reserved block ratio - %s", optarg); | ||||
| 				} | ||||
| 				reserved_ratio = xatou_range(optarg, 0, 50); | ||||
| 				m_flag = 1; | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| @@ -524,9 +519,7 @@ MOUNTS_COUNT_ERROR: | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| 			case 'r': | ||||
| 				if(safe_strtoul(optarg, &reserved_blocks)) { | ||||
| 					bb_error_msg_and_die("bad reserved blocks count - %s", optarg); | ||||
| 				} | ||||
| 				reserved_blocks = xatoul(optarg); | ||||
| 				r_flag = 1; | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| @@ -540,7 +533,8 @@ MOUNTS_COUNT_ERROR: | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| 				break; | ||||
| 			case 'u': | ||||
| 				if (safe_strtoul(optarg, &resuid)) | ||||
| 				resuid = bb_strtoul(optarg, NULL, 10); | ||||
| 				if (errno) | ||||
| 					resuid = bb_xgetpwnam(optarg); | ||||
| 				u_flag = 1; | ||||
| 				open_flag = EXT2_FLAG_RW; | ||||
| @@ -646,9 +640,9 @@ int tune2fs_main(int argc, char **argv) | ||||
| 	} | ||||
| 	if (m_flag) { | ||||
| 		sb->s_r_blocks_count = (sb->s_blocks_count / 100) | ||||
| 			* reserved_ratio; | ||||
| 				* reserved_ratio; | ||||
| 		ext2fs_mark_super_dirty(fs); | ||||
| 		printf("Setting reserved blocks percentage to %lu (%u blocks)\n", | ||||
| 		printf("Setting reserved blocks percentage to %u (%u blocks)\n", | ||||
| 			reserved_ratio, sb->s_r_blocks_count); | ||||
| 	} | ||||
| 	if (r_flag) { | ||||
|   | ||||
| @@ -85,30 +85,31 @@ | ||||
| /* CONFIG_LFS is on */ | ||||
| # if ULONG_MAX > 0xffffffff | ||||
| /* "long" is long enough on this system */ | ||||
| #  define STRTOOFF strtol | ||||
| #  define SAFE_STRTOOFF safe_strtol | ||||
| #  define XSTRTOUOFF xstrtoul | ||||
| #  define XSTRTOOFF xstrtoul | ||||
| /* usage: sz = BB_STRTOOFF(s, NULL, 10); if (errno || sz < 0) die(); */ | ||||
| #  define BB_STRTOOFF bb_strtoul | ||||
| #  define STRTOOFF strtoul | ||||
| /* usage: printf("size: %"OFF_FMT"d (%"OFF_FMT"x)\n", sz, sz); */ | ||||
| #  define OFF_FMT "l" | ||||
| # else | ||||
| /* "long" is too short, need "long long" */ | ||||
| #  define STRTOOFF strtoll | ||||
| #  define SAFE_STRTOOFF safe_strtoll | ||||
| #  define XSTRTOUOFF xstrtoull | ||||
| #  define XSTRTOOFF xstrtoull | ||||
| #  define BB_STRTOOFF bb_strtoull | ||||
| #  define STRTOOFF strtoull | ||||
| #  define OFF_FMT "ll" | ||||
| # endif | ||||
| #else | ||||
| # if 0 /* #if UINT_MAX == 0xffffffff */ | ||||
| /* Doesn't work. off_t is a long. gcc will throw warnings on printf("%d", off_t) | ||||
|  * even if long==int on this arch. Crap... */ | ||||
| #  define XSTRTOOFF xstrtou | ||||
| #  define BB_STRTOOFF bb_strtoi | ||||
| #  define STRTOOFF strtol | ||||
| #  define SAFE_STRTOOFF safe_strtoi | ||||
| #  define XSTRTOUOFF xstrtou | ||||
| #  define OFF_FMT "" | ||||
| # else | ||||
| #  define XSTRTOOFF xstrtoul | ||||
| #  define BB_STRTOOFF bb_strtol | ||||
| #  define STRTOOFF strtol | ||||
| #  define SAFE_STRTOOFF safe_strtol | ||||
| #  define XSTRTOUOFF xstrtoul | ||||
| #  define OFF_FMT "l" | ||||
| # endif | ||||
| #endif | ||||
| @@ -299,18 +300,6 @@ extern char *utoa(unsigned n); | ||||
| extern void itoa_to_buf(int n, char *buf, unsigned buflen); | ||||
| extern char *itoa(int n); | ||||
|  | ||||
| // FIXME: the prototype doesn't match libc strtoXX -> confusion | ||||
| // FIXME: alot of unchecked strtoXXX are still in tree | ||||
| // FIXME: atoi_or_else(str, N)? | ||||
| extern int safe_strtoi(const char *arg, int* value); | ||||
| extern int safe_strtou(const char *arg, unsigned* value); | ||||
| extern int safe_strtod(const char *arg, double* value); | ||||
| extern int safe_strtol(const char *arg, long* value); | ||||
| extern int safe_strtoll(const char *arg, long long* value); | ||||
| extern int safe_strtoul(const char *arg, unsigned long* value); | ||||
| extern int safe_strtoull(const char *arg, unsigned long long* value); | ||||
| extern int safe_strtou32(const char *arg, uint32_t* value); | ||||
|  | ||||
| struct suffix_mult { | ||||
| 	const char *suffix; | ||||
| 	unsigned mult; | ||||
|   | ||||
| @@ -104,3 +104,54 @@ extern inline uint32_t xatou32(const char *numstr) | ||||
| 		return xatoul(numstr); | ||||
| 	return BUG_xatou32_unimplemented(); | ||||
| } | ||||
|  | ||||
| /* Non-aborting kind of convertors */ | ||||
|  | ||||
| unsigned long long bb_strtoull(const char *arg, char **endp, int base); | ||||
| long long bb_strtoll(const char *arg, char **endp, int base); | ||||
|  | ||||
| #if ULONG_MAX == ULLONG_MAX | ||||
| extern inline | ||||
| unsigned long bb_strtoul(const char *arg, char **endp, int base) | ||||
| { return bb_strtoull(arg, endp, base); } | ||||
| extern inline | ||||
| unsigned long bb_strtol(const char *arg, char **endp, int base) | ||||
| { return bb_strtoll(arg, endp, base); } | ||||
| #else | ||||
| unsigned long bb_strtoul(const char *arg, char **endp, int base); | ||||
| long bb_strtol(const char *arg, char **endp, int base); | ||||
| #endif | ||||
|  | ||||
| #if UINT_MAX == ULLONG_MAX | ||||
| extern inline | ||||
| unsigned long bb_strtou(const char *arg, char **endp, int base) | ||||
| { return bb_strtoull(arg, endp, base); } | ||||
| extern inline | ||||
| unsigned long bb_strtoi(const char *arg, char **endp, int base) | ||||
| { return bb_strtoll(arg, endp, base); } | ||||
| #elif UINT_MAX == ULONG_MAX | ||||
| extern inline | ||||
| unsigned long bb_strtou(const char *arg, char **endp, int base) | ||||
| { return bb_strtoul(arg, endp, base); } | ||||
| extern inline | ||||
| unsigned long bb_strtoi(const char *arg, char **endp, int base) | ||||
| { return bb_strtol(arg, endp, base); } | ||||
| #else | ||||
| unsigned long bb_strtou(const char *arg, char **endp, int base); | ||||
| long bb_strtoi(const char *arg, char **endp, int base); | ||||
| #endif | ||||
|  | ||||
| int BUG_bb_strtou32_unimplemented(void); | ||||
| extern inline | ||||
| uint32_t bb_strtou32(const char *arg, char **endp, int base) | ||||
| { | ||||
| 	if (sizeof(uint32_t) == sizeof(unsigned)) | ||||
| 		return bb_strtou(arg, endp, base); | ||||
| 	if (sizeof(uint32_t) == sizeof(unsigned long)) | ||||
| 		return bb_strtoul(arg, endp, base); | ||||
| 	return BUG_bb_strtou32_unimplemented(); | ||||
| } | ||||
|  | ||||
| /* Floating point */ | ||||
|  | ||||
| /* double bb_strtod(const char *arg, char **endp); */ | ||||
|   | ||||
| @@ -10,6 +10,7 @@ lib-y += ask_confirmation.o | ||||
| lib-y += bb_askpass.o | ||||
| lib-y += bb_do_delay.o | ||||
| lib-y += bb_pwd.o | ||||
| lib-y += bb_strtonum.o | ||||
| lib-y += change_identity.o | ||||
| lib-y += chomp.o | ||||
| lib-y += compare_string_array.o | ||||
| @@ -67,7 +68,6 @@ lib-y += remove_file.o | ||||
| lib-y += restricted_shell.o | ||||
| lib-y += run_shell.o | ||||
| lib-y += safe_strncpy.o | ||||
| lib-y += safe_strtol.o | ||||
| lib-y += safe_write.o | ||||
| lib-y += setup_environment.o | ||||
| lib-y += sha1.o | ||||
|   | ||||
| @@ -119,7 +119,8 @@ procps_status_t* procps_scan(procps_status_t* sp, int flags) | ||||
| 			free_procps_scan(sp); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		if (safe_strtou(entry->d_name, &pid)) | ||||
| 		pid = bb_strtou(entry->d_name, NULL, 10); | ||||
| 		if (errno) | ||||
| 			continue; | ||||
|  | ||||
| 		/* After this point we have to break, not continue | ||||
|   | ||||
| @@ -1,147 +0,0 @@ | ||||
| /* vi: set sw=4 ts=4: */ | ||||
| /* | ||||
|  * Utility routines. | ||||
|  * | ||||
|  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | ||||
|  * | ||||
|  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||||
|  */ | ||||
|  | ||||
| #include <assert.h> | ||||
| #include "libbb.h" | ||||
|  | ||||
| int safe_strtod(const char *arg, double* value) | ||||
| { | ||||
| 	char *endptr; | ||||
| 	int errno_save = errno; | ||||
|  | ||||
| 	assert(arg!=NULL); | ||||
| 	errno = 0; | ||||
| 	*value = strtod(arg, &endptr); | ||||
| 	if (errno != 0 || *endptr != '\0' || endptr == arg) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	errno = errno_save; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int safe_strtoull(const char *arg, unsigned long long* value) | ||||
| { | ||||
| 	char *endptr; | ||||
| 	int errno_save = errno; | ||||
|  | ||||
| 	assert(arg!=NULL); | ||||
| 	if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */ | ||||
| 		return 1; | ||||
| 	errno = 0; | ||||
| 	*value = strtoull(arg, &endptr, 0); | ||||
| 	if (errno != 0 || *endptr != '\0' || endptr == arg) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	errno = errno_save; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int safe_strtoll(const char *arg, long long* value) | ||||
| { | ||||
| 	char *endptr; | ||||
| 	int errno_save = errno; | ||||
|  | ||||
| 	assert(arg!=NULL); | ||||
| 	errno = 0; | ||||
| 	*value = strtoll(arg, &endptr, 0); | ||||
| 	if (errno != 0 || *endptr != '\0' || endptr == arg) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	errno = errno_save; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int safe_strtoul(const char *arg, unsigned long* value) | ||||
| { | ||||
| 	char *endptr; | ||||
| 	int errno_save = errno; | ||||
|  | ||||
| 	assert(arg!=NULL); | ||||
| 	if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */ | ||||
| 		return 1; | ||||
| 	errno = 0; | ||||
| 	*value = strtoul(arg, &endptr, 0); | ||||
| 	if (errno != 0 || *endptr != '\0' || endptr == arg) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	errno = errno_save; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int safe_strtol(const char *arg, long* value) | ||||
| { | ||||
| 	char *endptr; | ||||
| 	int errno_save = errno; | ||||
|  | ||||
| 	assert(arg!=NULL); | ||||
| 	errno = 0; | ||||
| 	*value = strtol(arg, &endptr, 0); | ||||
| 	if (errno != 0 || *endptr != '\0' || endptr == arg) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 	errno = errno_save; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* TODO: This is what uclibc is doing. Try to do the same? */ | ||||
|  | ||||
| #if 0 | ||||
| #if defined __HAVE_ELF__ | ||||
|  | ||||
| # define strong_alias(name, aliasname) _strong_alias(name, aliasname) | ||||
| # define _strong_alias(name, aliasname) \ | ||||
|   extern __typeof (name) aliasname __attribute__ ((alias (#name))); | ||||
|  | ||||
| #else /* !defined __HAVE_ELF__ */ | ||||
|  | ||||
| #  define strong_alias(name, aliasname) _strong_alias (name, aliasname) | ||||
| #  define _strong_alias(name, aliasname) \ | ||||
| 	__asm__(".global " __C_SYMBOL_PREFIX__ #aliasname "\n" \ | ||||
| 	        ".set " __C_SYMBOL_PREFIX__ #aliasname "," __C_SYMBOL_PREFIX__ #name); | ||||
|  | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| int safe_strtoi(const char *arg, int* value) | ||||
| { | ||||
| 	int error; | ||||
| 	long lvalue; | ||||
| 	if (sizeof(long) == sizeof(int)) | ||||
| 		return safe_strtol(arg, (long*)value); | ||||
| 	lvalue = *value; | ||||
| 	error = safe_strtol(arg, &lvalue); | ||||
| 	if (lvalue < INT_MIN || lvalue > INT_MAX) | ||||
| 		return 1; | ||||
| 	*value = (int) lvalue; | ||||
| 	return error; | ||||
| } | ||||
|  | ||||
| int safe_strtou(const char *arg, unsigned* value) | ||||
| { | ||||
| 	int error; | ||||
| 	unsigned long lvalue; | ||||
| 	if (sizeof(unsigned long) == sizeof(unsigned)) | ||||
| 		return safe_strtoul(arg, (unsigned long*)value); | ||||
| 	lvalue = *value; | ||||
| 	error = safe_strtoul(arg, &lvalue); | ||||
| 	if (lvalue > UINT_MAX) | ||||
| 		return 1; | ||||
| 	*value = (unsigned) lvalue; | ||||
| 	return error; | ||||
| } | ||||
|  | ||||
| int BUG_safe_strtou32_unimplemented(void); | ||||
| int safe_strtou32(const char *arg, uint32_t* value) | ||||
| { | ||||
| 	if (sizeof(uint32_t) == sizeof(unsigned)) | ||||
| 		return safe_strtou(arg, (unsigned*)value); | ||||
| 	if (sizeof(uint32_t) == sizeof(unsigned long)) | ||||
| 		return safe_strtoul(arg, (unsigned long*)value); | ||||
| 	return BUG_safe_strtou32_unimplemented(); | ||||
| } | ||||
| @@ -19,15 +19,6 @@ | ||||
| #define XSTR_TYPE_MIN LLONG_MIN | ||||
| #define XSTR_STRTOU strtoull | ||||
| #include "xatonum_template.c" | ||||
| #undef type | ||||
| #undef xstrtou | ||||
| #undef xstrto | ||||
| #undef xatou | ||||
| #undef xato | ||||
| #undef XSTR_UTYPE_MAX | ||||
| #undef XSTR_TYPE_MAX | ||||
| #undef XSTR_TYPE_MIN | ||||
| #undef XSTR_STRTOU | ||||
|  | ||||
| #if ULONG_MAX != ULLONG_MAX | ||||
| #define type long | ||||
| @@ -40,15 +31,6 @@ | ||||
| #define XSTR_TYPE_MIN LONG_MIN | ||||
| #define XSTR_STRTOU strtoul | ||||
| #include "xatonum_template.c" | ||||
| #undef type | ||||
| #undef xstrtou | ||||
| #undef xstrto | ||||
| #undef xatou | ||||
| #undef xato | ||||
| #undef XSTR_UTYPE_MAX | ||||
| #undef XSTR_TYPE_MAX | ||||
| #undef XSTR_TYPE_MIN | ||||
| #undef XSTR_STRTOU | ||||
| #endif | ||||
|  | ||||
| #if UINT_MAX != ULONG_MAX | ||||
| @@ -72,15 +54,6 @@ extern inline unsigned bb_strtoui(const char *str, char **end, int b) | ||||
| /* libc has no strtoui, so we need to create/use our own */ | ||||
| #define XSTR_STRTOU bb_strtoui | ||||
| #include "xatonum_template.c" | ||||
| #undef type | ||||
| #undef xstrtou | ||||
| #undef xstrto | ||||
| #undef xatou | ||||
| #undef xato | ||||
| #undef XSTR_UTYPE_MAX | ||||
| #undef XSTR_TYPE_MAX | ||||
| #undef XSTR_TYPE_MIN | ||||
| #undef XSTR_STRTOU | ||||
| #endif | ||||
|  | ||||
| /* A few special cases */ | ||||
| @@ -90,11 +63,6 @@ int xatoi_u(const char *numstr) | ||||
| 	return xatou_range(numstr, 0, INT_MAX); | ||||
| } | ||||
|  | ||||
| uint32_t xatou32(const char *numstr) | ||||
| { | ||||
| 	return xatoul_range(numstr, 0, 0xffffffff); | ||||
| } | ||||
|  | ||||
| uint16_t xatou16(const char *numstr) | ||||
| { | ||||
| 	return xatou_range(numstr, 0, 0xffff); | ||||
|   | ||||
| @@ -173,3 +173,13 @@ type xato()(const char *numstr) | ||||
| { | ||||
| 	return xstrto(_range_sfx)(numstr, 10, XSTR_TYPE_MIN, XSTR_TYPE_MAX, NULL); | ||||
| } | ||||
|  | ||||
| #undef type | ||||
| #undef xstrtou | ||||
| #undef xstrto | ||||
| #undef xatou | ||||
| #undef xato | ||||
| #undef XSTR_UTYPE_MAX | ||||
| #undef XSTR_TYPE_MAX | ||||
| #undef XSTR_TYPE_MIN | ||||
| #undef XSTR_STRTOU | ||||
|   | ||||
| @@ -147,8 +147,8 @@ static FILE *dbf; | ||||
| static int bcode(const char *s) | ||||
| { | ||||
| 	int r; | ||||
| 	unsigned value; | ||||
| 	if (safe_strtou((char *)s, &value)) { | ||||
| 	unsigned value = bb_strtou(s, NULL, 10); | ||||
| 	if (errno) { | ||||
| 		return -1; | ||||
| 	} | ||||
| 	r = tty_value_to_baud(value); | ||||
|   | ||||
| @@ -124,7 +124,8 @@ int ftp_receive(ftp_host_info_t *server, FILE *control_stream, | ||||
| 	fd_data = xconnect_ftpdata(server, buf); | ||||
|  | ||||
| 	if (ftpcmd("SIZE ", server_path, control_stream, buf) == 213) { | ||||
| 		if (SAFE_STRTOOFF(buf + 4, &filesize)) | ||||
| 		filesize = BB_STRTOOFF(buf + 4, NULL, 10); | ||||
| 		if (errno || filesize < 0) | ||||
| 			bb_error_msg_and_die("SIZE error: %s", buf + 4); | ||||
| 	} else { | ||||
| 		filesize = -1; | ||||
|   | ||||
| @@ -64,7 +64,8 @@ static int read_str(const char *line, void *arg) | ||||
|  | ||||
| static int read_u32(const char *line, void *arg) | ||||
| { | ||||
| 	return safe_strtou32(line, (uint32_t*)arg) == 0; | ||||
| 	*((uint32_t*)arg) = bb_strtou32(line, NULL, 10); | ||||
| 	return errno == 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -101,7 +102,8 @@ static void attach_option(struct option_set **opt_list, | ||||
| 	struct option_set *existing, *new, **curr; | ||||
|  | ||||
| 	/* add it to an existing option */ | ||||
| 	if ((existing = find_option(*opt_list, option->code))) { | ||||
| 	existing = find_option(*opt_list, option->code); | ||||
| 	if (existing) { | ||||
| 		DEBUG("Attaching option %s to existing member of list", option->name); | ||||
| 		if (option->flags & OPTION_LIST) { | ||||
| 			if (existing->data[OPT_LEN] + length <= 255) { | ||||
|   | ||||
| @@ -335,7 +335,8 @@ int wget_main(int argc, char **argv) | ||||
| 			 */ | ||||
| 			while ((s = gethdr(buf, sizeof(buf), sfp, &n)) != NULL) { | ||||
| 				if (strcasecmp(buf, "content-length") == 0) { | ||||
| 					if (SAFE_STRTOOFF(s, &content_len) || content_len < 0) { | ||||
| 					content_len = BB_STRTOOFF(s, NULL, 10); | ||||
| 					if (errno || content_len < 0) { | ||||
| 						bb_error_msg_and_die("content-length %s is garbage", s); | ||||
| 					} | ||||
| 					got_clen = 1; | ||||
| @@ -402,7 +403,8 @@ int wget_main(int argc, char **argv) | ||||
| 		 * Querying file size | ||||
| 		 */ | ||||
| 		if (ftpcmd("SIZE ", target.path, sfp, buf) == 213) { | ||||
| 			if (SAFE_STRTOOFF(buf+4, &content_len) || content_len < 0) { | ||||
| 			content_len = BB_STRTOOFF(buf+4, NULL, 10); | ||||
| 			if (errno || content_len < 0) { | ||||
| 				bb_error_msg_and_die("SIZE value is garbage"); | ||||
| 			} | ||||
| 			got_clen = 1; | ||||
| @@ -437,7 +439,7 @@ int wget_main(int argc, char **argv) | ||||
| 		} | ||||
|  | ||||
| 		if (ftpcmd("RETR ", target.path, sfp, buf) > 150) | ||||
| 			bb_error_msg_and_die("bad response to %s: %s", "RETR", buf); | ||||
| 			bb_error_msg_and_die("bad response to RETR: %s", buf); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @@ -446,7 +448,7 @@ int wget_main(int argc, char **argv) | ||||
| 	 */ | ||||
| 	if (chunked) { | ||||
| 		fgets(buf, sizeof(buf), dfp); | ||||
| 		content_len = STRTOOFF(buf, (char **) NULL, 16); | ||||
| 		content_len = STRTOOFF(buf, NULL, 16); | ||||
| 		/* FIXME: error check?? */ | ||||
| 	} | ||||
|  | ||||
| @@ -480,7 +482,7 @@ int wget_main(int argc, char **argv) | ||||
| 		if (chunked) { | ||||
| 			safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */ | ||||
| 			safe_fgets(buf, sizeof(buf), dfp); | ||||
| 			content_len = STRTOOFF(buf, (char **) NULL, 16); | ||||
| 			content_len = STRTOOFF(buf, NULL, 16); | ||||
| 			/* FIXME: error check? */ | ||||
| 			if (content_len == 0) { | ||||
| 				chunked = 0; /* all done! */ | ||||
|   | ||||
| @@ -87,7 +87,8 @@ int renice_main(int argc, char **argv) | ||||
| 			} | ||||
| 			who = p->pw_uid; | ||||
| 		} else { | ||||
| 			if (safe_strtou(arg, &who)) { | ||||
| 			who = bb_strtou(arg, NULL, 10); | ||||
| 			if (errno) { | ||||
| 				bb_error_msg("bad value: %s", arg); | ||||
| 				goto HAD_ERROR; | ||||
| 			} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user