12#include "fuse_config.h" 
   22struct fuse_opt_context {
 
   39                        for (i = 0; i < args->
argc; i++)
 
 
   49static int alloc_failed(
void)
 
   51        fuse_log(FUSE_LOG_ERR, 
"fuse: memory allocation failed\n");
 
   64                return alloc_failed();
 
   66        newargv = realloc(args->
argv, (args->
argc + 2) * 
sizeof(
char *));
 
   69                return alloc_failed();
 
 
   79static int fuse_opt_insert_arg_common(
struct fuse_args *args, 
int pos,
 
   82        assert(pos <= args->
argc);
 
   86        if (pos != args->
argc - 1) {
 
   87                char *newarg = args->
argv[args->
argc - 1];
 
   88                memmove(&args->
argv[pos + 1], &args->
argv[pos],
 
   89                        sizeof(
char *) * (args->
argc - pos - 1));
 
   90                args->
argv[pos] = newarg;
 
   97        return fuse_opt_insert_arg_common(args, pos, arg);
 
 
  100static int next_arg(
struct fuse_opt_context *ctx, 
const char *opt)
 
  102        if (ctx->argctr + 1 >= ctx->argc) {
 
  103                fuse_log(FUSE_LOG_ERR, 
"fuse: missing argument after `%s'\n", opt);
 
  110static int add_arg(
struct fuse_opt_context *ctx, 
const char *arg)
 
  115static int add_opt_common(
char **opts, 
const char *opt, 
int esc)
 
  117        unsigned oldlen = *opts ? strlen(*opts) : 0;
 
  118        char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
 
  121                return alloc_failed();
 
  129        for (; *opt; opt++) {
 
  130                if (esc && (*opt == 
',' || *opt == 
'\\'))
 
  141        return add_opt_common(opts, opt, 0);
 
 
  146        return add_opt_common(opts, opt, 1);
 
 
  149static int add_opt(
struct fuse_opt_context *ctx, 
const char *opt)
 
  151        return add_opt_common(&ctx->opts, opt, 1);
 
  154static int call_proc(
struct fuse_opt_context *ctx, 
const char *arg, 
int key,
 
  161                int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
 
  162                if (res == -1 || !res)
 
  166                return add_opt(ctx, arg);
 
  168                return add_arg(ctx, arg);
 
  171static int match_template(
const char *t, 
const char *arg, 
unsigned *sepp)
 
  173        int arglen = strlen(arg);
 
  174        const char *sep = strchr(t, 
'=');
 
  175        sep = sep ? sep : strchr(t, 
' ');
 
  176        if (sep && (!sep[1] || sep[1] == 
'%')) {
 
  180                if (arglen >= tlen && strncmp(arg, t, tlen) == 0) {
 
  185        if (strcmp(t, arg) == 0) {
 
  193                                       const char *arg, 
unsigned *sepp)
 
  195        for (; opt && opt->
templ; opt++)
 
  196                if (match_template(opt->
templ, arg, sepp))
 
  204        return find_opt(opts, opt, &dummy) ? 1 : 0;
 
  207static int process_opt_param(
void *var, 
const char *format, 
const char *param,
 
  210        assert(format[0] == 
'%');
 
  211        if (format[1] == 
's') {
 
  213                char *copy = strdup(param);
 
  215                        return alloc_failed();
 
  220                if (sscanf(param, format, var) != 1) {
 
  221                        fuse_log(FUSE_LOG_ERR, 
"fuse: invalid parameter in option `%s'\n", arg);
 
  228static int process_opt(
struct fuse_opt_context *ctx,
 
  229                       const struct fuse_opt *opt, 
unsigned sep,
 
  230                       const char *arg, 
int iso)
 
  233                if (call_proc(ctx, arg, opt->
value, iso) == -1)
 
  236                void *var = (
char *)ctx->data + opt->
offset;
 
  237                if (sep && opt->
templ[sep + 1]) {
 
  238                        const char *param = arg + sep;
 
  239                        if (opt->
templ[sep] == 
'=')
 
  241                        if (process_opt_param(var, opt->
templ + sep + 1,
 
  245                        *(
int *)var = opt->
value;
 
  250static int process_opt_sep_arg(
struct fuse_opt_context *ctx,
 
  251                               const struct fuse_opt *opt, 
unsigned sep,
 
  252                               const char *arg, 
int iso)
 
  258        if (next_arg(ctx, arg) == -1)
 
  261        param = ctx->argv[ctx->argctr];
 
  262        newarg = malloc(sep + strlen(param) + 1);
 
  264                return alloc_failed();
 
  266        memcpy(newarg, arg, sep);
 
  267        strcpy(newarg + sep, param);
 
  268        res = process_opt(ctx, opt, sep, newarg, iso);
 
  274static int process_gopt(
struct fuse_opt_context *ctx, 
const char *arg, 
int iso)
 
  277        const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep);
 
  279                for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
 
  281                        if (sep && opt->
templ[sep] == 
' ' && !arg[sep])
 
  282                                res = process_opt_sep_arg(ctx, opt, sep, arg,
 
  285                                res = process_opt(ctx, opt, sep, arg, iso);
 
  294static int process_real_option_group(
struct fuse_opt_context *ctx, 
char *opts)
 
  303                if (*s == 
',' || end) {
 
  307                        res = process_gopt(ctx, opts, 1);
 
  312                        if (s[0] == 
'\\' && s[1] != 
'\0') {
 
  314                                if (s[0] >= 
'0' && s[0] <= 
'3' &&
 
  315                                    s[1] >= 
'0' && s[1] <= 
'7' &&
 
  316                                    s[2] >= 
'0' && s[2] <= 
'7') {
 
  317                                        *d++ = (s[0] - 
'0') * 0100 +
 
  318                                                (s[1] - 
'0') * 0010 +
 
  334static int process_option_group(
struct fuse_opt_context *ctx, 
const char *opts)
 
  337        char *copy = strdup(opts);
 
  340                fuse_log(FUSE_LOG_ERR, 
"fuse: memory allocation failed\n");
 
  343        res = process_real_option_group(ctx, copy);
 
  348static int process_one(
struct fuse_opt_context *ctx, 
const char *arg)
 
  350        if (ctx->nonopt || arg[0] != 
'-')
 
  352        else if (arg[1] == 
'o') {
 
  354                        return process_option_group(ctx, arg + 2);
 
  356                        if (next_arg(ctx, arg) == -1)
 
  359                        return process_option_group(ctx,
 
  360                                                    ctx->argv[ctx->argctr]);
 
  362        } 
else if (arg[1] == 
'-' && !arg[2]) {
 
  363                if (add_arg(ctx, arg) == -1)
 
  365                ctx->nonopt = ctx->outargs.argc;
 
  368                return process_gopt(ctx, arg, 0);
 
  371static int opt_parse(
struct fuse_opt_context *ctx)
 
  374                if (add_arg(ctx, ctx->argv[0]) == -1)
 
  378        for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++)
 
  379                if (process_one(ctx, ctx->argv[ctx->argctr]) == -1)
 
  389        if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc &&
 
  390            strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], 
"--") == 0) {
 
  391                free(ctx->outargs.argv[ctx->outargs.argc - 1]);
 
  392                ctx->outargs.argv[--ctx->outargs.argc] = NULL;
 
  402        struct fuse_opt_context ctx = {
 
  408        if (!args || !args->
argv || !args->
argc)
 
  411        ctx.argc = args->
argc;
 
  412        ctx.argv = args->
argv;
 
  414        res = opt_parse(&ctx);
 
 
void fuse_log(enum fuse_log_level level, const char *fmt,...)
int(* fuse_opt_proc_t)(void *data, const char *arg, int key, struct fuse_args *outargs)
#define FUSE_OPT_KEY_NONOPT
#define FUSE_OPT_KEY_DISCARD
#define FUSE_OPT_KEY_KEEP
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
void fuse_opt_free_args(struct fuse_args *args)
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_add_opt(char **opts, const char *opt)
int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
int fuse_opt_match(const struct fuse_opt opts[], const char *opt)