mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	opt: cygfuse: fuse3
This commit is contained in:
		
							
								
								
									
										169
									
								
								opt/cygfuse/fuse3/cygfuse.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								opt/cygfuse/fuse3/cygfuse.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| /** | ||||
|  * @file fuse3/cygfuse.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 <dlfcn.h> | ||||
| #include <pthread.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/cygwin.h> | ||||
|  | ||||
| static void *cygfuse_init_slow(int force); | ||||
| static void *cygfuse_init_winfsp(); | ||||
|  | ||||
| static pthread_mutex_t cygfuse_mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
| static void *cygfuse_handle = 0; | ||||
|  | ||||
| static inline void *cygfuse_init_fast(void) | ||||
| { | ||||
|     void *handle = cygfuse_handle; | ||||
|     __sync_synchronize(); /* memory barrier */ | ||||
|     if (0 == handle) | ||||
|         handle = cygfuse_init_slow(0); | ||||
|     return handle; | ||||
| } | ||||
|  | ||||
| static void *cygfuse_init_slow(int force) | ||||
| { | ||||
|     void *handle; | ||||
|     pthread_mutex_lock(&cygfuse_mutex); | ||||
|     handle = cygfuse_handle; | ||||
|     if (force || 0 == handle) | ||||
|     { | ||||
|         handle = cygfuse_init_winfsp(); | ||||
|         __sync_synchronize(); /* memory barrier */ | ||||
|         cygfuse_handle = handle; | ||||
|     } | ||||
|     pthread_mutex_unlock(&cygfuse_mutex); | ||||
|     return handle; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * 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_slow(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_fast(), 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_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_fuse3_parse_conn_info_opts); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_apply_conn_info_opts); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_version); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_pkgversion); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse_ntstatus_from_errno); | ||||
|  | ||||
|     /* fuse.h */ | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_main_real); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_lib_help); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_new_30); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_new); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_destroy); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_mount); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_unmount); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_loop); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_loop_mt_31); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_loop_mt); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_exit); | ||||
|     CYGFUSE_GET_API(h, fsp_fuse3_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() | ||||
| { | ||||
|     fprintf(stderr, "cygfuse: initialization failed: " CYGFUSE_WINFSP_NAME " not found\n"); | ||||
|     exit(1); | ||||
|     return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user