Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Major rework of fuse_opt_parse(3) so that it supports all th...



details:   https://anonhg.NetBSD.org/src/rev/0502c5c2b28d
branches:  trunk
changeset: 348936:0502c5c2b28d
user:      pho <pho%NetBSD.org@localhost>
date:      Wed Nov 16 16:11:42 2016 +0000

description:
Major rework of fuse_opt_parse(3) so that it supports all the functionality of the original function

diffstat:

 lib/librefuse/TODO                 |    4 +-
 lib/librefuse/refuse_opt.c         |  449 ++++++++++++++++++++++--------------
 tests/lib/librefuse/t_refuse_opt.c |  262 +++++++++++++++++++++-
 3 files changed, 539 insertions(+), 176 deletions(-)

diffs (truncated from 839 to 300 lines):

diff -r efa69ec7ec36 -r 0502c5c2b28d lib/librefuse/TODO
--- a/lib/librefuse/TODO        Wed Nov 16 12:31:33 2016 +0000
+++ b/lib/librefuse/TODO        Wed Nov 16 16:11:42 2016 +0000
@@ -1,9 +1,8 @@
-       $NetBSD: TODO,v 1.3 2007/05/03 21:02:54 agc Exp $
+       $NetBSD: TODO,v 1.4 2016/11/16 16:11:42 pho Exp $
 
 To Do
 =====
 address all XXX
-implement all fuse_opt
 implement proper lookup (pending some libpuffs stuff)
 support fuse_mt (i.e. worker threads, but that'll probably be smarter
                 to do inside of libpuffs)
@@ -23,3 +22,4 @@
 Finish off manual page
 fuse_setup
 fuse_teardown
+fuse_opt
diff -r efa69ec7ec36 -r 0502c5c2b28d lib/librefuse/refuse_opt.c
--- a/lib/librefuse/refuse_opt.c        Wed Nov 16 12:31:33 2016 +0000
+++ b/lib/librefuse/refuse_opt.c        Wed Nov 16 16:11:42 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: refuse_opt.c,v 1.17 2016/11/15 00:34:19 pho Exp $      */
+/*     $NetBSD: refuse_opt.c,v 1.18 2016/11/16 16:11:42 pho Exp $      */
 
 /*-
  * Copyright (c) 2007 Juan Romero Pardines.
@@ -25,15 +25,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * TODO:
- *     * -oblah,foo... works, but the options are not enabled.
- *     * -ofoo=%s (accepts a string) or -ofoo=%u (int) is not
- *       supported for now.
- *     * void *data: how is it used? I think it's used to enable
- *       options or pass values for the matching options.
- */
-
 #include <sys/types.h>
 
 #include <err.h>
@@ -50,21 +41,6 @@
 #define DPRINTF(x)
 #endif
 
-enum {
-       KEY_HELP,
-       KEY_VERBOSE,
-       KEY_VERSION
-};
-
-struct fuse_opt_option {
-       const struct fuse_opt *fop;
-       char *option;
-       int key;
-       void *data;
-};
-
-static int fuse_opt_popt(struct fuse_opt_option *, const struct fuse_opt *);
-
 /*
  * Public API.
  */
@@ -124,14 +100,17 @@
 void
 fuse_opt_free_args(struct fuse_args *ap)
 {
-       int     i;
-
-       for (i = 0; i < ap->argc; i++) {
-               free(ap->argv[i]);
+       if (ap) {
+               if (ap->allocated) {
+                       int     i;
+                       for (i = 0; i < ap->argc; i++) {
+                               free(ap->argv[i]);
+                       }
+                       free(ap->argv);
+               }
+               ap->argv = NULL;
+               ap->allocated = ap->argc = 0;
        }
-       free(ap->argv);
-       ap->argv = NULL;
-       ap->allocated = ap->argc = 0;
 }
 
 /* ARGSUSED */
@@ -207,7 +186,7 @@
        return add_opt(opts, opt, true);
 }
 
