dll: fuse_opt: support escaped options and related refactoring

This commit is contained in:
Bill Zissimopoulos 2016-05-31 15:34:26 -07:00
parent 765bb1e1a3
commit b559c7405f
2 changed files with 79 additions and 43 deletions

View File

@ -19,6 +19,11 @@
#include <fuse/fuse_opt.h>
#include <stdint.h>
/*
* Define the following symbol to support escaped commas (',') during fuse_opt_parse.
*/
#define FSP_FUSE_OPT_PARSE_ESCAPED_COMMAS
#define fsp_fuse_opt_match_none ((const char *)0) /* no option match */
#define fsp_fuse_opt_match_exact ((const char *)1) /* exact option match */
#define fsp_fuse_opt_match_next ((const char *)2) /* option match, value is next arg */
@ -30,7 +35,7 @@ typedef long long strtoint_result_t;
typedef long strtoint_result_t;
#endif
static strtoint_result_t strtoint(const char *p, const char *endp, int base, int is_signed)
static strtoint_result_t strtoint(const char *p, int base, int is_signed)
{
strtoint_result_t v;
int maxdig, maxalp, sign = +1;
@ -65,7 +70,7 @@ static strtoint_result_t strtoint(const char *p, const char *endp, int base, int
maxdig = 10 < base ? '9' : (base - 1) + '0';
maxalp = 10 < base ? (base - 1 - 10) + 'a' : 0;
for (v = 0; *p && endp != p; p++)
for (v = 0; *p; p++)
{
int c = *p;
@ -86,14 +91,14 @@ static strtoint_result_t strtoint(const char *p, const char *endp, int base, int
static void fsp_fuse_opt_match_templ(
const char *templ, const char **pspec,
const char **parg, const char *argend)
const char **parg)
{
const char *p, *q;
*pspec = 0;
for (p = templ, q = *parg;; p++, q++)
if ('\0' == *q || q == argend)
if ('\0' == *q)
{
if ('\0' == *p)
*parg = fsp_fuse_opt_match_exact;
@ -125,7 +130,7 @@ static void fsp_fuse_opt_match_templ(
static const struct fuse_opt *fsp_fuse_opt_find(
const struct fuse_opt opts[], const char **pspec,
const char **parg, const char *argend)
const char **parg)
{
const struct fuse_opt *opt;
const char *arg;
@ -133,7 +138,7 @@ static const struct fuse_opt *fsp_fuse_opt_find(
for (opt = opts; 0 != opt->templ; opt++)
{
arg = *parg;
fsp_fuse_opt_match_templ(opt->templ, pspec, &arg, argend);
fsp_fuse_opt_match_templ(opt->templ, pspec, &arg);
if (fsp_fuse_opt_match_none != arg)
{
*parg = arg;
@ -146,7 +151,7 @@ static const struct fuse_opt *fsp_fuse_opt_find(
static int fsp_fuse_opt_call_proc(struct fsp_fuse_env *env,
void *data, fuse_opt_proc_t proc,
const char *arg, const char *argend, const char *argl,
const char *arg, const char *argl,
int key, int is_opt,
struct fuse_args *outargs)
{
@ -156,17 +161,11 @@ static int fsp_fuse_opt_call_proc(struct fsp_fuse_env *env,
if (FUSE_OPT_KEY_DISCARD == key)
return 0;
if (0 != argend)
len0 = (int)(argend - arg);
else
len0 = lstrlenA(arg);
len0 = lstrlenA(arg);
if (0 != argend || (0 != argl && !(arg <= argl && argl < arg + len0)))
if (0 != argl && !(arg <= argl && argl < arg + len0))
{
if (0 != argl && !(arg <= argl && argl < arg + len0))
len1 = lstrlenA(argl);
else
len1 = 0;
len1 = lstrlenA(argl);
fullarg = env->memalloc(len0 + len1 + 1);
if (0 == fullarg)
@ -200,7 +199,11 @@ static int fsp_fuse_opt_call_proc(struct fsp_fuse_env *env,
goto exit;
}
#if defined(FSP_FUSE_OPT_PARSE_ESCAPED_COMMAS)
result = fsp_fuse_opt_add_opt_escaped(env, &outargs->argv[2], arg);
#else
result = fsp_fuse_opt_add_opt(env, &outargs->argv[2], arg);
#endif
if (-1 == result)
goto exit;
}
@ -221,7 +224,7 @@ exit:
static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
void *data, const struct fuse_opt *opt, fuse_opt_proc_t proc,
const char *spec,
const char *arg, const char *argend, const char *argl,
const char *arg, const char *argl,
int is_opt,
struct fuse_args *outargs)
{
@ -229,7 +232,7 @@ static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
if (-1L == opt->offset)
return fsp_fuse_opt_call_proc(env,
data, proc, arg, argend, argl, opt->value, is_opt, outargs);
data, proc, arg, argl, opt->value, is_opt, outargs);
else
{
int h, j, l, t, z;
@ -274,19 +277,19 @@ static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
z++;
break;
case 'd':
llv = strtoint(argl, argend, 10, 1);
llv = strtoint(argl, 10, 1);
goto ivar;
case 'i':
llv = strtoint(argl, argend, 0, 1);
llv = strtoint(argl, 0, 1);
goto ivar;
case 'o':
llv = strtoint(argl, argend, 8, 0);
llv = strtoint(argl, 8, 0);
goto ivar;
case 'u':
llv = strtoint(argl, argend, 10, 0);
llv = strtoint(argl, 10, 0);
goto ivar;
case 'x': case 'X':
llv = strtoint(argl, argend, 16, 0);
llv = strtoint(argl, 16, 0);
ivar:
if (z)
VAR(data, opt, size_t) = (size_t)llv;
@ -316,10 +319,7 @@ static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
VAR(data, opt, int) = (int)llv;
return 0;
case 's': case 'c':
if (arg <= argl && argl < argend)
len = (int)(argend - argl);
else
len = lstrlenA(argl);
len = lstrlenA(argl);
s = env->memalloc(len + 1);
if (0 == s)
return -1;
@ -339,7 +339,7 @@ static int fsp_fuse_opt_process_arg(struct fsp_fuse_env *env,
static int fsp_fuse_opt_parse_arg(struct fsp_fuse_env *env,
void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc,
const char *arg, const char *argend, const char *nextarg, int *pconsumed_nextarg,
const char *arg, const char *nextarg, int *pconsumed_nextarg,
int is_opt,
struct fuse_args *outargs)
{
@ -349,7 +349,7 @@ static int fsp_fuse_opt_parse_arg(struct fsp_fuse_env *env,
argl = arg;
opt = opts;
while (0 != (opt = fsp_fuse_opt_find(opt, &spec, &argl, argend)))
while (0 != (opt = fsp_fuse_opt_find(opt, &spec, &argl)))
{
if (fsp_fuse_opt_match_exact == argl)
argl = arg;
@ -362,7 +362,7 @@ static int fsp_fuse_opt_parse_arg(struct fsp_fuse_env *env,
}
if (-1 == fsp_fuse_opt_process_arg(env,
data, opt, proc, spec, arg, argend, argl, is_opt, outargs))
data, opt, proc, spec, arg, argl, is_opt, outargs))
return -1;
processed++;
@ -374,7 +374,7 @@ static int fsp_fuse_opt_parse_arg(struct fsp_fuse_env *env,
return 0;
return fsp_fuse_opt_call_proc(env,
data, proc, arg, argend, arg, FUSE_OPT_KEY_OPT, is_opt, outargs);
data, proc, arg, arg, FUSE_OPT_KEY_OPT, is_opt, outargs);
}
static int fsp_fuse_opt_proc0(void *data, const char *arg, int key,
@ -390,7 +390,8 @@ FSP_FUSE_API int fsp_fuse_opt_parse(struct fsp_fuse_env *env,
static struct fuse_args args0 = FUSE_ARGS_INIT(0, 0);
static struct fuse_opt opts0[1] = { FUSE_OPT_END };
struct fuse_args outargs = FUSE_ARGS_INIT(0, 0);
const char *arg, *argend;
const char *arg;
char *argcopy, *argend;
int dashdash = 0, consumed_nextarg;
if (0 == args)
@ -419,17 +420,40 @@ FSP_FUSE_API int fsp_fuse_opt_parse(struct fsp_fuse_env *env,
}
else
arg += 2;
for (argend = arg; *arg; argend++)
argcopy = env->memalloc(lstrlenA(arg) + 1);
if (0 == argcopy)
goto fail;
argend = argcopy;
for (;;)
{
if ('\0' == *argend || ',' == *argend)
#if defined(FSP_FUSE_OPT_PARSE_ESCAPED_COMMAS)
if ('\\' == *arg)
{
if (-1 == fsp_fuse_opt_parse_arg(env,
data, opts, proc, arg, argend, 0, 0, 1, &outargs))
goto fail;
arg = '\0' == *argend ? argend : argend + 1;
arg++;
*argend++ = *arg++;
continue;
}
#endif
if ('\0' == *arg || ',' == *arg)
{
*argend = '\0';
if (-1 == fsp_fuse_opt_parse_arg(env,
data, opts, proc, argcopy, 0, 0, 1, &outargs))
{
env->memfree(argcopy);
goto fail;
}
if ('\0' == *arg)
break;
arg++;
argend = argcopy;
}
else
*argend++ = *arg++;
}
env->memfree(argcopy);
break;
case '-':
if ('\0' == arg[2])
@ -443,7 +467,7 @@ FSP_FUSE_API int fsp_fuse_opt_parse(struct fsp_fuse_env *env,
default:
consumed_nextarg = 0;
if (-1 == fsp_fuse_opt_parse_arg(env,
data, opts, proc, arg, 0, args->argv[argi + 1], &consumed_nextarg, 0, &outargs))
data, opts, proc, arg, args->argv[argi + 1], &consumed_nextarg, 0, &outargs))
goto fail;
if (consumed_nextarg)
argi++;
@ -452,7 +476,7 @@ FSP_FUSE_API int fsp_fuse_opt_parse(struct fsp_fuse_env *env,
}
else
if (-1 == fsp_fuse_opt_call_proc(env,
data, proc, arg, 0, arg, FUSE_OPT_KEY_NONOPT, 0, &outargs))
data, proc, arg, arg, FUSE_OPT_KEY_NONOPT, 0, &outargs))
goto fail;
}
@ -596,5 +620,5 @@ FSP_FUSE_API int fsp_fuse_opt_match(struct fsp_fuse_env *env,
return 0;
const char *spec;
return fsp_fuse_opt_find(opts, &spec, &arg, 0) ? 1 : 0;
return fsp_fuse_opt_find(opts, &spec, &arg) ? 1 : 0;
}

View File

@ -15,6 +15,7 @@ struct data
long y;
long long z;
int dec, neg, hex, oct;
char *esc; int ESC;
int arg_discard, arg_keep;
int opt_discard, opt_keep;
int nonopt_discard, nonopt_keep;
@ -157,6 +158,10 @@ static int fuse_opt_parse_test_proc(void *data0, const char *arg, int key,
case 'z':
ASSERT(0);
return -1;
case 'ESC':
ASSERT(0 == strcmp("ESC=\\FOO,BAR\\", arg));
data->ESC = 1;
return 1;
}
}
@ -202,6 +207,9 @@ void fuse_opt_parse_test(void)
{ "--hex=%x", offsetof(struct data, hex), 'hex' },
{ "--oct=%o", offsetof(struct data, oct), 'oct' },
{ "esc=%s", offsetof(struct data, esc), 'esc' },
FUSE_OPT_KEY("ESC=", 'ESC'),
FUSE_OPT_KEY("--discard", FUSE_OPT_KEY_DISCARD),
FUSE_OPT_KEY("--keep", FUSE_OPT_KEY_KEEP),
@ -237,6 +245,7 @@ void fuse_opt_parse_test(void)
"--neg=-1234567890",
"--hex=ABCDEF",
"--oct=12345670",
"-oesc=\\\\foo\\,bar\\\\,ESC=\\\\FOO\\,BAR\\\\",
"--discard",
"--keep",
"--arg-discard",
@ -251,7 +260,7 @@ void fuse_opt_parse_test(void)
static char *outargv[] =
{
"exec",
"-o", "f,hlong,n=78,plong=80,opt-keep",
"-o", "f,hlong,n=78,plong=80,ESC=\\\\FOO\\,BAR\\\\,opt-keep",
"-b",
"--dlong",
"-j=74",
@ -312,6 +321,8 @@ void fuse_opt_parse_test(void)
ASSERT(-1234567890 == data.neg);
ASSERT(0xABCDEF == data.hex);
ASSERT(012345670 == data.oct);
ASSERT(0 == strcmp("\\foo,bar\\", data.esc));
ASSERT(1 == data.ESC);
ASSERT(1 == data.arg_discard);
ASSERT(1 == data.arg_keep);
ASSERT(1 == data.opt_discard);
@ -332,6 +343,7 @@ void fuse_opt_parse_test(void)
free(data.s);
free(data.t);
free(data.w);
free(data.esc);
}
void fuse_opt_tests(void)