mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
dll: fuse: refactoring
Split dll/fuse.c into dll/fuse.c and dll/fuse_loop.c to accommodate the complicated loop logic due to the last commit.
This commit is contained in:
parent
ae8e4e61f7
commit
a1b92d9095
@ -45,6 +45,7 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
|
||||||
|
<ClCompile Include="..\..\src\dll\fuse\fuse_loop.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
|
||||||
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
|
||||||
<ClCompile Include="..\..\src\dll\launch.c" />
|
<ClCompile Include="..\..\src\dll\launch.c" />
|
||||||
|
@ -148,6 +148,9 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c">
|
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c">
|
||||||
<Filter>Source\fuse3</Filter>
|
<Filter>Source\fuse3</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\fuse\fuse_loop.c">
|
||||||
|
<Filter>Source\fuse</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\library.def">
|
<None Include="..\..\src\dll\library.def">
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
#include <dll/fuse/library.h>
|
#include <dll/fuse/library.h>
|
||||||
|
|
||||||
#define FSP_FUSE_SECTORSIZE_MIN 512
|
|
||||||
#define FSP_FUSE_SECTORSIZE_MAX 4096
|
|
||||||
|
|
||||||
struct fuse_chan
|
struct fuse_chan
|
||||||
{
|
{
|
||||||
PWSTR MountPoint;
|
PWSTR MountPoint;
|
||||||
@ -223,251 +220,6 @@ FSP_FUSE_API int fsp_fuse_is_lib_option(struct fsp_fuse_env *env,
|
|||||||
return fsp_fuse_opt_match(env, fsp_fuse_core_opts, opt);
|
return fsp_fuse_opt_match(env, fsp_fuse_core_opts, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static INIT_ONCE fsp_fuse_svconce = INIT_ONCE_STATIC_INIT;
|
|
||||||
static HANDLE fsp_fuse_svcthread;
|
|
||||||
|
|
||||||
static DWORD WINAPI fsp_fuse_svcmain(PVOID Context)
|
|
||||||
{
|
|
||||||
return FspServiceRun(FspDiagIdent(), 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL WINAPI fsp_fuse_svcinit(
|
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
|
||||||
{
|
|
||||||
fsp_fuse_svcthread = CreateThread(0, 0, fsp_fuse_svcmain, 0, 0, 0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsp_fuse_loop_cleanup(struct fuse *f);
|
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
|
||||||
{
|
|
||||||
struct fuse_context *context;
|
|
||||||
struct fuse_conn_info conn;
|
|
||||||
NTSTATUS Result;
|
|
||||||
|
|
||||||
context = fsp_fuse_get_context(f->env);
|
|
||||||
if (0 == context)
|
|
||||||
{
|
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
context->fuse = f;
|
|
||||||
context->private_data = f->data;
|
|
||||||
context->uid = -1;
|
|
||||||
context->gid = -1;
|
|
||||||
context->pid = -1;
|
|
||||||
|
|
||||||
memset(&conn, 0, sizeof conn);
|
|
||||||
conn.proto_major = 7; /* pretend that we are FUSE kernel protocol 7.12 */
|
|
||||||
conn.proto_minor = 12; /* which was current at the time of FUSE 2.8 */
|
|
||||||
conn.async_read = 1;
|
|
||||||
conn.max_write = UINT_MAX;
|
|
||||||
conn.capable =
|
|
||||||
FUSE_CAP_ASYNC_READ |
|
|
||||||
//FUSE_CAP_POSIX_LOCKS | /* WinFsp handles locking in the FSD currently */
|
|
||||||
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
|
||||||
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
|
||||||
FUSE_CAP_BIG_WRITES |
|
|
||||||
FUSE_CAP_DONT_MASK |
|
|
||||||
FSP_FUSE_CAP_READDIR_PLUS |
|
|
||||||
FSP_FUSE_CAP_READ_ONLY |
|
|
||||||
FSP_FUSE_CAP_STAT_EX |
|
|
||||||
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
|
||||||
if (0 != f->ops.init)
|
|
||||||
{
|
|
||||||
context->private_data = f->data = f->ops.init(&conn);
|
|
||||||
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
|
||||||
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
|
||||||
if (!f->VolumeParams.CaseSensitiveSearch)
|
|
||||||
/*
|
|
||||||
* Disable GetDirInfoByName when file system is case-insensitive.
|
|
||||||
* The reason is that Windows always sends us queries with uppercase
|
|
||||||
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
|
||||||
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
|
||||||
*/
|
|
||||||
f->VolumeParams.PassQueryDirectoryFileName = FALSE;
|
|
||||||
f->conn_want = conn.want;
|
|
||||||
}
|
|
||||||
f->fsinit = TRUE;
|
|
||||||
if (0 != f->ops.statfs)
|
|
||||||
{
|
|
||||||
struct fuse_statvfs stbuf;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
memset(&stbuf, 0, sizeof stbuf);
|
|
||||||
err = f->ops.statfs("/", &stbuf);
|
|
||||||
if (0 != err)
|
|
||||||
{
|
|
||||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == f->VolumeParams.SectorSize && 0 != stbuf.f_frsize)
|
|
||||||
f->VolumeParams.SectorSize = (UINT16)stbuf.f_frsize;
|
|
||||||
#if 0
|
|
||||||
if (0 == f->VolumeParams.SectorsPerAllocationUnit && 0 != stbuf.f_frsize)
|
|
||||||
f->VolumeParams.SectorsPerAllocationUnit = (UINT16)(stbuf.f_bsize / stbuf.f_frsize);
|
|
||||||
#endif
|
|
||||||
if (0 == f->VolumeParams.MaxComponentLength)
|
|
||||||
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
|
||||||
}
|
|
||||||
if (0 != f->ops.getattr)
|
|
||||||
{
|
|
||||||
struct fuse_stat_ex stbuf;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
memset(&stbuf, 0, sizeof stbuf);
|
|
||||||
err = f->ops.getattr("/", (void *)&stbuf);
|
|
||||||
if (0 != err)
|
|
||||||
{
|
|
||||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
|
||||||
{
|
|
||||||
if (0 != stbuf.st_birthtim.tv_sec)
|
|
||||||
FspPosixUnixTimeToFileTime((void *)&stbuf.st_birthtim,
|
|
||||||
&f->VolumeParams.VolumeCreationTime);
|
|
||||||
else
|
|
||||||
if (0 != stbuf.st_ctim.tv_sec)
|
|
||||||
FspPosixUnixTimeToFileTime((void *)&stbuf.st_ctim,
|
|
||||||
&f->VolumeParams.VolumeCreationTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (0 != f->ops.readlink)
|
|
||||||
{
|
|
||||||
char buf[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* this should always fail with ENOSYS or EINVAL */
|
|
||||||
err = f->ops.readlink("/", buf, sizeof buf);
|
|
||||||
f->has_symlinks = -ENOSYS_(f->env) != err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
|
||||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
|
||||||
f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
|
||||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
|
||||||
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
|
||||||
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
|
||||||
if (f->VolumeParams.MaxComponentLength > 255)
|
|
||||||
f->VolumeParams.MaxComponentLength = 255;
|
|
||||||
|
|
||||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
|
||||||
{
|
|
||||||
FILETIME FileTime;
|
|
||||||
GetSystemTimeAsFileTime(&FileTime);
|
|
||||||
f->VolumeParams.VolumeCreationTime = *(PUINT64)&FileTime;
|
|
||||||
}
|
|
||||||
if (0 == f->VolumeParams.VolumeSerialNumber)
|
|
||||||
f->VolumeParams.VolumeSerialNumber =
|
|
||||||
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->HighPart ^
|
|
||||||
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->LowPart;
|
|
||||||
|
|
||||||
Result = FspFileSystemCreate(
|
|
||||||
f->VolumeParams.Prefix[0] ?
|
|
||||||
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
|
|
||||||
&f->VolumeParams, &fsp_fuse_intf,
|
|
||||||
&f->FileSystem);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
|
||||||
L"Cannot create " FSP_FUSE_LIBRARY_NAME " file system.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
f->FileSystem->UserContext = f;
|
|
||||||
FspFileSystemSetOperationGuard(f->FileSystem, fsp_fuse_op_enter, fsp_fuse_op_leave);
|
|
||||||
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
|
|
||||||
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
|
|
||||||
|
|
||||||
if (0 != f->MountPoint)
|
|
||||||
{
|
|
||||||
Result = FspFileSystemSetMountPoint(f->FileSystem,
|
|
||||||
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
|
||||||
L"Cannot set " FSP_FUSE_LIBRARY_NAME " file system mount point.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = FspFileSystemStartDispatcher(f->FileSystem, f->ThreadCount);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
|
||||||
L"Cannot start " FSP_FUSE_LIBRARY_NAME " file system dispatcher.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
fsp_fuse_loop_cleanup(f);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsp_fuse_loop_stop(struct fuse *f)
|
|
||||||
{
|
|
||||||
FspFileSystemStopDispatcher(f->FileSystem);
|
|
||||||
|
|
||||||
fsp_fuse_loop_cleanup(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fsp_fuse_loop_cleanup(struct fuse *f)
|
|
||||||
{
|
|
||||||
if (0 != f->FileSystem)
|
|
||||||
{
|
|
||||||
FspFileSystemDelete(f->FileSystem);
|
|
||||||
f->FileSystem = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f->fsinit)
|
|
||||||
{
|
|
||||||
if (f->ops.destroy)
|
|
||||||
f->ops.destroy(f->data);
|
|
||||||
f->fsinit = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FSP_FUSE_API NTSTATUS fsp_fuse_loop_internal(struct fuse *f)
|
|
||||||
{
|
|
||||||
HANDLE WaitObjects[2];
|
|
||||||
DWORD WaitResult;
|
|
||||||
NTSTATUS Result;
|
|
||||||
|
|
||||||
Result = fsp_fuse_loop_start(f);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
{
|
|
||||||
/* emulate WinFsp-FUSE v1.3 behavior! */
|
|
||||||
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
|
||||||
L"The service %s has failed to start (Status=%lx).", FspDiagIdent(), Result);
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitOnceExecuteOnce(&fsp_fuse_svconce, fsp_fuse_svcinit, 0, 0);
|
|
||||||
if (0 == fsp_fuse_svcthread)
|
|
||||||
{
|
|
||||||
fsp_fuse_loop_stop(f);
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if either the service thread dies or our event gets signaled, stop the loop */
|
|
||||||
WaitObjects[0] = fsp_fuse_svcthread;
|
|
||||||
WaitObjects[1] = f->LoopEvent;
|
|
||||||
WaitResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
|
|
||||||
if (WAIT_OBJECT_0 != WaitResult && WAIT_OBJECT_0 + 1 != WaitResult)
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
|
|
||||||
fsp_fuse_loop_stop(f);
|
|
||||||
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||||
struct fuse_args *outargs)
|
struct fuse_args *outargs)
|
||||||
{
|
{
|
||||||
@ -729,8 +481,6 @@ fail:
|
|||||||
FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env,
|
FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env,
|
||||||
struct fuse *f)
|
struct fuse *f)
|
||||||
{
|
{
|
||||||
fsp_fuse_loop_cleanup(f);
|
|
||||||
|
|
||||||
if (0 != f->LoopEvent)
|
if (0 != f->LoopEvent)
|
||||||
CloseHandle(f->LoopEvent);
|
CloseHandle(f->LoopEvent);
|
||||||
|
|
||||||
@ -739,20 +489,6 @@ FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env,
|
|||||||
fsp_fuse_obj_free(f);
|
fsp_fuse_obj_free(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env,
|
|
||||||
struct fuse *f)
|
|
||||||
{
|
|
||||||
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE;
|
|
||||||
return NT_SUCCESS(fsp_fuse_loop_internal(f)) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FSP_FUSE_API int fsp_fuse_loop_mt(struct fsp_fuse_env *env,
|
|
||||||
struct fuse *f)
|
|
||||||
{
|
|
||||||
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE;
|
|
||||||
return NT_SUCCESS(fsp_fuse_loop_internal(f)) ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env,
|
FSP_FUSE_API void fsp_fuse_exit(struct fsp_fuse_env *env,
|
||||||
struct fuse *f)
|
struct fuse *f)
|
||||||
{
|
{
|
||||||
@ -817,10 +553,3 @@ FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env,
|
|||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cygwin signal support */
|
|
||||||
|
|
||||||
FSP_FUSE_API void fsp_fuse_signal_handler(int sig)
|
|
||||||
{
|
|
||||||
FspServiceConsoleCtrlHandler(CTRL_BREAK_EVENT);
|
|
||||||
}
|
|
||||||
|
287
src/dll/fuse/fuse_loop.c
Normal file
287
src/dll/fuse/fuse_loop.c
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/fuse/fuse_loop.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2018 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 <dll/fuse/library.h>
|
||||||
|
|
||||||
|
#define FSP_FUSE_SECTORSIZE_MIN 512
|
||||||
|
#define FSP_FUSE_SECTORSIZE_MAX 4096
|
||||||
|
|
||||||
|
static INIT_ONCE fsp_fuse_svconce = INIT_ONCE_STATIC_INIT;
|
||||||
|
static HANDLE fsp_fuse_svcthread;
|
||||||
|
|
||||||
|
static DWORD WINAPI fsp_fuse_svcmain(PVOID Context)
|
||||||
|
{
|
||||||
|
return FspServiceRun(FspDiagIdent(), 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL WINAPI fsp_fuse_svcinit(
|
||||||
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
|
{
|
||||||
|
fsp_fuse_svcthread = CreateThread(0, 0, fsp_fuse_svcmain, 0, 0, 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fsp_fuse_loop_cleanup(struct fuse *f);
|
||||||
|
|
||||||
|
static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
||||||
|
{
|
||||||
|
struct fuse_context *context;
|
||||||
|
struct fuse_conn_info conn;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
context = fsp_fuse_get_context(f->env);
|
||||||
|
if (0 == context)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
context->fuse = f;
|
||||||
|
context->private_data = f->data;
|
||||||
|
context->uid = -1;
|
||||||
|
context->gid = -1;
|
||||||
|
context->pid = -1;
|
||||||
|
|
||||||
|
memset(&conn, 0, sizeof conn);
|
||||||
|
conn.proto_major = 7; /* pretend that we are FUSE kernel protocol 7.12 */
|
||||||
|
conn.proto_minor = 12; /* which was current at the time of FUSE 2.8 */
|
||||||
|
conn.async_read = 1;
|
||||||
|
conn.max_write = UINT_MAX;
|
||||||
|
conn.capable =
|
||||||
|
FUSE_CAP_ASYNC_READ |
|
||||||
|
//FUSE_CAP_POSIX_LOCKS | /* WinFsp handles locking in the FSD currently */
|
||||||
|
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
||||||
|
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
||||||
|
FUSE_CAP_BIG_WRITES |
|
||||||
|
FUSE_CAP_DONT_MASK |
|
||||||
|
FSP_FUSE_CAP_READDIR_PLUS |
|
||||||
|
FSP_FUSE_CAP_READ_ONLY |
|
||||||
|
FSP_FUSE_CAP_STAT_EX |
|
||||||
|
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
||||||
|
if (0 != f->ops.init)
|
||||||
|
{
|
||||||
|
context->private_data = f->data = f->ops.init(&conn);
|
||||||
|
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
||||||
|
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch)
|
||||||
|
/*
|
||||||
|
* Disable GetDirInfoByName when file system is case-insensitive.
|
||||||
|
* The reason is that Windows always sends us queries with uppercase
|
||||||
|
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
||||||
|
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
||||||
|
*/
|
||||||
|
f->VolumeParams.PassQueryDirectoryFileName = FALSE;
|
||||||
|
f->conn_want = conn.want;
|
||||||
|
}
|
||||||
|
f->fsinit = TRUE;
|
||||||
|
if (0 != f->ops.statfs)
|
||||||
|
{
|
||||||
|
struct fuse_statvfs stbuf;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(&stbuf, 0, sizeof stbuf);
|
||||||
|
err = f->ops.statfs("/", &stbuf);
|
||||||
|
if (0 != err)
|
||||||
|
{
|
||||||
|
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == f->VolumeParams.SectorSize && 0 != stbuf.f_frsize)
|
||||||
|
f->VolumeParams.SectorSize = (UINT16)stbuf.f_frsize;
|
||||||
|
#if 0
|
||||||
|
if (0 == f->VolumeParams.SectorsPerAllocationUnit && 0 != stbuf.f_frsize)
|
||||||
|
f->VolumeParams.SectorsPerAllocationUnit = (UINT16)(stbuf.f_bsize / stbuf.f_frsize);
|
||||||
|
#endif
|
||||||
|
if (0 == f->VolumeParams.MaxComponentLength)
|
||||||
|
f->VolumeParams.MaxComponentLength = (UINT16)stbuf.f_namemax;
|
||||||
|
}
|
||||||
|
if (0 != f->ops.getattr)
|
||||||
|
{
|
||||||
|
struct fuse_stat_ex stbuf;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(&stbuf, 0, sizeof stbuf);
|
||||||
|
err = f->ops.getattr("/", (void *)&stbuf);
|
||||||
|
if (0 != err)
|
||||||
|
{
|
||||||
|
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||||
|
{
|
||||||
|
if (0 != stbuf.st_birthtim.tv_sec)
|
||||||
|
FspPosixUnixTimeToFileTime((void *)&stbuf.st_birthtim,
|
||||||
|
&f->VolumeParams.VolumeCreationTime);
|
||||||
|
else
|
||||||
|
if (0 != stbuf.st_ctim.tv_sec)
|
||||||
|
FspPosixUnixTimeToFileTime((void *)&stbuf.st_ctim,
|
||||||
|
&f->VolumeParams.VolumeCreationTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 != f->ops.readlink)
|
||||||
|
{
|
||||||
|
char buf[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* this should always fail with ENOSYS or EINVAL */
|
||||||
|
err = f->ops.readlink("/", buf, sizeof buf);
|
||||||
|
f->has_symlinks = -ENOSYS_(f->env) != err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||||
|
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
||||||
|
f->VolumeParams.SectorSize > FSP_FUSE_SECTORSIZE_MAX)
|
||||||
|
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
||||||
|
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
||||||
|
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
||||||
|
if (f->VolumeParams.MaxComponentLength > 255)
|
||||||
|
f->VolumeParams.MaxComponentLength = 255;
|
||||||
|
|
||||||
|
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||||
|
{
|
||||||
|
FILETIME FileTime;
|
||||||
|
GetSystemTimeAsFileTime(&FileTime);
|
||||||
|
f->VolumeParams.VolumeCreationTime = *(PUINT64)&FileTime;
|
||||||
|
}
|
||||||
|
if (0 == f->VolumeParams.VolumeSerialNumber)
|
||||||
|
f->VolumeParams.VolumeSerialNumber =
|
||||||
|
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->HighPart ^
|
||||||
|
((PLARGE_INTEGER)&f->VolumeParams.VolumeCreationTime)->LowPart;
|
||||||
|
|
||||||
|
Result = FspFileSystemCreate(
|
||||||
|
f->VolumeParams.Prefix[0] ?
|
||||||
|
L"" FSP_FSCTL_NET_DEVICE_NAME : L"" FSP_FSCTL_DISK_DEVICE_NAME,
|
||||||
|
&f->VolumeParams, &fsp_fuse_intf,
|
||||||
|
&f->FileSystem);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"Cannot create " FSP_FUSE_LIBRARY_NAME " file system.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
f->FileSystem->UserContext = f;
|
||||||
|
FspFileSystemSetOperationGuard(f->FileSystem, fsp_fuse_op_enter, fsp_fuse_op_leave);
|
||||||
|
FspFileSystemSetOperationGuardStrategy(f->FileSystem, f->OpGuardStrategy);
|
||||||
|
FspFileSystemSetDebugLog(f->FileSystem, f->DebugLog);
|
||||||
|
|
||||||
|
if (0 != f->MountPoint)
|
||||||
|
{
|
||||||
|
Result = FspFileSystemSetMountPoint(f->FileSystem,
|
||||||
|
L'*' == f->MountPoint[0] && L'\0' == f->MountPoint[1] ? 0 : f->MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"Cannot set " FSP_FUSE_LIBRARY_NAME " file system mount point.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspFileSystemStartDispatcher(f->FileSystem, f->ThreadCount);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"Cannot start " FSP_FUSE_LIBRARY_NAME " file system dispatcher.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
fsp_fuse_loop_cleanup(f);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fsp_fuse_loop_stop(struct fuse *f)
|
||||||
|
{
|
||||||
|
FspFileSystemStopDispatcher(f->FileSystem);
|
||||||
|
|
||||||
|
fsp_fuse_loop_cleanup(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fsp_fuse_loop_cleanup(struct fuse *f)
|
||||||
|
{
|
||||||
|
if (0 != f->FileSystem)
|
||||||
|
{
|
||||||
|
FspFileSystemDelete(f->FileSystem);
|
||||||
|
f->FileSystem = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f->fsinit)
|
||||||
|
{
|
||||||
|
if (f->ops.destroy)
|
||||||
|
f->ops.destroy(f->data);
|
||||||
|
f->fsinit = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS fsp_fuse_loop_internal(struct fuse *f)
|
||||||
|
{
|
||||||
|
HANDLE WaitObjects[2];
|
||||||
|
DWORD WaitResult;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
Result = fsp_fuse_loop_start(f);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
/* emulate WinFsp-FUSE v1.3 behavior! */
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"The service %s has failed to start (Status=%lx).", FspDiagIdent(), Result);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitOnceExecuteOnce(&fsp_fuse_svconce, fsp_fuse_svcinit, 0, 0);
|
||||||
|
if (0 == fsp_fuse_svcthread)
|
||||||
|
{
|
||||||
|
fsp_fuse_loop_stop(f);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if either the service thread dies or our event gets signaled, stop the loop */
|
||||||
|
WaitObjects[0] = fsp_fuse_svcthread;
|
||||||
|
WaitObjects[1] = f->LoopEvent;
|
||||||
|
WaitResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
|
||||||
|
if (WAIT_OBJECT_0 != WaitResult && WAIT_OBJECT_0 + 1 != WaitResult)
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
fsp_fuse_loop_stop(f);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FUSE_API int fsp_fuse_loop(struct fsp_fuse_env *env,
|
||||||
|
struct fuse *f)
|
||||||
|
{
|
||||||
|
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_COARSE;
|
||||||
|
return NT_SUCCESS(fsp_fuse_loop_internal(f)) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_FUSE_API int fsp_fuse_loop_mt(struct fsp_fuse_env *env,
|
||||||
|
struct fuse *f)
|
||||||
|
{
|
||||||
|
f->OpGuardStrategy = FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY_FINE;
|
||||||
|
return NT_SUCCESS(fsp_fuse_loop_internal(f)) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cygwin signal support */
|
||||||
|
|
||||||
|
FSP_FUSE_API void fsp_fuse_signal_handler(int sig)
|
||||||
|
{
|
||||||
|
FspServiceConsoleCtrlHandler(CTRL_BREAK_EVENT);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user