mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
fuse_opt: implementation checkpoint
This commit is contained in:
parent
7db0f68dd7
commit
4d57a5c10e
@ -35,6 +35,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FSP_FUSE_MEMFN_P void *(*memalloc)(size_t), void (*memfree)(void *)
|
||||||
|
#define FSP_FUSE_MEMFN_A memalloc, memfree
|
||||||
|
#if defined(WINFSP_DLL_INTERNAL)
|
||||||
|
#define FSP_FUSE_MEMFN_V MemAlloc, MemFree
|
||||||
|
#else
|
||||||
|
#define FSP_FUSE_MEMFN_V malloc, free
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FUSE_OPT_KEY(templ, key) { templ, -1U, key }
|
#define FUSE_OPT_KEY(templ, key) { templ, -1U, key }
|
||||||
#define FUSE_OPT_END { NULL, 0, 0 }
|
#define FUSE_OPT_END { NULL, 0, 0 }
|
||||||
|
|
||||||
@ -63,48 +71,62 @@ typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
|
|||||||
struct fuse_args *outargs);
|
struct fuse_args *outargs);
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_parse(struct fuse_args *args, void *data,
|
FSP_FUSE_API int fsp_fuse_opt_parse(struct fuse_args *args, void *data,
|
||||||
const struct fuse_opt opts[], fuse_opt_proc_t proc);
|
const struct fuse_opt opts[], fuse_opt_proc_t proc,
|
||||||
FSP_FUSE_API int fsp_fuse_opt_add_opt(char **opts, const char *opt);
|
FSP_FUSE_MEMFN_P);
|
||||||
FSP_FUSE_API int fsp_fuse_opt_add_opt_escaped(char **opts, const char *opt);
|
FSP_FUSE_API int fsp_fuse_opt_add_arg(struct fuse_args *args, const char *arg,
|
||||||
FSP_FUSE_API int fsp_fuse_opt_add_arg(struct fuse_args *args, const char *arg);
|
FSP_FUSE_MEMFN_P);
|
||||||
FSP_FUSE_API int fsp_fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg);
|
FSP_FUSE_API int fsp_fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg,
|
||||||
FSP_FUSE_API void fsp_fuse_opt_free_args(struct fuse_args *args);
|
FSP_FUSE_MEMFN_P);
|
||||||
FSP_FUSE_API int fsp_fuse_opt_match(const struct fuse_opt opts[], const char *opt);
|
FSP_FUSE_API void fsp_fuse_opt_free_args(struct fuse_args *args,
|
||||||
|
FSP_FUSE_MEMFN_P);
|
||||||
|
FSP_FUSE_API int fsp_fuse_opt_add_opt(char **opts, const char *opt,
|
||||||
|
FSP_FUSE_MEMFN_P);
|
||||||
|
FSP_FUSE_API int fsp_fuse_opt_add_opt_escaped(char **opts, const char *opt,
|
||||||
|
FSP_FUSE_MEMFN_P);
|
||||||
|
FSP_FUSE_API int fsp_fuse_opt_match(const struct fuse_opt opts[], const char *opt,
|
||||||
|
FSP_FUSE_MEMFN_P);
|
||||||
|
|
||||||
static inline int fuse_opt_parse(struct fuse_args *args, void *data,
|
static inline int fuse_opt_parse(struct fuse_args *args, void *data,
|
||||||
const struct fuse_opt opts[], fuse_opt_proc_t proc)
|
const struct fuse_opt opts[], fuse_opt_proc_t proc)
|
||||||
{
|
{
|
||||||
return fsp_fuse_opt_parse(args, data, opts, proc);
|
return fsp_fuse_opt_parse(args, data, opts, proc,
|
||||||
}
|
FSP_FUSE_MEMFN_V);
|
||||||
|
|
||||||
static inline int fuse_opt_add_opt(char **opts, const char *opt)
|
|
||||||
{
|
|
||||||
return fsp_fuse_opt_add_opt(opts, opt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int fuse_opt_add_opt_escaped(char **opts, const char *opt)
|
|
||||||
{
|
|
||||||
return fsp_fuse_opt_add_opt_escaped(opts, opt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
static inline int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
||||||
{
|
{
|
||||||
return fsp_fuse_opt_add_arg(args, arg);
|
return fsp_fuse_opt_add_arg(args, arg,
|
||||||
|
FSP_FUSE_MEMFN_V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
|
static inline int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
|
||||||
{
|
{
|
||||||
return fsp_fuse_opt_insert_arg(args, pos, arg);
|
return fsp_fuse_opt_insert_arg(args, pos, arg,
|
||||||
|
FSP_FUSE_MEMFN_V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void fuse_opt_free_args(struct fuse_args *args)
|
static inline void fuse_opt_free_args(struct fuse_args *args)
|
||||||
{
|
{
|
||||||
fsp_fuse_opt_free_args(args);
|
fsp_fuse_opt_free_args(args,
|
||||||
|
FSP_FUSE_MEMFN_V);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fuse_opt_add_opt(char **opts, const char *opt)
|
||||||
|
{
|
||||||
|
return fsp_fuse_opt_add_opt(opts, opt,
|
||||||
|
FSP_FUSE_MEMFN_V);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fuse_opt_add_opt_escaped(char **opts, const char *opt)
|
||||||
|
{
|
||||||
|
return fsp_fuse_opt_add_opt_escaped(opts, opt,
|
||||||
|
FSP_FUSE_MEMFN_V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int fuse_opt_match(const struct fuse_opt opts[], const char *opt)
|
static inline int fuse_opt_match(const struct fuse_opt opts[], const char *opt)
|
||||||
{
|
{
|
||||||
return fsp_fuse_opt_match(opts, opt);
|
return fsp_fuse_opt_match(opts, opt,
|
||||||
|
FSP_FUSE_MEMFN_V);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -18,44 +18,304 @@
|
|||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
#include <fuse/fuse_opt.h>
|
#include <fuse/fuse_opt.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
static void fsp_fuse_opt_match_templ(
|
||||||
|
const char *templ, const char **pspec,
|
||||||
|
const char **parg, const char *argend)
|
||||||
|
{
|
||||||
|
const char *p, *q;
|
||||||
|
|
||||||
|
*pspec = 0;
|
||||||
|
|
||||||
|
for (p = templ, q = *parg;; p++, q++)
|
||||||
|
if ('\0' == *q || (0 != argend && q >= argend))
|
||||||
|
{
|
||||||
|
if ('\0' == *p)
|
||||||
|
*parg = fsp_fuse_opt_match_exact;
|
||||||
|
else if (' ' == *p)
|
||||||
|
*pspec = p + 1, *parg = fsp_fuse_opt_match_next;
|
||||||
|
else
|
||||||
|
*parg = fsp_fuse_opt_match_none;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ('=' == *p)
|
||||||
|
{
|
||||||
|
if (*q == *p)
|
||||||
|
*pspec = p + 1, *parg = q + 1;
|
||||||
|
else
|
||||||
|
*parg = fsp_fuse_opt_match_none;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (' ' == *p)
|
||||||
|
{
|
||||||
|
*pspec = p + 1, *parg = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (*q != *p)
|
||||||
|
{
|
||||||
|
*parg = fsp_fuse_opt_match_none;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct fuse_opt *fsp_fuse_opt_find(
|
||||||
|
const struct fuse_opt opts[], const char **pspec,
|
||||||
|
const char **parg, const char *argend)
|
||||||
|
{
|
||||||
|
const struct fuse_opt *opt;
|
||||||
|
const char *arg;
|
||||||
|
|
||||||
|
for (opt = opts; 0 != opt->templ; opt++)
|
||||||
|
{
|
||||||
|
arg = *parg;
|
||||||
|
fsp_fuse_opt_match_templ(opt->templ, pspec, &arg, argend);
|
||||||
|
if (fsp_fuse_opt_match_none != arg)
|
||||||
|
{
|
||||||
|
*parg = arg;
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_opt_process_arg(const struct fuse_opt *opt,
|
||||||
|
fuse_opt_proc_t proc, void *data,
|
||||||
|
const char *arg,
|
||||||
|
struct fuse_args *outargs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_opt_parse_arg(const struct fuse_opt opts[],
|
||||||
|
fuse_opt_proc_t proc, void *data,
|
||||||
|
const char *arg0, const char *argend, const char *arg1,
|
||||||
|
struct fuse_args *outargs)
|
||||||
|
{
|
||||||
|
const struct fuse_opt *opt;
|
||||||
|
const char *arg, *spec;
|
||||||
|
|
||||||
|
arg = arg0;
|
||||||
|
opt = opts;
|
||||||
|
while (0 != (opt = fsp_fuse_opt_find(opt, &spec, &arg, argend)))
|
||||||
|
{
|
||||||
|
if (fsp_fuse_opt_match_exact == arg)
|
||||||
|
{
|
||||||
|
arg = 0;
|
||||||
|
}
|
||||||
|
else if (fsp_fuse_opt_match_next == arg)
|
||||||
|
{
|
||||||
|
if (0 == arg1)
|
||||||
|
return -1; /* missing argument for option */
|
||||||
|
arg = arg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 == fsp_fuse_opt_process_arg(opt, proc, data, arg, outargs))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
arg = arg0;
|
||||||
|
opt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_opt_proc0(void *data, const char *arg, int key,
|
||||||
|
struct fuse_args *outargs)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_parse(struct fuse_args *args, void *data,
|
FSP_FUSE_API int fsp_fuse_opt_parse(struct fuse_args *args, void *data,
|
||||||
const struct fuse_opt opts[], fuse_opt_proc_t proc)
|
const struct fuse_opt opts[], fuse_opt_proc_t proc,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
{
|
{
|
||||||
// !!!: NEEDIMPL
|
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;
|
||||||
|
int dashdash = 0;
|
||||||
|
|
||||||
|
if (0 == args)
|
||||||
|
args = &args0;
|
||||||
|
if (0 == opts)
|
||||||
|
opts = opts0;
|
||||||
|
if (0 == proc)
|
||||||
|
proc = fsp_fuse_opt_proc0;
|
||||||
|
|
||||||
|
for (int argi = 0; args->argc > argi; argi++)
|
||||||
|
{
|
||||||
|
arg = args->argv[argi];
|
||||||
|
if ('-' == arg[0] && !dashdash)
|
||||||
|
{
|
||||||
|
switch (arg[1])
|
||||||
|
{
|
||||||
|
case 'o':
|
||||||
|
if ('\0' == arg[2])
|
||||||
|
{
|
||||||
|
if (args->argc <= argi + 1)
|
||||||
|
goto fail; /* missing argument for option "-o" */
|
||||||
|
arg = args->argv[++argi];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
arg += 2;
|
||||||
|
for (argend = arg;; argend++)
|
||||||
|
{
|
||||||
|
if ('\0' == *argend || ',' == *argend)
|
||||||
|
{
|
||||||
|
if (-1 == fsp_fuse_opt_parse_arg(opts, proc, data,
|
||||||
|
arg, argend, 0, &outargs))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else if ('\\' == *argend && '\0' != argend[1])
|
||||||
|
argend++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if ('\0' == arg[2])
|
||||||
|
{
|
||||||
|
dashdash = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
default:
|
||||||
|
if (-1 == fsp_fuse_opt_parse_arg(opts, proc, data,
|
||||||
|
arg, 0, args->argv[argi + 1], &outargs))
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FUSE_API int fsp_fuse_opt_add_arg(struct fuse_args *args, const char *arg,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
|
{
|
||||||
|
return fsp_fuse_opt_insert_arg(args, args->argc, arg, FSP_FUSE_MEMFN_A);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FUSE_API int fsp_fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
|
{
|
||||||
|
char **argv;
|
||||||
|
int argsize;
|
||||||
|
|
||||||
|
if (0 == args)
|
||||||
|
return -1;
|
||||||
|
if (!args->allocated && 0 != args->argv)
|
||||||
|
return -1;
|
||||||
|
if (0 > pos || pos > args->argc)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
argv = memalloc((args->argc + 2) * sizeof(char *));
|
||||||
|
if (0 == argv)
|
||||||
|
return -1;
|
||||||
|
argsize = lstrlenA(arg) + 1;
|
||||||
|
argv[pos] = memalloc(argsize);
|
||||||
|
if (0 == argv[pos])
|
||||||
|
{
|
||||||
|
memfree(argv);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(argv[pos], arg, argsize);
|
||||||
|
memcpy(argv, args->argv, pos);
|
||||||
|
memcpy(argv + pos + 1, args->argv + pos, args->argc - pos);
|
||||||
|
|
||||||
|
memfree(args->argv);
|
||||||
|
|
||||||
|
args->argc++;
|
||||||
|
args->argv = argv;
|
||||||
|
argv[args->argc] = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_add_opt(char **opts, const char *opt)
|
FSP_FUSE_API void fsp_fuse_opt_free_args(struct fuse_args *args,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
{
|
{
|
||||||
// !!!: NEEDIMPL
|
if (0 == args)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args->allocated && 0 != args->argv)
|
||||||
|
{
|
||||||
|
for (int argi = 0; args->argc > argi; argi++)
|
||||||
|
memfree(args->argv[argi]);
|
||||||
|
|
||||||
|
memfree(args->argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
args->argc = 0;
|
||||||
|
args->argv = 0;
|
||||||
|
args->allocated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fsp_fuse_opt_add_opt_internal(char **opts, const char *opt, int escaped,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
|
{
|
||||||
|
size_t optsize, optlen;
|
||||||
|
char *newopts;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
optsize = 0 != *opts ? lstrlenA(*opts) + 1 : 0;
|
||||||
|
for (p = opt, optlen = 0; *p; p++, optlen++)
|
||||||
|
if (escaped && (',' == *p || '\\' == *p))
|
||||||
|
optlen++;
|
||||||
|
|
||||||
|
newopts = memalloc(optsize + optlen + 1);
|
||||||
|
if (0 == newopts)
|
||||||
|
return -1;
|
||||||
|
memfree(*opts);
|
||||||
|
*opts = newopts;
|
||||||
|
|
||||||
|
if (0 != optsize)
|
||||||
|
{
|
||||||
|
memcpy(newopts, *opts, optsize - 1);
|
||||||
|
newopts[optsize - 1] = ',';
|
||||||
|
newopts += optsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = opt; *p; p++, newopts++)
|
||||||
|
{
|
||||||
|
if (escaped && (',' == *p || '\\' == *p))
|
||||||
|
*newopts++ = '\\';
|
||||||
|
*newopts = *p;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_add_opt_escaped(char **opts, const char *opt)
|
FSP_FUSE_API int fsp_fuse_opt_add_opt(char **opts, const char *opt,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
{
|
{
|
||||||
// !!!: NEEDIMPL
|
return fsp_fuse_opt_add_opt_internal(opts, opt, 0,
|
||||||
return 0;
|
FSP_FUSE_MEMFN_A);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
FSP_FUSE_API int fsp_fuse_opt_add_opt_escaped(char **opts, const char *opt,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
{
|
{
|
||||||
// !!!: NEEDIMPL
|
return fsp_fuse_opt_add_opt_internal(opts, opt, 1,
|
||||||
return 0;
|
FSP_FUSE_MEMFN_A);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
|
FSP_FUSE_API int fsp_fuse_opt_match(const struct fuse_opt opts[], const char *arg,
|
||||||
|
FSP_FUSE_MEMFN_P)
|
||||||
{
|
{
|
||||||
// !!!: NEEDIMPL
|
if (0 == opts)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
FSP_FUSE_API void fsp_fuse_opt_free_args(struct fuse_args *args)
|
const char *spec;
|
||||||
{
|
return fsp_fuse_opt_find(opts, &spec, &arg, 0) ? 1 : 0;
|
||||||
// !!!: NEEDIMPL
|
|
||||||
}
|
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_opt_match(const struct fuse_opt opts[], const char *opt)
|
|
||||||
{
|
|
||||||
// !!!: NEEDIMPL
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user