* Allow commas in options to be escaped with a backslash * Add new function: fuse_opt...
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 16 Oct 2008 19:11:28 +0000 (19:11 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 16 Oct 2008 19:11:28 +0000 (19:11 +0000)
ChangeLog
include/fuse_opt.h
lib/fuse_opt.c
lib/fuse_versionscript

index 7c34017203e539016996e3de0bbf6e8617e330ca..79ed2a5cf1ee4bee0e084db967fe95a034324c88 100644 (file)
--- 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
index 7ae08af647416daddaa17c454f612cd764e7a710..5595b4a44f627dc972149f5f335b4c069106869b 100644 (file)
@@ -211,6 +211,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
  *
index 8a9019b561357183af65530a5602cc6297edcb31..b15e7db11905b4f315fd99f0cac7231cb9368345 100644 (file)
@@ -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;
        }
index 3eedd0c6ddbcf911feef98bd4d34cc4e1398021a..2f6aff3603880b6ab55e4e787f81f6536dae8cb5 100644 (file)
@@ -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;