diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index aa9fd777c..72bb5325e 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -642,7 +642,26 @@ extern time_t my_timegm(const struct tm *tm); * is left untouched. */ extern const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags); -extern const char *parse_size_err(const char *text, unsigned *ret); +extern const char *parse_size_ui(const char *text, unsigned *ret); +extern const char *parse_size_ull(const char *text, ullong *ret); + +/* Parse a size from <_test> into <_ret> which must be compatible with a + * uint or ullong. The return value is a pointer to the first unparsable + * character (if any) or NULL if everything's OK. + */ +#define parse_size_err(_text, _ret) ({ \ + const char *_err; \ + if (sizeof(*(_ret)) > sizeof(int)) { \ + unsigned long long _tmp; \ + _err = parse_size_ull(_text, &_tmp); \ + *_ret = _tmp; \ + } else { \ + unsigned int _tmp; \ + _err = parse_size_ui(_text, &_tmp); \ + *_ret = _tmp; \ + } \ + _err; \ +}) /* * Parse binary string written in hexadecimal (source) and store the decoded diff --git a/src/tools.c b/src/tools.c index d2decb69b..224c5df97 100644 --- a/src/tools.c +++ b/src/tools.c @@ -2780,7 +2780,8 @@ const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags) * stored in . If an error is detected, the pointer to the unexpected * character is returned. If the conversion is successful, NULL is returned. */ -const char *parse_size_err(const char *text, unsigned *ret) { +const char *parse_size_ui(const char *text, unsigned *ret) +{ unsigned value = 0; if (!isdigit((unsigned char)*text)) @@ -2833,6 +2834,76 @@ const char *parse_size_err(const char *text, unsigned *ret) { return NULL; } +/* this function converts the string starting at to an ullong stored in + * . If an error is detected, the pointer to the unexpected character is + * returned. If the conversion is successful, NULL is returned. + */ +const char *parse_size_ull(const char *text, ullong *ret) +{ + ullong value = 0; + + if (!isdigit((unsigned char)*text)) + return text; + + while (1) { + unsigned int j; + + j = *text - '0'; + if (j > 9) + break; + if (value > ~0ULL / 10) + return text; + value *= 10; + if (value > (value + j)) + return text; + value += j; + text++; + } + + switch (*text) { + case '\0': + break; + case 'K': + case 'k': + if (value > ~0ULL >> 10) + return text; + value = value << 10; + break; + case 'M': + case 'm': + if (value > ~0ULL >> 20) + return text; + value = value << 20; + break; + case 'G': + case 'g': + if (value > ~0ULL >> 30) + return text; + value = value << 30; + break; + case 'T': + case 't': + if (value > ~0ULL >> 40) + return text; + value = value << 40; + break; + case 'P': + case 'p': + if (value > ~0ULL >> 50) + return text; + value = value << 50; + break; + default: + return text; + } + + if (*text != '\0' && *++text != '\0') + return text; + + *ret = value; + return NULL; +} + /* * Parse binary string written in hexadecimal (source) and store the decoded * result into binstr and set binstrlen to the length of binstr. Memory for