16881f68fSopenharmony_ci/* 26881f68fSopenharmony_ci FUSE: Filesystem in Userspace 36881f68fSopenharmony_ci Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu> 46881f68fSopenharmony_ci 56881f68fSopenharmony_ci Implementation of option parsing routines (dealing with `struct 66881f68fSopenharmony_ci fuse_args`). 76881f68fSopenharmony_ci 86881f68fSopenharmony_ci This program can be distributed under the terms of the GNU LGPLv2. 96881f68fSopenharmony_ci See the file COPYING.LIB 106881f68fSopenharmony_ci*/ 116881f68fSopenharmony_ci 126881f68fSopenharmony_ci#include "fuse_config.h" 136881f68fSopenharmony_ci#include "fuse_i.h" 146881f68fSopenharmony_ci#include "fuse_opt.h" 156881f68fSopenharmony_ci#include "fuse_misc.h" 166881f68fSopenharmony_ci 176881f68fSopenharmony_ci#include <stdio.h> 186881f68fSopenharmony_ci#include <stdlib.h> 196881f68fSopenharmony_ci#include <string.h> 206881f68fSopenharmony_ci#include <assert.h> 216881f68fSopenharmony_ci 226881f68fSopenharmony_cistruct fuse_opt_context { 236881f68fSopenharmony_ci void *data; 246881f68fSopenharmony_ci const struct fuse_opt *opt; 256881f68fSopenharmony_ci fuse_opt_proc_t proc; 266881f68fSopenharmony_ci int argctr; 276881f68fSopenharmony_ci int argc; 286881f68fSopenharmony_ci char **argv; 296881f68fSopenharmony_ci struct fuse_args outargs; 306881f68fSopenharmony_ci char *opts; 316881f68fSopenharmony_ci int nonopt; 326881f68fSopenharmony_ci}; 336881f68fSopenharmony_ci 346881f68fSopenharmony_civoid fuse_opt_free_args(struct fuse_args *args) 356881f68fSopenharmony_ci{ 366881f68fSopenharmony_ci if (args) { 376881f68fSopenharmony_ci if (args->argv && args->allocated) { 386881f68fSopenharmony_ci int i; 396881f68fSopenharmony_ci for (i = 0; i < args->argc; i++) 406881f68fSopenharmony_ci free(args->argv[i]); 416881f68fSopenharmony_ci free(args->argv); 426881f68fSopenharmony_ci } 436881f68fSopenharmony_ci args->argc = 0; 446881f68fSopenharmony_ci args->argv = NULL; 456881f68fSopenharmony_ci args->allocated = 0; 466881f68fSopenharmony_ci } 476881f68fSopenharmony_ci} 486881f68fSopenharmony_ci 496881f68fSopenharmony_cistatic int alloc_failed(void) 506881f68fSopenharmony_ci{ 516881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n"); 526881f68fSopenharmony_ci return -1; 536881f68fSopenharmony_ci} 546881f68fSopenharmony_ci 556881f68fSopenharmony_ciint fuse_opt_add_arg(struct fuse_args *args, const char *arg) 566881f68fSopenharmony_ci{ 576881f68fSopenharmony_ci char **newargv; 586881f68fSopenharmony_ci char *newarg; 596881f68fSopenharmony_ci 606881f68fSopenharmony_ci assert(!args->argv || args->allocated); 616881f68fSopenharmony_ci 626881f68fSopenharmony_ci newarg = strdup(arg); 636881f68fSopenharmony_ci if (!newarg) 646881f68fSopenharmony_ci return alloc_failed(); 656881f68fSopenharmony_ci 666881f68fSopenharmony_ci newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *)); 676881f68fSopenharmony_ci if (!newargv) { 686881f68fSopenharmony_ci free(newarg); 696881f68fSopenharmony_ci return alloc_failed(); 706881f68fSopenharmony_ci } 716881f68fSopenharmony_ci 726881f68fSopenharmony_ci args->argv = newargv; 736881f68fSopenharmony_ci args->allocated = 1; 746881f68fSopenharmony_ci args->argv[args->argc++] = newarg; 756881f68fSopenharmony_ci args->argv[args->argc] = NULL; 766881f68fSopenharmony_ci return 0; 776881f68fSopenharmony_ci} 786881f68fSopenharmony_ci 796881f68fSopenharmony_cistatic int fuse_opt_insert_arg_common(struct fuse_args *args, int pos, 806881f68fSopenharmony_ci const char *arg) 816881f68fSopenharmony_ci{ 826881f68fSopenharmony_ci assert(pos <= args->argc); 836881f68fSopenharmony_ci if (fuse_opt_add_arg(args, arg) == -1) 846881f68fSopenharmony_ci return -1; 856881f68fSopenharmony_ci 866881f68fSopenharmony_ci if (pos != args->argc - 1) { 876881f68fSopenharmony_ci char *newarg = args->argv[args->argc - 1]; 886881f68fSopenharmony_ci memmove(&args->argv[pos + 1], &args->argv[pos], 896881f68fSopenharmony_ci sizeof(char *) * (args->argc - pos - 1)); 906881f68fSopenharmony_ci args->argv[pos] = newarg; 916881f68fSopenharmony_ci } 926881f68fSopenharmony_ci return 0; 936881f68fSopenharmony_ci} 946881f68fSopenharmony_ci 956881f68fSopenharmony_ciint fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) 966881f68fSopenharmony_ci{ 976881f68fSopenharmony_ci return fuse_opt_insert_arg_common(args, pos, arg); 986881f68fSopenharmony_ci} 996881f68fSopenharmony_ci 1006881f68fSopenharmony_cistatic int next_arg(struct fuse_opt_context *ctx, const char *opt) 1016881f68fSopenharmony_ci{ 1026881f68fSopenharmony_ci if (ctx->argctr + 1 >= ctx->argc) { 1036881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "fuse: missing argument after `%s'\n", opt); 1046881f68fSopenharmony_ci return -1; 1056881f68fSopenharmony_ci } 1066881f68fSopenharmony_ci ctx->argctr++; 1076881f68fSopenharmony_ci return 0; 1086881f68fSopenharmony_ci} 1096881f68fSopenharmony_ci 1106881f68fSopenharmony_cistatic int add_arg(struct fuse_opt_context *ctx, const char *arg) 1116881f68fSopenharmony_ci{ 1126881f68fSopenharmony_ci return fuse_opt_add_arg(&ctx->outargs, arg); 1136881f68fSopenharmony_ci} 1146881f68fSopenharmony_ci 1156881f68fSopenharmony_cistatic int add_opt_common(char **opts, const char *opt, int esc) 1166881f68fSopenharmony_ci{ 1176881f68fSopenharmony_ci unsigned oldlen = *opts ? strlen(*opts) : 0; 1186881f68fSopenharmony_ci char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1); 1196881f68fSopenharmony_ci 1206881f68fSopenharmony_ci if (!d) 1216881f68fSopenharmony_ci return alloc_failed(); 1226881f68fSopenharmony_ci 1236881f68fSopenharmony_ci *opts = d; 1246881f68fSopenharmony_ci if (oldlen) { 1256881f68fSopenharmony_ci d += oldlen; 1266881f68fSopenharmony_ci *d++ = ','; 1276881f68fSopenharmony_ci } 1286881f68fSopenharmony_ci 1296881f68fSopenharmony_ci for (; *opt; opt++) { 1306881f68fSopenharmony_ci if (esc && (*opt == ',' || *opt == '\\')) 1316881f68fSopenharmony_ci *d++ = '\\'; 1326881f68fSopenharmony_ci *d++ = *opt; 1336881f68fSopenharmony_ci } 1346881f68fSopenharmony_ci *d = '\0'; 1356881f68fSopenharmony_ci 1366881f68fSopenharmony_ci return 0; 1376881f68fSopenharmony_ci} 1386881f68fSopenharmony_ci 1396881f68fSopenharmony_ciint fuse_opt_add_opt(char **opts, const char *opt) 1406881f68fSopenharmony_ci{ 1416881f68fSopenharmony_ci return add_opt_common(opts, opt, 0); 1426881f68fSopenharmony_ci} 1436881f68fSopenharmony_ci 1446881f68fSopenharmony_ciint fuse_opt_add_opt_escaped(char **opts, const char *opt) 1456881f68fSopenharmony_ci{ 1466881f68fSopenharmony_ci return add_opt_common(opts, opt, 1); 1476881f68fSopenharmony_ci} 1486881f68fSopenharmony_ci 1496881f68fSopenharmony_cistatic int add_opt(struct fuse_opt_context *ctx, const char *opt) 1506881f68fSopenharmony_ci{ 1516881f68fSopenharmony_ci return add_opt_common(&ctx->opts, opt, 1); 1526881f68fSopenharmony_ci} 1536881f68fSopenharmony_ci 1546881f68fSopenharmony_cistatic int call_proc(struct fuse_opt_context *ctx, const char *arg, int key, 1556881f68fSopenharmony_ci int iso) 1566881f68fSopenharmony_ci{ 1576881f68fSopenharmony_ci if (key == FUSE_OPT_KEY_DISCARD) 1586881f68fSopenharmony_ci return 0; 1596881f68fSopenharmony_ci 1606881f68fSopenharmony_ci if (key != FUSE_OPT_KEY_KEEP && ctx->proc) { 1616881f68fSopenharmony_ci int res = ctx->proc(ctx->data, arg, key, &ctx->outargs); 1626881f68fSopenharmony_ci if (res == -1 || !res) 1636881f68fSopenharmony_ci return res; 1646881f68fSopenharmony_ci } 1656881f68fSopenharmony_ci if (iso) 1666881f68fSopenharmony_ci return add_opt(ctx, arg); 1676881f68fSopenharmony_ci else 1686881f68fSopenharmony_ci return add_arg(ctx, arg); 1696881f68fSopenharmony_ci} 1706881f68fSopenharmony_ci 1716881f68fSopenharmony_cistatic int match_template(const char *t, const char *arg, unsigned *sepp) 1726881f68fSopenharmony_ci{ 1736881f68fSopenharmony_ci int arglen = strlen(arg); 1746881f68fSopenharmony_ci const char *sep = strchr(t, '='); 1756881f68fSopenharmony_ci sep = sep ? sep : strchr(t, ' '); 1766881f68fSopenharmony_ci if (sep && (!sep[1] || sep[1] == '%')) { 1776881f68fSopenharmony_ci int tlen = sep - t; 1786881f68fSopenharmony_ci if (sep[0] == '=') 1796881f68fSopenharmony_ci tlen ++; 1806881f68fSopenharmony_ci if (arglen >= tlen && strncmp(arg, t, tlen) == 0) { 1816881f68fSopenharmony_ci *sepp = sep - t; 1826881f68fSopenharmony_ci return 1; 1836881f68fSopenharmony_ci } 1846881f68fSopenharmony_ci } 1856881f68fSopenharmony_ci if (strcmp(t, arg) == 0) { 1866881f68fSopenharmony_ci *sepp = 0; 1876881f68fSopenharmony_ci return 1; 1886881f68fSopenharmony_ci } 1896881f68fSopenharmony_ci return 0; 1906881f68fSopenharmony_ci} 1916881f68fSopenharmony_ci 1926881f68fSopenharmony_cistatic const struct fuse_opt *find_opt(const struct fuse_opt *opt, 1936881f68fSopenharmony_ci const char *arg, unsigned *sepp) 1946881f68fSopenharmony_ci{ 1956881f68fSopenharmony_ci for (; opt && opt->templ; opt++) 1966881f68fSopenharmony_ci if (match_template(opt->templ, arg, sepp)) 1976881f68fSopenharmony_ci return opt; 1986881f68fSopenharmony_ci return NULL; 1996881f68fSopenharmony_ci} 2006881f68fSopenharmony_ci 2016881f68fSopenharmony_ciint fuse_opt_match(const struct fuse_opt *opts, const char *opt) 2026881f68fSopenharmony_ci{ 2036881f68fSopenharmony_ci unsigned dummy; 2046881f68fSopenharmony_ci return find_opt(opts, opt, &dummy) ? 1 : 0; 2056881f68fSopenharmony_ci} 2066881f68fSopenharmony_ci 2076881f68fSopenharmony_cistatic int process_opt_param(void *var, const char *format, const char *param, 2086881f68fSopenharmony_ci const char *arg) 2096881f68fSopenharmony_ci{ 2106881f68fSopenharmony_ci assert(format[0] == '%'); 2116881f68fSopenharmony_ci if (format[1] == 's') { 2126881f68fSopenharmony_ci char **s = var; 2136881f68fSopenharmony_ci char *copy = strdup(param); 2146881f68fSopenharmony_ci if (!copy) 2156881f68fSopenharmony_ci return alloc_failed(); 2166881f68fSopenharmony_ci 2176881f68fSopenharmony_ci free(*s); 2186881f68fSopenharmony_ci *s = copy; 2196881f68fSopenharmony_ci } else { 2206881f68fSopenharmony_ci if (sscanf(param, format, var) != 1) { 2216881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "fuse: invalid parameter in option `%s'\n", arg); 2226881f68fSopenharmony_ci return -1; 2236881f68fSopenharmony_ci } 2246881f68fSopenharmony_ci } 2256881f68fSopenharmony_ci return 0; 2266881f68fSopenharmony_ci} 2276881f68fSopenharmony_ci 2286881f68fSopenharmony_cistatic int process_opt(struct fuse_opt_context *ctx, 2296881f68fSopenharmony_ci const struct fuse_opt *opt, unsigned sep, 2306881f68fSopenharmony_ci const char *arg, int iso) 2316881f68fSopenharmony_ci{ 2326881f68fSopenharmony_ci if (opt->offset == -1U) { 2336881f68fSopenharmony_ci if (call_proc(ctx, arg, opt->value, iso) == -1) 2346881f68fSopenharmony_ci return -1; 2356881f68fSopenharmony_ci } else { 2366881f68fSopenharmony_ci void *var = (char *)ctx->data + opt->offset; 2376881f68fSopenharmony_ci if (sep && opt->templ[sep + 1]) { 2386881f68fSopenharmony_ci const char *param = arg + sep; 2396881f68fSopenharmony_ci if (opt->templ[sep] == '=') 2406881f68fSopenharmony_ci param ++; 2416881f68fSopenharmony_ci if (process_opt_param(var, opt->templ + sep + 1, 2426881f68fSopenharmony_ci param, arg) == -1) 2436881f68fSopenharmony_ci return -1; 2446881f68fSopenharmony_ci } else 2456881f68fSopenharmony_ci *(int *)var = opt->value; 2466881f68fSopenharmony_ci } 2476881f68fSopenharmony_ci return 0; 2486881f68fSopenharmony_ci} 2496881f68fSopenharmony_ci 2506881f68fSopenharmony_cistatic int process_opt_sep_arg(struct fuse_opt_context *ctx, 2516881f68fSopenharmony_ci const struct fuse_opt *opt, unsigned sep, 2526881f68fSopenharmony_ci const char *arg, int iso) 2536881f68fSopenharmony_ci{ 2546881f68fSopenharmony_ci int res; 2556881f68fSopenharmony_ci char *newarg; 2566881f68fSopenharmony_ci char *param; 2576881f68fSopenharmony_ci 2586881f68fSopenharmony_ci if (next_arg(ctx, arg) == -1) 2596881f68fSopenharmony_ci return -1; 2606881f68fSopenharmony_ci 2616881f68fSopenharmony_ci param = ctx->argv[ctx->argctr]; 2626881f68fSopenharmony_ci newarg = malloc(sep + strlen(param) + 1); 2636881f68fSopenharmony_ci if (!newarg) 2646881f68fSopenharmony_ci return alloc_failed(); 2656881f68fSopenharmony_ci 2666881f68fSopenharmony_ci memcpy(newarg, arg, sep); 2676881f68fSopenharmony_ci strcpy(newarg + sep, param); 2686881f68fSopenharmony_ci res = process_opt(ctx, opt, sep, newarg, iso); 2696881f68fSopenharmony_ci free(newarg); 2706881f68fSopenharmony_ci 2716881f68fSopenharmony_ci return res; 2726881f68fSopenharmony_ci} 2736881f68fSopenharmony_ci 2746881f68fSopenharmony_cistatic int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso) 2756881f68fSopenharmony_ci{ 2766881f68fSopenharmony_ci unsigned sep; 2776881f68fSopenharmony_ci const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep); 2786881f68fSopenharmony_ci if (opt) { 2796881f68fSopenharmony_ci for (; opt; opt = find_opt(opt + 1, arg, &sep)) { 2806881f68fSopenharmony_ci int res; 2816881f68fSopenharmony_ci if (sep && opt->templ[sep] == ' ' && !arg[sep]) 2826881f68fSopenharmony_ci res = process_opt_sep_arg(ctx, opt, sep, arg, 2836881f68fSopenharmony_ci iso); 2846881f68fSopenharmony_ci else 2856881f68fSopenharmony_ci res = process_opt(ctx, opt, sep, arg, iso); 2866881f68fSopenharmony_ci if (res == -1) 2876881f68fSopenharmony_ci return -1; 2886881f68fSopenharmony_ci } 2896881f68fSopenharmony_ci return 0; 2906881f68fSopenharmony_ci } else 2916881f68fSopenharmony_ci return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso); 2926881f68fSopenharmony_ci} 2936881f68fSopenharmony_ci 2946881f68fSopenharmony_cistatic int process_real_option_group(struct fuse_opt_context *ctx, char *opts) 2956881f68fSopenharmony_ci{ 2966881f68fSopenharmony_ci char *s = opts; 2976881f68fSopenharmony_ci char *d = s; 2986881f68fSopenharmony_ci int end = 0; 2996881f68fSopenharmony_ci 3006881f68fSopenharmony_ci while (!end) { 3016881f68fSopenharmony_ci if (*s == '\0') 3026881f68fSopenharmony_ci end = 1; 3036881f68fSopenharmony_ci if (*s == ',' || end) { 3046881f68fSopenharmony_ci int res; 3056881f68fSopenharmony_ci 3066881f68fSopenharmony_ci *d = '\0'; 3076881f68fSopenharmony_ci res = process_gopt(ctx, opts, 1); 3086881f68fSopenharmony_ci if (res == -1) 3096881f68fSopenharmony_ci return -1; 3106881f68fSopenharmony_ci d = opts; 3116881f68fSopenharmony_ci } else { 3126881f68fSopenharmony_ci if (s[0] == '\\' && s[1] != '\0') { 3136881f68fSopenharmony_ci s++; 3146881f68fSopenharmony_ci if (s[0] >= '0' && s[0] <= '3' && 3156881f68fSopenharmony_ci s[1] >= '0' && s[1] <= '7' && 3166881f68fSopenharmony_ci s[2] >= '0' && s[2] <= '7') { 3176881f68fSopenharmony_ci *d++ = (s[0] - '0') * 0100 + 3186881f68fSopenharmony_ci (s[1] - '0') * 0010 + 3196881f68fSopenharmony_ci (s[2] - '0'); 3206881f68fSopenharmony_ci s += 2; 3216881f68fSopenharmony_ci } else { 3226881f68fSopenharmony_ci *d++ = *s; 3236881f68fSopenharmony_ci } 3246881f68fSopenharmony_ci } else { 3256881f68fSopenharmony_ci *d++ = *s; 3266881f68fSopenharmony_ci } 3276881f68fSopenharmony_ci } 3286881f68fSopenharmony_ci s++; 3296881f68fSopenharmony_ci } 3306881f68fSopenharmony_ci 3316881f68fSopenharmony_ci return 0; 3326881f68fSopenharmony_ci} 3336881f68fSopenharmony_ci 3346881f68fSopenharmony_cistatic int process_option_group(struct fuse_opt_context *ctx, const char *opts) 3356881f68fSopenharmony_ci{ 3366881f68fSopenharmony_ci int res; 3376881f68fSopenharmony_ci char *copy = strdup(opts); 3386881f68fSopenharmony_ci 3396881f68fSopenharmony_ci if (!copy) { 3406881f68fSopenharmony_ci fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n"); 3416881f68fSopenharmony_ci return -1; 3426881f68fSopenharmony_ci } 3436881f68fSopenharmony_ci res = process_real_option_group(ctx, copy); 3446881f68fSopenharmony_ci free(copy); 3456881f68fSopenharmony_ci return res; 3466881f68fSopenharmony_ci} 3476881f68fSopenharmony_ci 3486881f68fSopenharmony_cistatic int process_one(struct fuse_opt_context *ctx, const char *arg) 3496881f68fSopenharmony_ci{ 3506881f68fSopenharmony_ci if (ctx->nonopt || arg[0] != '-') 3516881f68fSopenharmony_ci return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0); 3526881f68fSopenharmony_ci else if (arg[1] == 'o') { 3536881f68fSopenharmony_ci if (arg[2]) 3546881f68fSopenharmony_ci return process_option_group(ctx, arg + 2); 3556881f68fSopenharmony_ci else { 3566881f68fSopenharmony_ci if (next_arg(ctx, arg) == -1) 3576881f68fSopenharmony_ci return -1; 3586881f68fSopenharmony_ci 3596881f68fSopenharmony_ci return process_option_group(ctx, 3606881f68fSopenharmony_ci ctx->argv[ctx->argctr]); 3616881f68fSopenharmony_ci } 3626881f68fSopenharmony_ci } else if (arg[1] == '-' && !arg[2]) { 3636881f68fSopenharmony_ci if (add_arg(ctx, arg) == -1) 3646881f68fSopenharmony_ci return -1; 3656881f68fSopenharmony_ci ctx->nonopt = ctx->outargs.argc; 3666881f68fSopenharmony_ci return 0; 3676881f68fSopenharmony_ci } else 3686881f68fSopenharmony_ci return process_gopt(ctx, arg, 0); 3696881f68fSopenharmony_ci} 3706881f68fSopenharmony_ci 3716881f68fSopenharmony_cistatic int opt_parse(struct fuse_opt_context *ctx) 3726881f68fSopenharmony_ci{ 3736881f68fSopenharmony_ci if (ctx->argc) { 3746881f68fSopenharmony_ci if (add_arg(ctx, ctx->argv[0]) == -1) 3756881f68fSopenharmony_ci return -1; 3766881f68fSopenharmony_ci } 3776881f68fSopenharmony_ci 3786881f68fSopenharmony_ci for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) 3796881f68fSopenharmony_ci if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) 3806881f68fSopenharmony_ci return -1; 3816881f68fSopenharmony_ci 3826881f68fSopenharmony_ci if (ctx->opts) { 3836881f68fSopenharmony_ci if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 || 3846881f68fSopenharmony_ci fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) 3856881f68fSopenharmony_ci return -1; 3866881f68fSopenharmony_ci } 3876881f68fSopenharmony_ci 3886881f68fSopenharmony_ci /* If option separator ("--") is the last argument, remove it */ 3896881f68fSopenharmony_ci if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc && 3906881f68fSopenharmony_ci strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) { 3916881f68fSopenharmony_ci free(ctx->outargs.argv[ctx->outargs.argc - 1]); 3926881f68fSopenharmony_ci ctx->outargs.argv[--ctx->outargs.argc] = NULL; 3936881f68fSopenharmony_ci } 3946881f68fSopenharmony_ci 3956881f68fSopenharmony_ci return 0; 3966881f68fSopenharmony_ci} 3976881f68fSopenharmony_ci 3986881f68fSopenharmony_ciint fuse_opt_parse(struct fuse_args *args, void *data, 3996881f68fSopenharmony_ci const struct fuse_opt opts[], fuse_opt_proc_t proc) 4006881f68fSopenharmony_ci{ 4016881f68fSopenharmony_ci int res; 4026881f68fSopenharmony_ci struct fuse_opt_context ctx = { 4036881f68fSopenharmony_ci .data = data, 4046881f68fSopenharmony_ci .opt = opts, 4056881f68fSopenharmony_ci .proc = proc, 4066881f68fSopenharmony_ci }; 4076881f68fSopenharmony_ci 4086881f68fSopenharmony_ci if (!args || !args->argv || !args->argc) 4096881f68fSopenharmony_ci return 0; 4106881f68fSopenharmony_ci 4116881f68fSopenharmony_ci ctx.argc = args->argc; 4126881f68fSopenharmony_ci ctx.argv = args->argv; 4136881f68fSopenharmony_ci 4146881f68fSopenharmony_ci res = opt_parse(&ctx); 4156881f68fSopenharmony_ci if (res != -1) { 4166881f68fSopenharmony_ci struct fuse_args tmp = *args; 4176881f68fSopenharmony_ci *args = ctx.outargs; 4186881f68fSopenharmony_ci ctx.outargs = tmp; 4196881f68fSopenharmony_ci } 4206881f68fSopenharmony_ci free(ctx.opts); 4216881f68fSopenharmony_ci fuse_opt_free_args(&ctx.outargs); 4226881f68fSopenharmony_ci return res; 4236881f68fSopenharmony_ci} 424