+static int handle_option(struct fio_option *o, const char *ptr, void *data)
+{
+ unsigned int il, *ilp;
+ unsigned long long ull, *ullp;
+ unsigned long ul1, ul2, *ulp1, *ulp2;
+ char **cp;
+ int ret = 0, is_time = 0;
+
+ switch (o->type) {
+ case FIO_OPT_STR: {
+ fio_opt_str_fn *fn = o->cb;
+
+ ret = fn(data, ptr);
+ break;
+ }
+ case FIO_OPT_STR_VAL_TIME:
+ is_time = 1;
+ case FIO_OPT_STR_VAL: {
+ fio_opt_str_val_fn *fn = o->cb;
+
+ if (is_time)
+ ret = check_str_time(ptr, &ull);
+ else
+ ret = check_str_bytes(ptr, &ull);
+
+ if (ret)
+ break;
+
+ if (o->max_val && ull > o->max_val)
+ ull = o->max_val;
+
+ if (fn)
+ ret = fn(data, &ull);
+ else {
+ ullp = td_var(data, o->off1);
+ *ullp = ull;
+ }
+ break;
+ }
+ case FIO_OPT_STR_STORE:
+ cp = td_var(data, o->off1);
+ *cp = strdup(ptr);
+ break;
+ case FIO_OPT_RANGE: {
+ char tmp[128];
+ char *p1, *p2;
+
+ strncpy(tmp, ptr, sizeof(tmp) - 1);
+
+ p1 = strchr(tmp, '-');
+ if (!p1) {
+ ret = 1;
+ break;
+ }
+
+ 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);
+ if (ul1 > ul2) {
+ *ulp1 = ul2;
+ *ulp2 = ul1;
+ } else {
+ *ulp2 = ul2;
+ *ulp1 = ul1;
+ }
+ }
+
+ break;
+ }
+ case FIO_OPT_INT: {
+ fio_opt_int_fn *fn = o->cb;
+
+ ret = check_int(ptr, &il);
+ if (ret)
+ break;
+
+ if (o->max_val && il > o->max_val)
+ il = o->max_val;
+
+ if (fn)
+ ret = fn(data, &il);
+ else {
+ ilp = td_var(data, o->off1);
+ *ilp = il;
+ }
+ break;
+ }
+ case FIO_OPT_STR_SET: {
+ fio_opt_str_set_fn *fn = o->cb;
+
+ if (fn)
+ ret = fn(data);
+ else {
+ ilp = td_var(data, o->off1);
+ *ilp = 1;
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "Bad option type %d\n", o->type);
+ ret = 1;
+ }