14 #include "fuse_misc.h"    21 struct fuse_opt_context {
    38                         for (i = 0; i < args->
argc; i++)
    48 static int alloc_failed(
void)
    50         fprintf(stderr, 
"fuse: memory allocation failed\n");
    63                 return alloc_failed();
    65         newargv = realloc(args->
argv, (args->
argc + 2) * 
sizeof(
char *));
    68                 return alloc_failed();
    78 static int fuse_opt_insert_arg_common(
struct fuse_args *args, 
int pos,
    81         assert(pos <= args->
argc);
    85         if (pos != args->
argc - 1) {
    86                 char *newarg = args->
argv[args->
argc - 1];
    87                 memmove(&args->
argv[pos + 1], &args->
argv[pos],
    88                         sizeof(
char *) * (args->
argc - pos - 1));
    89                 args->
argv[pos] = newarg;
    96         return fuse_opt_insert_arg_common(args, pos, arg);
    99 static int next_arg(
struct fuse_opt_context *ctx, 
const char *opt)
   101         if (ctx->argctr + 1 >= ctx->argc) {
   102                 fprintf(stderr, 
"fuse: missing argument after `%s'\n", opt);
   109 static int add_arg(
struct fuse_opt_context *ctx, 
const char *arg)
   114 static int add_opt_common(
char **opts, 
const char *opt, 
int esc)
   116         unsigned oldlen = *opts ? strlen(*opts) : 0;
   117         char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
   120                 return alloc_failed();
   128         for (; *opt; opt++) {
   129                 if (esc && (*opt == 
',' || *opt == 
'\\'))
   140         return add_opt_common(opts, opt, 0);
   145         return add_opt_common(opts, opt, 1);
   148 static int add_opt(
struct fuse_opt_context *ctx, 
const char *opt)
   150         return add_opt_common(&ctx->opts, opt, 1);
   153 static int call_proc(
struct fuse_opt_context *ctx, 
const char *arg, 
int key,
   160                 int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
   161                 if (res == -1 || !res)
   165                 return add_opt(ctx, arg);
   167                 return add_arg(ctx, arg);
   170 static int match_template(
const char *t, 
const char *arg, 
unsigned *sepp)
   172         int arglen = strlen(arg);
   173         const char *sep = strchr(t, 
'=');
   174         sep = sep ? sep : strchr(t, 
' ');
   175         if (sep && (!sep[1] || sep[1] == 
'%')) {
   179                 if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
   184         if (strcmp(t, arg) == 0) {
   192                                        const char *arg, 
unsigned *sepp)
   194         for (; opt && opt->
templ; opt++)
   195                 if (match_template(opt->
templ, arg, sepp))
   203         return find_opt(opts, opt, &dummy) ? 1 : 0;
   206 static int process_opt_param(
void *var, 
const char *format, 
const char *param,
   209         assert(format[0] == 
'%');
   210         if (format[1] == 
's') {
   212                 char *copy = strdup(param);
   214                         return alloc_failed();
   219                 if (sscanf(param, format, var) != 1) {
   220                         fprintf(stderr, 
"fuse: invalid parameter in option `%s'\n", arg);
   227 static int process_opt(
struct fuse_opt_context *ctx,
   228                        const struct fuse_opt *opt, 
unsigned sep,
   229                        const char *arg, 
int iso)
   232                 if (call_proc(ctx, arg, opt->
value, iso) == -1)
   235                 void *var = ctx->data + opt->
offset;
   236                 if (sep && opt->
templ[sep + 1]) {
   237                         const char *param = arg + sep;
   238                         if (opt->
templ[sep] == 
'=')
   240                         if (process_opt_param(var, opt->
templ + sep + 1,
   244                         *(
int *)var = opt->
value;
   249 static int process_opt_sep_arg(
struct fuse_opt_context *ctx,
   250                                const struct fuse_opt *opt, 
unsigned sep,
   251                                const char *arg, 
int iso)
   257         if (next_arg(ctx, arg) == -1)
   260         param = ctx->argv[ctx->argctr];
   261         newarg = malloc(sep + strlen(param) + 1);
   263                 return alloc_failed();
   265         memcpy(newarg, arg, sep);
   266         strcpy(newarg + sep, param);
   267         res = process_opt(ctx, opt, sep, newarg, iso);
   273 static int process_gopt(
struct fuse_opt_context *ctx, 
const char *arg, 
int iso)
   276         const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
   278                 for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
   280                         if (sep && opt->
templ[sep] == 
' ' && !arg[sep])
   281                                 res = process_opt_sep_arg(ctx, opt, sep, arg,
   284                                 res = process_opt(ctx, opt, sep, arg, iso);
   293 static int process_real_option_group(
struct fuse_opt_context *ctx, 
char *opts)
   302                 if (*s == 
',' || end) {
   306                         res = process_gopt(ctx, opts, 1);
   311                         if (s[0] == 
'\\' && s[1] != 
'\0') {
   313                                 if (s[0] >= 
'0' && s[0] <= 
'3' &&
   314                                     s[1] >= 
'0' && s[1] <= 
'7' &&
   315                                     s[2] >= 
'0' && s[2] <= 
'7') {
   316                                         *d++ = (s[0] - 
'0') * 0100 +
   317                                                 (s[1] - 
'0') * 0010 +
   333 static int process_option_group(
struct fuse_opt_context *ctx, 
const char *opts)
   336         char *copy = strdup(opts);
   339                 fprintf(stderr, 
"fuse: memory allocation failed\n");
   342         res = process_real_option_group(ctx, copy);
   347 static int process_one(
struct fuse_opt_context *ctx, 
const char *arg)
   349         if (ctx->nonopt || arg[0] != 
'-')
   351         else if (arg[1] == 
'o') {
   353                         return process_option_group(ctx, arg + 2);
   355                         if (next_arg(ctx, arg) == -1)
   358                         return process_option_group(ctx,
   359                                                     ctx->argv[ctx->argctr]);
   361         } 
else if (arg[1] == 
'-' && !arg[2]) {
   362                 if (add_arg(ctx, arg) == -1)
   364                 ctx->nonopt = ctx->outargs.argc;
   367                 return process_gopt(ctx, arg, 0);
   370 static int opt_parse(
struct fuse_opt_context *ctx)
   373                 if (add_arg(ctx, ctx->argv[0]) == -1)
   377         for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++)
   378                 if (process_one(ctx, ctx->argv[ctx->argctr]) == -1)
   388         if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
   389             strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], 
"--") == 0) {
   390                 free(ctx->outargs.argv[ctx->outargs.argc - 1]);
   391                 ctx->outargs.argv[--ctx->outargs.argc] = NULL;
   401         struct fuse_opt_context ctx = {
   407         if (!args || !args->
argv || !args->
argc)
   410         ctx.argc = args->
argc;
   411         ctx.argv = args->
argv;
   413         res = opt_parse(&ctx);
 int fuse_opt_add_opt_escaped(char **opts, const char *opt)
int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc)
int fuse_opt_match(const struct fuse_opt opts[], const char *opt)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
#define FUSE_OPT_KEY_DISCARD
void fuse_opt_free_args(struct fuse_args *args)
#define FUSE_OPT_KEY_KEEP
int fuse_opt_add_opt(char **opts, const char *opt)
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
#define FUSE_OPT_KEY_NONOPT
int(* fuse_opt_proc_t)(void *data, const char *arg, int key, struct fuse_args *outargs)