fuse_opt: implementation checkpoint

This commit is contained in:
Bill Zissimopoulos 2016-05-29 17:12:28 -07:00
parent e14a26b540
commit 187311bb5e

View File

@ -58,7 +58,7 @@ static long long strtoint(const char *p, const char *endp, int base, int is_sign
maxdig = 10 < base ? '9' : (base - 1) + '0'; maxdig = 10 < base ? '9' : (base - 1) + '0';
maxalp = 10 < base ? (base - 1 - 10) + 'a' : 0; maxalp = 10 < base ? (base - 1 - 10) + 'a' : 0;
for (v = 0; endp > p; p++) for (v = 0; *p && endp != p; p++)
{ {
int c = *p; int c = *p;
@ -86,7 +86,7 @@ static void fsp_fuse_opt_match_templ(
*pspec = 0; *pspec = 0;
for (p = templ, q = *parg;; p++, q++) for (p = templ, q = *parg;; p++, q++)
if ('\0' == *q || (0 != argend && q >= argend)) if ('\0' == *q || q == argend)
{ {
if ('\0' == *p) if ('\0' == *p)
*parg = fsp_fuse_opt_match_exact; *parg = fsp_fuse_opt_match_exact;
@ -139,48 +139,71 @@ static const struct fuse_opt *fsp_fuse_opt_find(
static int fsp_fuse_opt_call_proc(void *data, static int fsp_fuse_opt_call_proc(void *data,
fuse_opt_proc_t proc, fuse_opt_proc_t proc,
const char *arg, int key, const char *arg, const char *argend,
int is_opt, int key, int is_opt,
struct fuse_args *outargs, struct fuse_args *outargs,
FSP_FUSE_MEMFN_P) FSP_FUSE_MEMFN_P)
{ {
switch (key) int result;
if (FUSE_OPT_KEY_DISCARD == key)
return 0;
if (0 != argend)
{ {
default: char *argcopy = memalloc(argend - arg + 1);
if (0 != proc) if (0 == argcopy)
{ return -1;
int result = proc(data, arg, key, outargs); memcpy(argcopy, arg, argend - arg);
if (-1 == result || 0 == result) argcopy[argend - arg] = '\0';
return result; arg = argcopy;
} }
/* fall through */
case FUSE_OPT_KEY_KEEP: if (FUSE_OPT_KEY_KEEP != key && 0 != proc)
{
result = proc(data, arg, key, outargs);
if (-1 == result || 0 == result)
goto exit;
}
if (is_opt) if (is_opt)
{ {
if (3 <= outargs->argc && if (3 <= outargs->argc &&
'-' == outargs->argv[1][0] && 'o' == outargs->argv[1][1] && '-' == outargs->argv[1][0] && 'o' == outargs->argv[1][1] &&
'\0' == outargs->argv[1][2]) '\0' == outargs->argv[1][2])
{ {
return fsp_fuse_opt_add_opt(&outargs->argv[2], arg, FSP_FUSE_MEMFN_A); result = fsp_fuse_opt_add_opt(&outargs->argv[2], arg, FSP_FUSE_MEMFN_A);
if (-1 == result)
goto exit;
} }
else else
{ {
if (-1 == fsp_fuse_opt_insert_arg(outargs, 1, "-o", FSP_FUSE_MEMFN_A)) result = fsp_fuse_opt_insert_arg(outargs, 1, "-o", FSP_FUSE_MEMFN_A);
return -1; if (-1 == result)
return fsp_fuse_opt_insert_arg(outargs, 2, arg, FSP_FUSE_MEMFN_A); goto exit;
result = fsp_fuse_opt_insert_arg(outargs, 2, arg, FSP_FUSE_MEMFN_A);
if (-1 == result)
goto exit;
} }
} }
else else
return fsp_fuse_opt_add_arg(outargs, arg, FSP_FUSE_MEMFN_A); {
return 0; result = fsp_fuse_opt_add_arg(outargs, arg, FSP_FUSE_MEMFN_A);
case FUSE_OPT_KEY_DISCARD: if (-1 == result)
return 0; goto exit;
} }
exit:
if (0 != argend)
memfree((void *)arg); /* argcopy */
return 0;
} }
static int fsp_fuse_opt_process_arg(void *data, static int fsp_fuse_opt_process_arg(void *data,
const struct fuse_opt *opt, fuse_opt_proc_t proc, const struct fuse_opt *opt, fuse_opt_proc_t proc,
const char *spec, const char *arg, const char *argend, const char *spec,
const char *arg, const char *argend, const char *argl,
int is_opt, int is_opt,
struct fuse_args *outargs, struct fuse_args *outargs,
FSP_FUSE_MEMFN_P) FSP_FUSE_MEMFN_P)
@ -188,13 +211,14 @@ static int fsp_fuse_opt_process_arg(void *data,
#define VAR(data, opt, type) *(type *)((char *)(data) + (opt)->offset) #define VAR(data, opt, type) *(type *)((char *)(data) + (opt)->offset)
if (-1L == opt->offset) if (-1L == opt->offset)
return fsp_fuse_opt_call_proc(data, proc, arg, opt->value, is_opt, outargs, return fsp_fuse_opt_call_proc(data, proc, arg, argend, opt->value, is_opt, outargs,
FSP_FUSE_MEMFN_A); FSP_FUSE_MEMFN_A);
else else
{ {
int h, j, l, t, z; int h, j, l, t, z;
long long llv; long long llv;
char *s; char *s;
int len;
if (0 == spec || '\0' == spec[0]) if (0 == spec || '\0' == spec[0])
{ {
@ -233,19 +257,19 @@ static int fsp_fuse_opt_process_arg(void *data,
z++; z++;
break; break;
case 'd': case 'd':
llv = strtoint(arg, argend, 10, 1); llv = strtoint(argl, argend, 10, 1);
goto ivar; goto ivar;
case 'i': case 'i':
llv = strtoint(arg, argend, 0, 1); llv = strtoint(argl, argend, 0, 1);
goto ivar; goto ivar;
case 'o': case 'o':
llv = strtoint(arg, argend, 8, 0); llv = strtoint(argl, argend, 8, 0);
goto ivar; goto ivar;
case 'u': case 'u':
llv = strtoint(arg, argend, 10, 0); llv = strtoint(argl, argend, 10, 0);
goto ivar; goto ivar;
case 'x': case 'X': case 'x': case 'X':
llv = strtoint(arg, argend, 16, 0); llv = strtoint(argl, argend, 16, 0);
ivar: ivar:
if (z) if (z)
VAR(data, opt, size_t) = (size_t)llv; VAR(data, opt, size_t) = (size_t)llv;
@ -265,10 +289,15 @@ static int fsp_fuse_opt_process_arg(void *data,
VAR(data, opt, int) = (int)llv; VAR(data, opt, int) = (int)llv;
return 0; return 0;
case 's': case 'c': case 's': case 'c':
s = memalloc(argend - arg); if (arg <= argl && argl < argend)
len = (int)(argend - argl);
else
len = lstrlenA(argl);
s = memalloc(len + 1);
if (0 == s) if (0 == s)
return -1; return -1;
memcpy(s, arg, argend - arg); memcpy(s, arg, len);
s[len] = '\0';
VAR(data, opt, const char *) = (const char *)s; VAR(data, opt, const char *) = (const char *)s;
return 0; return 0;
case 'a': case 'e': case 'E': case 'f': case 'g': case 'a': case 'e': case 'E': case 'f': case 'g':
@ -289,7 +318,7 @@ static int fsp_fuse_opt_parse_arg(void *data,
FSP_FUSE_MEMFN_P) FSP_FUSE_MEMFN_P)
{ {
const struct fuse_opt *opt; const struct fuse_opt *opt;
const char *spec, *argl, *argendl; const char *spec, *argl;
int processed = 0; int processed = 0;
argl = arg; argl = arg;
@ -297,16 +326,16 @@ static int fsp_fuse_opt_parse_arg(void *data,
while (0 != (opt = fsp_fuse_opt_find(opt, &spec, &argl, argend))) while (0 != (opt = fsp_fuse_opt_find(opt, &spec, &argl, argend)))
{ {
if (fsp_fuse_opt_match_exact == argl) if (fsp_fuse_opt_match_exact == argl)
argl = arg, argendl = argend; argl = arg;
else if (fsp_fuse_opt_match_next == argl) else if (fsp_fuse_opt_match_next == argl)
{ {
if (0 == nextarg) if (0 == nextarg)
return -1; /* missing argument for option */ return -1; /* missing argument for option */
argl = nextarg, argendl = 0; argl = nextarg;
} }
if (-1 == fsp_fuse_opt_process_arg(data, opt, proc, spec, argl, argendl, is_opt, outargs, if (-1 == fsp_fuse_opt_process_arg(data, opt, proc, spec, arg, argend, argl,
FSP_FUSE_MEMFN_A)) is_opt, outargs, FSP_FUSE_MEMFN_A))
return -1; return -1;
processed++; processed++;
@ -317,7 +346,7 @@ static int fsp_fuse_opt_parse_arg(void *data,
if (0 != processed) if (0 != processed)
return 0; return 0;
return fsp_fuse_opt_call_proc(data, proc, arg, FUSE_OPT_KEY_OPT, is_opt, outargs, return fsp_fuse_opt_call_proc(data, proc, arg, argend, FUSE_OPT_KEY_OPT, is_opt, outargs,
FSP_FUSE_MEMFN_A); FSP_FUSE_MEMFN_A);
} }
@ -392,7 +421,7 @@ FSP_FUSE_API int fsp_fuse_opt_parse(struct fuse_args *args, void *data,
} }
} }
else else
if (-1 == fsp_fuse_opt_call_proc(data, proc, arg, FUSE_OPT_KEY_NONOPT, 0, &outargs, if (-1 == fsp_fuse_opt_call_proc(data, proc, arg, 0, FUSE_OPT_KEY_NONOPT, 0, &outargs,
FSP_FUSE_MEMFN_A)) FSP_FUSE_MEMFN_A))
goto fail; goto fail;
} }