summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2008-10-16 19:11:28 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2008-10-16 19:11:28 +0000
commit5c094ac0150ebfef6a2c9c2c9d1c545a90ff4e96 (patch)
tree2d25ba53aac4907c1ca1ff82d46595103bc852f8
parentb7af77dc1dfb5eb91eb408a0aeaf30783b5974ab (diff)
downloadfuse-5c094ac0150ebfef6a2c9c2c9d1c545a90ff4e96.tar.gz
* Allow commas in options to be escaped with a backslash * Add new function: fuse_opt_add_opt_escaped() * Add missing fuse_reply_bmap() to the version script
-rw-r--r--ChangeLog8
-rw-r--r--include/fuse_opt.h9
-rw-r--r--lib/fuse_opt.c89
-rw-r--r--lib/fuse_versionscript8
4 files changed, 80 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c34017..79ed2a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-10-16 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Allow commas in options to be escaped with a backslash
+
+ * Add new function: fuse_opt_add_opt_escaped()
+
+ * Add missing fuse_reply_bmap() to the version script
+
2008-10-14 Miklos Szeredi <miklos@szeredi.hu>
* Pass current file flags to read and write operations
diff --git a/include/fuse_opt.h b/include/fuse_opt.h
index 7ae08af..5595b4a 100644
--- a/include/fuse_opt.h
+++ b/include/fuse_opt.h
@@ -212,6 +212,15 @@ int fuse_opt_parse(struct fuse_args *args, void *data,
int fuse_opt_add_opt(char **opts, const char *opt);
/**
+ * Add an option, escaping commas, to a comma separated option list
+ *
+ * @param opts is a pointer to an option list, may point to a NULL value
+ * @param opt is the option to add
+ * @return -1 on allocation error, 0 on success
+ */
+int fuse_opt_add_opt_escaped(char **opts, const char *opt);
+
+/**
* Add an argument to a NULL terminated argument vector
*
* @param args is the structure containing the current argument list
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index 8a9019b..b15e7db 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -109,29 +109,43 @@ static int add_arg(struct fuse_opt_context *ctx, const char *arg)
return fuse_opt_add_arg(&ctx->outargs, arg);
}
-int fuse_opt_add_opt(char **opts, const char *opt)
+static int add_opt_common(char **opts, const char *opt, int esc)
{
- char *newopts;
- if (!*opts)
- newopts = strdup(opt);
- else {
- unsigned oldlen = strlen(*opts);
- newopts = realloc(*opts, oldlen + 1 + strlen(opt) + 1);
- if (newopts) {
- newopts[oldlen] = ',';
- strcpy(newopts + oldlen + 1, opt);
- }
- }
- if (!newopts)
+ unsigned oldlen = *opts ? strlen(*opts) : 0;
+ char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
+
+ if (!d)
return alloc_failed();
- *opts = newopts;
+ *opts = d;
+ if (oldlen) {
+ d += oldlen;
+ *d++ = ',';
+ }
+
+ for (; *opt; opt++) {
+ if (esc && (*opt == ',' || *opt == '\\'))
+ *d++ = '\\';
+ *d++ = *opt;
+ }
+ *d = '\0';
+
return 0;
}
+int fuse_opt_add_opt(char **opts, const char *opt)
+{
+ return add_opt_common(opts, opt, 0);
+}
+
+int fuse_opt_add_opt_escaped(char **opts, const char *opt)
+{
+ return add_opt_common(opts, opt, 1);
+}
+
static int add_opt(struct fuse_opt_context *ctx, const char *opt)
{
- return fuse_opt_add_opt(&ctx->opts, opt);
+ return add_opt_common(&ctx->opts, opt, 1);
}
static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
@@ -274,18 +288,28 @@ static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
{
- char *sep;
-
- do {
- int res;
- sep = strchr(opts, ',');
- if (sep)
- *sep = '\0';
- res = process_gopt(ctx, opts, 1);
- if (res == -1)
- return -1;
- opts = sep + 1;
- } while (sep);
+ char *s = opts;
+ char *d = s;
+ int end = 0;
+
+ while (!end) {
+ if (*s == '\0')
+ end = 1;
+ if (*s == ',' || end) {
+ int res;
+
+ *d = '\0';
+ res = process_gopt(ctx, opts, 1);
+ if (res == -1)
+ return -1;
+ d = opts;
+ } else {
+ if (s[0] == '\\' && s[1] != '\0')
+ s++;
+ *d++ = *s;
+ }
+ s++;
+ }
return 0;
}
@@ -293,12 +317,8 @@ static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
{
int res;
- char *copy;
- const char *sep = strchr(opts, ',');
- if (!sep)
- return process_gopt(ctx, opts, 1);
+ char *copy = strdup(opts);
- copy = strdup(opts);
if (!copy) {
fprintf(stderr, "fuse: memory allocation failed\n");
return -1;
@@ -347,7 +367,10 @@ static int opt_parse(struct fuse_opt_context *ctx)
fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1)
return -1;
}
- if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc) {
+
+ /* If option separator ("--") is the last argument, remove it */
+ if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
+ strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) {
free(ctx->outargs.argv[ctx->outargs.argc - 1]);
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
}
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 3eedd0c..2f6aff3 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -151,7 +151,13 @@ FUSE_2.7 {
fuse_register_module;
fuse_reply_iov;
fuse_version;
+} FUSE_2.6;
+
+FUSE_2.8 {
+ global:
+ fuse_opt_add_opt_escaped;
+ fuse_reply_bmap;
local:
*;
-} FUSE_2.6;
+} FUSE_2.7;