Update to fuse_opt_parse(3) so that all option templates are now matched for
authorhelg <helg@openbsd.org>
Mon, 11 Dec 2017 12:31:00 +0000 (12:31 +0000)
committerhelg <helg@openbsd.org>
Mon, 11 Dec 2017 12:31:00 +0000 (12:31 +0000)
the supplied option. This allows the following templates to be supplied to set
multiple members of a struct at the same time. e.g.

#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }

static const struct fuse_opt fuse_lib_opts[] = {
      FUSE_LIB_OPT("gid=",      set_gid, 1),
      FUSE_LIB_OPT("gid=%u",        gid, 0),
      FUSE_OPT_END
};

If "-ogid=1000" is passed to fuse_opt_parse(3) it will set both:

fuse_config.set_gid=1
fuse_config.gid=1000

ok mpi@

lib/libfuse/fuse_opt.c

index 0b026cc..aa5436b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_opt.c,v 1.20 2017/12/11 12:01:55 helg Exp $ */
+/* $OpenBSD: fuse_opt.c,v 1.21 2017/12/11 12:31:00 helg Exp $ */
 /*
  * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
  * Copyright (c) 2013 Stefan Sperling <stsp@openbsd.org>
@@ -95,7 +95,6 @@ match_opt(const char *templ, const char *opt)
        return (0);
 }
 
-
 static int
 add_opt(char **opts, const char *opt)
 {
@@ -185,67 +184,76 @@ fuse_opt_add_arg(struct fuse_args *args, const char *name)
 }
 
 static int
-parse_opt(const struct fuse_opt *o, const char *val, void *data,
+parse_opt(const struct fuse_opt *o, const char *opt, void *data,
     fuse_opt_proc_t f, struct fuse_args *arg)
 {
-       int keyval;
-       size_t idx;
+       const char *val;
+       int keyval, ret, found;
+       size_t sep;
 
        if (o == NULL)
-               return IFUSE_OPT_KEEP;
+               return (IFUSE_OPT_KEEP);
 
        keyval = 0;
+       found = 0;
 
        for(; o->templ; o++) {
+               sep = match_opt(o->templ, opt);
+               if (sep == 0)
+                       continue;
+
+               found = 1;
+               val = opt;
+
                /* check key=value or -p n */
-               idx = strcspn(o->templ, "= ");
-
-               if (strncmp(val, o->templ, idx) == 0) {
-                       if (o->templ[idx] == '=') {
-                               keyval = 1;
-                               val = &val[idx + 1];
-                       } else if (o->templ[idx] == ' ') {
-                               keyval = 1;
-                               if (idx == strlen(val)) {
-                                       /* ask for next arg to be included */
-                                       return IFUSE_OPT_NEED_ANOTHER_ARG;
-                               } else if (strchr(o->templ, '%') != NULL) {
-                                       val = &val[idx];
-                               }
+               if (o->templ[sep] == '=') {
+                       keyval = 1;
+                       val = &opt[sep + 1];
+               } else if (o->templ[sep] == ' ') {
+                       keyval = 1;
+                       if (sep == strlen(opt)) {
+                               /* ask for next arg to be included */
+                               return (IFUSE_OPT_NEED_ANOTHER_ARG);
+                       } else if (strchr(o->templ, '%') != NULL) {
+                               val = &opt[sep];
                        }
+               }
 
-                       if (o->val == FUSE_OPT_KEY_DISCARD)
-                               return (IFUSE_OPT_DISCARD);
-
-                       if (o->val == FUSE_OPT_KEY_KEEP)
+               if (o->val == FUSE_OPT_KEY_DISCARD)
+                       ret = IFUSE_OPT_DISCARD;
+               else if (o->val == FUSE_OPT_KEY_KEEP)
+                       ret = IFUSE_OPT_KEEP;
+               else if (FUSE_OPT_IS_OPT_KEY(o)) {
+                       if (f == NULL)
                                return (IFUSE_OPT_KEEP);
 
-                       if (FUSE_OPT_IS_OPT_KEY(o)) {
-                               if (f == NULL)
-                                       return IFUSE_OPT_KEEP;
-
-                               return f(data, val, o->val, arg);
-                       } else if (data == NULL) {
-                               return (-1);
-                       } else if (strchr(o->templ, '%') == NULL) {
-                               *((int *)(data + o->off)) = o->val;
-                       } else if (strstr(o->templ, "%u") != NULL) {
-                               *((unsigned int*)(data + o->off)) = atoi(val);
-                       } else if (strstr(o->templ, "%lu") != NULL) {
-                               *((unsigned long*)(data + o->off)) =
-                                   strtoul(val, NULL, 0);
-                       } else if (strstr(o->templ, "%s") != NULL) {
-                               *((char **)(data + o->off)) = strdup(val);
-                       } else {
-                               /* TODO other parameterised templates */
-                       }
-
-                       return (IFUSE_OPT_DISCARD);
+                       ret = f(data, val, o->val, arg);
+               } else if (data == NULL) {
+                       return (-1);
+               } else if (strchr(o->templ, '%') == NULL) {
+                       *((int *)(data + o->off)) = o->val;
+                       ret = IFUSE_OPT_DISCARD;
+               } else if (strstr(o->templ, "%u") != NULL) {
+                       *((unsigned int*)(data + o->off)) = atoi(val);
+                       ret = IFUSE_OPT_DISCARD;
+               } else if (strstr(o->templ, "%lu") != NULL) {
+                       *((unsigned long*)(data + o->off)) =
+                           strtoul(val, NULL, 0);
+                       ret = IFUSE_OPT_DISCARD;
+               } else if (strstr(o->templ, "%s") != NULL) {
+                       *((char **)(data + o->off)) = strdup(val);
+                       ret = IFUSE_OPT_DISCARD;
+               } else {
+                       /* TODO other parameterised templates */
+                       ret = IFUSE_OPT_DISCARD;
                }
        }
 
+       if (found)
+               return (ret);
+
        if (f != NULL)
-               return f(data, val, FUSE_OPT_KEY_OPT, arg);
+               return f(data, opt, FUSE_OPT_KEY_OPT, arg);
 
        return (IFUSE_OPT_KEEP);
 }