mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 03:28:38 -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:
		| @@ -17,9 +17,6 @@ | ||||
|  | ||||
| #include <dll/fuse/library.h> | ||||
|  | ||||
| #define FSP_FUSE_SECTORSIZE_MIN         512 | ||||
| #define FSP_FUSE_SECTORSIZE_MAX         4096 | ||||
|  | ||||
| struct fuse_chan | ||||
| { | ||||
|     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); | ||||
| } | ||||
|  | ||||
| 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, | ||||
|     struct fuse_args *outargs) | ||||
| { | ||||
| @@ -729,8 +481,6 @@ fail: | ||||
| FSP_FUSE_API void fsp_fuse_destroy(struct fsp_fuse_env *env, | ||||
|     struct fuse *f) | ||||
| { | ||||
|     fsp_fuse_loop_cleanup(f); | ||||
|  | ||||
|     if (0 != 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_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, | ||||
|     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; | ||||
|         } | ||||
| } | ||||
|  | ||||
| /* 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); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user