summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhelg <helg@cvs.openbsd.org>2017-12-11 12:01:56 +0000
committerhelg <helg@cvs.openbsd.org>2017-12-11 12:01:56 +0000
commit5c86e84ed2fc7dfc54a2dd42491cd11e26629f79 (patch)
treecdf12d1b63cd0094752e0fd533755d8e0b1f0cf2
parent2868b8d6cd10181dc07d4214f7e356cb7c36e466 (diff)
The fuse_opt_match(3) library function does not match options correctly.
libfuse supports option templates of the following form that can be used to automatically parse arguments supplied on the command line. "-p " argument that takes an option e.g -p 22 or -p22 "-p %x" argument that takes an option parsed like sscanf(3) "cache=yes" matches -ocache=yes or -o cache=yes "cache=%s" matches -ocache=<string> or -o cache=<string> "cache=" matches same as above but value is passed to option proc "noatime" matches -onoatime or -o atime For example, it does not match options of the form "-p 22" or "cache=yes" to the corresponding templates "-p " and "cache=yes". This patch fixes that and updates the regression tests accordingly. ok mpi@
-rw-r--r--lib/libfuse/fuse_opt.c76
-rw-r--r--regress/lib/libfuse/fuse-opt-match.c87
2 files changed, 66 insertions, 97 deletions
diff --git a/lib/libfuse/fuse_opt.c b/lib/libfuse/fuse_opt.c
index 873b3380399..0b026cc6038 100644
--- a/lib/libfuse/fuse_opt.c
+++ b/lib/libfuse/fuse_opt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_opt.c,v 1.19 2017/11/16 12:56:58 helg Exp $ */
+/* $OpenBSD: fuse_opt.c,v 1.20 2017/12/11 12:01:55 helg Exp $ */
/*
* Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
* Copyright (c) 2013 Stefan Sperling <stsp@openbsd.org>
@@ -67,73 +67,35 @@ alloc_argv(struct fuse_args *args)
return (0);
}
-static int
+/*
+ * Returns the number of characters that matched for bounds checking later.
+ */
+static size_t
match_opt(const char *templ, const char *opt)
{
- const char *o, *t;
- char *arg;
-
- arg = strpbrk(templ, " =");
-
- /* verify template */
- t = templ;
- if (*t == '-') {
- t++;
- if (*t == '-')
- t++;
- if (*t == 'o' || *t == '\0')
- return (0);
- }
+ size_t sep, len;
- /* skip leading -, -o, and -- in option name */
- o = opt;
- if (*o == '-') {
- o++;
- if (*o == 'o' || *o == '-')
- o++;
- }
+ len = strlen(templ);
+ sep = strcspn(templ, "=");
- /* empty option name is invalid */
- if (*o == '\0')
- return (0);
+ if (sep == len)
+ sep = strcspn(templ, " ");
- /* match option name */
- while (*t && *o) {
- if (*t++ != *o++)
+ /* key=, key=%, "-k ", -k % */
+ if (sep < len && (templ[sep + 1] == '\0' || templ[sep + 1] == '%')) {
+ if (strncmp(opt, templ, sep) == 0)
+ return (sep);
+ else
return (0);
- if (arg && t == arg) {
- if (*o != ' ' && *o != '=')
- return (0);
- o++; /* o now points at argument */
- if (*o == '\0')
- return (0);
- break;
- }
}
- /* match argument */
- if (arg) {
- if (t != arg)
- return (0);
- t++;
- /* does template have an argument? */
- if (*t != '%' && *t != '\0')
- return (0);
- if (*t == '%' && t[1] == '\0')
- return (0);
- /* yes it does, consume argument in opt */
- while (*o && *o != ' ')
- o++;
- } else if (*t != '\0')
- return (0);
+ if (strcmp(opt, templ) == 0)
+ return (len);
- /* we should have consumed entire opt string */
- if (*o != '\0')
- return (0);
-
- return (1);
+ return (0);
}
+
static int
add_opt(char **opts, const char *opt)
{
diff --git a/regress/lib/libfuse/fuse-opt-match.c b/regress/lib/libfuse/fuse-opt-match.c
index 71daa0245f3..830f456ed3a 100644
--- a/regress/lib/libfuse/fuse-opt-match.c
+++ b/regress/lib/libfuse/fuse-opt-match.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Sylvestre Gallon <ccna.syl@gmail.com>
+ * Copyright (c) 2017 Helg Bredow <xx404@msn.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,55 +14,62 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <string.h>
+#include <assert.h>
+#include <stddef.h>
#include <fuse_opt.h>
-const struct fuse_opt nullopts[] = {
+static const struct fuse_opt emptyopts[] = {
FUSE_OPT_END
};
-const int nullresults[] = {
- 0, 0, 0, 0, 0, 0
-};
-
-const struct fuse_opt badopts[] = {
- FUSE_OPT_KEY("-p ", 0),
- FUSE_OPT_KEY("-C", 1),
- FUSE_OPT_KEY("-V", 3),
- FUSE_OPT_KEY("--version", 3),
- FUSE_OPT_KEY("-h", 2),
+static const struct fuse_opt opts[] = {
+ FUSE_OPT_KEY("-p ", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("-C", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("-V", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("--version", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("-h", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("const=false", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("cache=no", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("cache=yes", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("debug", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("ro", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("--foo=", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("bars=%s", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("--fool=%lu", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("-x ", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("-n %u", FUSE_OPT_KEY_DISCARD),
+ FUSE_OPT_KEY("-P", FUSE_OPT_KEY_DISCARD),
FUSE_OPT_END
};
-static int
-match_opts(const struct fuse_opt *opts, const int *results)
+int
+main(void)
{
- if (fuse_opt_match(opts, NULL) != 0)
- return (1);
+ assert(fuse_opt_match(emptyopts, "debug") == 0);
- if (fuse_opt_match(opts, "bar=") != results[0])
- return (3);
- if (fuse_opt_match(opts, "--foo=") != results[1])
- return (4);
- if (fuse_opt_match(opts, "bar=%s") != results[2])
- return (5);
- if (fuse_opt_match(opts, "--foo=%lu") != results[3])
- return (6);
- if (fuse_opt_match(opts, "-x ") != results[4])
- return (7);
- if (fuse_opt_match(opts, "-x %s") != results[5])
- return (8);
+ assert(fuse_opt_match(opts, NULL) == 0);
+ assert(fuse_opt_match(opts, "-p ") == 1);
+ assert(fuse_opt_match(opts, "-C") == 1);
+ assert(fuse_opt_match(opts, "-c") == 0);
+ assert(fuse_opt_match(opts, "-V") == 1);
+ assert(fuse_opt_match(opts, "--version") == 1);
+ assert(fuse_opt_match(opts, "-h") == 1);
+ assert(fuse_opt_match(opts, "const=false") == 1);
+ assert(fuse_opt_match(opts, "const=falsefalse") == 0);
+ assert(fuse_opt_match(opts, "cache=no") == 1);
+ assert(fuse_opt_match(opts, "cache=yes") == 1);
+ assert(fuse_opt_match(opts, "debug") == 1);
+ assert(fuse_opt_match(opts, "ro") == 1);
+ assert(fuse_opt_match(opts, "ro_fallback") == 0);
+ assert(fuse_opt_match(opts, "--foo=bar") == 1);
+ assert(fuse_opt_match(opts, "bars=foo") == 1);
+ assert(fuse_opt_match(opts, "--fool=bool") == 1);
+ assert(fuse_opt_match(opts, "--fool=1") == 1);
+ assert(fuse_opt_match(opts, "-x bar") == 1);
+ assert(fuse_opt_match(opts, "-xbar") == 1);
+ assert(fuse_opt_match(opts, "-n 100") == 1);
+ assert(fuse_opt_match(opts, "-n100") == 1);
+ assert(fuse_opt_match(opts, "-P") == 1);
return (0);
}
-
-int
-main(int ac, char **av)
-{
- if (match_opts(nullopts, nullresults) != 0)
- return (1);
- if (match_opts(badopts, nullresults) != 0)
- return (1);
- return (0);
-}
-