#include "log.h"
#include "lxclock.h"
#include "namespace.h"
+#include "parse.h"
#include "utils.h"
#ifndef PR_SET_MM
return pgsz;
}
+
+int parse_byte_size_string(const char *s, int64_t *converted)
+{
+ int ret, suffix_len;
+ long long int conv;
+ int64_t mltpl, overflow;
+ char *end;
+ char dup[LXC_NUMSTRLEN64 + 2];
+ char suffix[3];
+
+ if (!s || !strcmp(s, ""))
+ return -EINVAL;
+
+ end = stpncpy(dup, s, sizeof(dup));
+ if (*end != '\0')
+ return -EINVAL;
+
+ if (isdigit(*(end - 1)))
+ suffix_len = 0;
+ else if (isalpha(*(end - 1)))
+ suffix_len = 1;
+ else
+ return -EINVAL;
+
+ if ((end - 2) == dup && !isdigit(*(end - 2)))
+ return -EINVAL;
+
+ if (isalpha(*(end - 2))) {
+ if (suffix_len == 1)
+ suffix_len++;
+ else
+ return -EINVAL;
+ }
+
+ if (suffix_len > 0) {
+ memcpy(suffix, end - suffix_len, suffix_len);
+ *(suffix + suffix_len) = '\0';
+ *(end - suffix_len) = '\0';
+ }
+ dup[lxc_char_right_gc(dup, strlen(dup))] = '\0';
+
+ ret = lxc_safe_long_long(dup, &conv);
+ if (ret < 0)
+ return -ret;
+
+ if (suffix_len != 2) {
+ *converted = conv;
+ return 0;
+ }
+
+ if (!strcmp(suffix, "kB"))
+ mltpl = 1024;
+ else if (!strcmp(suffix, "MB"))
+ mltpl = 1024 * 1024;
+ else if (!strcmp(suffix, "GB"))
+ mltpl = 1024 * 1024 * 1024;
+ else
+ return -EINVAL;
+
+ overflow = conv * mltpl;
+ if (conv != 0 && (overflow / conv) != mltpl)
+ return -ERANGE;
+
+ *converted = overflow;
+ return 0;
+}
extern int lxc_safe_long(const char *numstr, long int *converted);
extern int lxc_safe_long_long(const char *numstr, long long int *converted);
extern int lxc_safe_ulong(const char *numstr, unsigned long *converted);
+/* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
+extern int parse_byte_size_string(const char *s, int64_t *converted);
/* Switch to a new uid and gid. */
int lxc_switch_uid_gid(uid_t uid, gid_t gid);
lxc_test_assert_abort(lxc_string_in_array("XYZ", (const char *[]){"BERTA", "ARQWE(9", "C8Zhkd", "7U", "XYZ", "UOIZ9", "=)()", NULL}));
}
+void test_parse_byte_size_string(void)
+{
+ int ret;
+ int64_t n;
+
+ ret = parse_byte_size_string("0", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 0)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1 ", &n);
+ if (ret == 0)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1B", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1kB", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1024)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1MB", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1048576)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1GB", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1073741824)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1TB", &n);
+ if (ret == 0)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1 B", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1 kB", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1024)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1 MB", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1048576)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1 GB", &n);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+ if (n != 1073741824)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("1 TB", &n);
+ if (ret == 0)
+ exit(EXIT_FAILURE);
+
+ ret = parse_byte_size_string("asdf", &n);
+ if (ret == 0)
+ exit(EXIT_FAILURE);
+}
+
int main(int argc, char *argv[])
{
test_lxc_string_replace();
test_lxc_safe_uint();
test_lxc_safe_int();
test_lxc_safe_long();
+ test_parse_byte_size_string();
exit(EXIT_SUCCESS);
}