mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
147 lines
4.3 KiB
C
147 lines
4.3 KiB
C
/**
|
|
* @file cygfuse/cygfuse.c
|
|
*
|
|
* @copyright 2015-2017 Bill Zissimopoulos
|
|
*/
|
|
/*
|
|
* This file is part of WinFsp.
|
|
*
|
|
* You can redistribute it and/or modify it under the terms of the GNU
|
|
* 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 <dlfcn.h>
|
|
#include <pthread.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/cygwin.h>
|
|
|
|
static void *cygfuse_init_winfsp();
|
|
static void *cygfuse_init_fail();
|
|
|
|
static pthread_mutex_t cygfuse_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
static void *cygfuse_handle = 0;
|
|
|
|
static inline void cygfuse_init(int force)
|
|
{
|
|
pthread_mutex_lock(&cygfuse_mutex);
|
|
if (force || 0 == cygfuse_handle)
|
|
cygfuse_handle = cygfuse_init_winfsp();
|
|
pthread_mutex_unlock(&cygfuse_mutex);
|
|
}
|
|
|
|
/*
|
|
* Unfortunately Cygwin fork is very fragile and cannot even correctly
|
|
* handle dlopen'ed DLL's if they are native (rather than Cygwin ones).
|
|
*
|
|
* So we have this very nasty hack where we reset the dlopen'ed handle
|
|
* immediately after daemonization. This will force cygfuse_init() to
|
|
* reload the WinFsp DLL and reset all API pointers in the daemonized
|
|
* process.
|
|
*/
|
|
static inline int cygfuse_daemon(int nochdir, int noclose)
|
|
{
|
|
if (-1 == daemon(nochdir, noclose))
|
|
return -1;
|
|
|
|
/* force reload of WinFsp DLL to workaround fork() problems */
|
|
cygfuse_init(1);
|
|
|
|
return 0;
|
|
}
|
|
#define daemon cygfuse_daemon
|
|
|
|
#define FSP_FUSE_API static
|
|
#define FSP_FUSE_API_NAME(api) (* pfn_ ## api)
|
|
#define FSP_FUSE_API_CALL(api) (cygfuse_init(0), pfn_ ## api)
|
|
#define FSP_FUSE_SYM(proto, ...) __attribute__ ((visibility("default"))) proto { __VA_ARGS__ }
|
|
#include <fuse_common.h>
|
|
#include <fuse.h>
|
|
#include <fuse_opt.h>
|
|
|
|
#if defined(__LP64__)
|
|
#define CYGFUSE_WINFSP_NAME "winfsp-x64.dll"
|
|
#else
|
|
#define CYGFUSE_WINFSP_NAME "winfsp-x86.dll"
|
|
#endif
|
|
#define CYGFUSE_WINFSP_PATH "bin\\" CYGFUSE_WINFSP_NAME
|
|
#define CYGFUSE_GET_API(h, n) \
|
|
if (0 == (*(void **)&(pfn_ ## n) = dlsym(h, #n)))\
|
|
return cygfuse_init_fail();
|
|
|
|
static void *cygfuse_init_winfsp()
|
|
{
|
|
void *h;
|
|
|
|
h = dlopen(CYGFUSE_WINFSP_NAME, RTLD_NOW);
|
|
if (0 == h)
|
|
{
|
|
char winpath[260], *psxpath;
|
|
int regfd, bytes;
|
|
|
|
regfd = open("/proc/registry32/HKEY_LOCAL_MACHINE/Software/WinFsp/InstallDir", O_RDONLY);
|
|
if (-1 == regfd)
|
|
return cygfuse_init_fail();
|
|
|
|
bytes = read(regfd, winpath, sizeof winpath - sizeof CYGFUSE_WINFSP_PATH);
|
|
close(regfd);
|
|
if (-1 == bytes || 0 == bytes)
|
|
return cygfuse_init_fail();
|
|
|
|
if ('\0' == winpath[bytes - 1])
|
|
bytes--;
|
|
memcpy(winpath + bytes, CYGFUSE_WINFSP_PATH, sizeof CYGFUSE_WINFSP_PATH);
|
|
|
|
psxpath = (char *)cygwin_create_path(CCP_WIN_A_TO_POSIX | CCP_PROC_CYGDRIVE, winpath);
|
|
if (0 == psxpath)
|
|
return cygfuse_init_fail();
|
|
|
|
h = dlopen(psxpath, RTLD_NOW);
|
|
free(psxpath);
|
|
if (0 == h)
|
|
return cygfuse_init_fail();
|
|
}
|
|
|
|
/* winfsp_fuse.h */
|
|
CYGFUSE_GET_API(h, fsp_fuse_signal_handler);
|
|
|
|
/* fuse_common.h */
|
|
CYGFUSE_GET_API(h, fsp_fuse_version);
|
|
CYGFUSE_GET_API(h, fsp_fuse_mount);
|
|
CYGFUSE_GET_API(h, fsp_fuse_unmount);
|
|
CYGFUSE_GET_API(h, fsp_fuse_parse_cmdline);
|
|
CYGFUSE_GET_API(h, fsp_fuse_ntstatus_from_errno);
|
|
|
|
/* fuse.h */
|
|
CYGFUSE_GET_API(h, fsp_fuse_main_real);
|
|
CYGFUSE_GET_API(h, fsp_fuse_is_lib_option);
|
|
CYGFUSE_GET_API(h, fsp_fuse_new);
|
|
CYGFUSE_GET_API(h, fsp_fuse_destroy);
|
|
CYGFUSE_GET_API(h, fsp_fuse_loop);
|
|
CYGFUSE_GET_API(h, fsp_fuse_loop_mt);
|
|
CYGFUSE_GET_API(h, fsp_fuse_exit);
|
|
CYGFUSE_GET_API(h, fsp_fuse_get_context);
|
|
|
|
/* fuse_opt.h */
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_parse);
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_add_arg);
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_insert_arg);
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_free_args);
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_add_opt);
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_add_opt_escaped);
|
|
CYGFUSE_GET_API(h, fsp_fuse_opt_match);
|
|
|
|
return h;
|
|
}
|
|
|
|
static void *cygfuse_init_fail()
|
|
{
|
|
abort();
|
|
return 0;
|
|
}
|