diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-10-08 12:49:22 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-10-08 12:49:22 +0000 |
commit | 87d25a2b8535dc627a02eb539fa3946be2a24647 (patch) | |
tree | fc4d14a910593d1235318bb36abe5e9f72d2039e /libbb | |
parent | 81177b14907e73f11560f69e0b4ec34371f1a7d5 (diff) | |
download | busybox-w32-87d25a2b8535dc627a02eb539fa3946be2a24647.tar.gz busybox-w32-87d25a2b8535dc627a02eb539fa3946be2a24647.tar.bz2 busybox-w32-87d25a2b8535dc627a02eb539fa3946be2a24647.zip |
attempt to regularize atoi mess.
git-svn-id: svn://busybox.net/trunk/busybox@16342 69ca8d6d-28ef-0310-b511-8ec308f3f277
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 909f527ba..4e992ef5b 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild | |||
@@ -15,7 +15,7 @@ lib-y:= \ | |||
15 | human_readable.o inet_common.o inode_hash.o isdirectory.o \ | 15 | human_readable.o inet_common.o inode_hash.o isdirectory.o \ |
16 | kernel_version.o last_char_is.o login.o \ | 16 | kernel_version.o last_char_is.o login.o \ |
17 | make_directory.o md5.o mode_string.o mtab_file.o \ | 17 | make_directory.o md5.o mode_string.o mtab_file.o \ |
18 | obscure.o parse_mode.o parse_number.o perror_msg.o \ | 18 | obscure.o parse_mode.o perror_msg.o \ |
19 | perror_msg_and_die.o get_console.o \ | 19 | perror_msg_and_die.o get_console.o \ |
20 | process_escape_sequence.o procps.o \ | 20 | process_escape_sequence.o procps.o \ |
21 | recursive_action.o remove_file.o \ | 21 | recursive_action.o remove_file.o \ |
@@ -23,7 +23,7 @@ lib-y:= \ | |||
23 | safe_strncpy.o setup_environment.o sha1.o simplify_path.o \ | 23 | safe_strncpy.o setup_environment.o sha1.o simplify_path.o \ |
24 | trim.o u_signal_names.o vdprintf.o verror_msg.o \ | 24 | trim.o u_signal_names.o vdprintf.o verror_msg.o \ |
25 | vherror_msg.o vperror_msg.o wfopen.o xconnect.o xgetcwd.o \ | 25 | vherror_msg.o vperror_msg.o wfopen.o xconnect.o xgetcwd.o \ |
26 | xgethostbyname.o xgethostbyname2.o xreadlink.o xgetlarg.o \ | 26 | xgethostbyname.o xgethostbyname2.o xreadlink.o \ |
27 | fclose_nonstdin.o fflush_stdout_and_exit.o \ | 27 | fclose_nonstdin.o fflush_stdout_and_exit.o \ |
28 | getopt32.o default_error_retval.o wfopen_input.o speed_table.o \ | 28 | getopt32.o default_error_retval.o wfopen_input.o speed_table.o \ |
29 | perror_nomsg_and_die.o perror_nomsg.o skip_whitespace.o bb_askpass.o \ | 29 | perror_nomsg_and_die.o perror_nomsg.o skip_whitespace.o bb_askpass.o \ |
@@ -55,7 +55,7 @@ lib-$(CONFIG_DEVFSD) += xregcomp.o | |||
55 | lib-y += messages.o | 55 | lib-y += messages.o |
56 | lib-y += xfuncs.o | 56 | lib-y += xfuncs.o |
57 | lib-y += printf.o | 57 | lib-y += printf.o |
58 | lib-y += xgetularg.o | 58 | lib-y += xatol.o |
59 | lib-y += safe_strtol.o | 59 | lib-y += safe_strtol.o |
60 | lib-y += bb_pwd.o | 60 | lib-y += bb_pwd.o |
61 | lib-y += llist.o | 61 | lib-y += llist.o |
diff --git a/libbb/loop.c b/libbb/loop.c index d22b39800..1b296d99b 100644 --- a/libbb/loop.c +++ b/libbb/loop.c | |||
@@ -48,11 +48,12 @@ char *query_loop(const char *device) | |||
48 | { | 48 | { |
49 | int fd; | 49 | int fd; |
50 | bb_loop_info loopinfo; | 50 | bb_loop_info loopinfo; |
51 | char *dev=0; | 51 | char *dev = 0; |
52 | 52 | ||
53 | if ((fd = open(device, O_RDONLY)) < 0) return 0; | 53 | fd = open(device, O_RDONLY); |
54 | if (fd < 0) return 0; | ||
54 | if (!ioctl(fd, BB_LOOP_GET_STATUS, &loopinfo)) | 55 | if (!ioctl(fd, BB_LOOP_GET_STATUS, &loopinfo)) |
55 | dev=xasprintf("%ld %s", (long) loopinfo.lo_offset, | 56 | dev = xasprintf("%ld %s", (long) loopinfo.lo_offset, |
56 | (char *)loopinfo.lo_file_name); | 57 | (char *)loopinfo.lo_file_name); |
57 | close(fd); | 58 | close(fd); |
58 | 59 | ||
@@ -64,8 +65,9 @@ int del_loop(const char *device) | |||
64 | { | 65 | { |
65 | int fd, rc; | 66 | int fd, rc; |
66 | 67 | ||
67 | if ((fd = open(device, O_RDONLY)) < 0) return 1; | 68 | fd = open(device, O_RDONLY); |
68 | rc=ioctl(fd, LOOP_CLR_FD, 0); | 69 | if (fd < 0) return 1; |
70 | rc = ioctl(fd, LOOP_CLR_FD, 0); | ||
69 | close(fd); | 71 | close(fd); |
70 | 72 | ||
71 | return rc; | 73 | return rc; |
@@ -77,7 +79,7 @@ int del_loop(const char *device) | |||
77 | search will re-use an existing loop device already bound to that | 79 | search will re-use an existing loop device already bound to that |
78 | file/offset if it finds one. | 80 | file/offset if it finds one. |
79 | */ | 81 | */ |
80 | int set_loop(char **device, const char *file, int offset) | 82 | int set_loop(char **device, const char *file, unsigned long long offset) |
81 | { | 83 | { |
82 | char dev[20], *try; | 84 | char dev[20], *try; |
83 | bb_loop_info loopinfo; | 85 | bb_loop_info loopinfo; |
@@ -85,34 +87,43 @@ int set_loop(char **device, const char *file, int offset) | |||
85 | int i, dfd, ffd, mode, rc=-1; | 87 | int i, dfd, ffd, mode, rc=-1; |
86 | 88 | ||
87 | /* Open the file. Barf if this doesn't work. */ | 89 | /* Open the file. Barf if this doesn't work. */ |
88 | if((ffd = open(file, mode=O_RDWR))<0 && (ffd = open(file,mode=O_RDONLY))<0) | 90 | mode = O_RDWR; |
89 | return -errno; | 91 | ffd = open(file, mode); |
92 | if (ffd < 0) { | ||
93 | mode = O_RDONLY; | ||
94 | ffd = open(file, mode); | ||
95 | if (ffd < 0) | ||
96 | return -errno; | ||
97 | } | ||
90 | 98 | ||
91 | /* Find a loop device. */ | 99 | /* Find a loop device. */ |
92 | try=*device ? : dev; | 100 | try = *device ? : dev; |
93 | for(i=0;rc;i++) { | 101 | for (i=0;rc;i++) { |
94 | sprintf(dev, LOOP_FORMAT, i); | 102 | sprintf(dev, LOOP_FORMAT, i); |
95 | 103 | ||
96 | /* Ran out of block devices, return failure. */ | 104 | /* Ran out of block devices, return failure. */ |
97 | if(stat(try, &statbuf) || !S_ISBLK(statbuf.st_mode)) { | 105 | if (stat(try, &statbuf) || !S_ISBLK(statbuf.st_mode)) { |
98 | rc=-ENOENT; | 106 | rc=-ENOENT; |
99 | break; | 107 | break; |
100 | } | 108 | } |
101 | /* Open the sucker and check its loopiness. */ | 109 | /* Open the sucker and check its loopiness. */ |
102 | if((dfd=open(try, mode))<0 && errno==EROFS) | 110 | dfd = open(try, mode); |
103 | dfd=open(try, mode = O_RDONLY); | 111 | if (dfd < 0 && errno == EROFS) { |
104 | if(dfd<0) goto try_again; | 112 | mode = O_RDONLY; |
113 | dfd = open(try, mode); | ||
114 | } | ||
115 | if (dfd < 0) goto try_again; | ||
105 | 116 | ||
106 | rc=ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); | 117 | rc = ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo); |
107 | 118 | ||
108 | /* If device free, claim it. */ | 119 | /* If device free, claim it. */ |
109 | if(rc && errno==ENXIO) { | 120 | if (rc && errno == ENXIO) { |
110 | memset(&loopinfo, 0, sizeof(loopinfo)); | 121 | memset(&loopinfo, 0, sizeof(loopinfo)); |
111 | safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); | 122 | safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE); |
112 | loopinfo.lo_offset = offset; | 123 | loopinfo.lo_offset = offset; |
113 | /* Associate free loop device with file. */ | 124 | /* Associate free loop device with file. */ |
114 | if(!ioctl(dfd, LOOP_SET_FD, ffd)) { | 125 | if (!ioctl(dfd, LOOP_SET_FD, ffd)) { |
115 | if (!ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo)) rc=0; | 126 | if (!ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo)) rc = 0; |
116 | else ioctl(dfd, LOOP_CLR_FD, 0); | 127 | else ioctl(dfd, LOOP_CLR_FD, 0); |
117 | } | 128 | } |
118 | 129 | ||
@@ -121,15 +132,16 @@ int set_loop(char **device, const char *file, int offset) | |||
121 | file isn't pretty either. In general, mounting the same file twice | 132 | file isn't pretty either. In general, mounting the same file twice |
122 | without using losetup manually is problematic.) | 133 | without using losetup manually is problematic.) |
123 | */ | 134 | */ |
124 | } else if(strcmp(file,(char *)loopinfo.lo_file_name) | 135 | } else if (strcmp(file,(char *)loopinfo.lo_file_name) |
125 | || offset!=loopinfo.lo_offset) rc=-1; | 136 | || offset!=loopinfo.lo_offset) rc = -1; |
126 | close(dfd); | 137 | close(dfd); |
127 | try_again: | 138 | try_again: |
128 | if(*device) break; | 139 | if (*device) break; |
129 | } | 140 | } |
130 | close(ffd); | 141 | close(ffd); |
131 | if(!rc) { | 142 | if (!rc) { |
132 | if(!*device) *device=strdup(dev); | 143 | if (!*device) *device = strdup(dev); |
133 | return mode==O_RDONLY ? 1 : 0; | 144 | return mode==O_RDONLY ? 1 : 0; |
134 | } else return rc; | 145 | } |
146 | return rc; | ||
135 | } | 147 | } |
diff --git a/libbb/parse_number.c b/libbb/parse_number.c deleted file mode 100644 index c7dafb7f0..000000000 --- a/libbb/parse_number.c +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * bb_xparse_number implementation for busybox | ||
4 | * | ||
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | #include <stdlib.h> | ||
11 | #include <string.h> | ||
12 | #include <limits.h> | ||
13 | #include <errno.h> | ||
14 | #include <assert.h> | ||
15 | #include "libbb.h" | ||
16 | |||
17 | unsigned long bb_xparse_number(const char *numstr, | ||
18 | const struct suffix_mult *suffixes) | ||
19 | { | ||
20 | unsigned long int r; | ||
21 | char *e; | ||
22 | int old_errno; | ||
23 | |||
24 | /* Since this is a lib function, we're not allowed to reset errno to 0. | ||
25 | * Doing so could break an app that is deferring checking of errno. | ||
26 | * So, save the old value so that we can restore it if successful. */ | ||
27 | old_errno = errno; | ||
28 | errno = 0; | ||
29 | r = strtoul(numstr, &e, 10); | ||
30 | |||
31 | if ((numstr != e) && !errno) { | ||
32 | errno = old_errno; /* Ok. So restore errno. */ | ||
33 | if (!*e) { | ||
34 | return r; | ||
35 | } | ||
36 | if (suffixes) { | ||
37 | assert(suffixes->suffix); /* No nul suffixes. */ | ||
38 | do { | ||
39 | if (strcmp(suffixes->suffix, e) == 0) { | ||
40 | if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */ | ||
41 | break; | ||
42 | } | ||
43 | return r * suffixes->mult; | ||
44 | } | ||
45 | ++suffixes; | ||
46 | } while (suffixes->suffix); | ||
47 | } | ||
48 | } | ||
49 | bb_error_msg_and_die("invalid number '%s'", numstr); | ||
50 | } | ||
diff --git a/libbb/safe_strtol.c b/libbb/safe_strtol.c index 027fc1e62..a7f012fbc 100644 --- a/libbb/safe_strtol.c +++ b/libbb/safe_strtol.c | |||
@@ -7,21 +7,10 @@ | |||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <stdlib.h> | ||
11 | #include <errno.h> | ||
12 | #include <assert.h> | 10 | #include <assert.h> |
13 | #include "libbb.h" | 11 | #include "libbb.h" |
14 | 12 | ||
15 | int safe_strtoi(char *arg, int* value) | 13 | int safe_strtod(const char *arg, double* value) |
16 | { | ||
17 | int error; | ||
18 | long lvalue = *value; | ||
19 | error = safe_strtol(arg, &lvalue); | ||
20 | *value = (int) lvalue; | ||
21 | return error; | ||
22 | } | ||
23 | |||
24 | int safe_strtod(char *arg, double* value) | ||
25 | { | 14 | { |
26 | char *endptr; | 15 | char *endptr; |
27 | int errno_save = errno; | 16 | int errno_save = errno; |
@@ -29,69 +18,132 @@ int safe_strtod(char *arg, double* value) | |||
29 | assert(arg!=NULL); | 18 | assert(arg!=NULL); |
30 | errno = 0; | 19 | errno = 0; |
31 | *value = strtod(arg, &endptr); | 20 | *value = strtod(arg, &endptr); |
32 | if (errno != 0 || *endptr!='\0' || endptr==arg) { | 21 | if (errno != 0 || *endptr != '\0' || endptr == arg) { |
33 | return 1; | 22 | return 1; |
34 | } | 23 | } |
35 | errno = errno_save; | 24 | errno = errno_save; |
36 | return 0; | 25 | return 0; |
37 | } | 26 | } |
38 | 27 | ||
39 | int safe_strtol(char *arg, long* value) | 28 | int safe_strtoull(const char *arg, unsigned long long* value) |
40 | { | 29 | { |
41 | char *endptr; | 30 | char *endptr; |
42 | int errno_save = errno; | 31 | int errno_save = errno; |
43 | 32 | ||
44 | assert(arg!=NULL); | 33 | assert(arg!=NULL); |
34 | if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */ | ||
35 | return 1; | ||
45 | errno = 0; | 36 | errno = 0; |
46 | *value = strtol(arg, &endptr, 0); | 37 | *value = strtoull(arg, &endptr, 0); |
47 | if (errno != 0 || *endptr!='\0' || endptr==arg) { | 38 | if (errno != 0 || *endptr != '\0' || endptr == arg) { |
48 | return 1; | 39 | return 1; |
49 | } | 40 | } |
50 | errno = errno_save; | 41 | errno = errno_save; |
51 | return 0; | 42 | return 0; |
52 | } | 43 | } |
53 | 44 | ||
54 | int safe_strtoul(char *arg, unsigned long* value) | 45 | int safe_strtoll(const char *arg, long long* value) |
55 | { | 46 | { |
56 | char *endptr; | 47 | char *endptr; |
57 | int errno_save = errno; | 48 | int errno_save = errno; |
58 | 49 | ||
59 | assert(arg!=NULL); | 50 | assert(arg!=NULL); |
60 | errno = 0; | 51 | errno = 0; |
61 | *value = strtoul(arg, &endptr, 0); | 52 | *value = strtoll(arg, &endptr, 0); |
62 | if (errno != 0 || *endptr!='\0' || endptr==arg) { | 53 | if (errno != 0 || *endptr != '\0' || endptr == arg) { |
63 | return 1; | 54 | return 1; |
64 | } | 55 | } |
65 | errno = errno_save; | 56 | errno = errno_save; |
66 | return 0; | 57 | return 0; |
67 | } | 58 | } |
68 | 59 | ||
69 | int safe_strtoll(char *arg, long long* value) | 60 | int safe_strtoul(const char *arg, unsigned long* value) |
70 | { | 61 | { |
71 | char *endptr; | 62 | char *endptr; |
72 | int errno_save = errno; | 63 | int errno_save = errno; |
73 | 64 | ||
74 | assert(arg!=NULL); | 65 | assert(arg!=NULL); |
66 | if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */ | ||
67 | return 1; | ||
75 | errno = 0; | 68 | errno = 0; |
76 | *value = strtoll(arg, &endptr, 0); | 69 | *value = strtoul(arg, &endptr, 0); |
77 | if (errno != 0 || *endptr!='\0' || endptr==arg) { | 70 | if (errno != 0 || *endptr != '\0' || endptr == arg) { |
78 | return 1; | 71 | return 1; |
79 | } | 72 | } |
80 | errno = errno_save; | 73 | errno = errno_save; |
81 | return 0; | 74 | return 0; |
82 | } | 75 | } |
83 | 76 | ||
84 | int safe_strtoull(char *arg, unsigned long long* value) | 77 | int safe_strtol(const char *arg, long* value) |
85 | { | 78 | { |
86 | char *endptr; | 79 | char *endptr; |
87 | int errno_save = errno; | 80 | int errno_save = errno; |
88 | 81 | ||
89 | assert(arg!=NULL); | 82 | assert(arg!=NULL); |
90 | errno = 0; | 83 | errno = 0; |
91 | *value = strtoull(arg, &endptr, 0); | 84 | *value = strtol(arg, &endptr, 0); |
92 | if (errno != 0 || *endptr!='\0' || endptr==arg) { | 85 | if (errno != 0 || *endptr != '\0' || endptr == arg) { |
93 | return 1; | 86 | return 1; |
94 | } | 87 | } |
95 | errno = errno_save; | 88 | errno = errno_save; |
96 | return 0; | 89 | return 0; |
97 | } | 90 | } |
91 | |||
92 | /* TODO: This is what uclibc is doing. Try to do the same? */ | ||
93 | |||
94 | #if 0 | ||
95 | #if defined __HAVE_ELF__ | ||
96 | |||
97 | # define strong_alias(name, aliasname) _strong_alias(name, aliasname) | ||
98 | # define _strong_alias(name, aliasname) \ | ||
99 | extern __typeof (name) aliasname __attribute__ ((alias (#name))); | ||
100 | |||
101 | #else /* !defined __HAVE_ELF__ */ | ||
102 | |||
103 | # define strong_alias(name, aliasname) _strong_alias (name, aliasname) | ||
104 | # define _strong_alias(name, aliasname) \ | ||
105 | __asm__(".global " __C_SYMBOL_PREFIX__ #aliasname "\n" \ | ||
106 | ".set " __C_SYMBOL_PREFIX__ #aliasname "," __C_SYMBOL_PREFIX__ #name); | ||
107 | |||
108 | #endif | ||
109 | #endif | ||
110 | |||
111 | int safe_strtoi(const char *arg, int* value) | ||
112 | { | ||
113 | if (sizeof(long) == sizeof(int)) { | ||
114 | return safe_strtol(arg, (long*)value); | ||
115 | } else { | ||
116 | int error; | ||
117 | long lvalue = *value; | ||
118 | error = safe_strtol(arg, &lvalue); | ||
119 | if (lvalue < INT_MIN || lvalue > INT_MAX) | ||
120 | return 1; | ||
121 | *value = (int) lvalue; | ||
122 | return error; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | int safe_strtou(const char *arg, unsigned* value) | ||
127 | { | ||
128 | if (sizeof(unsigned long) == sizeof(unsigned)) { | ||
129 | return safe_strtoul(arg, (unsigned long*)value); | ||
130 | } else { | ||
131 | int error; | ||
132 | unsigned long lvalue = *value; | ||
133 | error = safe_strtoul(arg, &lvalue); | ||
134 | if (lvalue > UINT_MAX) | ||
135 | return 1; | ||
136 | *value = (unsigned) lvalue; | ||
137 | return error; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | int BUG_safe_strtou32_unimplemented(void); | ||
142 | int safe_strtou32(const char *arg, uint32_t* value) | ||
143 | { | ||
144 | if (sizeof(uint32_t) == sizeof(unsigned)) | ||
145 | return safe_strtou(arg, (unsigned*)value); | ||
146 | if (sizeof(uint32_t) == sizeof(unsigned long)) | ||
147 | return safe_strtoul(arg, (unsigned long*)value); | ||
148 | return BUG_safe_strtou32_unimplemented(); | ||
149 | } | ||
diff --git a/libbb/xatol.c b/libbb/xatol.c new file mode 100644 index 000000000..82250a7bb --- /dev/null +++ b/libbb/xatol.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * ascii-to-numbers implementations for busybox | ||
4 | * | ||
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | #include "libbb.h" | ||
11 | |||
12 | unsigned long long xatoull(const char *numstr) | ||
13 | { | ||
14 | unsigned long long r; | ||
15 | int old_errno; | ||
16 | char *e; | ||
17 | if ((*numstr == '-') || (isspace)(*numstr)) | ||
18 | bb_error_msg_and_die("invalid number '%s'", numstr); | ||
19 | old_errno = errno; | ||
20 | errno = 0; | ||
21 | r = strtoull(numstr, &e, 10); | ||
22 | if (errno || (numstr == e) || *e) | ||
23 | /* Error / no digits / illegal trailing chars */ | ||
24 | bb_error_msg_and_die("invalid number '%s'", numstr); | ||
25 | /* No error. So restore errno. */ | ||
26 | errno = old_errno; | ||
27 | return r; | ||
28 | } | ||
29 | |||
30 | unsigned long xstrtoul_range_sfx(const char *numstr, int base, | ||
31 | unsigned long lower, | ||
32 | unsigned long upper, | ||
33 | const struct suffix_mult *suffixes) | ||
34 | { | ||
35 | unsigned long r; | ||
36 | int old_errno; | ||
37 | char *e; | ||
38 | |||
39 | /* Disallow '-' and any leading whitespace. Speed isn't critical here | ||
40 | * since we're parsing commandline args. So make sure we get the | ||
41 | * actual isspace function rather than a lnumstrer macro implementaion. */ | ||
42 | if ((*numstr == '-') || (isspace)(*numstr)) | ||
43 | goto inval; | ||
44 | |||
45 | /* Since this is a lib function, we're not allowed to reset errno to 0. | ||
46 | * Doing so could break an app that is deferring checking of errno. | ||
47 | * So, save the old value so that we can restore it if successful. */ | ||
48 | old_errno = errno; | ||
49 | errno = 0; | ||
50 | r = strtoul(numstr, &e, base); | ||
51 | /* Do the initial validity check. Note: The standards do not | ||
52 | * guarantee that errno is set if no digits were found. So we | ||
53 | * must test for this explicitly. */ | ||
54 | if (errno || (numstr == e)) | ||
55 | goto inval; /* error / no digits / illegal trailing chars */ | ||
56 | |||
57 | errno = old_errno; /* Ok. So restore errno. */ | ||
58 | |||
59 | /* Do optional suffix parsing. Allow 'empty' suffix tables. | ||
60 | * Note that we also allow nul suffixes with associated multipliers, | ||
61 | * to allow for scaling of the numstr by some default multiplier. */ | ||
62 | if (suffixes) { | ||
63 | while (suffixes->suffix) { | ||
64 | if (strcmp(suffixes->suffix, e) == 0) { | ||
65 | if (ULONG_MAX / suffixes->mult < r) | ||
66 | goto range; /* overflow! */ | ||
67 | ++e; | ||
68 | r *= suffixes->mult; | ||
69 | break; | ||
70 | } | ||
71 | ++suffixes; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /* Note: trailing space is an error. | ||
76 | It would be easy enough to allow though if desired. */ | ||
77 | if (*e) | ||
78 | goto inval; | ||
79 | /* Finally, check for range limits. */ | ||
80 | if (r >= lower && r <= upper) | ||
81 | return r; | ||
82 | range: | ||
83 | bb_error_msg_and_die("number %s is not in %lu..%lu range", | ||
84 | numstr, lower, upper); | ||
85 | inval: | ||
86 | bb_error_msg_and_die("invalid number '%s'", numstr); | ||
87 | } | ||
88 | |||
89 | unsigned long xstrtoul_range(const char *numstr, int base, | ||
90 | unsigned long lower, | ||
91 | unsigned long upper) | ||
92 | { | ||
93 | return xstrtoul_range_sfx(numstr, base, lower, upper, NULL); | ||
94 | } | ||
95 | |||
96 | unsigned long xstrtoul(const char *numstr, int base) | ||
97 | { | ||
98 | return xstrtoul_range_sfx(numstr, base, 0, ULONG_MAX, NULL); | ||
99 | } | ||
100 | |||
101 | unsigned long xatoul_range_sfx(const char *numstr, | ||
102 | unsigned long lower, | ||
103 | unsigned long upper, | ||
104 | const struct suffix_mult *suffixes) | ||
105 | { | ||
106 | return xstrtoul_range_sfx(numstr, 10, lower, upper, suffixes); | ||
107 | } | ||
108 | |||
109 | unsigned long xatoul_sfx(const char *numstr, | ||
110 | const struct suffix_mult *suffixes) | ||
111 | { | ||
112 | return xstrtoul_range_sfx(numstr, 10, 0, ULONG_MAX, suffixes); | ||
113 | } | ||
114 | |||
115 | unsigned long xatoul_range(const char *numstr, | ||
116 | unsigned long lower, | ||
117 | unsigned long upper) | ||
118 | { | ||
119 | return xstrtol_range_sfx(numstr, 10, lower, upper, NULL); | ||
120 | } | ||
121 | |||
122 | unsigned long xatoul(const char *numstr) | ||
123 | { | ||
124 | return xatoul_sfx(numstr, NULL); | ||
125 | } | ||
126 | |||
127 | /* Signed ones */ | ||
128 | |||
129 | long xstrtol_range_sfx(const char *numstr, int base, | ||
130 | long lower, | ||
131 | long upper, | ||
132 | const struct suffix_mult *suffixes) | ||
133 | { | ||
134 | unsigned long u = LONG_MAX; | ||
135 | long r; | ||
136 | const char *p = numstr; | ||
137 | |||
138 | if ((p[0] == '-') && (p[1] != '+')) { | ||
139 | ++p; | ||
140 | ++u; /* two's complement */ | ||
141 | } | ||
142 | |||
143 | r = xstrtoul_range_sfx(p, base, 0, u, suffixes); | ||
144 | |||
145 | if (*numstr == '-') { | ||
146 | r = -r; | ||
147 | } | ||
148 | |||
149 | if (r < lower || r > upper) { | ||
150 | bb_error_msg_and_die("number %s is not in %ld..%ld range", | ||
151 | numstr, lower, upper); | ||
152 | } | ||
153 | |||
154 | return r; | ||
155 | } | ||
156 | |||
157 | long xstrtol_range(const char *numstr, int base, long lower, long upper) | ||
158 | { | ||
159 | return xstrtol_range_sfx(numstr, base, lower, upper, NULL); | ||
160 | } | ||
161 | |||
162 | long xatol_range_sfx(const char *numstr, | ||
163 | long lower, | ||
164 | long upper, | ||
165 | const struct suffix_mult *suffixes) | ||
166 | { | ||
167 | return xstrtol_range_sfx(numstr, 10, lower, upper, suffixes); | ||
168 | } | ||
169 | |||
170 | long xatol_range(const char *numstr, long lower, long upper) | ||
171 | { | ||
172 | return xstrtol_range_sfx(numstr, 10, lower, upper, NULL); | ||
173 | } | ||
174 | |||
175 | long xatol_sfx(const char *numstr, const struct suffix_mult *suffixes) | ||
176 | { | ||
177 | return xstrtol_range_sfx(numstr, 10, LONG_MIN, LONG_MAX, suffixes); | ||
178 | } | ||
179 | |||
180 | long xatol(const char *numstr) | ||
181 | { | ||
182 | return xstrtol_range_sfx(numstr, 10, LONG_MIN, LONG_MAX, NULL); | ||
183 | } | ||
184 | |||
185 | /* Others */ | ||
186 | |||
187 | unsigned xatou(const char *numstr) | ||
188 | { | ||
189 | return xatoul_range(numstr, 0, UINT_MAX); | ||
190 | } | ||
191 | |||
192 | int xatoi(const char *numstr) | ||
193 | { | ||
194 | return xatol_range(numstr, INT_MIN, INT_MAX); | ||
195 | } | ||
196 | |||
197 | int xatoi_u(const char *numstr) | ||
198 | { | ||
199 | return xatoul_range(numstr, 0, INT_MAX); | ||
200 | } | ||
201 | |||
202 | uint32_t xatou32(const char *numstr) | ||
203 | { | ||
204 | return xatoul_range(numstr, 0, 0xffffffff); | ||
205 | } | ||
206 | |||
207 | uint16_t xatou16(const char *numstr) | ||
208 | { | ||
209 | return xatoul_range(numstr, 0, 0xffff); | ||
210 | } | ||
diff --git a/libbb/xgetlarg.c b/libbb/xgetlarg.c deleted file mode 100644 index 5b1e7b9d5..000000000 --- a/libbb/xgetlarg.c +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Copyright (C) 2003-2004 Erik Andersen <andersen@codepoet.org> | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
6 | */ | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <getopt.h> | ||
11 | #include <errno.h> | ||
12 | #include <assert.h> | ||
13 | #include <ctype.h> | ||
14 | |||
15 | #include "libbb.h" | ||
16 | |||
17 | long bb_xgetlarg(const char *arg, int base, long lower, long upper) | ||
18 | { | ||
19 | long result; | ||
20 | char *endptr; | ||
21 | int errno_save = errno; | ||
22 | |||
23 | if (ENABLE_DEBUG && arg==NULL) | ||
24 | bb_error_msg_and_die("Null in xgetlarg."); | ||
25 | |||
26 | errno = 0; | ||
27 | result = strtol(arg, &endptr, base); | ||
28 | if (errno != 0 || *endptr!='\0' || endptr==arg || result < lower || result > upper) | ||
29 | bb_show_usage(); | ||
30 | errno = errno_save; | ||
31 | return result; | ||
32 | } | ||
diff --git a/libbb/xgetularg.c b/libbb/xgetularg.c deleted file mode 100644 index 17ba581f7..000000000 --- a/libbb/xgetularg.c +++ /dev/null | |||
@@ -1,127 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * xgetularg* implementations for busybox | ||
4 | * | ||
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | #include <stdlib.h> | ||
11 | #include <string.h> | ||
12 | #include <limits.h> | ||
13 | #include <ctype.h> | ||
14 | #include <errno.h> | ||
15 | #include <assert.h> | ||
16 | #include "libbb.h" | ||
17 | |||
18 | unsigned long bb_xgetularg_bnd_sfx(const char *arg, int base, | ||
19 | unsigned long lower, | ||
20 | unsigned long upper, | ||
21 | const struct suffix_mult *suffixes) | ||
22 | { | ||
23 | unsigned long r; | ||
24 | int old_errno; | ||
25 | char *e; | ||
26 | |||
27 | assert(arg); | ||
28 | |||
29 | /* Disallow '-' and any leading whitespace. Speed isn't critical here | ||
30 | * since we're parsing commandline args. So make sure we get the | ||
31 | * actual isspace function rather than a larger macro implementaion. */ | ||
32 | if ((*arg == '-') || (isspace)(*arg)) { | ||
33 | bb_show_usage(); | ||
34 | } | ||
35 | |||
36 | /* Since this is a lib function, we're not allowed to reset errno to 0. | ||
37 | * Doing so could break an app that is deferring checking of errno. | ||
38 | * So, save the old value so that we can restore it if successful. */ | ||
39 | old_errno = errno; | ||
40 | errno = 0; | ||
41 | r = strtoul(arg, &e, base); | ||
42 | /* Do the initial validity check. Note: The standards do not | ||
43 | * guarantee that errno is set if no digits were found. So we | ||
44 | * must test for this explicitly. */ | ||
45 | if (errno || (arg == e)) { /* error or no digits */ | ||
46 | bb_show_usage(); | ||
47 | } | ||
48 | errno = old_errno; /* Ok. So restore errno. */ | ||
49 | |||
50 | /* Do optional suffix parsing. Allow 'empty' suffix tables. | ||
51 | * Note that we also all nul suffixes with associated multipliers, | ||
52 | * to allow for scaling of the arg by some default multiplier. */ | ||
53 | |||
54 | if (suffixes) { | ||
55 | while (suffixes->suffix) { | ||
56 | if (strcmp(suffixes->suffix, e) == 0) { | ||
57 | if (ULONG_MAX / suffixes->mult < r) { /* Overflow! */ | ||
58 | bb_show_usage(); | ||
59 | } | ||
60 | ++e; | ||
61 | r *= suffixes->mult; | ||
62 | break; | ||
63 | } | ||
64 | ++suffixes; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | /* Finally, check for illegal trailing chars and range limits. */ | ||
69 | /* Note: although we allow leading space (via stroul), trailing space | ||
70 | * is an error. It would be easy enough to allow though if desired. */ | ||
71 | if (*e || (r < lower) || (r > upper)) { | ||
72 | bb_show_usage(); | ||
73 | } | ||
74 | |||
75 | return r; | ||
76 | } | ||
77 | |||
78 | long bb_xgetlarg_bnd_sfx(const char *arg, int base, | ||
79 | long lower, | ||
80 | long upper, | ||
81 | const struct suffix_mult *suffixes) | ||
82 | { | ||
83 | unsigned long u = LONG_MAX; | ||
84 | long r; | ||
85 | const char *p = arg; | ||
86 | |||
87 | if ((*p == '-') && (p[1] != '+')) { | ||
88 | ++p; | ||
89 | ++u; /* two's complement */ | ||
90 | } | ||
91 | |||
92 | r = bb_xgetularg_bnd_sfx(p, base, 0, u, suffixes); | ||
93 | |||
94 | if (*arg == '-') { | ||
95 | r = -r; | ||
96 | } | ||
97 | |||
98 | if ((r < lower) || (r > upper)) { | ||
99 | bb_show_usage(); | ||
100 | } | ||
101 | |||
102 | return r; | ||
103 | } | ||
104 | |||
105 | long bb_xgetlarg10_sfx(const char *arg, const struct suffix_mult *suffixes) | ||
106 | { | ||
107 | return bb_xgetlarg_bnd_sfx(arg, 10, LONG_MIN, LONG_MAX, suffixes); | ||
108 | } | ||
109 | |||
110 | unsigned long bb_xgetularg_bnd(const char *arg, int base, | ||
111 | unsigned long lower, | ||
112 | unsigned long upper) | ||
113 | { | ||
114 | return bb_xgetularg_bnd_sfx(arg, base, lower, upper, NULL); | ||
115 | } | ||
116 | |||
117 | unsigned long bb_xgetularg10_bnd(const char *arg, | ||
118 | unsigned long lower, | ||
119 | unsigned long upper) | ||
120 | { | ||
121 | return bb_xgetularg_bnd(arg, 10, lower, upper); | ||
122 | } | ||
123 | |||
124 | unsigned long bb_xgetularg10(const char *arg) | ||
125 | { | ||
126 | return bb_xgetularg10_bnd(arg, 0, ULONG_MAX); | ||
127 | } | ||