]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
util: Fix suffix_si_parse to parse no decimal point but suffix value correctly
authorTokunori Ikegami <ikegami.t@gmail.com>
Sun, 14 May 2023 08:39:00 +0000 (17:39 +0900)
committerDaniel Wagner <wagi@monom.org>
Mon, 15 May 2023 15:10:36 +0000 (17:10 +0200)
For example create-ns command --ncap-si paramter value 800G parsed to 0 as invalid value.

Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
unit/test-suffix-si-parse.c
util/suffix.c

index bc9245522687279c99cf7f2adf0660c0dd9d0e8e..54cff0e6441a7a2e55b4e0932d551ec592f5c44a 100644 (file)
@@ -43,6 +43,12 @@ static struct tonum_test tonum_tests[] = {
        { "2,33", 0, -EINVAL },
        { "3..3", 0, -EINVAL },
        { "123.12MM", 0, -EINVAL },
+       { "800G", 800000000000, 0 },
+       { "800GG", 0, -EINVAL },
+       { "800G800", 0, -EINVAL },
+       { "800.0G", 800000000000, 0 },
+       { "800.G", 0, -EINVAL },
+       { "800.", 0, -EINVAL },
 };
 
 void tonum_test(struct tonum_test *test)
index 8ed080d402ed953ce7a09d5bf944a6ee9bdaebc4..f010f3b6a9c46629ef1a36aea6782fed9ae9db61 100644 (file)
@@ -40,6 +40,7 @@
 #include <float.h>
 #include <limits.h>
 #include <locale.h>
+#include <stdio.h>
 
 static struct si_suffix {
        long double magnitude;
@@ -68,11 +69,26 @@ const char *suffix_si_get(double *value)
        return suffix;
 }
 
+static bool suffix_si_check(const char val)
+{
+       int i;
+       struct si_suffix *s;
+
+       for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) {
+               s = &si_suffixes[i];
+
+               if (val == *s->suffix)
+                       return true;
+       }
+
+       return false;
+}
+
 int suffix_si_parse(const char *str, char **endptr, uint64_t *val)
 {
-       unsigned long long num, frac;
+       unsigned long long num, frac = 0;
        char *sep, *tmp;
-       int frac_len, len, i;
+       int frac_len = 0, len, i;
 
        num = strtoull(str, endptr, 0);
        if (str == *endptr ||
@@ -93,23 +109,31 @@ int suffix_si_parse(const char *str, char **endptr, uint64_t *val)
                len = 0;
 
        for (i = 0; i < len; i++) {
+               if (suffix_si_check((*endptr)[i]))
+                       break;
                if (((*endptr)[i] == '\0') || (*endptr)[i] != sep[i])
                        return -EINVAL;
        }
-       *endptr += len;
-       tmp = *endptr;
 
-       /* extract the digits after decimal point */
-       frac = strtoull(tmp, endptr, 0);
-       if (tmp == *endptr ||
-           ((frac == ULLONG_MAX) && errno == ERANGE))
-               return -EINVAL;
+       if (suffix_si_check((*endptr)[i])) {
+               if ((*endptr)[i + 1] != '\0')
+                       return -EINVAL;
+       } else {
+               *endptr += len;
+               tmp = *endptr;
+
+               /* extract the digits after decimal point */
+               frac = strtoull(tmp, endptr, 0);
+               if (tmp == *endptr ||
+                   ((frac == ULLONG_MAX) && errno == ERANGE))
+                       return -EINVAL;
 
-       /* test that we have max one character as suffix */
-       if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0')
-               return -EINVAL;
+               /* test that we have max one character as suffix */
+               if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0')
+                       return -EINVAL;
 
-       frac_len = *endptr - tmp;
+               frac_len = *endptr - tmp;
+       }
 
        for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) {
                struct si_suffix *s = &si_suffixes[i];