mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	Merge branch 'pvt-fuse3'
This commit is contained in:
		| @@ -5,9 +5,11 @@ v1.4B2 (2018.2 B2):: | ||||
|  | ||||
| Changes since v1.3: | ||||
|  | ||||
| * New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API. | ||||
| * FUSE3 API (version 3.2) is now available. The FUSE2 API (version 2.8) also remains supported. | ||||
| * New `Control` file system operation allows sending custom control codes to the file system using the Windows `DeviceIoControl` API. FUSE `ioctl` is also supported. | ||||
| * `FlushAndPurgeOnCleanup` has now been added to the .NET API. (GitHub PR #176; thanks @FrKaram.) | ||||
| * New sample file system "airfs" contributed by @JohnOberschelp. | ||||
| * New sample file system "airfs" contributed by @JohnOberschelp. Airfs is an in-memory file system like Memfs on which it is based on; it has received substantial improvements in how the file name space is maintained and has been modified to use modern C++ techniques by John. | ||||
| * New sample file system "passthrough-fuse3" passes all operations to an underlying file system. This file system is built using the FUSE3 API. It builds and runs on both Windows and Cygwin. | ||||
|  | ||||
|  | ||||
| v1.4B1 (2018.2 B1):: | ||||
|   | ||||
| @@ -281,6 +281,20 @@ | ||||
|                     <File Name="winfsp_fuse.h" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|             </Directory> | ||||
|             <Directory Id="INCDIR.fuse3" Name="fuse3"> | ||||
|                 <Component Id="C.fuse3.h"> | ||||
|                     <File Id="fuse3.h" Name="fuse.h" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.fuse3_common.h"> | ||||
|                     <File Id="fuse3_common.h" Name="fuse_common.h" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.fuse3_opt.h"> | ||||
|                     <File Id="fuse3_opt.h" Name="fuse_opt.h" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.winfsp_fuse3.h"> | ||||
|                     <File Id="winfsp_fuse3.h" Name="winfsp_fuse.h" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|             </Directory> | ||||
|         </DirectoryRef> | ||||
|         <DirectoryRef Id="LIBDIR" FileSource="..\build\$(var.Configuration)"> | ||||
|             <Component Id="C.winfsp_x64.lib"> | ||||
| @@ -309,6 +323,26 @@ | ||||
|                     KeyPath="yes" /> | ||||
|                 <Condition>NOT VersionNT64</Condition> | ||||
|             </Component> | ||||
|  | ||||
|             <!-- On Win64 copy fuse3-x64.pc --> | ||||
|             <Component Id="C.fuse3_x64.pc" Guid="FE59E3BA-E5EA-4822-80B1-19A1DE6B62C7"> | ||||
|                 <File | ||||
|                     Id="FILE.fuse3_x64.pc" | ||||
|                     Name="fuse3.pc" | ||||
|                     Source="..\build\$(var.Configuration)\fuse3-x64.pc" | ||||
|                     KeyPath="yes" /> | ||||
|                 <Condition>VersionNT64</Condition> | ||||
|             </Component> | ||||
|  | ||||
|             <!-- On Win32 copy fuse3-x86.pc --> | ||||
|             <Component Id="C.fuse3_x86.pc" Guid="176205D0-07EA-4DFC-947F-18E89ABDAFAB"> | ||||
|                 <File | ||||
|                     Id="FILE.fuse3_x86.pc" | ||||
|                     Name="fuse3.pc" | ||||
|                     Source="..\build\$(var.Configuration)\fuse3-x86.pc" | ||||
|                     KeyPath="yes" /> | ||||
|                 <Condition>NOT VersionNT64</Condition> | ||||
|             </Component> | ||||
|         </DirectoryRef> | ||||
|         <DirectoryRef Id="OPTDIR"> | ||||
|             <Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist"> | ||||
| @@ -415,6 +449,32 @@ | ||||
|                     <File Name="README.md" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|             </Directory> | ||||
|             <Directory Id="SMPDIR.passthrough_fuse3" Name="passthrough-fuse3"> | ||||
|                 <Component Id="C.passthrough_fuse3.c"> | ||||
|                     <File Name="passthrough-fuse3.c" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.winposix.c"> | ||||
|                     <File Id="F.passthrough_fuse3.winposix.c" Name="winposix.c" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.winposix.h"> | ||||
|                     <File Id="F.passthrough_fuse3.winposix.h" Name="winposix.h" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.sln"> | ||||
|                     <File Name="passthrough-fuse3.sln" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.vcxproj"> | ||||
|                     <File Name="passthrough-fuse3.vcxproj" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.vcxproj.filters"> | ||||
|                     <File Name="passthrough-fuse3.vcxproj.filters" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.Makefile"> | ||||
|                     <File Id="F.passthrough_fuse3.Makefile" Name="Makefile" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|                 <Component Id="C.passthrough_fuse3.README.md"> | ||||
|                     <File Id="F.passthrough_fuse3.README.md" Name="README.md" KeyPath="yes" /> | ||||
|                 </Component> | ||||
|             </Directory> | ||||
|             <Directory Id="SMPDIR.passthrough_dotnet" Name="passthrough-dotnet"> | ||||
|                 <Component Id="C.passthrough_dotnet.Program.cs"> | ||||
|                     <File Id="FILE.passthrough_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" /> | ||||
| @@ -493,12 +553,18 @@ | ||||
|             <ComponentRef Id="C.fuse_common.h" /> | ||||
|             <ComponentRef Id="C.fuse_opt.h" /> | ||||
|             <ComponentRef Id="C.winfsp_fuse.h" /> | ||||
|             <ComponentRef Id="C.fuse3.h" /> | ||||
|             <ComponentRef Id="C.fuse3_common.h" /> | ||||
|             <ComponentRef Id="C.fuse3_opt.h" /> | ||||
|             <ComponentRef Id="C.winfsp_fuse3.h" /> | ||||
|         </ComponentGroup> | ||||
|         <ComponentGroup Id="C.WinFsp.lib"> | ||||
|             <ComponentRef Id="C.winfsp_x64.lib" /> | ||||
|             <ComponentRef Id="C.winfsp_x86.lib" /> | ||||
|             <ComponentRef Id="C.fuse_x64.pc" /> | ||||
|             <ComponentRef Id="C.fuse_x86.pc" /> | ||||
|             <ComponentRef Id="C.fuse3_x64.pc" /> | ||||
|             <ComponentRef Id="C.fuse3_x86.pc" /> | ||||
|         </ComponentGroup> | ||||
|         <ComponentGroup Id="C.WinFsp.opt.fuse"> | ||||
|             <ComponentRef Id="C.fuse.tar.xz.x64" /> | ||||
| @@ -532,6 +598,14 @@ | ||||
|             <ComponentRef Id="C.passthrough_fuse.vcxproj.filters" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse.Makefile" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse.README.md" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.c" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.winposix.c" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.winposix.h" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.sln" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.vcxproj" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.vcxproj.filters" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.Makefile" /> | ||||
|             <ComponentRef Id="C.passthrough_fuse3.README.md" /> | ||||
|         </ComponentGroup> | ||||
|         <ComponentGroup Id="C.WinFsp.sym"> | ||||
|             <ComponentRef Id="C.winfsp_x64.sys.pdb" /> | ||||
|   | ||||
| @@ -20,6 +20,10 @@ | ||||
|     </ProjectConfiguration> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\..\inc\fuse3\fuse.h" /> | ||||
|     <ClInclude Include="..\..\inc\fuse3\fuse_common.h" /> | ||||
|     <ClInclude Include="..\..\inc\fuse3\fuse_opt.h" /> | ||||
|     <ClInclude Include="..\..\inc\fuse3\winfsp_fuse.h" /> | ||||
|     <ClInclude Include="..\..\inc\fuse\fuse.h" /> | ||||
|     <ClInclude Include="..\..\inc\fuse\fuse_common.h" /> | ||||
|     <ClInclude Include="..\..\inc\fuse\fuse_opt.h" /> | ||||
| @@ -28,6 +32,7 @@ | ||||
|     <ClInclude Include="..\..\inc\winfsp\launch.h" /> | ||||
|     <ClInclude Include="..\..\inc\winfsp\winfsp.h" /> | ||||
|     <ClInclude Include="..\..\inc\winfsp\winfsp.hpp" /> | ||||
|     <ClInclude Include="..\..\src\dll\fuse3\library.h" /> | ||||
|     <ClInclude Include="..\..\src\dll\fuse\library.h" /> | ||||
|     <ClInclude Include="..\..\src\dll\library.h" /> | ||||
|     <ClInclude Include="..\..\src\shared\minimal.h" /> | ||||
| @@ -35,6 +40,8 @@ | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="..\..\src\dll\dirbuf.c" /> | ||||
|     <ClCompile Include="..\..\src\dll\eventlog.c" /> | ||||
|     <ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c" /> | ||||
|     <ClCompile Include="..\..\src\dll\fuse3\fuse3.c" /> | ||||
|     <ClCompile Include="..\..\src\dll\fuse\fuse.c" /> | ||||
|     <ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" /> | ||||
|     <ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" /> | ||||
| @@ -79,6 +86,29 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse-$(PlatformTarget).pc</Outputs> | ||||
|       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects> | ||||
|     </CustomBuild> | ||||
|     <CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in"> | ||||
|       <FileType>Document</FileType> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc | ||||
| copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc | ||||
| copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc | ||||
| copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">echo arch=$(PlatformTarget) >$(OutDir)fuse3-$(PlatformTarget).pc | ||||
| copy /b $(OutDir)fuse3-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse3-$(PlatformTarget).pc >nul</Command> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Writing fuse3-$(PlatformTarget).pc</Message> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Writing fuse3-$(PlatformTarget).pc</Message> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Writing fuse3-$(PlatformTarget).pc</Message> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Writing fuse3-$(PlatformTarget).pc</Message> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse3-$(PlatformTarget).pc</Outputs> | ||||
|       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects> | ||||
|       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects> | ||||
|       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects> | ||||
|       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects> | ||||
|     </CustomBuild> | ||||
|     <None Include="..\..\src\dll\library.def" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|   | ||||
| @@ -21,6 +21,12 @@ | ||||
|     <Filter Include="Source\fuse"> | ||||
|       <UniqueIdentifier>{518cce17-85cd-489c-b4be-920a84c1d73c}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="Include\fuse3"> | ||||
|       <UniqueIdentifier>{12afd2f1-f5ec-4008-b6ef-89cc626019ea}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="Source\fuse3"> | ||||
|       <UniqueIdentifier>{96091a7b-3923-4a74-9491-3ee230c688f9}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\..\inc\winfsp\fsctl.h"> | ||||
| @@ -56,6 +62,21 @@ | ||||
|     <ClInclude Include="..\..\inc\winfsp\launch.h"> | ||||
|       <Filter>Include\winfsp</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\inc\fuse3\fuse.h"> | ||||
|       <Filter>Include\fuse3</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\inc\fuse3\fuse_common.h"> | ||||
|       <Filter>Include\fuse3</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\inc\fuse3\fuse_opt.h"> | ||||
|       <Filter>Include\fuse3</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\inc\fuse3\winfsp_fuse.h"> | ||||
|       <Filter>Include\fuse3</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\..\src\dll\fuse3\library.h"> | ||||
|       <Filter>Source\fuse3</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="..\..\src\dll\library.c"> | ||||
| @@ -121,6 +142,12 @@ | ||||
|     <ClCompile Include="..\..\src\dll\launch.c"> | ||||
|       <Filter>Source</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\dll\fuse3\fuse3.c"> | ||||
|       <Filter>Source\fuse3</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c"> | ||||
|       <Filter>Source\fuse3</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="..\..\src\dll\library.def"> | ||||
| @@ -139,5 +166,8 @@ | ||||
|     <CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in"> | ||||
|       <Filter>Source\fuse</Filter> | ||||
|     </CustomBuild> | ||||
|     <CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in"> | ||||
|       <Filter>Source\fuse3</Filter> | ||||
|     </CustomBuild> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
							
								
								
									
										334
									
								
								inc/fuse3/fuse.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								inc/fuse3/fuse.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,334 @@ | ||||
| /** | ||||
|  * @file fuse3/fuse.h | ||||
|  * WinFsp FUSE3 compatible API. | ||||
|  * | ||||
|  * This file is derived from libfuse/include/fuse.h: | ||||
|  *     FUSE: Filesystem in Userspace | ||||
|  *     Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu> | ||||
|  * | ||||
|  * @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. | ||||
|  */ | ||||
|  | ||||
| #ifndef FUSE_H_ | ||||
| #define FUSE_H_ | ||||
|  | ||||
| #include "fuse_common.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| struct fuse3; | ||||
|  | ||||
| enum fuse3_readdir_flags | ||||
| { | ||||
|     FUSE_READDIR_PLUS                   = (1 << 0), | ||||
| }; | ||||
|  | ||||
| enum fuse3_fill_dir_flags | ||||
| { | ||||
|     FUSE_FILL_DIR_PLUS                  = (1 << 1), | ||||
| }; | ||||
|  | ||||
| typedef int (*fuse3_fill_dir_t)(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off, | ||||
|     enum fuse3_fill_dir_flags flags); | ||||
|  | ||||
| struct fuse3_config | ||||
| { | ||||
|     int set_gid; | ||||
|     unsigned int gid; | ||||
|     int set_uid; | ||||
|     unsigned int uid; | ||||
|     int set_mode; | ||||
|     unsigned int umask; | ||||
|     double entry_timeout; | ||||
|     double negative_timeout; | ||||
|     double attr_timeout; | ||||
|     int intr; | ||||
|     int intr_signal; | ||||
|     int remember; | ||||
|     int hard_remove; | ||||
|     int use_ino; | ||||
|     int readdir_ino; | ||||
|     int direct_io; | ||||
|     int kernel_cache; | ||||
|     int auto_cache; | ||||
|     int ac_attr_timeout_set; | ||||
|     double ac_attr_timeout; | ||||
|     int nullpath_ok; | ||||
|     /* private */ | ||||
|     int show_help; | ||||
|     char *modules; | ||||
|     int debug; | ||||
| }; | ||||
|  | ||||
| struct fuse3_operations | ||||
| { | ||||
|     /* S - supported by WinFsp */ | ||||
|     /* S */ int (*getattr)(const char *path, struct fuse_stat *stbuf, | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* S */ int (*readlink)(const char *path, char *buf, size_t size); | ||||
|     /* S */ int (*mknod)(const char *path, fuse_mode_t mode, fuse_dev_t dev); | ||||
|     /* S */ int (*mkdir)(const char *path, fuse_mode_t mode); | ||||
|     /* S */ int (*unlink)(const char *path); | ||||
|     /* S */ int (*rmdir)(const char *path); | ||||
|     /* S */ int (*symlink)(const char *dstpath, const char *srcpath); | ||||
|     /* S */ int (*rename)(const char *oldpath, const char *newpath, unsigned int flags); | ||||
|     /* _ */ int (*link)(const char *srcpath, const char *dstpath); | ||||
|     /* S */ int (*chmod)(const char *path, fuse_mode_t mode, | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* S */ int (*chown)(const char *path, fuse_uid_t uid, fuse_gid_t gid, | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* S */ int (*truncate)(const char *path, fuse_off_t size, | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* S */ int (*open)(const char *path, struct fuse3_file_info *fi); | ||||
|     /* S */ int (*read)(const char *path, char *buf, size_t size, fuse_off_t off, | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* S */ int (*write)(const char *path, const char *buf, size_t size, fuse_off_t off, | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* S */ int (*statfs)(const char *path, struct fuse_statvfs *stbuf); | ||||
|     /* S */ int (*flush)(const char *path, struct fuse3_file_info *fi); | ||||
|     /* S */ int (*release)(const char *path, struct fuse3_file_info *fi); | ||||
|     /* S */ int (*fsync)(const char *path, int datasync, struct fuse3_file_info *fi); | ||||
|     /* _ */ int (*setxattr)(const char *path, const char *name, const char *value, size_t size, | ||||
|         int flags); | ||||
|     /* _ */ int (*getxattr)(const char *path, const char *name, char *value, size_t size); | ||||
|     /* _ */ int (*listxattr)(const char *path, char *namebuf, size_t size); | ||||
|     /* _ */ int (*removexattr)(const char *path, const char *name); | ||||
|     /* S */ int (*opendir)(const char *path, struct fuse3_file_info *fi); | ||||
|     /* S */ int (*readdir)(const char *path, void *buf, fuse3_fill_dir_t filler, fuse_off_t off, | ||||
|         struct fuse3_file_info *fi, enum fuse3_readdir_flags); | ||||
|     /* S */ int (*releasedir)(const char *path, struct fuse3_file_info *fi); | ||||
|     /* S */ int (*fsyncdir)(const char *path, int datasync, struct fuse3_file_info *fi); | ||||
|     /* S */ void *(*init)(struct fuse3_conn_info *conn, | ||||
|         struct fuse3_config *conf); | ||||
|     /* S */ void (*destroy)(void *data); | ||||
|     /* _ */ int (*access)(const char *path, int mask); | ||||
|     /* S */ int (*create)(const char *path, fuse_mode_t mode, struct fuse3_file_info *fi); | ||||
|     /* _ */ int (*lock)(const char *path, | ||||
|         struct fuse3_file_info *fi, int cmd, struct fuse_flock *lock); | ||||
|     /* S */ int (*utimens)(const char *path, const struct fuse_timespec tv[2], | ||||
|         struct fuse3_file_info *fi); | ||||
|     /* _ */ int (*bmap)(const char *path, size_t blocksize, uint64_t *idx); | ||||
|     /* S */ int (*ioctl)(const char *path, int cmd, void *arg, struct fuse3_file_info *fi, | ||||
|         unsigned int flags, void *data); | ||||
|     /* _ */ int (*poll)(const char *path, struct fuse3_file_info *fi, | ||||
|         struct fuse3_pollhandle *ph, unsigned *reventsp); | ||||
|     /* _ */ int (*write_buf)(const char *path, | ||||
|         struct fuse3_bufvec *buf, fuse_off_t off, struct fuse3_file_info *fi); | ||||
|     /* _ */ int (*read_buf)(const char *path, | ||||
|         struct fuse3_bufvec **bufp, size_t size, fuse_off_t off, struct fuse3_file_info *fi); | ||||
|     /* _ */ int (*flock)(const char *path, struct fuse3_file_info *, int op); | ||||
|     /* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len, | ||||
|         struct fuse3_file_info *fi); | ||||
| }; | ||||
|  | ||||
| struct fuse3_context | ||||
| { | ||||
|     struct fuse3 *fuse; | ||||
|     fuse_uid_t uid; | ||||
|     fuse_gid_t gid; | ||||
|     fuse_pid_t pid; | ||||
|     void *private_data; | ||||
|     fuse_mode_t umask; | ||||
| }; | ||||
|  | ||||
| #define fuse_main(argc, argv, ops, data)\ | ||||
|     fuse3_main_real(argc, argv, ops, sizeof *(ops), data) | ||||
|  | ||||
| FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_main_real)(struct fsp_fuse_env *env, | ||||
|     int argc, char *argv[], | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data); | ||||
| FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_lib_help)(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args); | ||||
| FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new_30)(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data); | ||||
| FSP_FUSE_API struct fuse3 *FSP_FUSE_API_NAME(fsp_fuse3_new)(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data); | ||||
| FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_destroy)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f); | ||||
| FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_mount)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f, const char *mountpoint); | ||||
| FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_unmount)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f); | ||||
| FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f); | ||||
| FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt_31)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f, int clone_fd); | ||||
| FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_loop_mt)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f, struct fuse3_loop_config *config); | ||||
| FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_exit)(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f); | ||||
| FSP_FUSE_API struct fuse3_context *FSP_FUSE_API_NAME(fsp_fuse3_get_context)(struct fsp_fuse_env *env); | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_main_real(int argc, char *argv[], | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_main_real) | ||||
|         (fsp_fuse_env(), argc, argv, ops, opsize, data); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_lib_help(struct fuse_args *args), | ||||
| { | ||||
|     FSP_FUSE_API_CALL(fsp_fuse3_lib_help) | ||||
|         (fsp_fuse_env(), args); | ||||
| }) | ||||
|  | ||||
| #if FUSE_USE_VERSION == 30 | ||||
| FSP_FUSE_SYM( | ||||
| struct fuse3 *fuse3_new_30(struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_new_30) | ||||
|         (fsp_fuse_env(), args, ops, opsize, data); | ||||
| }) | ||||
| #define fuse_new(args, op, size, data)\ | ||||
|     fuse3_new_30(args, op, size, data) | ||||
|  | ||||
| #else | ||||
| FSP_FUSE_SYM( | ||||
| struct fuse3 *fuse3_new(struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_new) | ||||
|         (fsp_fuse_env(), args, ops, opsize, data); | ||||
| }) | ||||
| #endif | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_destroy(struct fuse3 *f), | ||||
| { | ||||
|     FSP_FUSE_API_CALL(fsp_fuse3_destroy) | ||||
|         (fsp_fuse_env(), f); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_mount(struct fuse3 *f, const char *mountpoint), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_mount) | ||||
|         (fsp_fuse_env(), f, mountpoint); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_unmount(struct fuse3 *f), | ||||
| { | ||||
|     FSP_FUSE_API_CALL(fsp_fuse3_unmount) | ||||
|         (fsp_fuse_env(), f); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_loop(struct fuse3 *f), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_loop) | ||||
|         (fsp_fuse_env(), f); | ||||
| }) | ||||
|  | ||||
| #if FUSE_USE_VERSION < 32 | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_loop_mt_31(struct fuse3 *f, int clone_fd), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt_31) | ||||
|         (fsp_fuse_env(), f, clone_fd); | ||||
| }) | ||||
| #define fuse_loop_mt(f, clone_fd)\ | ||||
|     fuse3_loop_mt_31(f, clone_fd) | ||||
|  | ||||
| #else | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_loop_mt(struct fuse3 *f, struct fuse3_loop_config *config), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_loop_mt) | ||||
|         (fsp_fuse_env(), f, config); | ||||
| }) | ||||
| #endif | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_exit(struct fuse3 *f), | ||||
| { | ||||
|     FSP_FUSE_API_CALL(fsp_fuse3_exit) | ||||
|         (fsp_fuse_env(), f); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| struct fuse3_context *fuse3_get_context(void), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_get_context) | ||||
|         (fsp_fuse_env()); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_getgroups(int size, fuse_gid_t list[]), | ||||
| { | ||||
|     (void)size; | ||||
|     (void)list; | ||||
|     return -ENOSYS; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_interrupted(void), | ||||
| { | ||||
|     return 0; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_invalidate_path(struct fuse3 *f, const char *path), | ||||
| { | ||||
|     (void)f; | ||||
|     (void)path; | ||||
|     return -ENOENT; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_notify_poll(struct fuse3_pollhandle *ph), | ||||
| { | ||||
|     (void)ph; | ||||
|     return 0; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_start_cleanup_thread(struct fuse3 *f), | ||||
| { | ||||
|     (void)f; | ||||
|     return 0; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_stop_cleanup_thread(struct fuse3 *f), | ||||
| { | ||||
|     (void)f; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_clean_cache(struct fuse3 *f), | ||||
| { | ||||
|     (void)f; | ||||
|     return 600; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| struct fuse3_session *fuse3_get_session(struct fuse3 *f), | ||||
| { | ||||
|     return (struct fuse3_session *)f; | ||||
| }) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										232
									
								
								inc/fuse3/fuse_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								inc/fuse3/fuse_common.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | ||||
| /** | ||||
|  * @file fuse3/fuse_common.h | ||||
|  * WinFsp FUSE3 compatible API. | ||||
|  * | ||||
|  * This file is derived from libfuse/include/fuse_common.h: | ||||
|  *     FUSE: Filesystem in Userspace | ||||
|  *     Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu> | ||||
|  * | ||||
|  * @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. | ||||
|  */ | ||||
|  | ||||
| #ifndef FUSE_COMMON_H_ | ||||
| #define FUSE_COMMON_H_ | ||||
|  | ||||
| #include "winfsp_fuse.h" | ||||
| #include "fuse_opt.h" | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #define FUSE_MAJOR_VERSION              3 | ||||
| #define FUSE_MINOR_VERSION              2 | ||||
| #define FUSE_MAKE_VERSION(maj, min)     ((maj) * 10 + (min)) | ||||
| #define FUSE_VERSION                    FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) | ||||
|  | ||||
| #define FUSE_CAP_ASYNC_READ             (1 << 0) | ||||
| #define FUSE_CAP_POSIX_LOCKS            (1 << 1) | ||||
| #define FUSE_CAP_ATOMIC_O_TRUNC         (1 << 3) | ||||
| #define FUSE_CAP_EXPORT_SUPPORT         (1 << 4) | ||||
| #define FUSE_CAP_DONT_MASK              (1 << 6) | ||||
| #define FUSE_CAP_SPLICE_WRITE           (1 << 7) | ||||
| #define FUSE_CAP_SPLICE_MOVE            (1 << 8) | ||||
| #define FUSE_CAP_SPLICE_READ            (1 << 9) | ||||
| #define FUSE_CAP_FLOCK_LOCKS            (1 << 10) | ||||
| #define FUSE_CAP_IOCTL_DIR              (1 << 11) | ||||
| #define FUSE_CAP_AUTO_INVAL_DATA        (1 << 12) | ||||
| #define FUSE_CAP_READDIRPLUS            (1 << 13) | ||||
| #define FUSE_CAP_READDIRPLUS_AUTO       (1 << 14) | ||||
| #define FUSE_CAP_ASYNC_DIO              (1 << 15) | ||||
| #define FUSE_CAP_WRITEBACK_CACHE        (1 << 16) | ||||
| #define FUSE_CAP_NO_OPEN_SUPPORT        (1 << 17) | ||||
| #define FUSE_CAP_PARALLEL_DIROPS        (1 << 18) | ||||
| #define FUSE_CAP_POSIX_ACL              (1 << 19) | ||||
| #define FUSE_CAP_HANDLE_KILLPRIV        (1 << 20) | ||||
| #define FUSE_CAP_ALLOCATE               (1 << 27)   /* reserved (OSXFUSE) */ | ||||
| #define FUSE_CAP_EXCHANGE_DATA          (1 << 28)   /* reserved (OSXFUSE) */ | ||||
| #define FUSE_CAP_CASE_INSENSITIVE       (1 << 29)   /* file system is case insensitive */ | ||||
| #define FUSE_CAP_VOL_RENAME             (1 << 30)   /* reserved (OSXFUSE) */ | ||||
| #define FUSE_CAP_XTIMES                 (1 << 31)   /* reserved (OSXFUSE) */ | ||||
|  | ||||
| #define FSP_FUSE_CAP_CASE_INSENSITIVE   FUSE_CAP_CASE_INSENSITIVE | ||||
|  | ||||
| #define FUSE_IOCTL_COMPAT               (1 << 0) | ||||
| #define FUSE_IOCTL_UNRESTRICTED         (1 << 1) | ||||
| #define FUSE_IOCTL_RETRY                (1 << 2) | ||||
| #define FUSE_IOCTL_DIR                  (1 << 4) | ||||
| #define FUSE_IOCTL_MAX_IOV              256 | ||||
|  | ||||
| #define FUSE_BUFVEC_INIT(s)             \ | ||||
|     ((struct fuse3_bufvec){ 1, 0, 0, { {s, (enum fuse3_buf_flags)0, 0, -1, 0} } }) | ||||
|  | ||||
| struct fuse3_file_info | ||||
| { | ||||
|     int flags; | ||||
|     unsigned int writepage:1; | ||||
|     unsigned int direct_io:1; | ||||
|     unsigned int keep_cache:1; | ||||
|     unsigned int flush:1; | ||||
|     unsigned int nonseekable:1; | ||||
|     unsigned int flock_release:1; | ||||
|     unsigned int padding:27; | ||||
|     uint64_t fh; | ||||
|     uint64_t lock_owner; | ||||
|     uint32_t poll_events; | ||||
| }; | ||||
|  | ||||
| struct fuse3_loop_config | ||||
| { | ||||
|     int clone_fd; | ||||
|     unsigned int max_idle_threads; | ||||
| }; | ||||
|  | ||||
| struct fuse3_conn_info | ||||
| { | ||||
|     unsigned proto_major; | ||||
|     unsigned proto_minor; | ||||
|     unsigned max_write; | ||||
|     unsigned max_read; | ||||
|     unsigned max_readahead; | ||||
|     unsigned capable; | ||||
|     unsigned want; | ||||
|     unsigned max_background; | ||||
|     unsigned congestion_threshold; | ||||
|     unsigned time_gran; | ||||
|     unsigned reserved[22]; | ||||
| }; | ||||
|  | ||||
| enum fuse3_buf_flags | ||||
| { | ||||
|     FUSE_BUF_IS_FD                      = (1 << 1), | ||||
|     FUSE_BUF_FD_SEEK                    = (1 << 2), | ||||
|     FUSE_BUF_FD_RETRY                   = (1 << 3), | ||||
| }; | ||||
|  | ||||
| enum fuse3_buf_copy_flags | ||||
| { | ||||
|     FUSE_BUF_NO_SPLICE                  = (1 << 1), | ||||
|     FUSE_BUF_FORCE_SPLICE               = (1 << 2), | ||||
|     FUSE_BUF_SPLICE_MOVE                = (1 << 3), | ||||
|     FUSE_BUF_SPLICE_NONBLOCK            = (1 << 4), | ||||
| }; | ||||
|  | ||||
| struct fuse3_buf | ||||
| { | ||||
|     size_t size; | ||||
|     enum fuse3_buf_flags flags; | ||||
|     void *mem; | ||||
|     int fd; | ||||
|     fuse_off_t pos; | ||||
| }; | ||||
|  | ||||
| struct fuse3_bufvec | ||||
| { | ||||
|     size_t count; | ||||
|     size_t idx; | ||||
|     size_t off; | ||||
|     struct fuse3_buf buf[1]; | ||||
| }; | ||||
|  | ||||
| struct fuse3_session; | ||||
| struct fuse3_pollhandle; | ||||
| struct fuse3_conn_info_opts; | ||||
|  | ||||
| FSP_FUSE_API struct fuse3_conn_info_opts *FSP_FUSE_API_NAME(fsp_fuse3_parse_conn_info_opts)( | ||||
|     struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args); | ||||
| FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse3_apply_conn_info_opts)(struct fsp_fuse_env *env, | ||||
|     struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn); | ||||
| FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse3_version)(struct fsp_fuse_env *env); | ||||
| FSP_FUSE_API const char *FSP_FUSE_API_NAME(fsp_fuse3_pkgversion)(struct fsp_fuse_env *env); | ||||
| FSP_FUSE_API int32_t FSP_FUSE_API_NAME(fsp_fuse_ntstatus_from_errno)(struct fsp_fuse_env *env, | ||||
|     int err); | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| struct fuse3_conn_info_opts* fuse3_parse_conn_info_opts( | ||||
|     struct fuse_args *args), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_parse_conn_info_opts) | ||||
|         (fsp_fuse_env(), args); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_apply_conn_info_opts( | ||||
|     struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn), | ||||
| { | ||||
|     FSP_FUSE_API_CALL(fsp_fuse3_apply_conn_info_opts) | ||||
|         (fsp_fuse_env(), opts, conn); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_version(void), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_version) | ||||
|         (fsp_fuse_env()); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| const char *fuse3_pkgversion(void), | ||||
| { | ||||
|     return FSP_FUSE_API_CALL(fsp_fuse3_pkgversion) | ||||
|         (fsp_fuse_env()); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_pollhandle_destroy(struct fuse3_pollhandle *ph), | ||||
| { | ||||
|     (void)ph; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| size_t fuse3_buf_size(const struct fuse3_bufvec *bufv), | ||||
| { | ||||
|     (void)bufv; | ||||
|     return 0; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| ssize_t fuse3_buf_copy(struct fuse3_bufvec *dst, struct fuse3_bufvec *src, | ||||
|     enum fuse3_buf_copy_flags flags), | ||||
| { | ||||
|     (void)dst; | ||||
|     (void)src; | ||||
|     (void)flags; | ||||
|     return 0; | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_daemonize(int foreground), | ||||
| { | ||||
|     return fsp_fuse_daemonize(foreground); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| int fuse3_set_signal_handlers(struct fuse3_session *se), | ||||
| { | ||||
|     return fsp_fuse_set_signal_handlers(se); | ||||
| }) | ||||
|  | ||||
| FSP_FUSE_SYM( | ||||
| void fuse3_remove_signal_handlers(struct fuse3_session *se), | ||||
| { | ||||
|     (void)se; | ||||
|     fsp_fuse_set_signal_handlers(0); | ||||
| }) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										19
									
								
								inc/fuse3/fuse_opt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								inc/fuse3/fuse_opt.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /** | ||||
|  * @file fuse3/fuse_opt.h | ||||
|  * WinFsp FUSE3 compatible API. | ||||
|  * | ||||
|  * @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 "../fuse/fuse_opt.h" | ||||
							
								
								
									
										78
									
								
								inc/fuse3/winfsp_fuse.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								inc/fuse3/winfsp_fuse.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| /** | ||||
|  * @file fuse3/winfsp_fuse.h | ||||
|  * WinFsp FUSE3 compatible API. | ||||
|  * | ||||
|  * @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. | ||||
|  */ | ||||
|  | ||||
| #ifndef FUSE3_WINFSP_FUSE_H_INCLUDED | ||||
| #define FUSE3_WINFSP_FUSE_H_INCLUDED | ||||
|  | ||||
| #include "../fuse/winfsp_fuse.h" | ||||
|  | ||||
| #if defined(_WIN64) || defined(_WIN32) | ||||
| typedef intptr_t ssize_t; | ||||
| #endif | ||||
|  | ||||
| #if !defined(WINFSP_DLL_INTERNAL) | ||||
| #define fuse3                           fuse | ||||
| #define fuse3_apply_conn_info_opts      fuse_apply_conn_info_opts | ||||
| #define fuse3_buf                       fuse_buf | ||||
| #define fuse3_buf_copy                  fuse_buf_copy | ||||
| #define fuse3_buf_copy_flags            fuse_buf_copy_flags | ||||
| #define fuse3_buf_flags                 fuse_buf_flags | ||||
| #define fuse3_buf_size                  fuse_buf_size | ||||
| #define fuse3_bufvec                    fuse_bufvec | ||||
| #define fuse3_clean_cache               fuse_clean_cache | ||||
| #define fuse3_config                    fuse_config | ||||
| #define fuse3_conn_info                 fuse_conn_info | ||||
| #define fuse3_conn_info_opts            fuse_conn_info_opts | ||||
| #define fuse3_context                   fuse_context | ||||
| #define fuse3_daemonize                 fuse_daemonize | ||||
| #define fuse3_destroy                   fuse_destroy | ||||
| #define fuse3_exit                      fuse_exit | ||||
| #define fuse3_file_info                 fuse_file_info | ||||
| #define fuse3_fill_dir_flags            fuse_fill_dir_flags | ||||
| #define fuse3_fill_dir_t                fuse_fill_dir_t | ||||
| #define fuse3_get_context               fuse_get_context | ||||
| #define fuse3_get_session               fuse_get_session | ||||
| #define fuse3_getgroups                 fuse_getgroups | ||||
| #define fuse3_interrupted               fuse_interrupted | ||||
| #define fuse3_invalidate_path           fuse_invalidate_path | ||||
| #define fuse3_lib_help                  fuse_lib_help | ||||
| #define fuse3_loop                      fuse_loop | ||||
| #define fuse3_loop_config               fuse_loop_config | ||||
| #define fuse3_loop_mt                   fuse_loop_mt | ||||
| #define fuse3_loop_mt_31                fuse_loop_mt_31 | ||||
| #define fuse3_main_real                 fuse_main_real | ||||
| #define fuse3_mount                     fuse_mount | ||||
| #define fuse3_new                       fuse_new | ||||
| #define fuse3_new_30                    fuse_new_30 | ||||
| #define fuse3_notify_poll               fuse_notify_poll | ||||
| #define fuse3_operations                fuse_operations | ||||
| #define fuse3_parse_conn_info_opts      fuse_parse_conn_info_opts | ||||
| #define fuse3_pkgversion                fuse_pkgversion | ||||
| #define fuse3_pollhandle                fuse_pollhandle | ||||
| #define fuse3_pollhandle_destroy        fuse_pollhandle_destroy | ||||
| #define fuse3_readdir_flags             fuse_readdir_flags | ||||
| #define fuse3_remove_signal_handlers    fuse_remove_signal_handlers | ||||
| #define fuse3_session                   fuse_session | ||||
| #define fuse3_set_signal_handlers       fuse_set_signal_handlers | ||||
| #define fuse3_start_cleanup_thread      fuse_start_cleanup_thread | ||||
| #define fuse3_stop_cleanup_thread       fuse_stop_cleanup_thread | ||||
| #define fuse3_unmount                   fuse_unmount | ||||
| #define fuse3_version                   fuse_version | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
| @@ -27,30 +27,7 @@ struct fuse_chan | ||||
| }; | ||||
|  | ||||
| #define FSP_FUSE_CORE_OPT(n, f, v)      { n, offsetof(struct fsp_fuse_core_opt_data, f), v } | ||||
|  | ||||
| struct fsp_fuse_core_opt_data | ||||
| { | ||||
|     struct fsp_fuse_env *env; | ||||
|     int help, debug; | ||||
|     HANDLE DebugLogHandle; | ||||
|     int set_umask, umask, | ||||
|         set_create_umask, create_umask, | ||||
|         set_uid, uid, | ||||
|         set_gid, gid, | ||||
|         set_attr_timeout, attr_timeout, | ||||
|         rellinks; | ||||
|     int set_FileInfoTimeout, | ||||
|         set_DirInfoTimeout, | ||||
|         set_VolumeInfoTimeout, | ||||
|         set_KeepFileCache; | ||||
|     unsigned ThreadCount; | ||||
|     FSP_FSCTL_VOLUME_PARAMS VolumeParams; | ||||
|     UINT16 VolumeLabelLength; | ||||
|     WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)]; | ||||
| }; | ||||
| FSP_FSCTL_STATIC_ASSERT( | ||||
|     sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel, | ||||
|     "fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same."); | ||||
| #define FSP_FUSE_CORE_OPT_NOHELP_IDX    4 | ||||
|  | ||||
| static struct fuse_opt fsp_fuse_core_opts[] = | ||||
| { | ||||
| @@ -122,35 +99,6 @@ static struct fuse_opt fsp_fuse_core_opts[] = | ||||
| static INIT_ONCE fsp_fuse_initonce = INIT_ONCE_STATIC_INIT; | ||||
| static DWORD fsp_fuse_tlskey = TLS_OUT_OF_INDEXES; | ||||
|  | ||||
| struct fsp_fuse_obj_hdr | ||||
| { | ||||
|     void (*dtor)(void *); | ||||
|     __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[]; | ||||
| }; | ||||
|  | ||||
| static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size) | ||||
| { | ||||
|     struct fsp_fuse_obj_hdr *hdr; | ||||
|  | ||||
|     hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size); | ||||
|     if (0 == hdr) | ||||
|         return 0; | ||||
|  | ||||
|     hdr->dtor = env->memfree; | ||||
|     memset(hdr->ObjectBuf, 0, size); | ||||
|     return hdr->ObjectBuf; | ||||
| } | ||||
|  | ||||
| static inline void fsp_fuse_obj_free(void *obj) | ||||
| { | ||||
|     if (0 == obj) | ||||
|         return; | ||||
|  | ||||
|     struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr)); | ||||
|  | ||||
|     hdr->dtor(hdr); | ||||
| } | ||||
|  | ||||
| static BOOL WINAPI fsp_fuse_initialize( | ||||
|     PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) | ||||
| { | ||||
| @@ -383,7 +331,7 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) | ||||
|  | ||||
|         /* this should always fail with ENOSYS or EINVAL */ | ||||
|         err = f->ops.readlink("/", buf, sizeof buf); | ||||
|         f->has_symlinks = -ENOSYS != err; | ||||
|         f->has_symlinks = -ENOSYS_(f->env) != err; | ||||
|     } | ||||
|  | ||||
|     /* the FSD does not currently limit these VolumeParams fields; do so here! */ | ||||
| @@ -575,6 +523,18 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key, | ||||
|     } | ||||
| } | ||||
|  | ||||
| int fsp_fuse_core_opt_parse(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, struct fsp_fuse_core_opt_data *opt_data, | ||||
|     int help) | ||||
| { | ||||
|     if (help) | ||||
|         return fsp_fuse_opt_parse(env, args, opt_data, | ||||
|             fsp_fuse_core_opts, fsp_fuse_core_opt_proc); | ||||
|     else | ||||
|         return fsp_fuse_opt_parse(env, args, opt_data, | ||||
|             fsp_fuse_core_opts + FSP_FUSE_CORE_OPT_NOHELP_IDX, fsp_fuse_core_opt_proc); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, | ||||
|     struct fuse_chan *ch, struct fuse_args *args, | ||||
|     const struct fuse_operations *ops, size_t opsize, void *data) | ||||
| @@ -595,7 +555,7 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, | ||||
|     opt_data.VolumeParams.FileInfoTimeout = 1000; | ||||
|     opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE; | ||||
|  | ||||
|     if (-1 == fsp_fuse_opt_parse(env, args, &opt_data, fsp_fuse_core_opts, fsp_fuse_core_opt_proc)) | ||||
|     if (-1 == fsp_fuse_core_opt_parse(env, args, &opt_data, /*help=*/1)) | ||||
|         return 0; | ||||
|     if (opt_data.help) | ||||
|         return 0; | ||||
| @@ -788,6 +748,11 @@ FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env) | ||||
|     return context; | ||||
| } | ||||
|  | ||||
| struct fuse_context *fsp_fuse_get_context_internal(void) | ||||
| { | ||||
|     return TlsGetValue(fsp_fuse_tlskey); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env, | ||||
|     int err) | ||||
| { | ||||
|   | ||||
| @@ -266,7 +266,7 @@ loopend:; | ||||
|         if (0 != f->ops.getattr) | ||||
|             err = f->ops.getattr(PosixHiddenPath, (void *)&stbuf); | ||||
|         else | ||||
|             err = -ENOSYS; | ||||
|             err = -ENOSYS_(f->env); | ||||
|     } while (0 == err && 0 < --maxtries); | ||||
|  | ||||
|     if (0 == err) | ||||
| @@ -308,7 +308,7 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem, | ||||
|         if (0 != f->ops.getattr) | ||||
|             err = f->ops.getattr(PosixDotPath, (void *)&stbuf); | ||||
|         else | ||||
|             err = -ENOSYS; | ||||
|             err = -ENOSYS_(f->env); | ||||
|  | ||||
|         MemFree(PosixDotPath); | ||||
|  | ||||
| @@ -1427,7 +1427,8 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem, | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name, | ||||
| /* !static: used by fuse2to3 */ | ||||
| int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off) | ||||
| { | ||||
|     struct fuse_dirhandle *dh = buf; | ||||
| @@ -1617,7 +1618,8 @@ exit: | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name, | ||||
| /* !static: used by fuse2to3 */ | ||||
| int fsp_fuse_intf_AddDirInfo(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off) | ||||
| { | ||||
|     struct fuse_dirhandle *dh = buf; | ||||
|   | ||||
| @@ -25,12 +25,14 @@ | ||||
| #define FSP_FUSE_LIBRARY_NAME           LIBRARY_NAME "-FUSE" | ||||
|  | ||||
| #define FSP_FUSE_HDR_FROM_CONTEXT(c)    \ | ||||
|     (struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header)) | ||||
|     ((struct fsp_fuse_context_header *)((PUINT8)(c) - sizeof(struct fsp_fuse_context_header))) | ||||
| #define FSP_FUSE_CONTEXT_FROM_HDR(h)    \ | ||||
|     (struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header)) | ||||
|     ((struct fuse_context *)((PUINT8)(h) + sizeof(struct fsp_fuse_context_header))) | ||||
|  | ||||
| #define FSP_FUSE_HAS_SYMLINKS(f)        ((f)->has_symlinks) | ||||
|  | ||||
| #define ENOSYS_(env)                    ('C' == (env)->environment ? 88 : 40) | ||||
|  | ||||
| struct fuse | ||||
| { | ||||
|     struct fsp_fuse_env *env; | ||||
| @@ -54,6 +56,7 @@ struct fuse | ||||
|     FSP_FILE_SYSTEM *FileSystem; | ||||
|     FSP_SERVICE *Service; /* weak */ | ||||
|     volatile int exited; | ||||
|     struct fuse3 *fuse3; | ||||
| }; | ||||
|  | ||||
| struct fsp_fuse_context_header | ||||
| @@ -87,6 +90,11 @@ NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem, | ||||
| NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); | ||||
|  | ||||
| int fsp_fuse_intf_CanDeleteAddDirInfo(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off); | ||||
| int fsp_fuse_intf_AddDirInfo(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off); | ||||
|  | ||||
| extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf; | ||||
|  | ||||
| NTSTATUS fsp_fuse_get_token_uidgid( | ||||
| @@ -102,4 +110,65 @@ NTSTATUS fsp_fuse_get_token_uidgid( | ||||
| #define NFS_SPECFILE_LNK                0x00000000014b4e4c | ||||
| #define NFS_SPECFILE_SOCK               0x000000004B434F53 | ||||
|  | ||||
| /* FUSE obj alloc/free */ | ||||
|  | ||||
| struct fsp_fuse_obj_hdr | ||||
| { | ||||
|     void (*dtor)(void *); | ||||
|     __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ObjectBuf[]; | ||||
| }; | ||||
|  | ||||
| static inline void *fsp_fuse_obj_alloc(struct fsp_fuse_env *env, size_t size) | ||||
| { | ||||
|     struct fsp_fuse_obj_hdr *hdr; | ||||
|  | ||||
|     hdr = env->memalloc(sizeof(struct fsp_fuse_obj_hdr) + size); | ||||
|     if (0 == hdr) | ||||
|         return 0; | ||||
|  | ||||
|     hdr->dtor = env->memfree; | ||||
|     memset(hdr->ObjectBuf, 0, size); | ||||
|     return hdr->ObjectBuf; | ||||
| } | ||||
|  | ||||
| static inline void fsp_fuse_obj_free(void *obj) | ||||
| { | ||||
|     if (0 == obj) | ||||
|         return; | ||||
|  | ||||
|     struct fsp_fuse_obj_hdr *hdr = (PVOID)((PUINT8)obj - sizeof(struct fsp_fuse_obj_hdr)); | ||||
|  | ||||
|     hdr->dtor(hdr); | ||||
| } | ||||
|  | ||||
| struct fuse_context *fsp_fuse_get_context_internal(void); | ||||
|  | ||||
| struct fsp_fuse_core_opt_data | ||||
| { | ||||
|     struct fsp_fuse_env *env; | ||||
|     int help, debug; | ||||
|     HANDLE DebugLogHandle; | ||||
|     int set_umask, umask, | ||||
|         set_create_umask, create_umask, | ||||
|         set_uid, uid, | ||||
|         set_gid, gid, | ||||
|         set_attr_timeout, attr_timeout, | ||||
|         rellinks; | ||||
|     int set_FileInfoTimeout, | ||||
|         set_DirInfoTimeout, | ||||
|         set_VolumeInfoTimeout, | ||||
|         set_KeepFileCache; | ||||
|     unsigned ThreadCount; | ||||
|     FSP_FSCTL_VOLUME_PARAMS VolumeParams; | ||||
|     UINT16 VolumeLabelLength; | ||||
|     WCHAR VolumeLabel[sizeof ((FSP_FSCTL_VOLUME_INFO *)0)->VolumeLabel / sizeof(WCHAR)]; | ||||
| }; | ||||
| FSP_FSCTL_STATIC_ASSERT( | ||||
|     sizeof ((struct fuse *)0)->VolumeLabel == sizeof ((struct fsp_fuse_core_opt_data *)0)->VolumeLabel, | ||||
|     "fuse::VolumeLabel and fsp_fuse_core_opt_data::VolumeLabel: sizeof must be same."); | ||||
|  | ||||
| int fsp_fuse_core_opt_parse(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, struct fsp_fuse_core_opt_data *opt_data, | ||||
|     int help); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										656
									
								
								src/dll/fuse3/fuse2to3.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										656
									
								
								src/dll/fuse3/fuse2to3.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,656 @@ | ||||
| /** | ||||
|  * @file dll/fuse3/fuse2to3.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/fuse3/library.h> | ||||
|  | ||||
| static inline struct fuse3 *fuse2to3_getfuse3(void) | ||||
| { | ||||
|     return fsp_fuse_get_context_internal()->fuse->fuse3; | ||||
| } | ||||
|  | ||||
| static inline void fuse2to3_fi2from3(struct fuse_file_info *fi, struct fuse3_file_info *fi3) | ||||
| { | ||||
|     memset(fi, 0, sizeof *fi); | ||||
|     fi->flags = fi3->flags; | ||||
|     fi->writepage = fi3->writepage; | ||||
|     fi->direct_io = fi3->direct_io; | ||||
|     fi->keep_cache = fi3->keep_cache; | ||||
|     fi->flush = fi3->flush; | ||||
|     fi->nonseekable = fi3->nonseekable; | ||||
|     fi->fh = fi3->fh; | ||||
|     fi->lock_owner = fi3->lock_owner; | ||||
| } | ||||
|  | ||||
| static inline void fuse2to3_fi3from2(struct fuse3_file_info *fi3, struct fuse_file_info *fi) | ||||
| { | ||||
|     memset(fi3, 0, sizeof *fi3); | ||||
|     fi3->flags = fi->flags; | ||||
|     fi3->writepage = fi->writepage; | ||||
|     fi3->direct_io = fi->direct_io; | ||||
|     fi3->keep_cache = fi->keep_cache; | ||||
|     fi3->flush = fi->flush; | ||||
|     fi3->nonseekable = fi->nonseekable; | ||||
|     fi3->fh = fi->fh; | ||||
|     fi3->lock_owner = fi->lock_owner; | ||||
| } | ||||
|  | ||||
| static inline void fuse2to3_conn3from2(struct fuse3_conn_info *conn3, struct fuse_conn_info *conn) | ||||
| { | ||||
|     memset(conn3, 0, sizeof *conn3); | ||||
|     conn3->proto_major = 7;             /* pretend that we are FUSE kernel protocol 7.26 */ | ||||
|     conn3->proto_minor = 26;            /*     which was current at the time of FUSE 3.2 */ | ||||
|     conn3->max_write = conn->max_write; | ||||
|     conn3->max_read = conn->max_write; | ||||
|     conn3->max_readahead = conn->max_readahead; | ||||
|     conn3->capable = (conn->capable & ~FSP_FUSE_CAP_READDIR_PLUS) | FUSE_CAP_READDIRPLUS; | ||||
|     conn3->want = conn->want; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_getattr(const char *path, struct fuse_stat *stbuf) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.getattr(path, stbuf, 0); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_readlink(const char *path, char *buf, size_t size) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.readlink(path, buf, size); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_mknod(const char *path, fuse_mode_t mode, fuse_dev_t dev) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.mknod(path, mode, dev); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_mkdir(const char *path, fuse_mode_t mode) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.mkdir(path, mode); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_unlink(const char *path) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.unlink(path); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_rmdir(const char *path) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.rmdir(path); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_symlink(const char *dstpath, const char *srcpath) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.symlink(dstpath, srcpath); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_rename(const char *oldpath, const char *newpath) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.rename(oldpath, newpath, 0); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_link(const char *srcpath, const char *dstpath) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.link(srcpath, dstpath); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_chmod(const char *path, fuse_mode_t mode) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.chmod(path, mode, 0); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_chown(const char *path, fuse_uid_t uid, fuse_gid_t gid) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.chown(path, uid, gid, 0); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_truncate(const char *path, fuse_off_t size) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.truncate(path, size, 0); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_open(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.open(path, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_read(const char *path, char *buf, size_t size, fuse_off_t off, | ||||
|     struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.read(path, buf, size, off, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_write(const char *path, const char *buf, size_t size, fuse_off_t off, | ||||
|     struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.write(path, buf, size, off, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_statfs(const char *path, struct fuse_statvfs *stbuf) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.statfs(path, stbuf); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_flush(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.flush(path, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_release(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.release(path, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_fsync(const char *path, int datasync, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.fsync(path, datasync, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_setxattr(const char *path, const char *name, const char *value, size_t size, | ||||
|     int flags) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.setxattr(path, name, value, size, flags); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_getxattr(const char *path, const char *name, char *value, size_t size) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.getxattr(path, name, value, size); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_listxattr(const char *path, char *namebuf, size_t size) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.listxattr(path, namebuf, size); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_removexattr(const char *path, const char *name) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.removexattr(path, name); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_opendir(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.opendir(path, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_candel_filldir(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off, | ||||
|     enum fuse3_fill_dir_flags flags) | ||||
| { | ||||
|     return fsp_fuse_intf_CanDeleteAddDirInfo(buf, name, 0, off); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_filldir(void *buf, const char *name, | ||||
|     const struct fuse_stat *stbuf, fuse_off_t off, | ||||
|     enum fuse3_fill_dir_flags flags) | ||||
| { | ||||
|     return 0 != (flags & FUSE_FILL_DIR_PLUS) ? | ||||
|         fsp_fuse_intf_AddDirInfo(buf, name, stbuf, off) : | ||||
|         fsp_fuse_intf_AddDirInfo(buf, name, 0, off); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off, | ||||
|     struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse_dirhandle *dh = buf; | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res; | ||||
|     if (fsp_fuse_intf_CanDeleteAddDirInfo == filler) | ||||
|         res = f3->ops.readdir(path, buf, &fuse2to3_candel_filldir, off, &fi3, 0); | ||||
|     else if (fsp_fuse_intf_AddDirInfo == filler) | ||||
|         res = f3->ops.readdir(path, buf, &fuse2to3_filldir, off, &fi3, | ||||
|             dh->ReaddirPlus ? FUSE_READDIR_PLUS : 0); | ||||
|     else | ||||
|     { | ||||
|         FspDebugLog("fuse2to3_readdir = -ENOSYS (internal error: unknown filler)\n"); | ||||
|         res = -ENOSYS_(f3->fuse->env); | ||||
|     } | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_releasedir(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.releasedir(path, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_fsyncdir(const char *path, int datasync, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.fsyncdir(path, datasync, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static void *fuse2to3_init(struct fuse_conn_info *conn) | ||||
| { | ||||
|     struct fuse_context *context = fsp_fuse_get_context_internal(); | ||||
|     struct fuse *f = context->fuse; | ||||
|     struct fuse3 *f3 = f->fuse3; | ||||
|  | ||||
|     struct fuse3_conn_info conn3; | ||||
|     fuse2to3_conn3from2(&conn3, conn); | ||||
|  | ||||
|     struct fuse3_config conf3; | ||||
|     memset(&conf3, 0, sizeof conf3); | ||||
|     conf3.set_gid = f->set_gid; | ||||
|     conf3.gid = f->gid; | ||||
|     conf3.set_uid = f->set_uid; | ||||
|     conf3.uid = f->uid; | ||||
|     conf3.set_mode = f->set_umask; | ||||
|     conf3.umask = f->umask; | ||||
| #if 0 | ||||
|     /* | ||||
|      * Cannot set timeouts because of lack of floating point support. | ||||
|      * | ||||
|      * FUSE uses the `double` type for timeouts. This DLL does not use the standard library | ||||
|      * for a variety of reasons. This means that we cannot easily perform the computations | ||||
|      * below. | ||||
|      * | ||||
|      * If this becomes important (double) floating point values could perhaps be calculated | ||||
|      * using bit tricks. See below: | ||||
|      * - http://locklessinc.com/articles/i2f/ | ||||
|      * - https://stackoverflow.com/a/20308114 | ||||
|      */ | ||||
|     conf3.entry_timeout = f->VolumeParams.DirInfoTimeoutValid ? | ||||
|         f->VolumeParams.DirInfoTimeout / 1000 : f->VolumeParams.FileInfoTimeout / 1000; | ||||
|     conf3.negative_timeout = 0; | ||||
|     conf3.attr_timeout = f->VolumeParams.FileInfoTimeout / 1000; | ||||
|     conf3.ac_attr_timeout = conf3.attr_timeout; | ||||
| #endif | ||||
|  | ||||
|     void *res = f3->ops.init(&conn3, &conf3); | ||||
|  | ||||
|     conn->max_write = conn3.max_write; | ||||
|     conn->max_readahead = conn3.max_readahead; | ||||
|     conn->want = 0 != (conn3.want & FUSE_CAP_READDIRPLUS) ? FSP_FUSE_CAP_READDIR_PLUS : 0; | ||||
|     conn->want |= conn3.want & ~FUSE_CAP_READDIRPLUS; | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static void fuse2to3_destroy(void *data) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     f3->ops.destroy(data); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_access(const char *path, int mask) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.access(path, mask); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.create(path, mode, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_ftruncate(const char *path, fuse_off_t off, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.truncate(path, off, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_fgetattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.getattr(path, stbuf, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_lock(const char *path, | ||||
|     struct fuse_file_info *fi, int cmd, struct fuse_flock *lock) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.lock(path, &fi3, cmd, lock); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_utimens(const char *path, const struct fuse_timespec tv[2]) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.utimens(path, tv, 0); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_bmap(const char *path, size_t blocksize, uint64_t *idx) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     return f3->ops.bmap(path, blocksize, idx); | ||||
| } | ||||
|  | ||||
| static int fuse2to3_ioctl(const char *path, int cmd, void *arg, struct fuse_file_info *fi, | ||||
|     unsigned int flags, void *data) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.ioctl(path, cmd, arg, &fi3, flags, data); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_poll(const char *path, struct fuse_file_info *fi, | ||||
|     struct fuse_pollhandle *ph, unsigned *reventsp) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.poll(path, &fi3, (struct fuse3_pollhandle *)ph, reventsp); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_write_buf(const char *path, | ||||
|     struct fuse_bufvec *buf, fuse_off_t off, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.write_buf(path, | ||||
|         (struct fuse3_bufvec *)buf, /* revisit if we implement bufvec's */ | ||||
|         off, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_read_buf(const char *path, | ||||
|     struct fuse_bufvec **bufp, size_t size, fuse_off_t off, struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.read_buf(path, | ||||
|         (struct fuse3_bufvec **)bufp, /* revisit if we implement bufvec's */ | ||||
|         size, off, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_flock(const char *path, struct fuse_file_info *fi, int op) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.flock(path, &fi3, op); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fuse2to3_fallocate(const char *path, int mode, fuse_off_t off, fuse_off_t len, | ||||
|     struct fuse_file_info *fi) | ||||
| { | ||||
|     struct fuse3 *f3 = fuse2to3_getfuse3(); | ||||
|     struct fuse3_file_info fi3; | ||||
|     fuse2to3_fi3from2(&fi3, fi); | ||||
|     int res = f3->ops.fallocate(path, mode, off, len, &fi3); | ||||
|     fuse2to3_fi2from3(fi, &fi3); | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| static int fsp_fuse3_copy_args(struct fsp_fuse_env *env, | ||||
|     const struct fuse_args *args, | ||||
|     struct fuse_args *outargs) | ||||
| { | ||||
|     outargs->argc = 0; | ||||
|     outargs->argv = 0; | ||||
|     outargs->allocated = 0; | ||||
|  | ||||
|     for (int argi = 0; args->argc > argi; argi++) | ||||
|         if (-1 == fsp_fuse_opt_add_arg(env, outargs, args->argv[argi])) | ||||
|             goto fail; | ||||
|  | ||||
|     return 0; | ||||
|  | ||||
| fail: | ||||
|     fsp_fuse_opt_free_args(env, outargs); | ||||
|  | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static struct fuse3 *fsp_fuse3_new_common(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data, | ||||
|     int help) | ||||
| { | ||||
|     /* preflight args */ | ||||
|     struct fsp_fuse_core_opt_data opt_data; | ||||
|     struct fuse_args pfargs; | ||||
|     memset(&opt_data, 0, sizeof opt_data); | ||||
|     if (-1 == fsp_fuse3_copy_args(env, args, &pfargs)) | ||||
|         return 0; | ||||
|     int optres = fsp_fuse_core_opt_parse(env, &pfargs, &opt_data, /*help=*/1); | ||||
|     fsp_fuse_opt_free_args(env, &pfargs); | ||||
|     if (-1 == optres) | ||||
|         return 0; | ||||
|     if (opt_data.help) | ||||
|         return 0; | ||||
|  | ||||
|     struct fuse3 *f3 = 0; | ||||
|  | ||||
|     if (opsize > sizeof(struct fuse3_operations)) | ||||
|         opsize = sizeof(struct fuse3_operations); | ||||
|  | ||||
|     f3 = fsp_fuse_obj_alloc(env, sizeof *f3); | ||||
|     if (0 == f3) | ||||
|         goto fail; | ||||
|  | ||||
|     if (-1 == fsp_fuse3_copy_args(env, args, &f3->args)) | ||||
|         goto fail; | ||||
|     memcpy(&f3->ops, ops, opsize); | ||||
|     f3->data = data; | ||||
|  | ||||
|     return f3; | ||||
|  | ||||
| fail: | ||||
|     if (0 != f3) | ||||
|         fsp_fuse3_destroy(env, f3); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API struct fuse3 *fsp_fuse3_new_30(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data) | ||||
| { | ||||
|     return fsp_fuse3_new_common(env, args, ops, opsize, data, /*help=*/1); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API struct fuse3 *fsp_fuse3_new(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args, | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data) | ||||
| { | ||||
|     return fsp_fuse3_new_common(env, args, ops, opsize, data, /*help=*/0); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API void fsp_fuse3_destroy(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3) | ||||
| { | ||||
|     if (0 != f3->fuse) | ||||
|         fsp_fuse_destroy(env, f3->fuse); | ||||
|  | ||||
|     fsp_fuse_opt_free_args(env, &f3->args); | ||||
|  | ||||
|     fsp_fuse_obj_free(f3); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API int fsp_fuse3_mount(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3, const char *mountpoint) | ||||
| { | ||||
|     struct fuse_chan *ch = 0; | ||||
|     struct fuse *f = 0; | ||||
|     struct fuse_operations fuse2to3_ops = | ||||
|     { | ||||
|         .getattr = 0 != f3->ops.getattr ? fuse2to3_getattr : 0, | ||||
|         .readlink = 0 != f3->ops.readlink ? fuse2to3_readlink : 0, | ||||
|         .mknod = 0 != f3->ops.mknod ? fuse2to3_mknod : 0, | ||||
|         .mkdir = 0 != f3->ops.mkdir ? fuse2to3_mkdir : 0, | ||||
|         .unlink = 0 != f3->ops.unlink ? fuse2to3_unlink : 0, | ||||
|         .rmdir = 0 != f3->ops.rmdir ? fuse2to3_rmdir : 0, | ||||
|         .symlink = 0 != f3->ops.symlink ? fuse2to3_symlink : 0, | ||||
|         .rename = 0 != f3->ops.rename ? fuse2to3_rename : 0, | ||||
|         .link = 0 != f3->ops.link ? fuse2to3_link : 0, | ||||
|         .chmod = 0 != f3->ops.chmod ? fuse2to3_chmod : 0, | ||||
|         .chown = 0 != f3->ops.chown ? fuse2to3_chown : 0, | ||||
|         .truncate = 0 != f3->ops.truncate ? fuse2to3_truncate : 0, | ||||
|         .open = 0 != f3->ops.open ? fuse2to3_open : 0, | ||||
|         .read = 0 != f3->ops.read ? fuse2to3_read : 0, | ||||
|         .write = 0 != f3->ops.write ? fuse2to3_write : 0, | ||||
|         .statfs = 0 != f3->ops.statfs ? fuse2to3_statfs : 0, | ||||
|         .flush = 0 != f3->ops.flush ? fuse2to3_flush : 0, | ||||
|         .release = 0 != f3->ops.release ? fuse2to3_release : 0, | ||||
|         .fsync = 0 != f3->ops.fsync ? fuse2to3_fsync : 0, | ||||
|         .setxattr = 0 != f3->ops.setxattr ? fuse2to3_setxattr : 0, | ||||
|         .getxattr = 0 != f3->ops.getxattr ? fuse2to3_getxattr : 0, | ||||
|         .listxattr = 0 != f3->ops.listxattr ? fuse2to3_listxattr : 0, | ||||
|         .removexattr = 0 != f3->ops.removexattr ? fuse2to3_removexattr : 0, | ||||
|         .opendir = 0 != f3->ops.opendir ? fuse2to3_opendir : 0, | ||||
|         .readdir = 0 != f3->ops.readdir ? fuse2to3_readdir : 0, | ||||
|         .releasedir = 0 != f3->ops.releasedir ? fuse2to3_releasedir : 0, | ||||
|         .fsyncdir = 0 != f3->ops.fsyncdir ? fuse2to3_fsyncdir : 0, | ||||
|         .init = 0 != f3->ops.init ? fuse2to3_init : 0, | ||||
|         .destroy = 0 != f3->ops.destroy ? fuse2to3_destroy : 0, | ||||
|         .access = 0 != f3->ops.access ? fuse2to3_access : 0, | ||||
|         .create = 0 != f3->ops.create ? fuse2to3_create : 0, | ||||
|         .ftruncate = 0 != f3->ops.truncate ? fuse2to3_ftruncate : 0, | ||||
|         .fgetattr = 0 != f3->ops.getattr ? fuse2to3_fgetattr : 0, | ||||
|         .lock = 0 != f3->ops.lock ? fuse2to3_lock : 0, | ||||
|         .utimens = 0 != f3->ops.utimens ? fuse2to3_utimens : 0, | ||||
|         .bmap = 0 != f3->ops.bmap ? fuse2to3_bmap : 0, | ||||
|         .ioctl = 0 != f3->ops.ioctl ? fuse2to3_ioctl : 0, | ||||
|         .poll = 0 != f3->ops.poll ? fuse2to3_poll : 0, | ||||
|         .write_buf = 0 != f3->ops.write_buf ? fuse2to3_write_buf : 0, | ||||
|         .read_buf = 0 != f3->ops.read_buf ? fuse2to3_read_buf : 0, | ||||
|         .flock = 0 != f3->ops.flock ? fuse2to3_flock : 0, | ||||
|         .fallocate = 0 != f3->ops.fallocate ? fuse2to3_fallocate : 0, | ||||
|     }; | ||||
|  | ||||
|     ch = fsp_fuse_mount(env, mountpoint, &f3->args); | ||||
|     if (0 == ch) | ||||
|         goto fail; | ||||
|  | ||||
|     f = fsp_fuse_new(env, ch, &f3->args, &fuse2to3_ops, sizeof fuse2to3_ops, f3->data); | ||||
|     if (0 == f) | ||||
|         goto fail; | ||||
|  | ||||
|     /* | ||||
|      * Free the fuse_chan which is no longer needed. Note that this behavior is WinFsp-FUSE | ||||
|      * specific, because WinFsp-FUSE only allocates/frees fuse_chan memory during fuse_mount/ | ||||
|      * fuse_unmount and does not perform any actual mounting/unmounting. This would not work | ||||
|      * on a different FUSE implementation. | ||||
|      * | ||||
|      * (Store mountpoint and ch inside struct fuse3 so that they can be freed during fuse_destroy | ||||
|      * in that case.) | ||||
|      */ | ||||
|     fsp_fuse_unmount(env, mountpoint, ch); | ||||
|  | ||||
|     /* Free the args which are no longer needed. */ | ||||
|     fsp_fuse_opt_free_args(env, &f3->args); | ||||
|  | ||||
|     f->fuse3 = f3; | ||||
|     f3->fuse = f; | ||||
|  | ||||
|     return 0; | ||||
|  | ||||
| fail: | ||||
|     if (0 != f) | ||||
|         fsp_fuse_destroy(env, f); | ||||
|  | ||||
|     if (0 != ch) | ||||
|         fsp_fuse_unmount(env, mountpoint, ch); | ||||
|  | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API void fsp_fuse3_unmount(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3) | ||||
| { | ||||
|     fsp_fuse_destroy(env, f3->fuse); | ||||
|     f3->fuse = 0; | ||||
| } | ||||
							
								
								
									
										152
									
								
								src/dll/fuse3/fuse3.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								src/dll/fuse3/fuse3.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| /** | ||||
|  * @file dll/fuse3/fuse3.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/fuse3/library.h> | ||||
|  | ||||
| FSP_FUSE_API int fsp_fuse3_main_real(struct fsp_fuse_env *env, | ||||
|     int argc, char *argv[], | ||||
|     const struct fuse3_operations *ops, size_t opsize, void *data) | ||||
| { | ||||
|     struct fuse_args args = FUSE_ARGS_INIT(argc, argv); | ||||
|     char *mountpoint = 0; | ||||
|     int multithreaded = 0; | ||||
|     int foreground = 0; | ||||
|     struct fuse3 *f3 = 0; | ||||
|     int mounted = 0; | ||||
|     int signal_handlers = 0; | ||||
|     int result; | ||||
|  | ||||
|     result = fsp_fuse_parse_cmdline(env, &args, &mountpoint, &multithreaded, &foreground); | ||||
|     if (-1 == result) | ||||
|         goto exit; | ||||
|  | ||||
|     f3 = fsp_fuse3_new_30(env, &args, ops, opsize, data); | ||||
|     if (0 == f3) | ||||
|     { | ||||
|         result = -1; | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     result = fsp_fuse3_mount(env, f3, mountpoint); | ||||
|     if (-1 == result) | ||||
|         goto exit; | ||||
|     mounted = 1; | ||||
|  | ||||
|     result = env->daemonize(foreground); | ||||
|     if (-1 == result) | ||||
|         goto exit; | ||||
|  | ||||
|     result = env->set_signal_handlers(f3); | ||||
|     if (-1 == result) | ||||
|         goto exit; | ||||
|     signal_handlers = 1; | ||||
|  | ||||
|     result = multithreaded ? fsp_fuse3_loop_mt(env, f3, 0) : fsp_fuse3_loop(env, f3); | ||||
|  | ||||
| exit: | ||||
|     if (signal_handlers) | ||||
|         env->set_signal_handlers(0); | ||||
|  | ||||
|     if (mounted) | ||||
|         fsp_fuse3_unmount(env, f3); | ||||
|  | ||||
|     if (0 != f3) | ||||
|         fsp_fuse3_destroy(env, f3); | ||||
|  | ||||
|     env->memfree(mountpoint); | ||||
|  | ||||
|     fsp_fuse_opt_free_args(env, &args); | ||||
|  | ||||
|     /* main() style return: 0 success, 1 error */ | ||||
|     return !!result; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API void fsp_fuse3_lib_help(struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args) | ||||
| { | ||||
|     char *helpargv[] = | ||||
|     { | ||||
|         "UNKNOWN", | ||||
|         "-h", | ||||
|         0 | ||||
|     }; | ||||
|     struct fuse_args helpargs = FUSE_ARGS_INIT(2, helpargv); | ||||
|     struct fsp_fuse_core_opt_data opt_data; | ||||
|  | ||||
|     memset(&opt_data, 0, sizeof opt_data); | ||||
|     fsp_fuse_core_opt_parse(env, &helpargs, &opt_data, /*help=*/1); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API int fsp_fuse3_loop(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3) | ||||
| { | ||||
|     return 0 == fsp_fuse_loop(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API int fsp_fuse3_loop_mt_31(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3, int clone_fd) | ||||
| { | ||||
|     return 0 == fsp_fuse_loop_mt(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API int fsp_fuse3_loop_mt(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3, struct fuse3_loop_config *config) | ||||
| { | ||||
|     return 0 == fsp_fuse_loop_mt(env, f3->fuse) ? 0 : -EINVAL/* same on MSVC and Cygwin */; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API void fsp_fuse3_exit(struct fsp_fuse_env *env, | ||||
|     struct fuse3 *f3) | ||||
| { | ||||
|     fsp_fuse_exit(env, f3->fuse); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API struct fuse3_context *fsp_fuse3_get_context(struct fsp_fuse_env *env) | ||||
| { | ||||
|     FSP_FSCTL_STATIC_ASSERT( | ||||
|         sizeof(struct fuse_context) == sizeof(struct fuse3_context), | ||||
|         "incompatible structs fuse_context and fuse3_context"); | ||||
|     FSP_FSCTL_STATIC_ASSERT(FIELD_OFFSET( | ||||
|         struct fuse_context, private_data) == FIELD_OFFSET(struct fuse3_context, private_data), | ||||
|         "incompatible structs fuse_context and fuse3_context"); | ||||
|     return (struct fuse3_context *)fsp_fuse_get_context(env); | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API struct fuse3_conn_info_opts *fsp_fuse3_parse_conn_info_opts( | ||||
|     struct fsp_fuse_env *env, | ||||
|     struct fuse_args *args) | ||||
| { | ||||
|     static int dummy; | ||||
|     return (struct fuse3_conn_info_opts *)&dummy; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API void fsp_fuse3_apply_conn_info_opts(struct fsp_fuse_env *env, | ||||
|     struct fuse3_conn_info_opts *opts, struct fuse3_conn_info *conn) | ||||
| { | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API int fsp_fuse3_version(struct fsp_fuse_env *env) | ||||
| { | ||||
|     return FUSE_VERSION; | ||||
| } | ||||
|  | ||||
| FSP_FUSE_API const char *fsp_fuse3_pkgversion(struct fsp_fuse_env *env) | ||||
| { | ||||
| #define STR(x)                          #x | ||||
|     return STR(FUSE_MAJOR_VERSION) "." STR(FUSE_MINOR_VERSION); | ||||
| #undef STR | ||||
| } | ||||
							
								
								
									
										10
									
								
								src/dll/fuse3/fuse3.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/dll/fuse3/fuse3.pc.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| prefix=${pcfiledir}/.. | ||||
| incdir=${prefix}/inc/fuse3 | ||||
| implib=${prefix}/bin/winfsp-${arch}.dll | ||||
|  | ||||
| Name: fuse3 | ||||
| Description: WinFsp FUSE3 compatible API | ||||
| Version: 3.2 | ||||
| URL: http://www.secfs.net/winfsp/ | ||||
| Libs: "${implib}" | ||||
| Cflags: -I"${incdir}" | ||||
							
								
								
									
										37
									
								
								src/dll/fuse3/library.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/dll/fuse3/library.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /** | ||||
|  * @file dll/fuse3/library.h | ||||
|  * | ||||
|  * @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. | ||||
|  */ | ||||
|  | ||||
| #ifndef WINFSP_DLL_FUSE3_LIBRARY_H_INCLUDED | ||||
| #define WINFSP_DLL_FUSE3_LIBRARY_H_INCLUDED | ||||
|  | ||||
| #include <dll/fuse/library.h> | ||||
| #undef FUSE_H_ | ||||
| #undef FUSE_COMMON_H_ | ||||
| #undef FUSE_MAJOR_VERSION | ||||
| #undef FUSE_MINOR_VERSION | ||||
| #undef fuse_main | ||||
| #include <fuse3/fuse.h> | ||||
|  | ||||
| struct fuse3 | ||||
| { | ||||
|     struct fuse_args args; | ||||
|     struct fuse3_operations ops; | ||||
|     void *data; | ||||
|     struct fuse *fuse; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -83,6 +83,10 @@ set opt_tests=^ | ||||
|     sample-fsx-passthrough-fuse-x64 ^ | ||||
|     sample-passthrough-fuse-x86 ^ | ||||
|     sample-fsx-passthrough-fuse-x86 ^ | ||||
|     sample-passthrough-fuse3-x64 ^ | ||||
|     sample-fsx-passthrough-fuse3-x64 ^ | ||||
|     sample-passthrough-fuse3-x86 ^ | ||||
|     sample-fsx-passthrough-fuse3-x86 ^ | ||||
|     sample-passthrough-dotnet ^ | ||||
|     compat-v1.2-memfs-x64 ^ | ||||
|     compat-v1.2-memfs-x86 ^ | ||||
| @@ -707,6 +711,28 @@ call :__run_sample_fsx_fuse_test passthrough-fuse x86 passthrough-fuse-x86 fsx | ||||
| if !ERRORLEVEL! neq 0 goto fail | ||||
| exit /b 0 | ||||
|  | ||||
| :sample-passthrough-fuse3-x64 | ||||
| call :__run_sample_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 winfsp-tests-x64 ^ | ||||
|     "-create_fileattr_test -setfileinfo_test" | ||||
| if !ERRORLEVEL! neq 0 goto fail | ||||
| exit /b 0 | ||||
|  | ||||
| :sample-passthrough-fuse3-x86 | ||||
| call :__run_sample_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 winfsp-tests-x86 ^ | ||||
|     "-create_fileattr_test -setfileinfo_test" | ||||
| if !ERRORLEVEL! neq 0 goto fail | ||||
| exit /b 0 | ||||
|  | ||||
| :sample-fsx-passthrough-fuse3-x64 | ||||
| call :__run_sample_fsx_fuse_test passthrough-fuse3 x64 passthrough-fuse3-x64 fsx | ||||
| if !ERRORLEVEL! neq 0 goto fail | ||||
| exit /b 0 | ||||
|  | ||||
| :sample-fsx-passthrough-fuse3-x86 | ||||
| call :__run_sample_fsx_fuse_test passthrough-fuse3 x86 passthrough-fuse3-x86 fsx | ||||
| if !ERRORLEVEL! neq 0 goto fail | ||||
| exit /b 0 | ||||
|  | ||||
| :__run_sample_disk_test | ||||
| set RunSampleTestExit=0 | ||||
| call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1" | ||||
| @@ -783,11 +809,16 @@ net use | findstr L: | ||||
| pushd >nul | ||||
| cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail) | ||||
| L: | ||||
| "%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^ | ||||
|     --external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^ | ||||
|     -create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^ | ||||
|     -getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^ | ||||
|     -reparse* -stream* | ||||
| if X%5==XNOEXCL ( | ||||
|     "%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^ | ||||
|         --external --resilient | ||||
| ) else ( | ||||
|     "%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^ | ||||
|         --external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^ | ||||
|         -create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^ | ||||
|         -getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^ | ||||
|         -reparse* -stream* %~5 | ||||
| ) | ||||
| if !ERRORLEVEL! neq 0 set RunSampleTestExit=1 | ||||
| popd | ||||
| echo net use L: /delete | ||||
|   | ||||
							
								
								
									
										7
									
								
								tst/passthrough-fuse3/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								tst/passthrough-fuse3/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| build | ||||
| *.ncb | ||||
| *.suo | ||||
| *.vcproj.* | ||||
| *.vcxproj.user | ||||
| *.exe | ||||
| *.install | ||||
							
								
								
									
										18
									
								
								tst/passthrough-fuse3/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tst/passthrough-fuse3/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| usage: | ||||
| 	@echo "make cygfuse3|winfsp-fuse3" 1>&2 | ||||
| 	@echo "" 1>&2 | ||||
| 	@echo "   cygfuse3        Link with CYGFUSE3" 1>&2 | ||||
| 	@echo "   winfsp-fuse3    Link with WinFsp-FUSE3" 1>&2 | ||||
| 	@exit 2 | ||||
|  | ||||
| cygfuse3: passthrough-cygfuse3 | ||||
|  | ||||
| winfsp-fuse3: passthrough-winfsp-fuse3 | ||||
|  | ||||
| passthrough-cygfuse3: passthrough-fuse3.c | ||||
| 	gcc $^ -o $@ -g -Wall `pkg-config fuse3 --cflags --libs` | ||||
|  | ||||
| passthrough-winfsp-fuse3: export PKG_CONFIG_PATH=$(PWD)/winfsp.install/lib | ||||
| passthrough-winfsp-fuse3: passthrough-fuse3.c | ||||
| 	ln -nsf "`regtool --wow32 get '/HKLM/Software/WinFsp/InstallDir' | cygpath -au -f -`" winfsp.install | ||||
| 	gcc $^ -o $@ -g -Wall `pkg-config fuse3 --cflags --libs` | ||||
							
								
								
									
										7
									
								
								tst/passthrough-fuse3/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								tst/passthrough-fuse3/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| `Passthrough-fuse3` is a simple FUSE3 file system that passes all file system operations to an underlying file system. | ||||
|  | ||||
| It can be built with the following tools: | ||||
|  | ||||
| - Using Visual Studio (`winfsp.sln`). | ||||
| - Using Cygwin GCC and linking directly with the WinFsp DLL (`make winfsp-fuse3`). | ||||
| - Using Cygwin GCC and linking to CYGFUSE3 (`make cygfuse3`). | ||||
							
								
								
									
										331
									
								
								tst/passthrough-fuse3/passthrough-fuse3.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								tst/passthrough-fuse3/passthrough-fuse3.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,331 @@ | ||||
| /** | ||||
|  * @file passthrough-fuse.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 <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <limits.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <fuse.h> | ||||
|  | ||||
| #if defined(_WIN64) || defined(_WIN32) | ||||
| #include "winposix.h" | ||||
| #else | ||||
| #include <dirent.h> | ||||
| #include <unistd.h> | ||||
| #endif | ||||
|  | ||||
| #define FSNAME                          "passthrough" | ||||
| #define PROGNAME                        "passthrough-fuse" | ||||
|  | ||||
| #define concat_path(ptfs, fn, fp)       (sizeof fp > (unsigned)snprintf(fp, sizeof fp, "%s%s", ptfs->rootdir, fn)) | ||||
|  | ||||
| #define fi_dirbit                       (0x8000000000000000ULL) | ||||
| #define fi_fh(fi, MASK)                 ((fi)->fh & (MASK)) | ||||
| #define fi_setfh(fi, FH, MASK)          ((fi)->fh = (intptr_t)(FH) | (MASK)) | ||||
| #define fi_fd(fi)                       (fi_fh(fi, fi_dirbit) ? \ | ||||
|     dirfd((DIR *)(intptr_t)fi_fh(fi, ~fi_dirbit)) : (int)fi_fh(fi, ~fi_dirbit)) | ||||
| #define fi_dirp(fi)                     ((DIR *)(intptr_t)fi_fh(fi, ~fi_dirbit)) | ||||
| #define fi_setfd(fi, fd)                (fi_setfh(fi, fd, 0)) | ||||
| #define fi_setdirp(fi, dirp)            (fi_setfh(fi, dirp, fi_dirbit)) | ||||
|  | ||||
| #define ptfs_impl_fullpath(n)           \ | ||||
|     char full ## n[PATH_MAX];           \ | ||||
|     if (!concat_path(((PTFS *)fuse_get_context()->private_data), n, full ## n))\ | ||||
|         return -ENAMETOOLONG;           \ | ||||
|     n = full ## n | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|     const char *rootdir; | ||||
| } PTFS; | ||||
|  | ||||
| static int ptfs_getattr(const char *path, struct fuse_stat *stbuf, struct fuse_file_info *fi) | ||||
| { | ||||
|     if (0 == fi) | ||||
|     { | ||||
|         ptfs_impl_fullpath(path); | ||||
|  | ||||
|         return -1 != lstat(path, stbuf) ? 0 : -errno; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         int fd = fi_fd(fi); | ||||
|  | ||||
|         return -1 != fstat(fd, stbuf) ? 0 : -errno; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int ptfs_mkdir(const char *path, fuse_mode_t mode) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != mkdir(path, mode) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_unlink(const char *path) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != unlink(path) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_rmdir(const char *path) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != rmdir(path) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_rename(const char *oldpath, const char *newpath, unsigned int flags) | ||||
| { | ||||
|     ptfs_impl_fullpath(newpath); | ||||
|     ptfs_impl_fullpath(oldpath); | ||||
|  | ||||
|     return -1 != rename(oldpath, newpath) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_chmod(const char *path, fuse_mode_t mode, struct fuse_file_info *fi) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != chmod(path, mode) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_chown(const char *path, fuse_uid_t uid, fuse_gid_t gid, struct fuse_file_info *fi) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != lchown(path, uid, gid) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_truncate(const char *path, fuse_off_t size, struct fuse_file_info *fi) | ||||
| { | ||||
|     if (0 == fi) | ||||
|     { | ||||
|         ptfs_impl_fullpath(path); | ||||
|  | ||||
|         return -1 != truncate(path, size) ? 0 : -errno; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         int fd = fi_fd(fi); | ||||
|  | ||||
|         return -1 != ftruncate(fd, size) ? 0 : -errno; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int ptfs_open(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     int fd; | ||||
|     return -1 != (fd = open(path, fi->flags)) ? (fi_setfd(fi, fd), 0) : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_read(const char *path, char *buf, size_t size, fuse_off_t off, | ||||
|     struct fuse_file_info *fi) | ||||
| { | ||||
|     int fd = fi_fd(fi); | ||||
|  | ||||
|     int nb; | ||||
|     return -1 != (nb = pread(fd, buf, size, off)) ? nb : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_write(const char *path, const char *buf, size_t size, fuse_off_t off, | ||||
|     struct fuse_file_info *fi) | ||||
| { | ||||
|     int fd = fi_fd(fi); | ||||
|  | ||||
|     int nb; | ||||
|     return -1 != (nb = pwrite(fd, buf, size, off)) ? nb : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_statfs(const char *path, struct fuse_statvfs *stbuf) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != statvfs(path, stbuf) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_release(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     int fd = fi_fd(fi); | ||||
|  | ||||
|     close(fd); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int ptfs_fsync(const char *path, int datasync, struct fuse_file_info *fi) | ||||
| { | ||||
|     int fd = fi_fd(fi); | ||||
|  | ||||
|     return -1 != fsync(fd) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_opendir(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     DIR *dirp; | ||||
|     return 0 != (dirp = opendir(path)) ? (fi_setdirp(fi, dirp), 0) : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off, | ||||
|     struct fuse_file_info *fi, enum fuse_readdir_flags flags) | ||||
| { | ||||
|     DIR *dirp = fi_dirp(fi); | ||||
|     struct dirent *de; | ||||
|  | ||||
|     rewinddir(dirp); | ||||
|     for (;;) | ||||
|     { | ||||
|         errno = 0; | ||||
|         if (0 == (de = readdir(dirp))) | ||||
|             break; | ||||
| #if defined(_WIN64) || defined(_WIN32) | ||||
|         if (0 != filler(buf, de->d_name, &de->d_stat, 0, FUSE_FILL_DIR_PLUS)) | ||||
| #else | ||||
|         if (0 != filler(buf, de->d_name, 0, 0, 0)) | ||||
| #endif | ||||
|             return -ENOMEM; | ||||
|     } | ||||
|  | ||||
|     return -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_releasedir(const char *path, struct fuse_file_info *fi) | ||||
| { | ||||
|     DIR *dirp = fi_dirp(fi); | ||||
|  | ||||
|     return -1 != closedir(dirp) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static void *ptfs_init(struct fuse_conn_info *conn, struct fuse_config *conf) | ||||
| { | ||||
|     conn->want |= (conn->capable & FUSE_CAP_READDIRPLUS); | ||||
|  | ||||
| #if defined(FSP_FUSE_CAP_CASE_INSENSITIVE) | ||||
|     conn->want |= (conn->capable & FSP_FUSE_CAP_CASE_INSENSITIVE); | ||||
| #endif | ||||
|  | ||||
|     return fuse_get_context()->private_data; | ||||
| } | ||||
|  | ||||
| static int ptfs_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     int fd; | ||||
|     return -1 != (fd = open(path, fi->flags, mode)) ? (fi_setfd(fi, fd), 0) : -errno; | ||||
| } | ||||
|  | ||||
| static int ptfs_utimens(const char *path, const struct fuse_timespec tv[2], struct fuse_file_info *fi) | ||||
| { | ||||
|     ptfs_impl_fullpath(path); | ||||
|  | ||||
|     return -1 != utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW) ? 0 : -errno; | ||||
| } | ||||
|  | ||||
| static struct fuse_operations ptfs_ops = | ||||
| { | ||||
|     .getattr = ptfs_getattr, | ||||
|     .mkdir = ptfs_mkdir, | ||||
|     .unlink = ptfs_unlink, | ||||
|     .rmdir = ptfs_rmdir, | ||||
|     .rename = ptfs_rename, | ||||
|     .chmod = ptfs_chmod, | ||||
|     .chown = ptfs_chown, | ||||
|     .truncate = ptfs_truncate, | ||||
|     .open = ptfs_open, | ||||
|     .read = ptfs_read, | ||||
|     .write = ptfs_write, | ||||
|     .statfs = ptfs_statfs, | ||||
|     .release = ptfs_release, | ||||
|     .fsync = ptfs_fsync, | ||||
|     .opendir = ptfs_opendir, | ||||
|     .readdir = ptfs_readdir, | ||||
|     .releasedir = ptfs_releasedir, | ||||
|     .init = ptfs_init, | ||||
|     .create = ptfs_create, | ||||
|     .utimens = ptfs_utimens, | ||||
| }; | ||||
|  | ||||
| static void usage(void) | ||||
| { | ||||
|     fprintf(stderr, "usage: " PROGNAME " [FUSE options] rootdir mountpoint\n"); | ||||
|     exit(2); | ||||
| } | ||||
|  | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|     PTFS ptfs = { 0 }; | ||||
|  | ||||
|     if (3 <= argc && '-' != argv[argc - 2][0] && '-' != argv[argc - 1][0]) | ||||
|     { | ||||
|         ptfs.rootdir = realpath(argv[argc - 2], 0); /* memory freed at process end */ | ||||
|         argv[argc - 2] = argv[argc - 1]; | ||||
|         argc--; | ||||
|     } | ||||
|  | ||||
| #if defined(_WIN64) || defined(_WIN32) | ||||
|     /* | ||||
|      * When building for Windows (rather than Cygwin or POSIX OS) | ||||
|      * allow the path to be specified using the --VolumePrefix | ||||
|      * switch using the syntax \\passthrough-fuse\C$\Path. This | ||||
|      * allows us to run the file system under the WinFsp.Launcher | ||||
|      * and start it using commands like: | ||||
|      * | ||||
|      *     net use z: \\passthrough-fuse\C$\Path | ||||
|      */ | ||||
|     if (0 == ptfs.rootdir) | ||||
|         for (int argi = 1; argc > argi; argi++) | ||||
|         { | ||||
|             int strncmp(const char *a, const char *b, size_t length); | ||||
|             char *strchr(const char *s, int c); | ||||
|             char *p = 0; | ||||
|  | ||||
|             if (0 == strncmp("--UNC=", argv[argi], sizeof "--UNC=" - 1)) | ||||
|                 p = argv[argi] + sizeof "--UNC=" - 1; | ||||
|             else if (0 == strncmp("--VolumePrefix=", argv[argi], sizeof "--VolumePrefix=" - 1)) | ||||
|                 p = argv[argi] + sizeof "--VolumePrefix=" - 1; | ||||
|  | ||||
|             if (0 != p && '\\' != p[1]) | ||||
|             { | ||||
|                 p = strchr(p + 1, '\\'); | ||||
|                 if (0 != p && | ||||
|                     ( | ||||
|                     ('A' <= p[1] && p[1] <= 'Z') || | ||||
|                     ('a' <= p[1] && p[1] <= 'z') | ||||
|                     ) && | ||||
|                     '$' == p[2]) | ||||
|                 { | ||||
|                     p[2] = ':'; | ||||
|                     ptfs.rootdir = realpath(p + 1, 0); /* memory freed at process end */ | ||||
|                     p[2] = '$'; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|     if (0 == ptfs.rootdir) | ||||
|         usage(); | ||||
|  | ||||
|     return fuse_main(argc, argv, &ptfs_ops, &ptfs); | ||||
| } | ||||
							
								
								
									
										28
									
								
								tst/passthrough-fuse3/passthrough-fuse3.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tst/passthrough-fuse3/passthrough-fuse3.sln
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
|  | ||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
| # Visual Studio 14 | ||||
| VisualStudioVersion = 14.0.25420.1 | ||||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "passthrough-fuse3", "passthrough-fuse3.vcxproj", "{5E99498C-D30C-48EF-A04A-7977C0305FAC}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|x64 = Debug|x64 | ||||
| 		Debug|x86 = Debug|x86 | ||||
| 		Release|x64 = Release|x64 | ||||
| 		Release|x86 = Release|x86 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x64.ActiveCfg = Debug|x64 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x64.Build.0 = Debug|x64 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x86.ActiveCfg = Debug|Win32 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Debug|x86.Build.0 = Debug|Win32 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x64.ActiveCfg = Release|x64 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x64.Build.0 = Release|x64 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x86.ActiveCfg = Release|Win32 | ||||
| 		{5E99498C-D30C-48EF-A04A-7977C0305FAC}.Release|x86.Build.0 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
							
								
								
									
										190
									
								
								tst/passthrough-fuse3/passthrough-fuse3.vcxproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								tst/passthrough-fuse3/passthrough-fuse3.vcxproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup Label="ProjectConfigurations"> | ||||
|     <ProjectConfiguration Include="Debug|Win32"> | ||||
|       <Configuration>Debug</Configuration> | ||||
|       <Platform>Win32</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Release|Win32"> | ||||
|       <Configuration>Release</Configuration> | ||||
|       <Platform>Win32</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Debug|x64"> | ||||
|       <Configuration>Debug</Configuration> | ||||
|       <Platform>x64</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Release|x64"> | ||||
|       <Configuration>Release</Configuration> | ||||
|       <Platform>x64</Platform> | ||||
|     </ProjectConfiguration> | ||||
|   </ItemGroup> | ||||
|   <PropertyGroup Label="Globals"> | ||||
|     <ProjectGuid>{5E99498C-D30C-48EF-A04A-7977C0305FAC}</ProjectGuid> | ||||
|     <Keyword>Win32Proj</Keyword> | ||||
|     <RootNamespace>passthroughfuse3</RootNamespace> | ||||
|     <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||||
|   <ImportGroup Label="ExtensionSettings"> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="Shared"> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <PropertyGroup Label="UserMacros" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <LinkIncremental>true</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|     <LinkIncremental>true</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <LinkIncremental>false</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||||
|     <LinkIncremental>false</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <ClCompile> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <Optimization>Disabled</Optimization> | ||||
|       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories> | ||||
|       <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | ||||
|       <DisableSpecificWarnings>4996</DisableSpecificWarnings> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|     <ClCompile> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <Optimization>Disabled</Optimization> | ||||
|       <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories> | ||||
|       <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | ||||
|       <DisableSpecificWarnings>4996</DisableSpecificWarnings> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <ClCompile> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <Optimization>MaxSpeed</Optimization> | ||||
|       <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
|       <IntrinsicFunctions>true</IntrinsicFunctions> | ||||
|       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories> | ||||
|       <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | ||||
|       <DisableSpecificWarnings>4996</DisableSpecificWarnings> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||||
|     <ClCompile> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <Optimization>MaxSpeed</Optimization> | ||||
|       <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
|       <IntrinsicFunctions>true</IntrinsicFunctions> | ||||
|       <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc\fuse3;$(MSBuildProgramFiles32)\WinFsp\inc</AdditionalIncludeDirectories> | ||||
|       <RuntimeLibrary>MultiThreaded</RuntimeLibrary> | ||||
|       <DisableSpecificWarnings>4996</DisableSpecificWarnings> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="passthrough-fuse3.c" /> | ||||
|     <ClCompile Include="winposix.c" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="winposix.h" /> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
|   <ImportGroup Label="ExtensionTargets"> | ||||
|   </ImportGroup> | ||||
| </Project> | ||||
							
								
								
									
										21
									
								
								tst/passthrough-fuse3/passthrough-fuse3.vcxproj.filters
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tst/passthrough-fuse3/passthrough-fuse3.vcxproj.filters
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="Source"> | ||||
|       <UniqueIdentifier>{bfbcc136-ea14-4445-8f9b-1fa7f8aedc71}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="passthrough-fuse3.c"> | ||||
|       <Filter>Source</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="winposix.c"> | ||||
|       <Filter>Source</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="winposix.h"> | ||||
|       <Filter>Source</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
							
								
								
									
										634
									
								
								tst/passthrough-fuse3/winposix.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										634
									
								
								tst/passthrough-fuse3/winposix.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,634 @@ | ||||
| /** | ||||
|  * @file winposix.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. | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This is a very simple Windows POSIX layer. It handles all the POSIX | ||||
|  * file API's required to implement passthrough-fuse in POSIX, however | ||||
|  * the API handling is rather unsophisticated. | ||||
|  * | ||||
|  * Ways to improve it: use the FspPosix* API's to properly handle | ||||
|  * file names and security. | ||||
|  */ | ||||
|  | ||||
| #include <winfsp/winfsp.h> | ||||
| #include <fcntl.h> | ||||
| #include <fuse.h> | ||||
| #include "winposix.h" | ||||
|  | ||||
| struct _DIR | ||||
| { | ||||
|     HANDLE h, fh; | ||||
|     struct dirent de; | ||||
|     char path[]; | ||||
| }; | ||||
|  | ||||
| #if defined(FSP_FUSE_USE_STAT_EX) | ||||
| static inline uint32_t MapFileAttributesToFlags(UINT32 FileAttributes) | ||||
| { | ||||
|     uint32_t flags = 0; | ||||
|  | ||||
|     if (FileAttributes & FILE_ATTRIBUTE_READONLY) | ||||
|         flags |= FSP_FUSE_UF_READONLY; | ||||
|     if (FileAttributes & FILE_ATTRIBUTE_HIDDEN) | ||||
|         flags |= FSP_FUSE_UF_HIDDEN; | ||||
|     if (FileAttributes & FILE_ATTRIBUTE_SYSTEM) | ||||
|         flags |= FSP_FUSE_UF_SYSTEM; | ||||
|     if (FileAttributes & FILE_ATTRIBUTE_ARCHIVE) | ||||
|         flags |= FSP_FUSE_UF_ARCHIVE; | ||||
|  | ||||
|     return flags; | ||||
| } | ||||
|  | ||||
| static inline UINT32 MapFlagsToFileAttributes(uint32_t flags) | ||||
| { | ||||
|     UINT32 FileAttributes = 0; | ||||
|  | ||||
|     if (flags & FSP_FUSE_UF_READONLY) | ||||
|         FileAttributes |= FILE_ATTRIBUTE_READONLY; | ||||
|     if (flags & FSP_FUSE_UF_HIDDEN) | ||||
|         FileAttributes |= FILE_ATTRIBUTE_HIDDEN; | ||||
|     if (flags & FSP_FUSE_UF_SYSTEM) | ||||
|         FileAttributes |= FILE_ATTRIBUTE_SYSTEM; | ||||
|     if (flags & FSP_FUSE_UF_ARCHIVE) | ||||
|         FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; | ||||
|  | ||||
|     return FileAttributes; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static int maperror(int winerrno); | ||||
|  | ||||
| static inline void *error0(void) | ||||
| { | ||||
|     errno = maperror(GetLastError()); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static inline int error(void) | ||||
| { | ||||
|     errno = maperror(GetLastError()); | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| char *realpath(const char *path, char *resolved) | ||||
| { | ||||
|     char *result; | ||||
|  | ||||
|     if (0 == resolved) | ||||
|     { | ||||
|         result = malloc(PATH_MAX); /* sets errno */ | ||||
|         if (0 == result) | ||||
|             return 0; | ||||
|     } | ||||
|     else | ||||
|         result = resolved; | ||||
|  | ||||
|     int err = 0; | ||||
|     DWORD len = GetFullPathNameA(path, PATH_MAX, result, 0); | ||||
|     if (0 == len) | ||||
|         err = GetLastError(); | ||||
|     else if (PATH_MAX < len) | ||||
|         err = ERROR_INVALID_PARAMETER; | ||||
|  | ||||
|     if (0 == err) | ||||
|     { | ||||
|         HANDLE h = CreateFileA(result, | ||||
|             FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|             0, | ||||
|             OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|         if (INVALID_HANDLE_VALUE != h) | ||||
|             CloseHandle(h); | ||||
|         else | ||||
|             err = GetLastError(); | ||||
|     } | ||||
|  | ||||
|     if (0 != err) | ||||
|     { | ||||
|         if (result != resolved) | ||||
|             free(result); | ||||
|  | ||||
|         errno = maperror(err); | ||||
|         result = 0; | ||||
|     } | ||||
|  | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| int statvfs(const char *path, struct fuse_statvfs *stbuf) | ||||
| { | ||||
|     char root[PATH_MAX]; | ||||
|     DWORD | ||||
|         VolumeSerialNumber, | ||||
|         MaxComponentLength, | ||||
|         SectorsPerCluster, | ||||
|         BytesPerSector, | ||||
|         NumberOfFreeClusters, | ||||
|         TotalNumberOfClusters; | ||||
|  | ||||
|     if (!GetVolumePathNameA(path, root, PATH_MAX) || | ||||
|         !GetVolumeInformationA(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) || | ||||
|         !GetDiskFreeSpaceA(root, &SectorsPerCluster, &BytesPerSector, | ||||
|             &NumberOfFreeClusters, &TotalNumberOfClusters)) | ||||
|     { | ||||
|         return error(); | ||||
|     } | ||||
|  | ||||
|     memset(stbuf, 0, sizeof *stbuf); | ||||
|     stbuf->f_bsize = SectorsPerCluster * BytesPerSector; | ||||
|     stbuf->f_frsize = SectorsPerCluster * BytesPerSector; | ||||
|     stbuf->f_blocks = TotalNumberOfClusters; | ||||
|     stbuf->f_bfree = NumberOfFreeClusters; | ||||
|     stbuf->f_bavail = TotalNumberOfClusters; | ||||
|     stbuf->f_fsid = VolumeSerialNumber; | ||||
|     stbuf->f_namemax = MaxComponentLength; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int open(const char *path, int oflag, ...) | ||||
| { | ||||
|     static DWORD da[] = { GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE, 0 }; | ||||
|     static DWORD cd[] = { OPEN_EXISTING, OPEN_ALWAYS, TRUNCATE_EXISTING, CREATE_ALWAYS }; | ||||
|     DWORD DesiredAccess = 0 == (oflag & _O_APPEND) ? | ||||
|         da[oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)] : | ||||
|         (da[oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)] & ~FILE_WRITE_DATA) | FILE_APPEND_DATA; | ||||
|     DWORD CreationDisposition = (_O_CREAT | _O_EXCL) == (oflag & (_O_CREAT | _O_EXCL)) ? | ||||
|         CREATE_NEW : | ||||
|         cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8]; | ||||
|  | ||||
|     HANDLE h = CreateFileA(path, | ||||
|         DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|         0/* default security */, | ||||
|         CreationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|  | ||||
|     if (INVALID_HANDLE_VALUE == h) | ||||
|         return error(); | ||||
|  | ||||
|     return (int)(intptr_t)h; | ||||
| } | ||||
|  | ||||
| int fstat(int fd, struct fuse_stat *stbuf) | ||||
| { | ||||
|     HANDLE h = (HANDLE)(intptr_t)fd; | ||||
|     BY_HANDLE_FILE_INFORMATION FileInfo; | ||||
|  | ||||
|     if (!GetFileInformationByHandle(h, &FileInfo)) | ||||
|         return error(); | ||||
|  | ||||
|     memset(stbuf, 0, sizeof *stbuf); | ||||
|     stbuf->st_mode = 0777 | | ||||
|         ((FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0040000/* S_IFDIR */ : 0); | ||||
|     stbuf->st_nlink = 1; | ||||
|     stbuf->st_size = ((UINT64)FileInfo.nFileSizeHigh << 32) | ((UINT64)FileInfo.nFileSizeLow); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftCreationTime, (void *)&stbuf->st_birthtim); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftLastAccessTime, (void *)&stbuf->st_atim); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftLastWriteTime, (void *)&stbuf->st_mtim); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FileInfo.ftLastWriteTime, (void *)&stbuf->st_ctim); | ||||
| #if defined(FSP_FUSE_USE_STAT_EX) | ||||
|     stbuf->st_flags = MapFileAttributesToFlags(FileInfo.dwFileAttributes); | ||||
| #endif | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int ftruncate(int fd, fuse_off_t size) | ||||
| { | ||||
|     HANDLE h = (HANDLE)(intptr_t)fd; | ||||
|     FILE_END_OF_FILE_INFO EndOfFileInfo; | ||||
|  | ||||
|     EndOfFileInfo.EndOfFile.QuadPart = size; | ||||
|  | ||||
|     if (!SetFileInformationByHandle(h, FileEndOfFileInfo, &EndOfFileInfo, sizeof EndOfFileInfo)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset) | ||||
| { | ||||
|     HANDLE h = (HANDLE)(intptr_t)fd; | ||||
|     OVERLAPPED Overlapped = { 0 }; | ||||
|     DWORD BytesTransferred; | ||||
|  | ||||
|     Overlapped.Offset = (DWORD)offset; | ||||
|     Overlapped.OffsetHigh = (DWORD)(offset >> 32); | ||||
|  | ||||
|     if (!ReadFile(h, buf, (DWORD)nbyte, &BytesTransferred, &Overlapped)) | ||||
|     { | ||||
|         if (ERROR_HANDLE_EOF == GetLastError()) | ||||
|             return 0; | ||||
|         return error(); | ||||
|     } | ||||
|  | ||||
|     return BytesTransferred; | ||||
| } | ||||
|  | ||||
| int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset) | ||||
| { | ||||
|     HANDLE h = (HANDLE)(intptr_t)fd; | ||||
|     OVERLAPPED Overlapped = { 0 }; | ||||
|     DWORD BytesTransferred; | ||||
|  | ||||
|     Overlapped.Offset = (DWORD)offset; | ||||
|     Overlapped.OffsetHigh = (DWORD)(offset >> 32); | ||||
|  | ||||
|     if (!WriteFile(h, buf, (DWORD)nbyte, &BytesTransferred, &Overlapped)) | ||||
|         return error(); | ||||
|  | ||||
|     return BytesTransferred; | ||||
| } | ||||
|  | ||||
| int fsync(int fd) | ||||
| { | ||||
|     HANDLE h = (HANDLE)(intptr_t)fd; | ||||
|  | ||||
|     if (!FlushFileBuffers(h)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int close(int fd) | ||||
| { | ||||
|     HANDLE h = (HANDLE)(intptr_t)fd; | ||||
|  | ||||
|     if (!CloseHandle(h)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lstat(const char *path, struct fuse_stat *stbuf) | ||||
| { | ||||
|     HANDLE h = CreateFileA(path, | ||||
|         FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|         0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == h) | ||||
|         return error(); | ||||
|  | ||||
|     int res = fstat((int)(intptr_t)h, stbuf); | ||||
|  | ||||
|     CloseHandle(h); | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| int chmod(const char *path, fuse_mode_t mode) | ||||
| { | ||||
|     /* we do not support file security */ | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid) | ||||
| { | ||||
|     /* we do not support file security */ | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int lchflags(const char *path, uint32_t flags) | ||||
| { | ||||
| #if defined(FSP_FUSE_USE_STAT_EX) | ||||
|     UINT32 FileAttributes = MapFlagsToFileAttributes(flags); | ||||
|  | ||||
|     if (0 == FileAttributes) | ||||
|         FileAttributes = FILE_ATTRIBUTE_NORMAL; | ||||
|  | ||||
|     if (!SetFileAttributesA(path, FileAttributes)) | ||||
|         return error(); | ||||
| #endif | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int truncate(const char *path, fuse_off_t size) | ||||
| { | ||||
|     HANDLE h = CreateFileA(path, | ||||
|         FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|         0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == h) | ||||
|         return error(); | ||||
|  | ||||
|     int res = ftruncate((int)(intptr_t)h, size); | ||||
|  | ||||
|     CloseHandle(h); | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| int utime(const char *path, const struct fuse_utimbuf *timbuf) | ||||
| { | ||||
|     if (0 == timbuf) | ||||
|         return utimensat(AT_FDCWD, path, 0, AT_SYMLINK_NOFOLLOW); | ||||
|     else | ||||
|     { | ||||
|         struct fuse_timespec times[2]; | ||||
|         times[0].tv_sec = timbuf->actime; | ||||
|         times[0].tv_nsec = 0; | ||||
|         times[1].tv_sec = timbuf->modtime; | ||||
|         times[1].tv_nsec = 0; | ||||
|         return utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2], int flag) | ||||
| { | ||||
|     /* ignore dirfd and assume that it is always AT_FDCWD */ | ||||
|     /* ignore flag and assume that it is always AT_SYMLINK_NOFOLLOW */ | ||||
|  | ||||
|     HANDLE h = CreateFileA(path, | ||||
|         FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|         0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == h) | ||||
|         return error(); | ||||
|  | ||||
|     UINT64 LastAccessTime, LastWriteTime; | ||||
|     if (0 == times) | ||||
|     { | ||||
|         FILETIME FileTime; | ||||
|         GetSystemTimeAsFileTime(&FileTime); | ||||
|         LastAccessTime = LastWriteTime = *(PUINT64)&FileTime; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         FspPosixUnixTimeToFileTime((void *)×[0], &LastAccessTime); | ||||
|         FspPosixUnixTimeToFileTime((void *)×[1], &LastWriteTime); | ||||
|     } | ||||
|  | ||||
|     int res = SetFileTime(h, | ||||
|         0, (PFILETIME)&LastAccessTime, (PFILETIME)&LastWriteTime) ? 0 : error(); | ||||
|  | ||||
|     CloseHandle(h); | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| int setcrtime(const char *path, const struct fuse_timespec *tv) | ||||
| { | ||||
|     HANDLE h = CreateFileA(path, | ||||
|         FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|         0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == h) | ||||
|         return error(); | ||||
|  | ||||
|     UINT64 CreationTime; | ||||
|     FspPosixUnixTimeToFileTime((void *)tv, &CreationTime); | ||||
|  | ||||
|     int res = SetFileTime(h, | ||||
|         (PFILETIME)&CreationTime, 0, 0) ? 0 : error(); | ||||
|  | ||||
|     CloseHandle(h); | ||||
|  | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| int unlink(const char *path) | ||||
| { | ||||
|     if (!DeleteFileA(path)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int rename(const char *oldpath, const char *newpath) | ||||
| { | ||||
|     if (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int mkdir(const char *path, fuse_mode_t mode) | ||||
| { | ||||
|     if (!CreateDirectoryA(path, 0/* default security */)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int rmdir(const char *path) | ||||
| { | ||||
|     if (!RemoveDirectoryA(path)) | ||||
|         return error(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| DIR *opendir(const char *path) | ||||
| { | ||||
|     HANDLE h = CreateFileA(path, | ||||
|         FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|         0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == h) | ||||
|         return error0(); | ||||
|  | ||||
|     size_t pathlen = strlen(path); | ||||
|     if (0 < pathlen && '/' == path[pathlen - 1]) | ||||
|         pathlen--; | ||||
|  | ||||
|     DIR *dirp = malloc(sizeof *dirp + pathlen + 3); /* sets errno */ | ||||
|     if (0 == dirp) | ||||
|     { | ||||
|         CloseHandle(h); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     memset(dirp, 0, sizeof *dirp); | ||||
|     dirp->h = h; | ||||
|     dirp->fh = INVALID_HANDLE_VALUE; | ||||
|     memcpy(dirp->path, path, pathlen); | ||||
|     dirp->path[pathlen + 0] = '/'; | ||||
|     dirp->path[pathlen + 1] = '*'; | ||||
|     dirp->path[pathlen + 2] = '\0'; | ||||
|  | ||||
|     return dirp; | ||||
| } | ||||
|  | ||||
| int dirfd(DIR *dirp) | ||||
| { | ||||
|     return (int)(intptr_t)dirp->h; | ||||
| } | ||||
|  | ||||
| void rewinddir(DIR *dirp) | ||||
| { | ||||
|     if (INVALID_HANDLE_VALUE != dirp->fh) | ||||
|     { | ||||
|         FindClose(dirp->fh); | ||||
|         dirp->fh = INVALID_HANDLE_VALUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct dirent *readdir(DIR *dirp) | ||||
| { | ||||
|     WIN32_FIND_DATAA FindData; | ||||
|     struct fuse_stat *stbuf = &dirp->de.d_stat; | ||||
|  | ||||
|     if (INVALID_HANDLE_VALUE == dirp->fh) | ||||
|     { | ||||
|         dirp->fh = FindFirstFileA(dirp->path, &FindData); | ||||
|         if (INVALID_HANDLE_VALUE == dirp->fh) | ||||
|             return error0(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (!FindNextFileA(dirp->fh, &FindData)) | ||||
|         { | ||||
|             if (ERROR_NO_MORE_FILES == GetLastError()) | ||||
|                 return 0; | ||||
|             return error0(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     memset(stbuf, 0, sizeof *stbuf); | ||||
|     stbuf->st_mode = 0777 | | ||||
|         ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0040000/* S_IFDIR */ : 0); | ||||
|     stbuf->st_nlink = 1; | ||||
|     stbuf->st_size = ((UINT64)FindData.nFileSizeHigh << 32) | ((UINT64)FindData.nFileSizeLow); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftCreationTime, (void *)&stbuf->st_birthtim); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftLastAccessTime, (void *)&stbuf->st_atim); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftLastWriteTime, (void *)&stbuf->st_mtim); | ||||
|     FspPosixFileTimeToUnixTime(*(PUINT64)&FindData.ftLastWriteTime, (void *)&stbuf->st_ctim); | ||||
| #if defined(FSP_FUSE_USE_STAT_EX) | ||||
|     stbuf->st_flags = MapFileAttributesToFlags(FindData.dwFileAttributes); | ||||
| #endif | ||||
|  | ||||
|     strcpy(dirp->de.d_name, FindData.cFileName); | ||||
|  | ||||
|     return &dirp->de; | ||||
| } | ||||
|  | ||||
| int closedir(DIR *dirp) | ||||
| { | ||||
|     if (INVALID_HANDLE_VALUE != dirp->fh) | ||||
|         FindClose(dirp->fh); | ||||
|  | ||||
|     CloseHandle(dirp->h); | ||||
|     free(dirp); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int maperror(int winerrno) | ||||
| { | ||||
|     switch (winerrno) | ||||
|     { | ||||
|     case ERROR_INVALID_FUNCTION: | ||||
|         return EINVAL; | ||||
|     case ERROR_FILE_NOT_FOUND: | ||||
|         return ENOENT; | ||||
|     case ERROR_PATH_NOT_FOUND: | ||||
|         return ENOENT; | ||||
|     case ERROR_TOO_MANY_OPEN_FILES: | ||||
|         return EMFILE; | ||||
|     case ERROR_ACCESS_DENIED: | ||||
|         return EACCES; | ||||
|     case ERROR_INVALID_HANDLE: | ||||
|         return EBADF; | ||||
|     case ERROR_ARENA_TRASHED: | ||||
|         return ENOMEM; | ||||
|     case ERROR_NOT_ENOUGH_MEMORY: | ||||
|         return ENOMEM; | ||||
|     case ERROR_INVALID_BLOCK: | ||||
|         return ENOMEM; | ||||
|     case ERROR_BAD_ENVIRONMENT: | ||||
|         return E2BIG; | ||||
|     case ERROR_BAD_FORMAT: | ||||
|         return ENOEXEC; | ||||
|     case ERROR_INVALID_ACCESS: | ||||
|         return EINVAL; | ||||
|     case ERROR_INVALID_DATA: | ||||
|         return EINVAL; | ||||
|     case ERROR_INVALID_DRIVE: | ||||
|         return ENOENT; | ||||
|     case ERROR_CURRENT_DIRECTORY: | ||||
|         return EACCES; | ||||
|     case ERROR_NOT_SAME_DEVICE: | ||||
|         return EXDEV; | ||||
|     case ERROR_NO_MORE_FILES: | ||||
|         return ENOENT; | ||||
|     case ERROR_LOCK_VIOLATION: | ||||
|         return EACCES; | ||||
|     case ERROR_BAD_NETPATH: | ||||
|         return ENOENT; | ||||
|     case ERROR_NETWORK_ACCESS_DENIED: | ||||
|         return EACCES; | ||||
|     case ERROR_BAD_NET_NAME: | ||||
|         return ENOENT; | ||||
|     case ERROR_FILE_EXISTS: | ||||
|         return EEXIST; | ||||
|     case ERROR_CANNOT_MAKE: | ||||
|         return EACCES; | ||||
|     case ERROR_FAIL_I24: | ||||
|         return EACCES; | ||||
|     case ERROR_INVALID_PARAMETER: | ||||
|         return EINVAL; | ||||
|     case ERROR_NO_PROC_SLOTS: | ||||
|         return EAGAIN; | ||||
|     case ERROR_DRIVE_LOCKED: | ||||
|         return EACCES; | ||||
|     case ERROR_BROKEN_PIPE: | ||||
|         return EPIPE; | ||||
|     case ERROR_DISK_FULL: | ||||
|         return ENOSPC; | ||||
|     case ERROR_INVALID_TARGET_HANDLE: | ||||
|         return EBADF; | ||||
|     case ERROR_WAIT_NO_CHILDREN: | ||||
|         return ECHILD; | ||||
|     case ERROR_CHILD_NOT_COMPLETE: | ||||
|         return ECHILD; | ||||
|     case ERROR_DIRECT_ACCESS_HANDLE: | ||||
|         return EBADF; | ||||
|     case ERROR_NEGATIVE_SEEK: | ||||
|         return EINVAL; | ||||
|     case ERROR_SEEK_ON_DEVICE: | ||||
|         return EACCES; | ||||
|     case ERROR_DIR_NOT_EMPTY: | ||||
|         return ENOTEMPTY; | ||||
|     case ERROR_NOT_LOCKED: | ||||
|         return EACCES; | ||||
|     case ERROR_BAD_PATHNAME: | ||||
|         return ENOENT; | ||||
|     case ERROR_MAX_THRDS_REACHED: | ||||
|         return EAGAIN; | ||||
|     case ERROR_LOCK_FAILED: | ||||
|         return EACCES; | ||||
|     case ERROR_ALREADY_EXISTS: | ||||
|         return EEXIST; | ||||
|     case ERROR_FILENAME_EXCED_RANGE: | ||||
|         return ENOENT; | ||||
|     case ERROR_NESTING_NOT_ALLOWED: | ||||
|         return EAGAIN; | ||||
|     case ERROR_NOT_ENOUGH_QUOTA: | ||||
|         return ENOMEM; | ||||
|     default: | ||||
|         if (ERROR_WRITE_PROTECT <= winerrno && winerrno <= ERROR_SHARING_BUFFER_EXCEEDED) | ||||
|             return EACCES; | ||||
|         else if (ERROR_INVALID_STARTING_CODESEG <= winerrno && winerrno <= ERROR_INFLOOP_IN_RELOC_CHAIN) | ||||
|             return ENOEXEC; | ||||
|         else | ||||
|             return EINVAL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| long WinFspLoad(void) | ||||
| { | ||||
|     return FspLoad(0); | ||||
| } | ||||
							
								
								
									
										77
									
								
								tst/passthrough-fuse3/winposix.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								tst/passthrough-fuse3/winposix.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| /** | ||||
|  * @file winposix.h | ||||
|  * | ||||
|  * @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. | ||||
|  */ | ||||
|  | ||||
| #ifndef WINPOSIX_H_INCLUDED | ||||
| #define WINPOSIX_H_INCLUDED | ||||
|  | ||||
| #define O_RDONLY                        _O_RDONLY | ||||
| #define O_WRONLY                        _O_WRONLY | ||||
| #define O_RDWR                          _O_RDWR | ||||
| #define O_APPEND                        _O_APPEND | ||||
| #define O_CREAT                         _O_CREAT | ||||
| #define O_EXCL                          _O_EXCL | ||||
| #define O_TRUNC                         _O_TRUNC | ||||
|  | ||||
| #define PATH_MAX                        1024 | ||||
| #define AT_FDCWD                        -2 | ||||
| #define AT_SYMLINK_NOFOLLOW             2 | ||||
|  | ||||
| typedef struct _DIR DIR; | ||||
| struct dirent | ||||
| { | ||||
|     struct fuse_stat d_stat; | ||||
|     char d_name[255]; | ||||
| }; | ||||
|  | ||||
| char *realpath(const char *path, char *resolved); | ||||
|  | ||||
| int statvfs(const char *path, struct fuse_statvfs *stbuf); | ||||
|  | ||||
| int open(const char *path, int oflag, ...); | ||||
| int fstat(int fd, struct fuse_stat *stbuf); | ||||
| int ftruncate(int fd, fuse_off_t size); | ||||
| int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset); | ||||
| int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset); | ||||
| int fsync(int fd); | ||||
| int close(int fd); | ||||
|  | ||||
| int lstat(const char *path, struct fuse_stat *stbuf); | ||||
| int chmod(const char *path, fuse_mode_t mode); | ||||
| int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid); | ||||
| int lchflags(const char *path, uint32_t flags); | ||||
| int truncate(const char *path, fuse_off_t size); | ||||
| int utime(const char *path, const struct fuse_utimbuf *timbuf); | ||||
| int utimensat(int dirfd, const char *path, const struct fuse_timespec times[2], int flag); | ||||
| int setcrtime(const char *path, const struct fuse_timespec *tv); | ||||
| int unlink(const char *path); | ||||
| int rename(const char *oldpath, const char *newpath); | ||||
|  | ||||
| int mkdir(const char *path, fuse_mode_t mode); | ||||
| int rmdir(const char *path); | ||||
|  | ||||
| DIR *opendir(const char *path); | ||||
| int dirfd(DIR *dirp); | ||||
| void rewinddir(DIR *dirp); | ||||
| struct dirent *readdir(DIR *dirp); | ||||
| int closedir(DIR *dirp); | ||||
|  | ||||
| long WinFspLoad(void); | ||||
| #undef fuse_main | ||||
| #define fuse_main(argc, argv, ops, data)\ | ||||
|     (WinFspLoad(), fuse_main_real(argc, argv, ops, sizeof *(ops), data)) | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user