On Mon, 16 Oct 2017 15:33:45 +0200
Martin Pieuchot <[email protected]> wrote:
> On 14/10/17(Sat) 01:23, Helg Bredow wrote:
> > The attached patch vastly improves fuse argument and option parsing. For
> > example, all sshfs options will now be parsed successfully. It's a
> > substantial patch and can't be easily broken down further.
> >
> > In addition, this also adds support for the -d and -odebug options.
> >
> > I've also included a regression test that confirms it's working as intended.
> >
> > The only contentious part of the patch is that fuse no longer fails if it
> > doesn't recognise an argument or option, it only prints a message to
> > stdout. This is because fuse file systems can pass additional options to
> > fuse and most are not supported and/or recognised yet and this would
> > prevent those file systems from running.
> >
> > I'm happy to take feedback and recommendations.
>
> Your diffs are good but it would be easier if you could submit one diff
> per issue.
>
> For example, split the debug part, the foreground part, the options and
> the regress. This will allow us to integrate some non contentious part
> of your diff then discuss the rest.
>
> You also want to have a look at /usr/lib/check_sym since you're adding
> new symbols to the library.
I've split the patch. This one improves argument and option parsing so that
almost all sshfs arguments and options will now parse. It won't recognise
-ocache=no since fuse_opt_match() is incorrect (fuse will treat it the same as
-ocache=yes). I'll submit a patch for that some other time.
Running check_sym tells me:
No dynamic export changes
External reference changes:
added:
atoi
strchr
strsep
strstr
strtoul
I take that to mean that there is no need to bump the major or minor version
for this patch. Is that correct?
Index: fuse_opt.c
===================================================================
RCS file: /cvs/src/lib/libfuse/fuse_opt.c,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 fuse_opt.c
--- fuse_opt.c 4 Jan 2017 12:01:22 -0000 1.18
+++ fuse_opt.c 17 Oct 2017 13:57:35 -0000
@@ -222,57 +222,70 @@ static int
parse_opt(const struct fuse_opt *o, const char *val, void *data,
fuse_opt_proc_t f, struct fuse_args *arg)
{
- int found, ret, keyval;
+ int keyval;
size_t idx;
- ret = 0;
- found = 0;
- keyval = 0;
+#define DISCARD 0
+#define KEEP 1
+#define NEED_ANOTHER_ARG 2
- /* check if it is a key=value entry */
- idx = strcspn(val, "=");
- if (idx != strlen(val)) {
- idx++;
- keyval = 1;
- }
+ if (o == NULL)
+ return KEEP;
+
+ keyval = 0;
for(; o->templ; o++) {
- if ((keyval && strncmp(val, o->templ, idx) == 0) ||
- (!keyval && strcmp(val, o->templ) == 0)) {
+ /* 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 NEED_ANOTHER_ARG;
+ } else if (strchr(o->templ, '%') != NULL) {
+ val = &val[idx];
+ }
+ }
+
if (o->val == FUSE_OPT_KEY_DISCARD)
- return (1);
+ return (DISCARD);
+
+ if (o->val == FUSE_OPT_KEY_KEEP)
+ return (KEEP);
if (FUSE_OPT_IS_OPT_KEY(o)) {
- if (keyval)
- ret = f(data, &val[idx], o->val, arg);
- else
- ret = f(data, val, o->val, arg);
- }
+ if (f == NULL)
+ return KEEP;
- if (o->off != ULONG_MAX && data && o->val >= 0) {
- ret = f(data, val, o->val, arg);
- int *addr = (int *)(data + o->off);
- *addr = o->val;
- ret = 0;
+ 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 */
}
- if (ret == -1)
- return (ret);
- if (ret == 1)
- fuse_opt_add_arg(arg, val);
- found++;
- break;
+ return DISCARD;
}
}
- if (!found) {
- ret = f(data, val, FUSE_OPT_KEY_OPT, arg);
- if (ret == 1)
- fuse_opt_add_arg(arg, val);
- return (ret);
- }
+ if (f != NULL)
+ return f(data, val, FUSE_OPT_KEY_OPT, arg);
- return (ret);
+ return (KEEP);
}
/*
@@ -287,11 +300,12 @@ fuse_opt_parse(struct fuse_args *args, v
const struct fuse_opt *opt, fuse_opt_proc_t f)
{
struct fuse_args outargs;
- const char *arg;
- int ret = 0;
+ const char *arg, *ap;
+ char *optlist, *tofree;
+ int ret;
int i;
- if (!f || !args || !args->argc || !args->argv)
+ if (!args || !args->argc || !args->argv)
return (0);
bzero(&outargs, sizeof(outargs));
@@ -299,28 +313,66 @@ fuse_opt_parse(struct fuse_args *args, v
for (i = 1; i < args->argc; i++) {
arg = args->argv[i];
+ ret = 0;
/* not - and not -- */
if (arg[0] != '-') {
- ret = f(data, arg, FUSE_OPT_KEY_NONOPT, &outargs);
+ if (f == NULL)
+ ret = KEEP;
+ else
+ ret = f(data, arg, FUSE_OPT_KEY_NONOPT,
&outargs);
- if (ret == 1)
+ if (ret == KEEP)
fuse_opt_add_arg(&outargs, arg);
if (ret == -1)
goto err;
} else if (arg[1] == 'o') {
if (arg[2])
arg += 2; /* -ofoo,bar */
- else
- arg = args->argv[++i];
+ else {
+ if (++i >= args->argc)
+ goto err;
- ret = parse_opt(opt, arg, data, f, &outargs);
+ arg = args->argv[i];
+ }
+
+ tofree = optlist = strdup(arg);
+ if (optlist == NULL)
+ goto err;
+
+ while ((ap = strsep(&optlist, ",")) != NULL &&
+ ret != -1) {
+ ret = parse_opt(opt, ap, data, f, &outargs);
+ if (ret == KEEP) {
+ fuse_opt_add_arg(&outargs, "-o");
+ fuse_opt_add_arg(&outargs, ap);
+ }
+ }
+
+ free(tofree);
if (ret == -1)
goto err;
} else {
ret = parse_opt(opt, arg, data, f, &outargs);
+ if (ret == KEEP)
+ fuse_opt_add_arg(&outargs, arg);
+ else if (ret == NEED_ANOTHER_ARG) {
+ /* arg needs a value */
+ if (++i >= args->argc)
+ goto err;
+
+ if (asprintf(&tofree, "%s%s", arg,
+ args->argv[i]) == -1)
+ goto err;
+
+ ret = parse_opt(opt, tofree, data, f, &outargs);
+ if (ret == KEEP)
+ fuse_opt_add_arg(&outargs, tofree);
+ free(tofree);
+ }
+
if (ret == -1)
goto err;
}
@@ -333,6 +385,8 @@ err:
args->allocated = outargs.allocated;
args->argc = outargs.argc;
args->argv = outargs.argv;
+ if (ret != 0)
+ ret = -1;
return (ret);
}