mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
dll: fuse_opt: support escaped options and related refactoring
This commit is contained in:
parent
765bb1e1a3
commit
b559c7405f
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user