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: | 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.) | * `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):: | v1.4B1 (2018.2 B1):: | ||||||
|   | |||||||
| @@ -281,6 +281,20 @@ | |||||||
|                     <File Name="winfsp_fuse.h" KeyPath="yes" /> |                     <File Name="winfsp_fuse.h" KeyPath="yes" /> | ||||||
|                 </Component> |                 </Component> | ||||||
|             </Directory> |             </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> | ||||||
|         <DirectoryRef Id="LIBDIR" FileSource="..\build\$(var.Configuration)"> |         <DirectoryRef Id="LIBDIR" FileSource="..\build\$(var.Configuration)"> | ||||||
|             <Component Id="C.winfsp_x64.lib"> |             <Component Id="C.winfsp_x64.lib"> | ||||||
| @@ -309,6 +323,26 @@ | |||||||
|                     KeyPath="yes" /> |                     KeyPath="yes" /> | ||||||
|                 <Condition>NOT VersionNT64</Condition> |                 <Condition>NOT VersionNT64</Condition> | ||||||
|             </Component> |             </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> | ||||||
|         <DirectoryRef Id="OPTDIR"> |         <DirectoryRef Id="OPTDIR"> | ||||||
|             <Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist"> |             <Directory Id="OPTDIR.cygfuse" Name="cygfuse" FileSource="..\..\..\opt\cygfuse\dist"> | ||||||
| @@ -415,6 +449,32 @@ | |||||||
|                     <File Name="README.md" KeyPath="yes" /> |                     <File Name="README.md" KeyPath="yes" /> | ||||||
|                 </Component> |                 </Component> | ||||||
|             </Directory> |             </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"> |             <Directory Id="SMPDIR.passthrough_dotnet" Name="passthrough-dotnet"> | ||||||
|                 <Component Id="C.passthrough_dotnet.Program.cs"> |                 <Component Id="C.passthrough_dotnet.Program.cs"> | ||||||
|                     <File Id="FILE.passthrough_dotnet.Program.cs" Name="Program.cs" KeyPath="yes" /> |                     <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_common.h" /> | ||||||
|             <ComponentRef Id="C.fuse_opt.h" /> |             <ComponentRef Id="C.fuse_opt.h" /> | ||||||
|             <ComponentRef Id="C.winfsp_fuse.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> | ||||||
|         <ComponentGroup Id="C.WinFsp.lib"> |         <ComponentGroup Id="C.WinFsp.lib"> | ||||||
|             <ComponentRef Id="C.winfsp_x64.lib" /> |             <ComponentRef Id="C.winfsp_x64.lib" /> | ||||||
|             <ComponentRef Id="C.winfsp_x86.lib" /> |             <ComponentRef Id="C.winfsp_x86.lib" /> | ||||||
|             <ComponentRef Id="C.fuse_x64.pc" /> |             <ComponentRef Id="C.fuse_x64.pc" /> | ||||||
|             <ComponentRef Id="C.fuse_x86.pc" /> |             <ComponentRef Id="C.fuse_x86.pc" /> | ||||||
|  |             <ComponentRef Id="C.fuse3_x64.pc" /> | ||||||
|  |             <ComponentRef Id="C.fuse3_x86.pc" /> | ||||||
|         </ComponentGroup> |         </ComponentGroup> | ||||||
|         <ComponentGroup Id="C.WinFsp.opt.fuse"> |         <ComponentGroup Id="C.WinFsp.opt.fuse"> | ||||||
|             <ComponentRef Id="C.fuse.tar.xz.x64" /> |             <ComponentRef Id="C.fuse.tar.xz.x64" /> | ||||||
| @@ -532,6 +598,14 @@ | |||||||
|             <ComponentRef Id="C.passthrough_fuse.vcxproj.filters" /> |             <ComponentRef Id="C.passthrough_fuse.vcxproj.filters" /> | ||||||
|             <ComponentRef Id="C.passthrough_fuse.Makefile" /> |             <ComponentRef Id="C.passthrough_fuse.Makefile" /> | ||||||
|             <ComponentRef Id="C.passthrough_fuse.README.md" /> |             <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> | ||||||
|         <ComponentGroup Id="C.WinFsp.sym"> |         <ComponentGroup Id="C.WinFsp.sym"> | ||||||
|             <ComponentRef Id="C.winfsp_x64.sys.pdb" /> |             <ComponentRef Id="C.winfsp_x64.sys.pdb" /> | ||||||
|   | |||||||
| @@ -20,6 +20,10 @@ | |||||||
|     </ProjectConfiguration> |     </ProjectConfiguration> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <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.h" /> | ||||||
|     <ClInclude Include="..\..\inc\fuse\fuse_common.h" /> |     <ClInclude Include="..\..\inc\fuse\fuse_common.h" /> | ||||||
|     <ClInclude Include="..\..\inc\fuse\fuse_opt.h" /> |     <ClInclude Include="..\..\inc\fuse\fuse_opt.h" /> | ||||||
| @@ -28,6 +32,7 @@ | |||||||
|     <ClInclude Include="..\..\inc\winfsp\launch.h" /> |     <ClInclude Include="..\..\inc\winfsp\launch.h" /> | ||||||
|     <ClInclude Include="..\..\inc\winfsp\winfsp.h" /> |     <ClInclude Include="..\..\inc\winfsp\winfsp.h" /> | ||||||
|     <ClInclude Include="..\..\inc\winfsp\winfsp.hpp" /> |     <ClInclude Include="..\..\inc\winfsp\winfsp.hpp" /> | ||||||
|  |     <ClInclude Include="..\..\src\dll\fuse3\library.h" /> | ||||||
|     <ClInclude Include="..\..\src\dll\fuse\library.h" /> |     <ClInclude Include="..\..\src\dll\fuse\library.h" /> | ||||||
|     <ClInclude Include="..\..\src\dll\library.h" /> |     <ClInclude Include="..\..\src\dll\library.h" /> | ||||||
|     <ClInclude Include="..\..\src\shared\minimal.h" /> |     <ClInclude Include="..\..\src\shared\minimal.h" /> | ||||||
| @@ -35,6 +40,8 @@ | |||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="..\..\src\dll\dirbuf.c" /> |     <ClCompile Include="..\..\src\dll\dirbuf.c" /> | ||||||
|     <ClCompile Include="..\..\src\dll\eventlog.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.c" /> | ||||||
|     <ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" /> |     <ClCompile Include="..\..\src\dll\fuse\fuse_compat.c" /> | ||||||
|     <ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" /> |     <ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" /> | ||||||
| @@ -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> |       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)fuse-$(PlatformTarget).pc</Outputs> | ||||||
|       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects> |       <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects> | ||||||
|     </CustomBuild> |     </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" /> |     <None Include="..\..\src\dll\library.def" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|   | |||||||
| @@ -21,6 +21,12 @@ | |||||||
|     <Filter Include="Source\fuse"> |     <Filter Include="Source\fuse"> | ||||||
|       <UniqueIdentifier>{518cce17-85cd-489c-b4be-920a84c1d73c}</UniqueIdentifier> |       <UniqueIdentifier>{518cce17-85cd-489c-b4be-920a84c1d73c}</UniqueIdentifier> | ||||||
|     </Filter> |     </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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\..\inc\winfsp\fsctl.h"> |     <ClInclude Include="..\..\inc\winfsp\fsctl.h"> | ||||||
| @@ -56,6 +62,21 @@ | |||||||
|     <ClInclude Include="..\..\inc\winfsp\launch.h"> |     <ClInclude Include="..\..\inc\winfsp\launch.h"> | ||||||
|       <Filter>Include\winfsp</Filter> |       <Filter>Include\winfsp</Filter> | ||||||
|     </ClInclude> |     </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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="..\..\src\dll\library.c"> |     <ClCompile Include="..\..\src\dll\library.c"> | ||||||
| @@ -121,6 +142,12 @@ | |||||||
|     <ClCompile Include="..\..\src\dll\launch.c"> |     <ClCompile Include="..\..\src\dll\launch.c"> | ||||||
|       <Filter>Source</Filter> |       <Filter>Source</Filter> | ||||||
|     </ClCompile> |     </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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="..\..\src\dll\library.def"> |     <None Include="..\..\src\dll\library.def"> | ||||||
| @@ -139,5 +166,8 @@ | |||||||
|     <CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in"> |     <CustomBuild Include="..\..\src\dll\fuse\fuse.pc.in"> | ||||||
|       <Filter>Source\fuse</Filter> |       <Filter>Source\fuse</Filter> | ||||||
|     </CustomBuild> |     </CustomBuild> | ||||||
|  |     <CustomBuild Include="..\..\src\dll\fuse3\fuse3.pc.in"> | ||||||
|  |       <Filter>Source\fuse3</Filter> | ||||||
|  |     </CustomBuild> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </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 } | #define FSP_FUSE_CORE_OPT(n, f, v)      { n, offsetof(struct fsp_fuse_core_opt_data, f), v } | ||||||
|  | #define FSP_FUSE_CORE_OPT_NOHELP_IDX    4 | ||||||
| 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."); |  | ||||||
|  |  | ||||||
| static struct fuse_opt fsp_fuse_core_opts[] = | 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 INIT_ONCE fsp_fuse_initonce = INIT_ONCE_STATIC_INIT; | ||||||
| static DWORD fsp_fuse_tlskey = TLS_OUT_OF_INDEXES; | 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( | static BOOL WINAPI fsp_fuse_initialize( | ||||||
|     PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) |     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 */ |         /* this should always fail with ENOSYS or EINVAL */ | ||||||
|         err = f->ops.readlink("/", buf, sizeof buf); |         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! */ |     /* 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, | FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env, | ||||||
|     struct fuse_chan *ch, struct fuse_args *args, |     struct fuse_chan *ch, struct fuse_args *args, | ||||||
|     const struct fuse_operations *ops, size_t opsize, void *data) |     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.FileInfoTimeout = 1000; | ||||||
|     opt_data.VolumeParams.FlushAndPurgeOnCleanup = TRUE; |     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; |         return 0; | ||||||
|     if (opt_data.help) |     if (opt_data.help) | ||||||
|         return 0; |         return 0; | ||||||
| @@ -788,6 +748,11 @@ FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env) | |||||||
|     return context; |     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, | FSP_FUSE_API int32_t fsp_fuse_ntstatus_from_errno(struct fsp_fuse_env *env, | ||||||
|     int err) |     int err) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -266,7 +266,7 @@ loopend:; | |||||||
|         if (0 != f->ops.getattr) |         if (0 != f->ops.getattr) | ||||||
|             err = f->ops.getattr(PosixHiddenPath, (void *)&stbuf); |             err = f->ops.getattr(PosixHiddenPath, (void *)&stbuf); | ||||||
|         else |         else | ||||||
|             err = -ENOSYS; |             err = -ENOSYS_(f->env); | ||||||
|     } while (0 == err && 0 < --maxtries); |     } while (0 == err && 0 < --maxtries); | ||||||
|  |  | ||||||
|     if (0 == err) |     if (0 == err) | ||||||
| @@ -308,7 +308,7 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem, | |||||||
|         if (0 != f->ops.getattr) |         if (0 != f->ops.getattr) | ||||||
|             err = f->ops.getattr(PosixDotPath, (void *)&stbuf); |             err = f->ops.getattr(PosixDotPath, (void *)&stbuf); | ||||||
|         else |         else | ||||||
|             err = -ENOSYS; |             err = -ENOSYS_(f->env); | ||||||
|  |  | ||||||
|         MemFree(PosixDotPath); |         MemFree(PosixDotPath); | ||||||
|  |  | ||||||
| @@ -1427,7 +1427,8 @@ static NTSTATUS fsp_fuse_intf_SetFileSize(FSP_FILE_SYSTEM *FileSystem, | |||||||
|     return STATUS_SUCCESS; |     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) |     const struct fuse_stat *stbuf, fuse_off_t off) | ||||||
| { | { | ||||||
|     struct fuse_dirhandle *dh = buf; |     struct fuse_dirhandle *dh = buf; | ||||||
| @@ -1617,7 +1618,8 @@ exit: | |||||||
|     return Result; |     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) |     const struct fuse_stat *stbuf, fuse_off_t off) | ||||||
| { | { | ||||||
|     struct fuse_dirhandle *dh = buf; |     struct fuse_dirhandle *dh = buf; | ||||||
|   | |||||||
| @@ -25,12 +25,14 @@ | |||||||
| #define FSP_FUSE_LIBRARY_NAME           LIBRARY_NAME "-FUSE" | #define FSP_FUSE_LIBRARY_NAME           LIBRARY_NAME "-FUSE" | ||||||
|  |  | ||||||
| #define FSP_FUSE_HDR_FROM_CONTEXT(c)    \ | #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)    \ | #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 FSP_FUSE_HAS_SYMLINKS(f)        ((f)->has_symlinks) | ||||||
|  |  | ||||||
|  | #define ENOSYS_(env)                    ('C' == (env)->environment ? 88 : 40) | ||||||
|  |  | ||||||
| struct fuse | struct fuse | ||||||
| { | { | ||||||
|     struct fsp_fuse_env *env; |     struct fsp_fuse_env *env; | ||||||
| @@ -54,6 +56,7 @@ struct fuse | |||||||
|     FSP_FILE_SYSTEM *FileSystem; |     FSP_FILE_SYSTEM *FileSystem; | ||||||
|     FSP_SERVICE *Service; /* weak */ |     FSP_SERVICE *Service; /* weak */ | ||||||
|     volatile int exited; |     volatile int exited; | ||||||
|  |     struct fuse3 *fuse3; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct fsp_fuse_context_header | 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, | NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem, | ||||||
|     FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response); |     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; | extern FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf; | ||||||
|  |  | ||||||
| NTSTATUS fsp_fuse_get_token_uidgid( | NTSTATUS fsp_fuse_get_token_uidgid( | ||||||
| @@ -102,4 +110,65 @@ NTSTATUS fsp_fuse_get_token_uidgid( | |||||||
| #define NFS_SPECFILE_LNK                0x00000000014b4e4c | #define NFS_SPECFILE_LNK                0x00000000014b4e4c | ||||||
| #define NFS_SPECFILE_SOCK               0x000000004B434F53 | #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 | #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-fsx-passthrough-fuse-x64 ^ | ||||||
|     sample-passthrough-fuse-x86 ^ |     sample-passthrough-fuse-x86 ^ | ||||||
|     sample-fsx-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 ^ |     sample-passthrough-dotnet ^ | ||||||
|     compat-v1.2-memfs-x64 ^ |     compat-v1.2-memfs-x64 ^ | ||||||
|     compat-v1.2-memfs-x86 ^ |     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 | if !ERRORLEVEL! neq 0 goto fail | ||||||
| exit /b 0 | 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 | :__run_sample_disk_test | ||||||
| set RunSampleTestExit=0 | set RunSampleTestExit=0 | ||||||
| call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1" | call %ProjRoot%\tools\build-sample %Configuration% %2 %1 "%TMP%\%1" | ||||||
| @@ -783,11 +809,16 @@ net use | findstr L: | |||||||
| pushd >nul | pushd >nul | ||||||
| cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail) | cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail) | ||||||
| L: | L: | ||||||
| "%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^ | if X%5==XNOEXCL ( | ||||||
|     --external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^ |     "%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^ | ||||||
|     -create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^ |         --external --resilient | ||||||
|     -getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^ | ) else ( | ||||||
|     -reparse* -stream* |     "%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 | if !ERRORLEVEL! neq 0 set RunSampleTestExit=1 | ||||||
| popd | popd | ||||||
| echo net use L: /delete | 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