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;