opt: cygfuse: rename cygfuse.cpp to cygfuse.c and fix fork problem

This commit is contained in:
Bill Zissimopoulos 2016-06-22 11:12:33 -07:00
parent 8c1c407b34
commit f2a0eb544e
3 changed files with 148 additions and 124 deletions

View File

@ -1,8 +1,8 @@
Version = $(shell sed -n '/^VERSION=/s/VERSION=\(.*\)/\1/p' fuse.cygport) Version = $(shell sed -n '/^VERSION=/s/VERSION=\(.*\)/\1/p' fuse.cygport)
#Debug = -g #Debug = -g
cygfuse-$(Version).dll libfuse-$(Version).dll.a fuse.pc: cygfuse.cpp fuse.pc.in cygfuse-$(Version).dll libfuse-$(Version).dll.a fuse.pc: cygfuse.c fuse.pc.in
g++ $(Debug) -shared -o cygfuse-$(Version).dll -Wl,--out-implib=libfuse-$(Version).dll.a -I../../inc/fuse cygfuse.cpp gcc $(Debug) -shared -o cygfuse-$(Version).dll -Wl,--out-implib=libfuse-$(Version).dll.a -I../../inc/fuse cygfuse.c
[ -n "$(Debug)" ] || strip cygfuse-$(Version).dll [ -n "$(Debug)" ] || strip cygfuse-$(Version).dll
sed "s/@Version@/$(Version)/g" fuse.pc.in > fuse.pc sed "s/@Version@/$(Version)/g" fuse.pc.in > fuse.pc

146
opt/cygfuse/cygfuse.c Normal file
View File

@ -0,0 +1,146 @@
/**
* @file cygfuse/cygfuse.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 <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;
}

View File

@ -1,122 +0,0 @@
/**
* @file cygfuse/cygfuse.cpp
*
* @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 <windows.h>
#undef _WIN32
#undef _WIN64
static HANDLE cygfuse_init_winfsp();
static HANDLE cygfuse_init_fail(int err);
static inline void cygfuse_init()
{
static HANDLE Handle = cygfuse_init_winfsp();
}
#define FSP_FUSE_API static
#define FSP_FUSE_API_NAME(api) (* pfn_ ## api)
#define FSP_FUSE_API_CALL(api) (cygfuse_init(), 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_API_GET(h, n) \
if (0 == (*(FARPROC *)&(pfn_ ## n) = GetProcAddress((HMODULE)h, #n)))\
return cygfuse_init_fail(ERROR_PROC_NOT_FOUND);
static HANDLE cygfuse_init_fail(int err)
{
//RaiseException(ERROR_SEVERITY_ERROR | (109/*FACILITY_VISUALCPP*/ << 16) | err, 0, 0, 0);
abort();
return 0;
}
static HANDLE cygfuse_init_winfsp()
{
HANDLE Handle;
Handle = LoadLibraryW(L"" CYGFUSE_WINFSP_NAME);
if (0 == Handle)
{
HKEY RegKey;
DWORD RegResult, RegType;
WCHAR Path[MAX_PATH];
DWORD Size;
Size = sizeof(Path);
if (ERROR_SUCCESS == (RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"Software\\WinFsp", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &RegKey)))
{
RegResult = RegQueryValueExW(RegKey, L"InstallDir", 0, &RegType, (PBYTE)Path, &Size);
RegCloseKey(RegKey);
}
if (ERROR_SUCCESS != RegResult)
return cygfuse_init_fail(ERROR_MOD_NOT_FOUND);
Size /= sizeof(WCHAR);
if (Size >= MAX_PATH)
Size = MAX_PATH - 1;
Path[Size] = L'\0';
Size = lstrlenW(Path);
if (Size * sizeof(WCHAR) + sizeof L"" CYGFUSE_WINFSP_PATH > MAX_PATH * sizeof(WCHAR))
return cygfuse_init_fail(ERROR_MOD_NOT_FOUND);
memcpy(Path + Size, L"" CYGFUSE_WINFSP_PATH, sizeof L"" CYGFUSE_WINFSP_PATH);
Handle = LoadLibraryW(Path);
if (0 == Handle)
return cygfuse_init_fail(ERROR_MOD_NOT_FOUND);
}
/* winfsp_fuse.h */
CYGFUSE_API_GET(Handle, fsp_fuse_signal_handler);
/* fuse_common.h */
CYGFUSE_API_GET(Handle, fsp_fuse_version);
CYGFUSE_API_GET(Handle, fsp_fuse_mount);
CYGFUSE_API_GET(Handle, fsp_fuse_unmount);
CYGFUSE_API_GET(Handle, fsp_fuse_parse_cmdline);
CYGFUSE_API_GET(Handle, fsp_fuse_ntstatus_from_errno);
/* fuse.h */
CYGFUSE_API_GET(Handle, fsp_fuse_main_real);
CYGFUSE_API_GET(Handle, fsp_fuse_is_lib_option);
CYGFUSE_API_GET(Handle, fsp_fuse_new);
CYGFUSE_API_GET(Handle, fsp_fuse_destroy);
CYGFUSE_API_GET(Handle, fsp_fuse_loop);
CYGFUSE_API_GET(Handle, fsp_fuse_loop_mt);
CYGFUSE_API_GET(Handle, fsp_fuse_exit);
CYGFUSE_API_GET(Handle, fsp_fuse_get_context);
/* fuse_opt.h */
CYGFUSE_API_GET(Handle, fsp_fuse_opt_parse);
CYGFUSE_API_GET(Handle, fsp_fuse_opt_add_arg);
CYGFUSE_API_GET(Handle, fsp_fuse_opt_insert_arg);
CYGFUSE_API_GET(Handle, fsp_fuse_opt_free_args);
CYGFUSE_API_GET(Handle, fsp_fuse_opt_add_opt);
CYGFUSE_API_GET(Handle, fsp_fuse_opt_add_opt_escaped);
CYGFUSE_API_GET(Handle, fsp_fuse_opt_match);
return Handle;
}