diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index 30711263..3b33f8f0 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -32,6 +32,7 @@ + diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index 619ad2d2..ec83dbde 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -91,6 +91,9 @@ Source\fuse + + Source\fuse + diff --git a/inc/fuse/fuse.h b/inc/fuse/fuse.h index e8d30f36..d525e9ba 100644 --- a/inc/fuse/fuse.h +++ b/inc/fuse/fuse.h @@ -105,6 +105,13 @@ struct fuse_context FSP_FUSE_API int fsp_fuse_main_real(struct fsp_fuse_env *env, int argc, char *argv[], const struct fuse_operations *ops, size_t opsize, void *data); +FSP_FUSE_API struct fuse *fsp_fuse_setup(struct fsp_fuse_env *env, + int argc, char *argv[], + const struct fuse_operations *ops, size_t opsize, + char **mountpoint, int *multithreaded, + void *data); +FSP_FUSE_API void fsp_fuse_teardown(struct fsp_fuse_env *env, + struct fuse *f, char *mountpoint); FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env, const char *opt); FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, @@ -126,6 +133,20 @@ static inline int fuse_main_real(int argc, char *argv[], return fsp_fuse_main_real(fsp_fuse_env(), argc, argv, ops, opsize, data); } +static inline struct fuse *fuse_setup(int argc, char *argv[], + const struct fuse_operations *ops, size_t opsize, + char **mountpoint, int *multithreaded, + void *data) +{ + return fsp_fuse_setup(fsp_fuse_env(), + argc, argv, ops, opsize, mountpoint, multithreaded, data); +} + +static inline void fuse_teardown(struct fuse *f, char *mountpoint) +{ + fsp_fuse_teardown(fsp_fuse_env(), f, mountpoint); +} + static inline int fuse_is_lib_option(const char *opt) { return fsp_fuse_is_lib_option(fsp_fuse_env(), opt); diff --git a/inc/fuse/fuse_common.h b/inc/fuse/fuse_common.h index e99b1a35..c88a700c 100644 --- a/inc/fuse/fuse_common.h +++ b/inc/fuse/fuse_common.h @@ -83,8 +83,8 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env, FSP_FUSE_API void fsp_fuse_unmount(struct fsp_fuse_env *env, const char *mountpoint, struct fuse_chan *ch); FSP_FUSE_API int fsp_fuse_parse_cmdline(struct fsp_fuse_env *env, - struct fuse_args *args, char **mountpoint, - int *multithreaded, int *foreground); + struct fuse_args *args, + char **mountpoint, int *multithreaded, int *foreground); static inline int fuse_version(void) { @@ -101,8 +101,8 @@ static inline void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) fsp_fuse_unmount(fsp_fuse_env(), mountpoint, ch); } -static inline int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, - int *multithreaded, int *foreground) +static inline int fuse_parse_cmdline(struct fuse_args *args, + char **mountpoint, int *multithreaded, int *foreground) { return fsp_fuse_parse_cmdline(fsp_fuse_env(), args, mountpoint, multithreaded, foreground); } @@ -114,19 +114,17 @@ static inline void fuse_pollhandle_destroy(struct fuse_pollhandle *ph) static inline int fuse_daemonize(int foreground) { - (void)foreground; - return 0; + return fsp_fuse_daemonize(foreground); } static inline int fuse_set_signal_handlers(struct fuse_session *se) { - (void)se; - return 0; + return fsp_fuse_set_signal_handlers(se); } static inline void fuse_remove_signal_handlers(struct fuse_session *se) { - (void)se; + fsp_fuse_remove_signal_handlers(se); } #ifdef __cplusplus diff --git a/inc/fuse/winfsp_fuse.h b/inc/fuse/winfsp_fuse.h index cc5d7fde..f2b69646 100644 --- a/inc/fuse/winfsp_fuse.h +++ b/inc/fuse/winfsp_fuse.h @@ -46,7 +46,7 @@ extern "C" { * understanding of the types and ours. */ -#if defined(_MSC_VER) +#if defined(_WIN64) || defined(_WIN32) typedef uint32_t fuse_uid_t; typedef uint32_t fuse_gid_t; @@ -103,9 +103,23 @@ struct fuse_statvfs }; #if defined(WINFSP_DLL_INTERNAL) -#define FSP_FUSE_ENV_INIT { 'W', MemAlloc, MemFree } +#define FSP_FUSE_ENV_INIT \ + { \ + 'W', \ + MemAlloc, MemFree, \ + fsp_fuse_daemonize, \ + fsp_fuse_set_signal_handlers, \ + fsp_fuse_remove_signal_handlers,\ + } #else -#define FSP_FUSE_ENV_INIT { 'W', malloc, free } +#define FSP_FUSE_ENV_INIT \ + { \ + 'W', \ + malloc, free, \ + fsp_fuse_daemonize, \ + fsp_fuse_set_signal_handlers, \ + fsp_fuse_remove_signal_handlers,\ + } #endif #elif defined(__CYGWIN__) @@ -136,7 +150,14 @@ struct fuse_statvfs #define fuse_stat stat #define fuse_statvfs statvfs -#define FSP_FUSE_ENV_INIT { 'C', malloc, free } +#define FSP_FUSE_ENV_INIT \ + { \ + 'C', \ + malloc, free, \ + fsp_fuse_daemonize, \ + fsp_fuse_set_signal_handlers, \ + fsp_fuse_remove_signal_handlers,\ + } /* * Note that long is 8 bytes long in Cygwin64 and 4 bytes long in Win64. @@ -152,8 +173,41 @@ struct fsp_fuse_env unsigned environment; void *(*memalloc)(size_t); void (*memfree)(void *); + int (*daemonize)(int); + int (*set_signal_handlers)(void *); + void (*remove_signal_handlers)(void *); }; +static inline int fsp_fuse_daemonize(int foreground) +{ +#if defined(_WIN64) || defined(_WIN32) + (void)foreground; + return 0; +#elif defined(__CYGWIN__) + int daemon(int nochdir, int noclose); + int chdir(const char *path); + if (!foreground) + { + if (-1 == daemon(0, 0)) + return -1; + } + else + chdir("/"); + return 0; +#endif +} + +static inline int fsp_fuse_set_signal_handlers(void *se) +{ + (void)se; + return 0; +} + +static inline void fsp_fuse_remove_signal_handlers(void *se) +{ + (void)se; +} + static inline struct fsp_fuse_env *fsp_fuse_env(void) { static struct fsp_fuse_env env = FSP_FUSE_ENV_INIT; diff --git a/src/dll/fuse/fuse.c b/src/dll/fuse/fuse.c index 6adb7115..cc55d1ba 100644 --- a/src/dll/fuse/fuse.c +++ b/src/dll/fuse/fuse.c @@ -132,22 +132,6 @@ FSP_FUSE_API void fsp_fuse_unmount(struct fsp_fuse_env *env, MemFree(ch); } -FSP_FUSE_API int fsp_fuse_parse_cmdline(struct fsp_fuse_env *env, - struct fuse_args *args, char **mountpoint, - int *multithreaded, int *foreground) -{ - // !!!: NEEDIMPL - return 0; -} - -FSP_FUSE_API int fsp_fuse_main_real(struct fsp_fuse_env *env, - int argc, char *argv[], - const struct fuse_operations *ops, size_t opsize, void *data) -{ - // !!!: NEEDIMPL - return 0; -} - FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env, const char *opt) { diff --git a/src/dll/fuse/fuse_main.c b/src/dll/fuse/fuse_main.c new file mode 100644 index 00000000..93930da4 --- /dev/null +++ b/src/dll/fuse/fuse_main.c @@ -0,0 +1,153 @@ +/** + * @file dll/fuse/fuse_main.c + * + * @copyright 2015-2016 Bill Zissimopoulos + */ +/* + * This file is part of WinFsp. + * + * You can redistribute it and/or modify it under the terms of the + * GNU Affero General Public License version 3 as published by the + * Free Software Foundation. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + */ + +#include +#include + +#define FSP_FUSE_DEFAULT_OPT(n, f, v) { n, offsetof(struct fsp_fuse_default_opt_data, f), v } + +struct fsp_fuse_default_opt_data +{ + struct fsp_fuse_env *env; + char *mountpoint; + int singlethread; + int foreground; +}; + +static int fsp_fuse_default_opt_proc(void *data0, const char *arg, int key, + struct fuse_args *outargs) +{ + struct fsp_fuse_default_opt_data *data = data0; + + switch (key) + { + default: + return 1; + case 'h': + FspServiceLog(EVENTLOG_ERROR_TYPE, L"" + "usage: %s mountpoint [options]\n" + "\n" + " -o opt,[opt...] mount options\n" + " -h --help print help\n" + " -V --version print version\n" + "\n" + "FUSE options:\n" + " -d -o debug enable debug output (implies -f)\n" + " -f foreground operation\n" + " -s disable multi-threaded operation\n" + "\n", + FspDiagIdent()); + fsp_fuse_opt_add_arg(data->env, outargs, "-h"); + return 0; + case 'V': + FspServiceLog(EVENTLOG_ERROR_TYPE, + L"WinFsp-FUSE v%d.%d", + FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION); + return 1; + case FUSE_OPT_KEY_NONOPT: + if (0 == data->mountpoint) + { + size_t size = lstrlenA(arg) + 1; + data->mountpoint = data->env->memalloc(size); + if (0 == data->mountpoint) + return -1; + memcpy(data->mountpoint, arg, size); + } + else + FspServiceLog(EVENTLOG_ERROR_TYPE, + L"invalid argument \"%S\"", arg); + return 1; + } +} + +FSP_FUSE_API int fsp_fuse_parse_cmdline(struct fsp_fuse_env *env, + struct fuse_args *args, + char **mountpoint, int *multithreaded, int *foreground) +{ + static struct fuse_opt opts[] = + { + FSP_FUSE_DEFAULT_OPT("-d", foreground, 1), + FSP_FUSE_DEFAULT_OPT("debug", foreground, 1), + FSP_FUSE_DEFAULT_OPT("-f", foreground, 1), + FSP_FUSE_DEFAULT_OPT("-s", singlethread, 1), + FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("-h", 'h'), + FUSE_OPT_KEY("--help", 'h'), + FUSE_OPT_KEY("--ho", 'h'), + FUSE_OPT_KEY("-V", 'V'), + FUSE_OPT_KEY("--version", 'V'), + FUSE_OPT_END, + }; + struct fsp_fuse_default_opt_data data; + + memset(&data, 0, sizeof data); + data.env = env; + + if (-1 == fsp_fuse_opt_parse(env, args, &data, opts, fsp_fuse_default_opt_proc)) + return -1; + + if (0 != mountpoint) + *mountpoint = data.mountpoint; + else + env->memfree(mountpoint); + + if (0 != multithreaded) + *multithreaded = !data.singlethread; + + if (0 != foreground) + *foreground = data.foreground; + + return 0; +} + +FSP_FUSE_API int fsp_fuse_main_real(struct fsp_fuse_env *env, + int argc, char *argv[], + const struct fuse_operations *ops, size_t opsize, void *data) +{ + struct fuse *f; + char *mountpoint = 0; + int multithreaded = 0; + int result; + + f = fsp_fuse_setup(env, argc, argv, ops, opsize, &mountpoint, &multithreaded, data); + if (0 == f) + return 1; + + result = multithreaded ? fsp_fuse_loop_mt(env, f) : fsp_fuse_loop(env, f); + + fsp_fuse_teardown(env, f, mountpoint); + + /* main() style return: 0 success, 1 error */ + return !!result; +} + +FSP_FUSE_API struct fuse *fsp_fuse_setup(struct fsp_fuse_env *env, + int argc, char *argv[], + const struct fuse_operations *ops, size_t opsize, + char **mountpoint, int *multithreaded, + void *data) +{ + // !!!: NEEDIMPL + return 0; +} + +FSP_FUSE_API void fsp_fuse_teardown(struct fsp_fuse_env *env, + struct fuse *f, char *mountpoint) +{ + // !!!: NEEDIMPL +}