summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorsyl <syl@cvs.openbsd.org>2013-07-11 11:41:14 +0000
committersyl <syl@cvs.openbsd.org>2013-07-11 11:41:14 +0000
commit7af59e9ed5721cb4e58cd41207ba61a521d546d7 (patch)
tree074b5a35bfdc5eeb68c5993006e3c7d0ca5fd2cf /lib
parente910acc1c82238c0f5107464ffb55739430ba0d7 (diff)
Merge fuse_opt code with stsp@ fuse_opt code.
ok tedu@
Diffstat (limited to 'lib')
-rw-r--r--lib/libfuse/fuse_opt.c269
-rw-r--r--lib/libfuse/fuse_opt.h9
2 files changed, 231 insertions, 47 deletions
diff --git a/lib/libfuse/fuse_opt.c b/lib/libfuse/fuse_opt.c
index 28f5661a723..4d8b609aa32 100644
--- a/lib/libfuse/fuse_opt.c
+++ b/lib/libfuse/fuse_opt.c
@@ -1,6 +1,7 @@
-/* $OpenBSD: fuse_opt.c,v 1.4 2013/06/12 22:44:42 tedu Exp $ */
+/* $OpenBSD: fuse_opt.c,v 1.5 2013/07/11 11:41:12 syl Exp $ */
/*
* Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
+ * Copyright (c) 2013 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,6 +16,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -22,44 +24,197 @@
#include "fuse_opt.h"
#include "fuse_private.h"
-int
-fuse_opt_add_arg(struct fuse_args *args, const char *name)
+static void
+free_argv(char **argv, int argc)
{
- char **av;
int i;
- /* copy argv, we cannot reallocate the orignal argv */
- if (args->allocated == 0) {
- av = malloc((args->argc + 1) * sizeof(*av));
- if (av == NULL)
- return (-1);
+ for (i = 0; i < argc; i++)
+ free(argv[i]);
+ free(argv);
+}
+
+static int
+alloc_argv(struct fuse_args *args)
+{
+ char **argv;
+ int i;
+
+ assert(!args->allocated);
+
+ argv = calloc(args->argc, sizeof(*argv));
+ if (argv == NULL)
+ return (-1);
+ if (args->argv) {
for (i = 0; i < args->argc; i++) {
- av[i] = strdup(args->argv[i]);
- if (av[i] == NULL)
+ argv[i] = strdup(args->argv[i]);
+ if (argv[i] == NULL) {
+ free_argv(argv, i + 1);
return (-1);
+ }
+ }
+ }
+
+ args->allocated = 1;
+ args->argv = argv;
+
+ return (0);
+}
+
+static int
+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);
+ }
+
+ /* skip leading -, -o, and -- in option name */
+ o = opt;
+ if (*o == '-') {
+ o++;
+ if (*o == 'o' || *o == '-')
+ o++;
+ }
+
+ /* empty option name is invalid */
+ if (*o == '\0')
+ return (0);
+
+ /* match option name */
+ while (*t && *o) {
+ if (*t++ != *o++)
+ 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);
+
+ /* we should have consumed entire opt string */
+ if (*o != '\0')
+ return (0);
+
+ return (1);
+}
+
+static int
+add_opt(char **opts, const char *opt)
+{
+ char *new_opts;
- av[args->argc] = strdup(name);
- if (av[args->argc] == NULL)
+ if (*opts == NULL) {
+ *opts = strdup(opt);
+ if (*opts == NULL)
return (-1);
+ return (0);
+ }
- args->argc++;
- args->argv = av;
- args->allocated = 1;
- } else {
- av = realloc(args->argv, (args->argc + 1) * sizeof(*av));
- if (av == NULL)
+ if (asprintf(&new_opts, "%s,%s", *opts, opt) == -1)
+ return (-1);
+
+ free(*opts);
+ *opts = new_opts;
+ return (0);
+}
+
+int
+fuse_opt_add_opt(char **opts, const char *opt)
+{
+ int ret;
+
+ if (opt == NULL || opt[0] == '\0')
+ return (-1);
+
+ ret = add_opt(opts, opt);
+ return (ret);
+}
+
+int
+fuse_opt_add_opt_escaped(char **opts, const char *opt)
+{
+ size_t size = 0, escaped = 0;
+ const char *s = opt;
+ char *escaped_opt, *p;
+ int ret;
+
+ if (opt == NULL || opt[0] == '\0')
+ return (-1);
+
+ while (*s) {
+ /* malloc(size + escaped) overflow check */
+ if (size >= (SIZE_T_MAX / 2))
return (-1);
- args->argv = av;
- args->argc++;
- args->argv[args->argc - 1] = strdup(name);
- if (args->argv[args->argc - 1] == NULL)
+ if (*s == ',' || *s == '\\')
+ escaped++;
+ s++;
+ size++;
+ }
+
+ if (escaped > 0) {
+ escaped_opt = malloc(size + escaped);
+ if (escaped_opt == NULL)
+ return (-1);
+ s = opt;
+ p = escaped_opt;
+ while (*s) {
+ switch (*s) {
+ case ',':
+ case '\\':
+ *p++ = '\\';
+ /* FALLTHROUGH */
+ default:
+ *p++ = *s++;
+ }
+ }
+ *p = '\0';
+ } else {
+ escaped_opt = strdup(opt);
+ if (escaped_opt == NULL)
return (-1);
}
- return (0);
+ ret = add_opt(opts, escaped_opt);
+ free(escaped_opt);
+ return (ret);
+}
+
+int
+fuse_opt_add_arg(struct fuse_args *args, const char *name)
+{
+ return (fuse_opt_insert_arg(args, args->argc, name));
}
int
@@ -115,42 +270,66 @@ fuse_opt_parse(struct fuse_args *args, void *data, struct fuse_opt *opt,
}
int
-fuse_opt_insert_arg(struct fuse_args *args, int p, const char *arg)
+fuse_opt_insert_arg(struct fuse_args *args, int p, const char *name)
{
char **av;
+ char *this_arg, *next_arg;
int i;
- if (p > args->argc + 1)
- return -1;
+ if (name == NULL || name[0] == '\0')
+ return (-1);
- if (args->allocated) {
- av = realloc(args->argv, (args->argc + 1) * sizeof(char *));
- if (av == NULL)
- return (-1);
+ if (!args->allocated && alloc_argv(args))
+ return (-1);
- args->argv = av;
- args->argc++;
- for (i = args->argc - 1; i > p; i++)
- args->argv[i] = args->argv[i - 1];
+ if (p < 0 || p > args->argc)
+ return (-1);
- args->argv[p] = strdup(arg);
- if (args->argv[p] == NULL)
- return (-1);
+ av = realloc(args->argv, (args->argc + 1) * sizeof(*av));
+ if (av == NULL)
+ return (-1);
+
+ this_arg = strdup(name);
+ if (this_arg == NULL) {
+ free(av);
+ return (-1);
+ }
+
+ args->argc++;
+ args->argv = av;
+ for (i = p; i < args->argc; i++) {
+ next_arg = args->argv[i];
+ args->argv[i] = this_arg;
+ this_arg = next_arg;
}
return (0);
}
-int
+void
fuse_opt_free_args(struct fuse_args *args)
{
- int i;
+ if (!args->allocated)
+ return;
- if (args->allocated)
- for (i = 0; i < args->argc; i++)
- free(args->argv[i]);
- free(args->argv);
- args->allocated = 0;
+ free_argv(args->argv, args->argc);
+ args->argv = 0;
args->argc = 0;
+ args->allocated = 0;
+}
+
+int
+fuse_opt_match(const struct fuse_opt *opts, const char *opt)
+{
+ const struct fuse_opt *this_opt = opts;
+
+ if (opt == NULL || opt[0] == '\0')
+ return (0);
+
+ while (this_opt->templ) {
+ if (match_opt(this_opt->templ, opt))
+ return (1);
+ this_opt++;
+ }
return (0);
}
diff --git a/lib/libfuse/fuse_opt.h b/lib/libfuse/fuse_opt.h
index a3ff5ae0b42..c1ae74be1ea 100644
--- a/lib/libfuse/fuse_opt.h
+++ b/lib/libfuse/fuse_opt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuse_opt.h,v 1.1 2013/06/12 22:36:06 tedu Exp $ */
+/* $OpenBSD: fuse_opt.h,v 1.2 2013/07/11 11:41:13 syl Exp $ */
/*
* Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
@@ -37,7 +37,10 @@ struct fuse_opt {
typedef int (*fuse_opt_proc_t)(void *, const char *, int, struct fuse_args *);
int fuse_opt_add_arg(struct fuse_args *, const char *);
int fuse_opt_insert_arg(struct fuse_args *, int, const char *);
-int fuse_opt_free_args(struct fuse_args *);
+void fuse_opt_free_args(struct fuse_args *);
+int fuse_opt_add_opt(char **, const char *);
+int fuse_opt_add_opt_escaped(char **, const char *);
+int fuse_opt_match(const struct fuse_opt *, const char *);
int fuse_opt_parse(struct fuse_args *, void *, struct fuse_opt *,
fuse_opt_proc_t);
@@ -47,6 +50,8 @@ int fuse_opt_parse(struct fuse_args *, void *, struct fuse_opt *,
#define FUSE_OPT_END { NULL, 0, 0 }
#define FUSE_OPT_KEY_OPT -1
#define FUSE_OPT_KEY_NONOPT -2
+#define FUSE_OPT_KEY_KEEP -3
+#define FUSE_OPT_KEY_DISCARD -4
#ifdef __cplusplus
}