-static bool match_templ(const char *templ, const char *opt, size_t *sep_idx)
+static bool match_templ(const char *templ, const char *opt, int *sep_idx)
 {
        const char *sep = strpbrk(templ, "= ");
 
@@ -227,7 +206,7 @@
        else {
                if (strcmp(templ, opt) == 0) {
                        if (sep_idx != NULL)
-                               *sep_idx = 0;
+                               *sep_idx = -1;
                        return true;
                }
                else {
@@ -237,7 +216,7 @@
 }
 
 static const struct fuse_opt *
-find_opt(const struct fuse_opt *opts, const char *opt, size_t *sep_idx)
+find_opt(const struct fuse_opt *opts, const char *opt, int *sep_idx)
 {
        for (; opts != NULL && opts->templ != NULL; opts++) {
                if (match_templ(opts->templ, opt, sep_idx))
@@ -256,167 +235,293 @@
        return find_opt(opts, opt, NULL) != NULL ? 1 : 0;
 }
 
-/*
- * Returns 0 if foo->option was matched with any option from opts,
- * and sets the following on match:
- *
- *     * foo->key is set to the foo->fop->value if offset == -1.
- *     * foo->fop points to the matched struct opts.
- *
- * otherwise returns 1.
- */
-static int
-fuse_opt_popt(struct fuse_opt_option *foo, const struct fuse_opt *opts)
+static int call_proc(fuse_opt_proc_t proc, void* data,
+               const char* arg, int key, struct fuse_args *outargs, bool is_opt)
 {
-       int i, found = 0;
-       char *match;
-       
-       if (!foo->option) {
-               (void)fprintf(stderr, "fuse: missing argument after -o\n");
-               return 1;
+       if (key == FUSE_OPT_KEY_DISCARD)
+               return 0;
+
+       if (key != FUSE_OPT_KEY_KEEP && proc != NULL) {
+               const int rv = proc(data, arg, key, outargs);
+
+               if (rv == -1 || /* error   */
+                       rv ==  0    /* discard */)
+                       return rv;
        }
-       /* 
-        * iterate over argv and opts to see
-        * if there's a match with any template.
-        */
-       for (match = strtok(foo->option, ",");
-            match; match = strtok(NULL, ",")) {
-
-               DPRINTF(("%s: specified option='%s'\n", __func__, match));
-               found = 0;
-
-               for (i = 0; opts && opts->templ; opts++, i++) {
 
-                       DPRINTF(("%s: opts->templ='%s' opts->offset=%d "
-                           "opts->value=%d\n", __func__, opts->templ,
-                           opts->offset, opts->value));
-
-                       /* option is ok */
-                       if (strcmp(match, opts->templ) == 0) {
-                               DPRINTF(("%s: option matched='%s'\n",
-                                   __func__, match));
-                               found++;
-                               /*
-                                * our fop pointer now points 
-                                * to the matched struct opts.
-                                */
-                               foo->fop = opts;
-                               /* 
-                                * assign default key value, necessary for
-                                * KEY_HELP, KEY_VERSION and KEY_VERBOSE.
-                                */
-                               if (foo->fop->offset == -1)
-                                       foo->key = foo->fop->value;
-                               /* reset counter */
-                               opts -= i;
-                               break;
-                       }
+       if (is_opt) {
+               /* Do we already have "-o" at the beginning of outargs? */
+               if (outargs->argc >= 3 && strcmp(outargs->argv[1], "-o") == 0) {
+                       /* Append the option to the comma-separated list. */
+                       if (fuse_opt_add_opt_escaped(&outargs->argv[2], arg) == -1)
+                               return -1;
                }
-               /* invalid option */
-               if (!found) {
-                       (void)fprintf(stderr, "fuse: '%s' is not a "
-                           "valid option\n", match);
-                       return 1;
+               else {
+                       /* Insert -o arg at the beginning. */
+                       if (fuse_opt_insert_arg(outargs, 1, "-o") == -1)
+                               return -1;
+                       if (fuse_opt_insert_arg(outargs, 2, arg) == -1)
+                               return -1;
                }
        }
+       else {
+               if (fuse_opt_add_arg(outargs, arg) == -1)
+                       return -1;
+       }
 
        return 0;
 }
 
-/* ARGSUSED1 */
-int
-fuse_opt_parse(struct fuse_args *args, void *data,
-        const struct fuse_opt *opts, fuse_opt_proc_t proc)
+/* Skip the current argv if possible. */
+static int next_arg(const struct fuse_args *args, int *i)
+{
+       if (*i + 1 >= args->argc) {
+               (void)fprintf(stderr, "fuse: missing argument"
+                               " after '%s'\n", args->argv[*i]);
+               return -1;
+       }
+       else {
+               *i += 1;
+               return 0;
+       }
+}
+
+/* Parse a single argument with a matched template. */
+static int
+parse_matched_arg(const char* arg, struct fuse_args *outargs,
+               const struct fuse_opt* opt, int sep_idx, void* data,
+               fuse_opt_proc_t proc, bool is_opt)
+{
+       if (opt->offset == -1) {
+               /* The option description does not want any variables to be
+                * updated.*/
+               if (call_proc(proc, data, arg, opt->value, outargs, is_opt) == -1)
+                       return -1;
+       }
+       else {
+               void *var = (char*)data + opt->offset;
+
+               if (sep_idx > 0 && opt->templ[sep_idx + 1] == '%') {
+                       /* "foo=%y" or "-x %y" */
+                       const char* param =
+                               opt->templ[sep_idx] == '=' ? &arg[sep_idx + 1] : &arg[sep_idx];
+
+                       if (opt->templ[sep_idx + 2] == 's') {
+                               char* dup = strdup(param);
+                               if (dup == NULL)
+                                       return -1;
+
+                               *(char **)var = dup;
+                       }
+                       else {
+                               /* The format string is not a literal. We all know
+                                * this is a bad idea but it's exactly what fuse_opt
+                                * wants to do... */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+                               if (sscanf(param, &opt->templ[sep_idx + 1], var) == -1) {
+#pragma GCC diagnostic pop
+                                       (void)fprintf(stderr, "fuse: '%s' is not a "
+                                                               "valid parameter for option '%.*s'\n",
+                                                               param, sep_idx, opt->templ);
+                                       return -1;
+                               }
+                       }
+               }
+               else {
+                       /* No parameter format is given. */
+                       *(int *)var = opt->value;
+               }
+       }
+       return 0;
+}
+
+/* Parse a single argument with matching templates. */
+static int
+parse_arg(struct fuse_args* args, int *argi, const char* arg,
+               struct fuse_args *outargs, void *data,
+               const struct fuse_opt *opts, fuse_opt_proc_t proc, bool is_opt)
 {
-       struct fuse_opt_option foo;
-       char *buf;
-       int i, rv = 0;
+       int sep_idx;
+       const struct fuse_opt *opt = find_opt(opts, arg, &sep_idx);
+
+       if (opt) {
+               /* An argument can match to multiple templates. Process them
+                * all. */
+               for (; opt != NULL && opt->templ != NULL;



Home | Main Index | Thread Index | Old Index