allow specifying larger /tmp tmpfs mounts Extract the size string-parsing and overflow-checking wrapper into util.c. Test: New unit tests. Change-Id: I31ba2f1a77217a2f13cda078e5e6a80104fbcd32 Signed-off-by: Martin Pelikán <[email protected]>
diff --git a/util.c b/util.c index d91d068..a96c71f 100644 --- a/util.c +++ b/util.c
@@ -7,6 +7,7 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <stdint.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> @@ -157,6 +158,56 @@ return value; } +/* + * parse_size, specified as a string with a decimal number in bytes, + * possibly with one 1-character suffix like "10K" or "6G". + * Assumes both pointers are non-NULL. + * + * Returns 0 on success, negative errno on failure. + * Only writes to result on success. + */ +int parse_size(size_t *result, const char *sizespec) +{ + const char prefixes[] = "KMGTPE"; + size_t i, multiplier = 1, nsize, size = 0; + unsigned long long parsed; + const size_t len = strlen(sizespec); + char *end; + + if (len == 0 || sizespec[0] == '-') + return -EINVAL; + + for (i = 0; i < sizeof(prefixes); ++i) { + if (sizespec[len - 1] == prefixes[i]) { +#if __WORDSIZE == 32 + if (i >= 3) + return -ERANGE; +#endif + multiplier = 1024; + while (i-- > 0) + multiplier *= 1024; + break; + } + } + + /* We only need size_t but strtoul(3) is too small on IL32P64. */ + parsed = strtoull(sizespec, &end, 10); + if (parsed == ULLONG_MAX) + return -errno; + if (parsed >= SIZE_MAX) + return -ERANGE; + if ((multiplier != 1 && end != sizespec + len - 1) || + (multiplier == 1 && end != sizespec + len)) + return -EINVAL; + size = (size_t)parsed; + + nsize = size * multiplier; + if (nsize / multiplier != size) + return -ERANGE; + *result = nsize; + return 0; +} + char *strip(char *s) { char *end;