From 5c094ac0150ebfef6a2c9c2c9d1c545a90ff4e96 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 16 Oct 2008 19:11:28 +0000 Subject: [PATCH] * 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 --- ChangeLog | 8 ++++ include/fuse_opt.h | 9 +++++ lib/fuse_opt.c | 89 ++++++++++++++++++++++++++---------------- lib/fuse_versionscript | 8 +++- 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 + + * 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 * 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 @@ -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 * 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; -- 2.30.2