diff options
author | Denis Vlasenko | 2006-10-08 12:49:22 +0000 |
---|---|---|
committer | Denis Vlasenko | 2006-10-08 12:49:22 +0000 |
commit | 1385899416a4396385ad421ae1f532be7103738a (patch) | |
tree | fc4d14a910593d1235318bb36abe5e9f72d2039e /libbb | |
parent | 5625415085e68ac5e150f54e685417c866620d76 (diff) | |
download | busybox-1385899416a4396385ad421ae1f532be7103738a.zip busybox-1385899416a4396385ad421ae1f532be7103738a.tar.gz |
attempt to regularize atoi mess.
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Kbuild | 6 | ||||
-rw-r--r-- | libbb/loop.c | 60 | ||||
-rw-r--r-- | libbb/parse_number.c | 50 | ||||
-rw-r--r-- | libbb/safe_strtol.c | 102 | ||||
-rw-r--r-- | libbb/xatol.c | 210 | ||||
-rw-r--r-- | libbb/xgetlarg.c | 32 | ||||
-rw-r--r-- | libbb/xgetularg.c | 127 |
7 files changed, 326 insertions, 261 deletions
diff --git a/libbb/Kbuild b/libbb/Kbuild index 909f527..4e992ef 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild @@ -15,7 +15,7 @@ lib-y:= \ human_readable.o inet_common.o inode_hash.o isdirectory.o \ kernel_version.o last_char_is.o login.o \ make_directory.o md5.o mode_string.o mtab_file.o \ - obscure.o parse_mode.o parse_number.o perror_msg.o \ + obscure.o parse_mode.o perror_msg.o \ perror_msg_and_die.o get_console.o \ process_escape_sequence.o procps.o \ recursive_action.o remove_file.o \ @@ -23,7 +23,7 @@ lib-y:= \ safe_strncpy.o setup_environment.o sha1.o simplify_path.o \ trim.o u_signal_names.o vdprintf.o verror_msg.o \ vherror_msg.o vperror_msg.o wfopen.o xconnect.o xgetcwd.o \ - xgethostbyname.o xgethostbyname2.o xreadlink.o xgetlarg.o \ + xgethostbyname.o xgethostbyname2.o xreadlink.o \ fclose_nonstdin.o fflush_stdout_and_exit.o \ getopt32.o default_error_retval.o wfopen_input.o speed_table.o \ perror_nomsg_and_die.o perror_nomsg.o skip_whitespace.o bb_askpass.o \ @@ -55,7 +55,7 @@ lib-$(CONFIG_DEVFSD) += xregcomp.o lib-y += messages.o lib-y += xfuncs.o lib-y += printf.o -lib-y += xgetularg.o +lib-y += xatol.o lib-y += safe_strtol.o lib-y += bb_pwd.o lib-y += llist.o diff --git a/libbb/loop.c b/libbb/loop.c index d22b398..1b296d9 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -48,11 +48,12 @@ char *query_loop(const char *device) { int fd; bb_loop_info loopinfo; - char *dev=0; + char *dev = 0; - if ((fd = open(device, O_RDONLY)) < 0) return 0; + fd = open(device, O_RDONLY); + if (fd < 0) return 0; if (!ioctl(fd, BB_LOOP_GET_STATUS, &loopinfo)) - dev=xasprintf("%ld %s", (long) loopinfo.lo_offset, + dev = xasprintf("%ld %s", (long) loopinfo.lo_offset, (char *)loopinfo.lo_file_name); close(fd); @@ -64,8 +65,9 @@ int del_loop(const char *device) { int fd, rc; - if ((fd = open(device, O_RDONLY)) < 0) return 1; - rc=ioctl(fd, LOOP_CLR_FD, 0); + fd = open(device, O_RDONLY); + if (fd < 0) return 1; + rc = ioctl(fd, LOOP_CLR_FD, 0); close(fd); return rc; @@ -77,7 +79,7 @@ int del_loop(const char *device) search will re-use an existing loop device already bound to that file/offset if it finds one. */ -int set_loop(char **device, const char *file, int offset) +int set_loop(char **device, const char *file, unsigned long long offset) { char dev[20], *try; bb_loop_info loopinfo; @@ -85,34 +87,43 @@ int set_loop(char **device, const char *file, int offset) int i, dfd, ffd, mode, rc=-1; /* Open the file. Barf if this doesn't work. */ - if((ffd = open(file, mode=O_RDWR))<0 && (ffd = open(file,mode=O_RDONLY))<0) - return -errno; + mode = O_RDWR; + ffd = open(file, mode); + if (ffd < 0) { + mode = O_RDONLY; + ffd = open(file, mode); + if (ffd < 0) + return -errno; + } /* Find a loop device. */ - try=*device ? : dev; - for(i=0;rc;i++) { + try = *device ? : dev; + for (i=0;rc;i++) { sprintf(dev, LOOP_FORMAT, i); /* Ran out of block devices, return failure. */ - if(stat(try, &statbuf) || !S_ISBLK(statbuf.st_mode)) { + if (stat(try, &statbuf) || !S_ISBLK(statbuf.st_mode)) { rc=-ENOENT; break; } /* Open the sucker and check its loopiness. */ - if((dfd=open(try, mode))<0 && errno==EROFS) - dfd=open(try, mode = O_RDONLY); - if(dfd<0) goto try_again; + dfd = open(try, mode); + if (dfd < 0 && errno == EROFS) { + mode = O_RDONLY; + dfd = open(try, mode); + } + if (dfd < 0) goto try_again; - rc=ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); + rc = ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); /* If device free, claim it. */ - if(rc && errno==ENXIO) { + if (rc && errno == ENXIO) { memset(&loopinfo, 0, sizeof(loopinfo)); safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); loopinfo.lo_offset = offset; /* Associate free loop device with file. */ - if(!ioctl(dfd, LOOP_SET_FD, ffd)) { - if (!ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo)) rc=0; + if (!ioctl(dfd, LOOP_SET_FD, ffd)) { + if (!ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo)) rc = 0; else ioctl(dfd, LOOP_CLR_FD, 0); } @@ -121,15 +132,16 @@ int set_loop(char **device, const char *file, int offset) file isn't pretty either. In general, mounting the same file twice without using losetup manually is problematic.) */ - } else if(strcmp(file,(char *)loopinfo.lo_file_name) - || offset!=loopinfo.lo_offset) rc=-1; + } else if (strcmp(file,(char *)loopinfo.lo_file_name) + || offset!=loopinfo.lo_offset) rc = -1; close(dfd); try_again: - if(*device) break; + if (*device) break; } close(ffd); - if(!rc) { - if(!*device) *device=strdup(dev); + if (!rc) { + if (!*device) *device = strdup(dev); return mode==O_RDONLY ? 1 : 0; - } else return rc; + } + return rc; } diff --git a/libbb/parse_number.c b/libbb/parse_number.c deleted file mode 100644 index c7dafb7..0000000 --- a/libbb/parse_number.c +++ /dev/null @@ -1,50 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * bb_xparse_number implementation for busybox - * - * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ - -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <errno.h> -#include <assert.h> -#include "libbb.h" - -unsigned long bb_xparse_number(const char *numstr, - const struct suffix_mult *suffixes) -{ - unsigned long int r; - char *e; - int old_errno; - - /* Since this is a lib function, we're not allowed to reset errno to 0. - * Doing so could break an app that is deferring checking of errno. - * So, save the old value so that we can restore it if successful. */ - old_errno = errno; - errno = 0; - r = strtoul(numstr, &e, 10); - - if ((numstr != e) && !errno) { - errno = old_errno; /* Ok. So restore errno. */ - if (!*e) { - return r; - } - if (suffixes) { - assert(suffixes->suffix); /* No nul suffixes. */ - do { - if (strcmp(suffixes->suffix, e) == 0) { - if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */ - break; - } - return r * suffixes->mult; - } - ++suffixes; - } while (suffixes->suffix); - } - } - bb_error_msg_and_die("invalid number '%s'", numstr); -} diff --git a/libbb/safe_strtol.c b/libbb/safe_strtol.c index 027fc1e..a7f012f 100644 --- a/libbb/safe_strtol.c +++ b/libbb/safe_strtol.c @@ -7,21 +7,10 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include <stdlib.h> -#include <errno.h> #include <assert.h> #include "libbb.h" -int safe_strtoi(char *arg, int* value) -{ - int error; - long lvalue = *value; - error = safe_strtol(arg, &lvalue); - *value = (int) lvalue; - return error; -} - -int safe_strtod(char *arg, double* value) +int safe_strtod(const char *arg, double* value) { char *endptr; int errno_save = errno; @@ -29,69 +18,132 @@ int safe_strtod(char *arg, double* value) assert(arg!=NULL); errno = 0; *value = strtod(arg, &endptr); - if (errno != 0 || *endptr!='\0' || endptr==arg) { + if (errno != 0 || *endptr != '\0' || endptr == arg) { return 1; } errno = errno_save; return 0; } -int safe_strtol(char *arg, long* value) +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 = strtol(arg, &endptr, 0); - if (errno != 0 || *endptr!='\0' || endptr==arg) { + *value = strtoull(arg, &endptr, 0); + if (errno != 0 || *endptr != '\0' || endptr == arg) { return 1; } errno = errno_save; return 0; } -int safe_strtoul(char *arg, unsigned long* value) +int safe_strtoll(const char *arg, long long* value) { char *endptr; int errno_save = errno; assert(arg!=NULL); errno = 0; - *value = strtoul(arg, &endptr, 0); - if (errno != 0 || *endptr!='\0' || endptr==arg) { + *value = strtoll(arg, &endptr, 0); + if (errno != 0 || *endptr != '\0' || endptr == arg) { return 1; } errno = errno_save; return 0; } -int safe_strtoll(char *arg, long long* value) +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 = strtoll(arg, &endptr, 0); - if (errno != 0 || *endptr!='\0' || endptr==arg) { + *value = strtoul(arg, &endptr, 0); + if (errno != 0 || *endptr != '\0' || endptr == arg) { return 1; } errno = errno_save; return 0; } -int safe_strtoull(char *arg, unsigned long long* value) +int safe_strtol(const char *arg, long* value) { char *endptr; int errno_save = errno; assert(arg!=NULL); errno = 0; - *value = strtoull(arg, &endptr, 0); - if (errno != 0 || *endptr!='\0' || endptr==arg) { + *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) +{ + if (sizeof(long) == sizeof(int)) { + return safe_strtol(arg, (long*)value); + } else { + int error; + long 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) +{ + if (sizeof(unsigned long) == sizeof(unsigned)) { + return safe_strtoul(arg, (unsigned long*)value); + } else { + int error; + unsigned long 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(); +} diff --git a/libbb/xatol.c b/libbb/xatol.c new file mode 100644 index 0000000..82250a7 --- /dev/null +++ b/libbb/xatol.c @@ -0,0 +1,210 @@ +/* vi: set sw=4 ts=4: */ +/* + * ascii-to-numbers implementations for busybox + * + * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ + +#include "libbb.h" + +unsigned long long xatoull(const char *numstr) +{ + unsigned long long r; + int old_errno; + char *e; + if ((*numstr == '-') || (isspace)(*numstr)) + bb_error_msg_and_die("invalid number '%s'", numstr); + old_errno = errno; + errno = 0; + r = strtoull(numstr, &e, 10); + if (errno || (numstr == e) || *e) + /* Error / no digits / illegal trailing chars */ + bb_error_msg_and_die("invalid number '%s'", numstr); + /* No error. So restore errno. */ + errno = old_errno; + return r; +} + +unsigned long xstrtoul_range_sfx(const char *numstr, int base, + unsigned long lower, + unsigned long upper, + const struct suffix_mult *suffixes) +{ + unsigned long r; + int old_errno; + char *e; + + /* Disallow '-' and any leading whitespace. Speed isn't critical here + * since we're parsing commandline args. So make sure we get the + * actual isspace function rather than a lnumstrer macro implementaion. */ + if ((*numstr == '-') || (isspace)(*numstr)) + goto inval; + + /* Since this is a lib function, we're not allowed to reset errno to 0. + * Doing so could break an app that is deferring checking of errno. + * So, save the old value so that we can restore it if successful. */ + old_errno = errno; + errno = 0; + r = strtoul(numstr, &e, base); + /* Do the initial validity check. Note: The standards do not + * guarantee that errno is set if no digits were found. So we + * must test for this explicitly. */ + if (errno || (numstr == e)) + goto inval; /* error / no digits / illegal trailing chars */ + + errno = old_errno; /* Ok. So restore errno. */ + + /* Do optional suffix parsing. Allow 'empty' suffix tables. + * Note that we also allow nul suffixes with associated multipliers, + * to allow for scaling of the numstr by some default multiplier. */ + if (suffixes) { + while (suffixes->suffix) { + if (strcmp(suffixes->suffix, e) == 0) { + if (ULONG_MAX / suffixes->mult < r) + goto range; /* overflow! */ + ++e; + r *= suffixes->mult; + break; + } + ++suffixes; + } + } + + /* Note: trailing space is an error. + It would be easy enough to allow though if desired. */ + if (*e) + goto inval; + /* Finally, check for range limits. */ + if (r >= lower && r <= upper) + return r; + range: + bb_error_msg_and_die("number %s is not in %lu..%lu range", + numstr, lower, upper); + inval: + bb_error_msg_and_die("invalid number '%s'", numstr); +} + +unsigned long xstrtoul_range(const char *numstr, int base, + unsigned long lower, + unsigned long upper) +{ + return xstrtoul_range_sfx(numstr, base, lower, upper, NULL); +} + +unsigned long xstrtoul(const char *numstr, int base) +{ + return xstrtoul_range_sfx(numstr, base, 0, ULONG_MAX, NULL); +} + +unsigned long xatoul_range_sfx(const char *numstr, + unsigned long lower, + unsigned long upper, + const struct suffix_mult *suffixes) +{ + return xstrtoul_range_sfx(numstr, 10, lower, upper, suffixes); +} + +unsigned long xatoul_sfx(const char *numstr, + const struct suffix_mult *suffixes) +{ + return xstrtoul_range_sfx(numstr, 10, 0, ULONG_MAX, suffixes); +} + +unsigned long xatoul_range(const char *numstr, + unsigned long lower, + unsigned long upper) +{ + return xstrtol_range_sfx(numstr, 10, lower, upper, NULL); +} + +unsigned long xatoul(const char *numstr) +{ + return xatoul_sfx(numstr, NULL); +} + +/* Signed ones */ + +long xstrtol_range_sfx(const char *numstr, int base, + long lower, + long upper, + const struct suffix_mult *suffixes) +{ + unsigned long u = LONG_MAX; + long r; + const char *p = numstr; + + if ((p[0] == '-') && (p[1] != '+')) { + ++p; + ++u; /* two's complement */ + } + + r = xstrtoul_range_sfx(p, base, 0, u, suffixes); + + if (*numstr == '-') { + r = -r; + } + + if (r < lower || r > upper) { + bb_error_msg_and_die("number %s is not in %ld..%ld range", + numstr, lower, upper); + } + + return r; +} + +long xstrtol_range(const char *numstr, int base, long lower, long upper) +{ + return xstrtol_range_sfx(numstr, base, lower, upper, NULL); +} + +long xatol_range_sfx(const char *numstr, + long lower, + long upper, + const struct suffix_mult *suffixes) +{ + return xstrtol_range_sfx(numstr, 10, lower, upper, suffixes); +} + +long xatol_range(const char *numstr, long lower, long upper) +{ + return xstrtol_range_sfx(numstr, 10, lower, upper, NULL); +} + +long xatol_sfx(const char *numstr, const struct suffix_mult *suffixes) +{ + return xstrtol_range_sfx(numstr, 10, LONG_MIN, LONG_MAX, suffixes); +} + +long xatol(const char *numstr) +{ + return xstrtol_range_sfx(numstr, 10, LONG_MIN, LONG_MAX, NULL); +} + +/* Others */ + +unsigned xatou(const char *numstr) +{ + return xatoul_range(numstr, 0, UINT_MAX); +} + +int xatoi(const char *numstr) +{ + return xatol_range(numstr, INT_MIN, INT_MAX); +} + +int xatoi_u(const char *numstr) +{ + return xatoul_range(numstr, 0, INT_MAX); +} + +uint32_t xatou32(const char *numstr) +{ + return xatoul_range(numstr, 0, 0xffffffff); +} + +uint16_t xatou16(const char *numstr) +{ + return xatoul_range(numstr, 0, 0xffff); +} diff --git a/libbb/xgetlarg.c b/libbb/xgetlarg.c deleted file mode 100644 index 5b1e7b9..0000000 --- a/libbb/xgetlarg.c +++ /dev/null @@ -1,32 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Copyright (C) 2003-2004 Erik Andersen <andersen@codepoet.org> - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <getopt.h> -#include <errno.h> -#include <assert.h> -#include <ctype.h> - -#include "libbb.h" - -long bb_xgetlarg(const char *arg, int base, long lower, long upper) -{ - long result; - char *endptr; - int errno_save = errno; - - if (ENABLE_DEBUG && arg==NULL) - bb_error_msg_and_die("Null in xgetlarg."); - - errno = 0; - result = strtol(arg, &endptr, base); - if (errno != 0 || *endptr!='\0' || endptr==arg || result < lower || result > upper) - bb_show_usage(); - errno = errno_save; - return result; -} diff --git a/libbb/xgetularg.c b/libbb/xgetularg.c deleted file mode 100644 index 17ba581..0000000 --- a/libbb/xgetularg.c +++ /dev/null @@ -1,127 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * xgetularg* implementations for busybox - * - * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> - * - * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. - */ - -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <ctype.h> -#include <errno.h> -#include <assert.h> -#include "libbb.h" - -unsigned long bb_xgetularg_bnd_sfx(const char *arg, int base, - unsigned long lower, - unsigned long upper, - const struct suffix_mult *suffixes) -{ - unsigned long r; - int old_errno; - char *e; - - assert(arg); - - /* Disallow '-' and any leading whitespace. Speed isn't critical here - * since we're parsing commandline args. So make sure we get the - * actual isspace function rather than a larger macro implementaion. */ - if ((*arg == '-') || (isspace)(*arg)) { - bb_show_usage(); - } - - /* Since this is a lib function, we're not allowed to reset errno to 0. - * Doing so could break an app that is deferring checking of errno. - * So, save the old value so that we can restore it if successful. */ - old_errno = errno; - errno = 0; - r = strtoul(arg, &e, base); - /* Do the initial validity check. Note: The standards do not - * guarantee that errno is set if no digits were found. So we - * must test for this explicitly. */ - if (errno || (arg == e)) { /* error or no digits */ - bb_show_usage(); - } - errno = old_errno; /* Ok. So restore errno. */ - - /* Do optional suffix parsing. Allow 'empty' suffix tables. - * Note that we also all nul suffixes with associated multipliers, - * to allow for scaling of the arg by some default multiplier. */ - - if (suffixes) { - while (suffixes->suffix) { - if (strcmp(suffixes->suffix, e) == 0) { - if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */ - bb_show_usage(); - } - ++e; - r *= suffixes->mult; - break; - } - ++suffixes; - } - } - - /* Finally, check for illegal trailing chars and range limits. */ - /* Note: although we allow leading space (via stroul), trailing space - * is an error. It would be easy enough to allow though if desired. */ - if (*e || (r < lower) || (r > upper)) { - bb_show_usage(); - } - - return r; -} - -long bb_xgetlarg_bnd_sfx(const char *arg, int base, - long lower, - long upper, - const struct suffix_mult *suffixes) -{ - unsigned long u = LONG_MAX; - long r; - const char *p = arg; - - if ((*p == '-') && (p[1] != '+')) { - ++p; - ++u; /* two's complement */ - } - - r = bb_xgetularg_bnd_sfx(p, base, 0, u, suffixes); - - if (*arg == '-') { - r = -r; - } - - if ((r < lower) || (r > upper)) { - bb_show_usage(); - } - - return r; -} - -long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes) -{ - return bb_xgetlarg_bnd_sfx(arg, 10, LONG_MIN, LONG_MAX, suffixes); -} - -unsigned long bb_xgetularg_bnd(const char *arg, int base, - unsigned long lower, - unsigned long upper) -{ - return bb_xgetularg_bnd_sfx(arg, base, lower, upper, NULL); -} - -unsigned long bb_xgetularg10_bnd(const char *arg, - unsigned long lower, - unsigned long upper) -{ - return bb_xgetularg_bnd(arg, 10, lower, upper); -} - -unsigned long bb_xgetularg10(const char *arg) -{ - return bb_xgetularg10_bnd(arg, 0, ULONG_MAX); -} |