[PATCH] Fix int vs long problems in parsing some options
[fio.git] / parse.c
diff --git a/parse.c b/parse.c
index 204b9d25bf20c5f10ac566d417802ecf090cb757..f37878f1cbc8d6a94f8d21aac91ea04a08deff5d 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -48,9 +48,8 @@ static unsigned long get_mult_bytes(char c)
 /*
  * convert string into decimal value, noting any size suffix
  */
-static int str_to_decimal(char *p, unsigned long long *val, int kilo)
+static int str_to_decimal(const char *str, unsigned long long *val, int kilo)
 {
-       char *str = p;
        int len;
 
        len = strlen(str);
@@ -66,12 +65,12 @@ static int str_to_decimal(char *p, unsigned long long *val, int kilo)
        return 0;
 }
 
-static int check_str_bytes(char *p, unsigned long long *val)
+static int check_str_bytes(const char *p, unsigned long long *val)
 {
        return str_to_decimal(p, val, 1);
 }
 
-static int check_str_time(char *p, unsigned long long *val)
+static int check_str_time(const char *p, unsigned long long *val)
 {
        return str_to_decimal(p, val, 0);
 }
@@ -94,7 +93,7 @@ void strip_blank_end(char *p)
        *(s + 1) = '\0';
 }
 
-static int check_range_bytes(char *str, unsigned long *val)
+static int check_range_bytes(const char *str, unsigned long *val)
 {
        char suffix;
 
@@ -109,7 +108,7 @@ static int check_range_bytes(char *str, unsigned long *val)
        return 1;
 }
 
-int check_int(char *p, unsigned int *val)
+static int check_int(const char *p, unsigned int *val)
 {
        if (sscanf(p, "%u", val) == 1)
                return 0;
@@ -117,41 +116,29 @@ int check_int(char *p, unsigned int *val)
        return 1;
 }
 
-int check_strset(char *p, char *name)
-{
-       return strncmp(p, name, strlen(name));
-}
-
 static struct fio_option *find_option(struct fio_option *options,
                                      const char *opt)
 {
-       struct fio_option *o;
-       int i = 0;
-
-       do {
-               o = &options[i];
-               if (!o->name)
-                       break;
+       struct fio_option *o = &options[0];
 
+       while (o->name) {
                if (!strcmp(o->name, opt))
                        return o;
 
-               i++;
-       } while (1);
+               o++;
+       }
 
        return NULL;
 }
 
-static int handle_option(struct fio_option *o, char *ptr, void *data)
+static int handle_option(struct fio_option *o, const char *ptr, void *data)
 {
-       unsigned int il, *ilp;
+       unsigned int il, *ilp1, *ilp2;
        unsigned long long ull, *ullp;
-       unsigned long ul1, ul2, *ulp1, *ulp2;
-       char *tmpbuf, **cp;
+       unsigned long ul1, ul2;
+       char **cp;
        int ret = 0, is_time = 0;
 
-       tmpbuf = malloc(4096);
-
        switch (o->type) {
        case FIO_OPT_STR: {
                fio_opt_str_fn *fn = o->cb;
@@ -161,7 +148,8 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
        }
        case FIO_OPT_STR_VAL_TIME:
                is_time = 1;
-       case FIO_OPT_STR_VAL: {
+       case FIO_OPT_STR_VAL:
+       case FIO_OPT_STR_VAL_INT: {
                fio_opt_str_val_fn *fn = o->cb;
 
                if (is_time)
@@ -178,8 +166,13 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
                if (fn)
                        ret = fn(data, &ull);
                else {
-                       ullp = td_var(data, o->off1);
-                       *ullp = ull;
+                       if (o->type == FIO_OPT_STR_VAL_INT) {
+                               ilp1 = td_var(data, o->off1);
+                               *ilp1 = ull;
+                       } else {
+                               ullp = td_var(data, o->off1);
+                               *ullp = ull;
+                       }
                }
                break;
        }
@@ -188,9 +181,12 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
                *cp = strdup(ptr);
                break;
        case FIO_OPT_RANGE: {
+               char tmp[128];
                char *p1, *p2;
 
-               p1 = strchr(ptr, '-');
+               strncpy(tmp, ptr, sizeof(tmp) - 1);
+
+               p1 = strchr(tmp, '-');
                if (!p1) {
                        ret = 1;
                        break;
@@ -198,18 +194,19 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
 
                p2 = p1 + 1;
                *p1 = '\0';
+               p1 = tmp;
 
                ret = 1;
                if (!check_range_bytes(p1, &ul1) && !check_range_bytes(p2, &ul2)) {
                        ret = 0;
-                       ulp1 = td_var(data, o->off1);
-                       ulp2 = td_var(data, o->off2);
+                       ilp1 = td_var(data, o->off1);
+                       ilp2 = td_var(data, o->off2);
                        if (ul1 > ul2) {
-                               *ulp1 = ul2;
-                               *ulp2 = ul1;
+                               *ilp1 = ul2;
+                               *ilp2 = ul1;
                        } else {
-                               *ulp2 = ul2;
-                               *ulp1 = ul1;
+                               *ilp2 = ul2;
+                               *ilp1 = ul1;
                        }
                }       
                        
@@ -228,8 +225,8 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
                if (fn)
                        ret = fn(data, &il);
                else {
-                       ilp = td_var(data, o->off1);
-                       *ilp = il;
+                       ilp1 = td_var(data, o->off1);
+                       *ilp1 = il;
                }
                break;
        }
@@ -239,8 +236,8 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
                if (fn)
                        ret = fn(data);
                else {
-                       ilp = td_var(data, o->off1);
-                       *ilp = 1;
+                       ilp1 = td_var(data, o->off1);
+                       *ilp1 = 1;
                }
                break;
        }
@@ -249,17 +246,34 @@ static int handle_option(struct fio_option *o, char *ptr, void *data)
                ret = 1;
        }
 
-       free(tmpbuf);
        return ret;
 }
 
+int parse_cmd_option(const char *opt, const char *val,
+                    struct fio_option *options, void *data)
+{
+       struct fio_option *o;
+
+       o = find_option(options, opt);
+       if (!o) {
+               fprintf(stderr, "Bad option %s\n", opt);
+               return 1;
+       }
+
+       if (!handle_option(o, val, data))
+               return 0;
+
+       fprintf(stderr, "fio: failed parsing %s=%s\n", opt, val);
+       return 1;
+}
+
 int parse_option(const char *opt, struct fio_option *options, void *data)
 {
-       struct fio_option *o = find_option(options, opt);
+       struct fio_option *o;
        char *pre, *post;
        char tmp[64];
 
-       strcpy(tmp, opt);
+       strncpy(tmp, opt, sizeof(tmp) - 1);
 
        pre = strchr(tmp, '=');
        if (pre) {
@@ -278,5 +292,9 @@ int parse_option(const char *opt, struct fio_option *options, void *data)
                return 1;
        }
 
-       return handle_option(o, post, data);
+       if (!handle_option(o, post, data))
+               return 0;
+
+       fprintf(stderr, "fio: failed parsing %s\n", opt);
+       return 1;
 }