├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── dokan_fuse ├── CMakelists.txt ├── build.ps1 ├── cleancmake.bat ├── dokan_fuse.vcxproj ├── dokan_fuse.vcxproj.filters ├── include │ ├── ScopeGuard.h │ ├── docanfuse.h │ ├── fuse.h │ ├── fuse_common.h │ ├── fuse_opt.h │ ├── fuse_sem_fix.h │ ├── fuse_win.h │ ├── fusemain.h │ └── utils.h └── src │ ├── docanfuse.cpp │ ├── dokanfuse.def │ ├── dokanfuse.rc │ ├── fuse_helpers.c │ ├── fuse_opt.c │ ├── fusemain.cpp │ ├── resource.h │ └── utils.cpp ├── include ├── CL │ ├── cl.h │ ├── cl.hpp │ ├── cl_1_1.hpp │ ├── cl_d3d10.h │ ├── cl_d3d10_ext.h │ ├── cl_d3d11_ext.h │ ├── cl_d3d9_ext.h │ ├── cl_ext.h │ ├── cl_gl.h │ ├── cl_gl_ext.h │ ├── cl_platform.h │ ├── debugcl.hpp │ └── opencl.h ├── entry.hpp ├── memory.hpp ├── util.hpp └── vramfs.hpp ├── lib └── OpenCL.dll ├── mount.sh └── src ├── dir.cpp ├── entry.cpp ├── file.cpp ├── memory.cpp ├── symlink.cpp ├── util.cpp └── vramfs.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries 2 | bin/ 3 | build/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Eric Zhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -Wall -Wextra -std=c++11 -Iinclude/ -I"C:\Program Files\Dokan\Dokan Library-1.0.0\include\dokan" -Idokan_fuse/include -D_FILE_OFFSET_BITS=64 3 | LDFLAGS =-Llib/ -lOpenCL -L"C:\Program Files\Dokan\Dokan Library-1.0.0" -ldokan1 4 | 5 | CXXFLAGS += -g -Og -pg -DOPENCL_1_1 6 | 7 | bin/vramfs: build/util.o build/memory.o build/entry.o build/file.o build/dir.o build/symlink.o build/vramfs.o build/docanfuse.o build/fuse_helpers.o build/fuse_opt.o build/fusemain.o build/utils.o | bin 8 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ 9 | 10 | build bin: 11 | @mkdir -p $@ 12 | 13 | build/%.o: src/%.cpp | build 14 | $(CXX) $(CXXFLAGS) -c -o $@ $< 15 | 16 | build/%.o: dokan_fuse/src/%.cpp | build 17 | $(CXX) $(CXXFLAGS) -c -o $@ $< 18 | 19 | build/%.o: dokan_fuse/src/%.c | build 20 | $(CXX) $(CXXFLAGS) -c -o $@ $< 21 | 22 | .PHONY: test 23 | test: bin/vramfs.exe 24 | bin/vramfs.exe R: 128M 25 | 26 | .PHONY: clean 27 | clean: 28 | rm -rf build/ bin/ 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vramfs on Windows 2 | ====== 3 | This project tries to port vramfs to Windows using dokan library (dokanfuse). 4 | 5 | vramfs: https://github.com/Overv/vramfs 6 | dokany: https://github.com/dokan-dev/dokany 7 | 8 | **Credit:** 9 | vramfs: Alexander Overvoorde et al. 10 | dokany: Hiroki Asakawa as original author 11 | and now dokany team 12 | 13 | **WARNING:** 14 | Now the program is barely working. But the partition shows at explorer and 15 | has information like free space. Partition size parsing is now working with 16 | msys toolchain. Other function like creating file is not working yet. 17 | 18 | **Dependency:** 19 | 20 | dokan library 21 | msys2 64bit 22 | g++ 23 | an graphic card or CPU that support OpenCL 24 | 25 | **Usage:** 26 | 27 | $git clone https://github.com/x1596357/vramfs-on-Windows 28 | $cd vramfs-on-Windows 29 | $make (or make OPENCL_1_1=1) 30 | $./mount.sh 31 | 32 | I use Windows 10 64-bit and my laptop uses Nvidia 840M with 2GiB memory. 33 | So, the libs are for 64-bit system and I'm not going to work on 32bit system 34 | and other graphic card besides Nvidia soon. I need to get it to work first, right? 35 | In lib/x64,there is OpenCL64.dll extracted from Nvidia driver, you may want to use 36 | yours to replace it. There is also dokanfuse.dll compiled from my dokany fork. 37 | 38 | For debugging purpuse, this program now uses CPU as the backend device. This means 39 | you can run it regardles of your graphic card vendor so long as you have OpenCL support. 40 | You may want to install OpenCL runtime support for your CPU from CPU vendors. 41 | You can change it to use your GPU easily by changing the CL_DEVICE_TYPE_CPU to 42 | CL_DEVICE_TYPE_GPU. Later I might add command line options to change it at runtime. 43 | 44 | **Issues:** 45 | 46 | 1. **It doesn't work and causes BSOD!!!** 47 | Well, I'm working to it. This project is just got started. Please be patient. 48 | 49 | 50 | **License** 51 | 52 | The MIT License (MIT) 53 | 54 | Copyright (c) 2015 Eric Zhang 55 | 56 | Permission is hereby granted, free of charge, to any person obtaining a copy 57 | of this software and associated documentation files (the "Software"), to 58 | deal in the Software without restriction, including without limitation the 59 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 60 | sell copies of the Software, and to permit persons to whom the Software is 61 | furnished to do so, subject to the following conditions: 62 | 63 | The above copyright notice and this permission notice shall be included in 64 | all copies or substantial portions of the Software. 65 | 66 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 67 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 68 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 69 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 70 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 71 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 72 | IN THE SOFTWARE. -------------------------------------------------------------------------------- /dokan_fuse/CMakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.4) 2 | 3 | project (dokanfuse1) 4 | 5 | set(CMAKE_LEGACY_CYGWIN_WIN32 0) 6 | 7 | set(CMAKE_BUILD_TYPE Release) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 9 | 10 | file(GLOB source src/*.cpp src/*.c) 11 | 12 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include 13 | ${CMAKE_CURRENT_SOURCE_DIR}/../sys) 14 | 15 | add_library(dokanfuse1 SHARED ${source}) -------------------------------------------------------------------------------- /dokan_fuse/build.ps1: -------------------------------------------------------------------------------- 1 | $currentPath=Get-Location 2 | 3 | & dokan_fuse/cleancmake.bat 4 | & C:\cygwin\bin\bash -lc "cd '$currentPath'/dokan_fuse/ && cmake . && make" 5 | & C:\cygwin\bin\bash -lc "cd '$currentPath'/samples/fuse_mirror/ && gcc -o mirror fusexmp.c -I../../dokan_fuse/include -D_FILE_OFFSET_BITS=64 -L../../dokan_fuse -lcygdokanfuse1" 6 | New-Item -Force -Type Directory "Win32/Cygwin/" 7 | copy-item "dokan_fuse/cygdokanfuse1.dll" "Win32/Cygwin/" 8 | copy-item "samples/fuse_mirror/mirror.exe" "Win32/Cygwin/" 9 | Remove-Item "dokan_fuse/cygdokanfuse1.dll" 10 | Remove-Item "samples/fuse_mirror/mirror.exe" 11 | 12 | & dokan_fuse/cleancmake.bat 13 | & C:\cygwin64\bin\bash -lc "cd '$currentPath'/dokan_fuse/ && cmake . && make" 14 | & C:\cygwin64\bin\bash -lc "cd '$currentPath'/samples/fuse_mirror/ && gcc -o mirror fusexmp.c -I../../dokan_fuse/include -D_FILE_OFFSET_BITS=64 -L../../dokan_fuse -lcygdokanfuse1" 15 | New-Item -Force -Type Directory "x64/Cygwin/" 16 | copy-item "dokan_fuse/cygdokanfuse1.dll" "x64/Cygwin/" 17 | copy-item "samples/fuse_mirror/mirror.exe" "x64/Cygwin/" 18 | Remove-Item "dokan_fuse/cygdokanfuse1.dll" 19 | Remove-Item "samples/fuse_mirror/mirror.exe" 20 | 21 | & dokan_fuse/cleancmake.bat 22 | & C:\msys64\mingw32_shell.bat -lc "cd '$currentPath'/dokan_fuse/ && cmake . -G 'MSYS Makefiles' && make" | Out-Host 23 | New-Item -Force -Type Directory "Win32/Msys2/" 24 | copy-item "dokan_fuse/libdokanfuse1.dll" "Win32/Msys2/" 25 | Remove-Item "dokan_fuse/libdokanfuse1.dll" 26 | 27 | & dokan_fuse/cleancmake.bat 28 | & C:\msys64\mingw64_shell.bat -lc "cd '$currentPath'/dokan_fuse/ && cmake . -G 'MSYS Makefiles' && make" | Out-Host 29 | New-Item -Force -Type Directory "x64/Msys2/" 30 | copy-item "dokan_fuse/libdokanfuse1.dll" "x64/Msys2/" 31 | Remove-Item "dokan_fuse/libdokanfuse1.dll" -------------------------------------------------------------------------------- /dokan_fuse/cleancmake.bat: -------------------------------------------------------------------------------- 1 | del CMakeCache.txt /Q /S 2 | for /d /r . %%d in (CMakeFiles) do @if exist "%%d" rd /s/q "%%d" -------------------------------------------------------------------------------- /dokan_fuse/dokan_fuse.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {4AF8149D-C526-4D38-A4BC-9FFA67EDF924} 23 | Win32Proj 24 | Win32 25 | dokan_fuse 26 | 10.0.10586.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | false 32 | MultiByte 33 | v140 34 | 35 | 36 | DynamicLibrary 37 | false 38 | MultiByte 39 | v140 40 | 41 | 42 | DynamicLibrary 43 | false 44 | MultiByte 45 | v140 46 | 47 | 48 | DynamicLibrary 49 | false 50 | MultiByte 51 | v140 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | <_ProjectFileVersion>10.0.20506.1 74 | $(SolutionDir)$(Platform)\$(Configuration)\ 75 | $(SolutionDir)$(Platform)\$(Configuration)\ 76 | $(Platform)\$(Configuration)\ 77 | $(Platform)\$(Configuration)\ 78 | dokanfuse$(DOKANAPIVersion) 79 | dokanfuse$(DOKANAPIVersion) 80 | .dll 81 | .dll 82 | true 83 | true 84 | true 85 | true 86 | $(SolutionDir)$(Platform)\$(Configuration)\ 87 | $(SolutionDir)$(Platform)\$(Configuration)\ 88 | $(Platform)\$(Configuration)\ 89 | $(Platform)\$(Configuration)\ 90 | dokanfuse$(DOKANAPIVersion) 91 | dokanfuse$(DOKANAPIVersion) 92 | .dll 93 | .dll 94 | false 95 | false 96 | true 97 | true 98 | 99 | 100 | 101 | ../sys;include;src;%(AdditionalIncludeDirectories) 102 | Debug/ 103 | EnableFastChecks 104 | CompileAsCpp 105 | ProgramDatabase 106 | Sync 107 | Disabled 108 | Disabled 109 | NotUsing 110 | MultiThreadedDebugDLL 111 | true 112 | Level3 113 | WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_DEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 114 | $(IntDir) 115 | 116 | 117 | WIN32;_WINDOWS;_DEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 118 | include;src;%(AdditionalIncludeDirectories) 119 | 120 | 121 | include;src;%(AdditionalIncludeDirectories) 122 | $(IntDir) 123 | %(Filename).h 124 | %(Filename).tlb 125 | %(Filename)_i.c 126 | %(Filename)_p.c 127 | 128 | 129 | /machine:X86 /debug %(AdditionalOptions) 130 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib 131 | %(AdditionalLibraryDirectories) 132 | true 133 | %(IgnoreSpecificDefaultLibraries) 134 | $(OutDir)$(TargetName).lib 135 | src/dokanfuse.def 136 | $(OutDir)$(TargetName).pdb 137 | Console 138 | 139 | 140 | 141 | 142 | false 143 | 144 | 145 | MachineX86 146 | 147 | 148 | 149 | 150 | ../sys;include;src;%(AdditionalIncludeDirectories) 151 | Debug/ 152 | EnableFastChecks 153 | CompileAsCpp 154 | ProgramDatabase 155 | Sync 156 | Disabled 157 | Disabled 158 | NotUsing 159 | MultiThreadedDebugDLL 160 | true 161 | Level3 162 | WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_DEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 163 | $(IntDir) 164 | 165 | 166 | WIN32;_WINDOWS;_DEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 167 | include;src;%(AdditionalIncludeDirectories) 168 | 169 | 170 | include;src;%(AdditionalIncludeDirectories) 171 | $(IntDir) 172 | %(Filename).h 173 | %(Filename).tlb 174 | %(Filename)_i.c 175 | %(Filename)_p.c 176 | 177 | 178 | /machine:X64 /debug %(AdditionalOptions) 179 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib 180 | %(AdditionalLibraryDirectories) 181 | true 182 | %(IgnoreSpecificDefaultLibraries) 183 | $(OutDir)$(TargetName).lib 184 | src/dokanfuse.def 185 | $(OutDir)$(TargetName).pdb 186 | Console 187 | 188 | 189 | 190 | 191 | false 192 | 193 | 194 | MachineX64 195 | 196 | 197 | 198 | 199 | ../sys;include;src;%(AdditionalIncludeDirectories) 200 | $(Platform)\$(Configuration)\ 201 | CompileAsCpp 202 | Sync 203 | AnySuitable 204 | MaxSpeed 205 | NotUsing 206 | MultiThreadedDLL 207 | true 208 | Level3 209 | WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;NDEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 210 | $(IntDir) 211 | 212 | 213 | 214 | 215 | WIN32;_WINDOWS;NDEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 216 | include;src;%(AdditionalIncludeDirectories) 217 | 218 | 219 | include;src;%(AdditionalIncludeDirectories) 220 | $(IntDir) 221 | %(Filename).h 222 | %(Filename).tlb 223 | %(Filename)_i.c 224 | %(Filename)_p.c 225 | 226 | 227 | /machine:X86 %(AdditionalOptions) 228 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib 229 | %(AdditionalLibraryDirectories) 230 | false 231 | %(IgnoreSpecificDefaultLibraries) 232 | $(OutDir)$(TargetName).lib 233 | src/dokanfuse.def 234 | $(OutDir)$(TargetName).pdb 235 | Console 236 | 237 | 238 | 239 | 240 | false 241 | 242 | 243 | MachineX86 244 | 245 | 246 | 247 | 248 | ../sys;include;src;%(AdditionalIncludeDirectories) 249 | $(Platform)\$(Configuration)\ 250 | CompileAsCpp 251 | Sync 252 | AnySuitable 253 | MaxSpeed 254 | NotUsing 255 | MultiThreadedDLL 256 | true 257 | Level3 258 | WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;NDEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 259 | $(IntDir) 260 | 261 | 262 | 263 | 264 | WIN32;_WINDOWS;NDEBUG;FUSE_USE_VERSION=27;_FILE_OFFSET_BITS=64;fuse_EXPORTS;%(PreprocessorDefinitions) 265 | include;src;%(AdditionalIncludeDirectories) 266 | 267 | 268 | include;src;%(AdditionalIncludeDirectories) 269 | $(IntDir) 270 | %(Filename).h 271 | %(Filename).tlb 272 | %(Filename)_i.c 273 | %(Filename)_p.c 274 | 275 | 276 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib 277 | %(AdditionalLibraryDirectories) 278 | false 279 | %(IgnoreSpecificDefaultLibraries) 280 | $(OutDir)$(TargetName).lib 281 | src/dokanfuse.def 282 | $(OutDir)$(TargetName).pdb 283 | Console 284 | 285 | 286 | 287 | 288 | false 289 | 290 | 291 | MachineX64 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | CompileAsC 306 | CompileAsC 307 | CompileAsC 308 | CompileAsC 309 | 310 | 311 | CompileAsC 312 | CompileAsC 313 | CompileAsC 314 | CompileAsC 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | -------------------------------------------------------------------------------- /dokan_fuse/dokan_fuse.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Source Files 6 | 7 | 8 | Source Files 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | 50 | 51 | {F62D76B2-8E06-40C3-8464-5E72EA562C3F} 52 | 53 | 54 | {FF79298E-CCE0-41AB-88E5-A2C622984E41} 55 | 56 | 57 | {e33d6674-e9b8-41fc-aaf8-95e971b27e7a} 58 | 59 | 60 | 61 | 62 | Resource Files 63 | 64 | 65 | 66 | 67 | Source Files 68 | 69 | 70 | -------------------------------------------------------------------------------- /dokan_fuse/include/ScopeGuard.h: -------------------------------------------------------------------------------- 1 | #ifndef SCOPEGUARD_H_ 2 | #define SCOPEGUARD_H_ 3 | 4 | #include 5 | 6 | template 7 | class RefHolder 8 | { 9 | T& ref_; 10 | public: 11 | RefHolder(T& ref) : ref_(ref) {} 12 | operator T& () const 13 | { 14 | return ref_; 15 | } 16 | private: 17 | // Disable assignment - not implemented 18 | RefHolder& operator=(const RefHolder&); 19 | }; 20 | 21 | template 22 | inline RefHolder ByRef(T& t) 23 | { 24 | return RefHolder(t); 25 | } 26 | 27 | class ScopeGuardImplBase 28 | { 29 | ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); 30 | protected: 31 | ~ScopeGuardImplBase() 32 | { 33 | } 34 | ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() 35 | : dismissed_(other.dismissed_) 36 | { 37 | other.Dismiss(); 38 | } 39 | template 40 | static void SafeExecute(J& j) throw() 41 | { 42 | if (!j.dismissed_) 43 | try 44 | { 45 | j.Execute(); 46 | } 47 | catch(...) 48 | { 49 | assert(!"Exception while performing cleanup!"); 50 | } 51 | } 52 | 53 | mutable bool dismissed_; 54 | public: 55 | ScopeGuardImplBase() throw() : dismissed_(false) 56 | { 57 | } 58 | void Dismiss() const throw() 59 | { 60 | dismissed_ = true; 61 | } 62 | }; 63 | 64 | typedef const ScopeGuardImplBase& ScopeGuard; 65 | 66 | template 67 | class ScopeGuardImpl0 : public ScopeGuardImplBase 68 | { 69 | public: 70 | static ScopeGuardImpl0 MakeGuard(F fun) 71 | { 72 | return ScopeGuardImpl0(fun); 73 | } 74 | ~ScopeGuardImpl0() throw() 75 | { 76 | SafeExecute(*this); 77 | } 78 | void Execute() 79 | { 80 | fun_(); 81 | } 82 | protected: 83 | ScopeGuardImpl0(F fun) : fun_(fun) 84 | { 85 | } 86 | F fun_; 87 | }; 88 | 89 | template 90 | inline ScopeGuardImpl0 MakeGuard(F fun) 91 | { 92 | return ScopeGuardImpl0::MakeGuard(fun); 93 | } 94 | 95 | template 96 | class ScopeGuardImpl1 : public ScopeGuardImplBase 97 | { 98 | public: 99 | static ScopeGuardImpl1 MakeGuard(F fun, P1 p1) 100 | { 101 | return ScopeGuardImpl1(fun, p1); 102 | } 103 | ~ScopeGuardImpl1() throw() 104 | { 105 | SafeExecute(*this); 106 | } 107 | void Execute() 108 | { 109 | fun_(p1_); 110 | } 111 | protected: 112 | ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) 113 | { 114 | } 115 | F fun_; 116 | const P1 p1_; 117 | }; 118 | 119 | template 120 | inline ScopeGuardImpl1 MakeGuard(F fun, P1 p1) 121 | { 122 | return ScopeGuardImpl1::MakeGuard(fun, p1); 123 | } 124 | 125 | template 126 | class ScopeGuardImpl2: public ScopeGuardImplBase 127 | { 128 | public: 129 | static ScopeGuardImpl2 MakeGuard(F fun, P1 p1, P2 p2) 130 | { 131 | return ScopeGuardImpl2(fun, p1, p2); 132 | } 133 | ~ScopeGuardImpl2() throw() 134 | { 135 | SafeExecute(*this); 136 | } 137 | void Execute() 138 | { 139 | fun_(p1_, p2_); 140 | } 141 | protected: 142 | ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) 143 | { 144 | } 145 | F fun_; 146 | const P1 p1_; 147 | const P2 p2_; 148 | }; 149 | 150 | template 151 | inline ScopeGuardImpl2 MakeGuard(F fun, P1 p1, P2 p2) 152 | { 153 | return ScopeGuardImpl2::MakeGuard(fun, p1, p2); 154 | } 155 | 156 | template 157 | class ScopeGuardImpl3 : public ScopeGuardImplBase 158 | { 159 | public: 160 | static ScopeGuardImpl3 MakeGuard(F fun, P1 p1, P2 p2, P3 p3) 161 | { 162 | return ScopeGuardImpl3(fun, p1, p2, p3); 163 | } 164 | ~ScopeGuardImpl3() throw() 165 | { 166 | SafeExecute(*this); 167 | } 168 | void Execute() 169 | { 170 | fun_(p1_, p2_, p3_); 171 | } 172 | protected: 173 | ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) 174 | { 175 | } 176 | F fun_; 177 | const P1 p1_; 178 | const P2 p2_; 179 | const P3 p3_; 180 | }; 181 | 182 | template 183 | inline ScopeGuardImpl3 MakeGuard(F fun, P1 p1, P2 p2, P3 p3) 184 | { 185 | return ScopeGuardImpl3::MakeGuard(fun, p1, p2, p3); 186 | } 187 | 188 | //************************************************************ 189 | 190 | template 191 | class ObjScopeGuardImpl0 : public ScopeGuardImplBase 192 | { 193 | public: 194 | static ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) 195 | { 196 | return ObjScopeGuardImpl0(obj, memFun); 197 | } 198 | ~ObjScopeGuardImpl0() throw() 199 | { 200 | SafeExecute(*this); 201 | } 202 | void Execute() 203 | { 204 | (obj_.*memFun_)(); 205 | } 206 | protected: 207 | ObjScopeGuardImpl0(Obj& obj, MemFun memFun) 208 | : obj_(obj), memFun_(memFun) {} 209 | Obj& obj_; 210 | MemFun memFun_; 211 | }; 212 | 213 | template 214 | inline ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) 215 | { 216 | return ObjScopeGuardImpl0::MakeObjGuard(obj, memFun); 217 | } 218 | 219 | template 220 | class ObjScopeGuardImpl1 : public ScopeGuardImplBase 221 | { 222 | public: 223 | static ObjScopeGuardImpl1 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) 224 | { 225 | return ObjScopeGuardImpl1(obj, memFun, p1); 226 | } 227 | ~ObjScopeGuardImpl1() throw() 228 | { 229 | SafeExecute(*this); 230 | } 231 | void Execute() 232 | { 233 | (obj_.*memFun_)(p1_); 234 | } 235 | protected: 236 | ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) 237 | : obj_(obj), memFun_(memFun), p1_(p1) {} 238 | Obj& obj_; 239 | MemFun memFun_; 240 | const P1 p1_; 241 | }; 242 | 243 | template 244 | inline ObjScopeGuardImpl1 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) 245 | { 246 | return ObjScopeGuardImpl1::MakeObjGuard(obj, memFun, p1); 247 | } 248 | 249 | template 250 | class ObjScopeGuardImpl2 : public ScopeGuardImplBase 251 | { 252 | public: 253 | static ObjScopeGuardImpl2 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 254 | { 255 | return ObjScopeGuardImpl2(obj, memFun, p1, p2); 256 | } 257 | ~ObjScopeGuardImpl2() throw() 258 | { 259 | SafeExecute(*this); 260 | } 261 | void Execute() 262 | { 263 | (obj_.*memFun_)(p1_, p2_); 264 | } 265 | protected: 266 | ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) 267 | : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} 268 | Obj& obj_; 269 | MemFun memFun_; 270 | const P1 p1_; 271 | const P2 p2_; 272 | }; 273 | 274 | template 275 | inline ObjScopeGuardImpl2 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 276 | { 277 | return ObjScopeGuardImpl2::MakeObjGuard(obj, memFun, p1, p2); 278 | } 279 | 280 | #define CONCATENATE_DIRECT(s1, s2) s1##s2 281 | #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2) 282 | #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__) 283 | 284 | #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard 285 | #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard 286 | 287 | #endif //SCOPEGUARD_H_ 288 | -------------------------------------------------------------------------------- /dokan_fuse/include/docanfuse.h: -------------------------------------------------------------------------------- 1 | #ifndef _DOCAN_FUSE_H_ 2 | #define _DOCAN_FUSE_H_ 3 | 4 | #include 5 | 6 | #define FUSE_THREAD_COUNT 10 7 | #define DOKAN_DLL L"dokan" DOKAN_MAJOR_API_VERSION L".dll" 8 | 9 | struct fuse_config 10 | { 11 | unsigned int umask; 12 | unsigned int fileumask, dirumask; 13 | const char *fsname, *volname; 14 | int help; 15 | int debug; 16 | int setsignals; 17 | unsigned int timeoutInSec; 18 | }; 19 | 20 | struct fuse_session 21 | { 22 | fuse_chan *ch; 23 | }; 24 | 25 | struct fuse_chan 26 | { 27 | fuse_chan():ResolvedDokanMain(NULL), ResolvedDokanUnmount(NULL), ResolvedDokanRemoveMountPoint(NULL), dokanDll(NULL) {} 28 | ~fuse_chan(); 29 | 30 | //This method dynamically loads DOKAN functions 31 | bool init(); 32 | 33 | typedef int (__stdcall *DokanMainType)(PDOKAN_OPTIONS,PDOKAN_OPERATIONS); 34 | typedef BOOL (__stdcall *DokanUnmountType)(WCHAR DriveLetter); 35 | typedef BOOL (__stdcall *DokanRemoveMountPointType)(LPCWSTR MountPoint); 36 | DokanMainType ResolvedDokanMain; 37 | DokanUnmountType ResolvedDokanUnmount; 38 | DokanRemoveMountPointType ResolvedDokanRemoveMountPoint; 39 | 40 | std::string mountpoint; 41 | private: 42 | HMODULE dokanDll; 43 | }; 44 | 45 | struct fuse 46 | { 47 | bool within_loop; 48 | std::unique_ptr ch; 49 | fuse_session sess; 50 | fuse_config conf; 51 | 52 | struct fuse_operations ops; 53 | void *user_data; 54 | 55 | fuse() : within_loop(), user_data() 56 | { 57 | memset(&conf,0,sizeof(fuse_config)); 58 | memset(&sess, 0, sizeof(fuse_session)); 59 | memset(&ops, 0, sizeof(fuse_operations)); 60 | } 61 | }; 62 | 63 | #endif //_DOCAN_FUSE_H_ 64 | -------------------------------------------------------------------------------- /dokan_fuse/include/fuse_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | FUSE: Filesystem in Userspace 3 | Copyright (C) 2001-2007 Miklos Szeredi 4 | 5 | This program can be distributed under the terms of the GNU LGPLv2. 6 | See the file COPYING.LIB. 7 | */ 8 | 9 | /** @file */ 10 | 11 | #if !defined(_FUSE_H_) && !defined(_FUSE_LOWLEVEL_H_) 12 | #error "Never include directly; use or instead." 13 | #endif 14 | 15 | #ifndef _FUSE_COMMON_H_ 16 | #define _FUSE_COMMON_H_ 17 | 18 | #include "fuse_opt.h" 19 | #ifndef _MSC_VER 20 | #include 21 | #endif 22 | 23 | /** Major version of FUSE library interface */ 24 | #define FUSE_MAJOR_VERSION 2 25 | 26 | /** Minor version of FUSE library interface */ 27 | #define FUSE_MINOR_VERSION 7 28 | 29 | #define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min)) 30 | #define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) 31 | 32 | /* This interface uses 64 bit off_t, except on Windows where it's 33 | possible to use 32-bit filelengths for compatibility with MSVC CRT */ 34 | #ifndef WIN32 35 | /* This interface uses 64 bit off_t */ 36 | #if _FILE_OFFSET_BITS != 64 37 | #error Please add -D_FILE_OFFSET_BITS=64 to your compile flags! 38 | #endif 39 | #endif 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /** 46 | * Information about open files 47 | * 48 | * Changed in version 2.5 49 | */ 50 | struct fuse_file_info { 51 | /** Open flags. Available in open() and release() */ 52 | int flags; 53 | 54 | /** Old file handle, don't use */ 55 | unsigned long fh_old; 56 | 57 | /** In case of a write operation indicates if this was caused by a 58 | writepage */ 59 | int writepage; 60 | 61 | /** Can be filled in by open, to use direct I/O on this file. 62 | Introduced in version 2.4 */ 63 | unsigned int direct_io : 1; 64 | 65 | /** Can be filled in by open, to indicate, that cached file data 66 | need not be invalidated. Introduced in version 2.4 */ 67 | unsigned int keep_cache : 1; 68 | 69 | /** Indicates a flush operation. Set in flush operation, also 70 | maybe set in highlevel lock operation and lowlevel release 71 | operation. Introduced in version 2.6 */ 72 | unsigned int flush : 1; 73 | 74 | /** Padding. Do not use*/ 75 | unsigned int padding : 29; 76 | 77 | /** File handle. May be filled in by filesystem in open(). 78 | Available in all other file operations */ 79 | uint64_t fh; 80 | 81 | /** Lock owner id. Available in locking operations and flush */ 82 | uint64_t lock_owner; 83 | }; 84 | 85 | /** 86 | * Connection information, passed to the ->init() method 87 | * 88 | * Some of the elements are read-write, these can be changed to 89 | * indicate the value requested by the filesystem. The requested 90 | * value must usually be smaller than the indicated value. 91 | */ 92 | struct fuse_conn_info { 93 | /** 94 | * Major version of the protocol (read-only) 95 | */ 96 | unsigned proto_major; 97 | 98 | /** 99 | * Minor version of the protocol (read-only) 100 | */ 101 | unsigned proto_minor; 102 | 103 | /** 104 | * Is asynchronous read supported (read-write) 105 | */ 106 | unsigned async_read; 107 | 108 | /** 109 | * Maximum size of the write buffer 110 | */ 111 | unsigned max_write; 112 | 113 | /** 114 | * Maximum readahead 115 | */ 116 | unsigned max_readahead; 117 | 118 | /** 119 | * For future use. 120 | */ 121 | unsigned reserved[27]; 122 | }; 123 | 124 | struct fuse_session; 125 | struct fuse_chan; 126 | 127 | /** 128 | * Create a FUSE mountpoint 129 | * 130 | * Returns a control file descriptor suitable for passing to 131 | * fuse_new() 132 | * 133 | * @param mountpoint the mount point path 134 | * @param args argument vector 135 | * @return the communication channel on success, NULL on failure 136 | */ 137 | struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args); 138 | 139 | /** 140 | * Umount a FUSE mountpoint 141 | * 142 | * @param mountpoint the mount point path 143 | * @param ch the communication channel 144 | */ 145 | void fuse_unmount(const char *mountpoint, struct fuse_chan *ch); 146 | 147 | /** 148 | * Parse common options 149 | * 150 | * The following options are parsed: 151 | * 152 | * '-f' foreground 153 | * '-d' '-odebug' foreground, but keep the debug option 154 | * '-s' single threaded 155 | * '-h' '--help' help 156 | * '-ho' help without header 157 | * '-ofsname=..' file system name, if not present, then set to the program 158 | * name 159 | * 160 | * All parameters may be NULL 161 | * 162 | * @param args argument vector 163 | * @param mountpoint the returned mountpoint, should be freed after use 164 | * @param multithreaded set to 1 unless the '-s' option is present 165 | * @param foreground set to 1 if one of the relevant options is present 166 | * @return 0 on success, -1 on failure 167 | */ 168 | int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, 169 | int *multithreaded, int *foreground); 170 | 171 | /** 172 | * Go into the background 173 | * 174 | * @param foreground if true, stay in the foreground 175 | * @return 0 on success, -1 on failure 176 | */ 177 | int fuse_daemonize(int foreground); 178 | 179 | /** 180 | * Get the version of the library 181 | * 182 | * @return the version 183 | */ 184 | int fuse_version(void); 185 | 186 | /* ----------------------------------------------------------- * 187 | * Signal handling * 188 | * ----------------------------------------------------------- */ 189 | 190 | /** 191 | * Exit session on HUP, TERM and INT signals and ignore PIPE signal 192 | * 193 | * Stores session in a global variable. May only be called once per 194 | * process until fuse_remove_signal_handlers() is called. 195 | * 196 | * @param se the session to exit 197 | * @return 0 on success, -1 on failure 198 | */ 199 | int fuse_set_signal_handlers(struct fuse_session *se); 200 | 201 | /** 202 | * Restore default signal handlers 203 | * 204 | * Resets global session. After this fuse_set_signal_handlers() may 205 | * be called again. 206 | * 207 | * @param se the same session as given in fuse_set_signal_handlers() 208 | */ 209 | void fuse_remove_signal_handlers(struct fuse_session *se); 210 | 211 | /* ----------------------------------------------------------- * 212 | * Compatibility stuff * 213 | * ----------------------------------------------------------- */ 214 | 215 | #if FUSE_USE_VERSION < 26 216 | # ifdef __FreeBSD__ 217 | # if FUSE_USE_VERSION < 25 218 | # error On FreeBSD API version 25 or greater must be used 219 | # endif 220 | # endif 221 | # include "fuse_common_compat.h" 222 | # undef FUSE_MINOR_VERSION 223 | # undef fuse_main 224 | # define fuse_unmount fuse_unmount_compat22 225 | # if FUSE_USE_VERSION == 25 226 | # define FUSE_MINOR_VERSION 5 227 | # define fuse_mount fuse_mount_compat25 228 | # elif FUSE_USE_VERSION == 24 || FUSE_USE_VERSION == 22 229 | # define FUSE_MINOR_VERSION 4 230 | # define fuse_mount fuse_mount_compat22 231 | # elif FUSE_USE_VERSION == 21 232 | # define FUSE_MINOR_VERSION 1 233 | # define fuse_mount fuse_mount_compat22 234 | # elif FUSE_USE_VERSION == 11 235 | # warning Compatibility with API version 11 is deprecated 236 | # undef FUSE_MAJOR_VERSION 237 | # define FUSE_MAJOR_VERSION 1 238 | # define FUSE_MINOR_VERSION 1 239 | # define fuse_mount fuse_mount_compat1 240 | # else 241 | # error Compatibility with API version other than 21, 22, 24, 25 and 11 not supported 242 | # endif 243 | #endif 244 | 245 | #ifdef __cplusplus 246 | } 247 | #endif 248 | 249 | #endif /* _FUSE_COMMON_H_ */ 250 | -------------------------------------------------------------------------------- /dokan_fuse/include/fuse_opt.h: -------------------------------------------------------------------------------- 1 | /* 2 | FUSE: Filesystem in Userspace 3 | Copyright (C) 2001-2007 Miklos Szeredi 4 | 5 | This program can be distributed under the terms of the GNU LGPLv2. 6 | See the file COPYING.LIB. 7 | */ 8 | 9 | #ifndef _FUSE_OPT_H_ 10 | #define _FUSE_OPT_H_ 11 | 12 | /** @file 13 | * 14 | * This file defines the option parsing interface of FUSE 15 | */ 16 | 17 | #ifdef _MSC_VER 18 | #define STRDUP _strdup 19 | #else 20 | #define STRDUP strdup 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /** 28 | * Option description 29 | * 30 | * This structure describes a single option, and and action associated 31 | * with it, in case it matches. 32 | * 33 | * More than one such match may occur, in which case the action for 34 | * each match is executed. 35 | * 36 | * There are three possible actions in case of a match: 37 | * 38 | * i) An integer (int or unsigned) variable determined by 'offset' is 39 | * set to 'value' 40 | * 41 | * ii) The processing function is called, with 'value' as the key 42 | * 43 | * iii) An integer (any) or string (char *) variable determined by 44 | * 'offset' is set to the value of an option parameter 45 | * 46 | * 'offset' should normally be either set to 47 | * 48 | * - 'offsetof(struct foo, member)' actions i) and iii) 49 | * 50 | * - -1 action ii) 51 | * 52 | * The 'offsetof()' macro is defined in the header. 53 | * 54 | * The template determines which options match, and also have an 55 | * effect on the action. Normally the action is either i) or ii), but 56 | * if a format is present in the template, then action iii) is 57 | * performed. 58 | * 59 | * The types of templates are: 60 | * 61 | * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only 62 | * themselves. Invalid values are "--" and anything beginning 63 | * with "-o" 64 | * 65 | * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or 66 | * the relevant option in a comma separated option list 67 | * 68 | * 3) "bar=", "--foo=", etc. These are variations of 1) and 2) 69 | * which have a parameter 70 | * 71 | * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform 72 | * action iii). 73 | * 74 | * 5) "-x ", etc. Matches either "-xparam" or "-x param" as 75 | * two separate arguments 76 | * 77 | * 6) "-x %s", etc. Combination of 4) and 5) 78 | * 79 | * If the format is "%s", memory is allocated for the string unlike 80 | * with scanf(). 81 | */ 82 | struct fuse_opt { 83 | /** Matching template and optional parameter formatting */ 84 | const char *templ; 85 | 86 | /** 87 | * Offset of variable within 'data' parameter of fuse_opt_parse() 88 | * or -1 89 | */ 90 | unsigned long offset; 91 | 92 | /** 93 | * Value to set the variable to, or to be passed as 'key' to the 94 | * processing function. Ignored if template has a format 95 | */ 96 | int value; 97 | }; 98 | 99 | /** 100 | * Key option. In case of a match, the processing function will be 101 | * called with the specified key. 102 | */ 103 | #define FUSE_OPT_KEY(templ, key) { templ, (unsigned int)(-1), key } 104 | 105 | /** 106 | * Last option. An array of 'struct fuse_opt' must end with a NULL 107 | * template value 108 | */ 109 | #define FUSE_OPT_END { NULL } 110 | 111 | /** 112 | * Argument list 113 | */ 114 | struct fuse_args { 115 | /** Argument count */ 116 | int argc; 117 | 118 | /** Argument vector. NULL terminated */ 119 | char **argv; 120 | 121 | /** Is 'argv' allocated? */ 122 | int allocated; 123 | }; 124 | 125 | /** 126 | * Initializer for 'struct fuse_args' 127 | */ 128 | #define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } 129 | 130 | /** 131 | * Key value passed to the processing function if an option did not 132 | * match any template 133 | */ 134 | #define FUSE_OPT_KEY_OPT -1 135 | 136 | /** 137 | * Key value passed to the processing function for all non-options 138 | * 139 | * Non-options are the arguments beginning with a charater other than 140 | * '-' or all arguments after the special '--' option 141 | */ 142 | #define FUSE_OPT_KEY_NONOPT -2 143 | 144 | /** 145 | * Special key value for options to keep 146 | * 147 | * Argument is not passed to processing function, but behave as if the 148 | * processing function returned 1 149 | */ 150 | #define FUSE_OPT_KEY_KEEP -3 151 | 152 | /** 153 | * Special key value for options to discard 154 | * 155 | * Argument is not passed to processing function, but behave as if the 156 | * processing function returned zero 157 | */ 158 | #define FUSE_OPT_KEY_DISCARD -4 159 | 160 | /** 161 | * Processing function 162 | * 163 | * This function is called if 164 | * - option did not match any 'struct fuse_opt' 165 | * - argument is a non-option 166 | * - option did match and offset was set to -1 167 | * 168 | * The 'arg' parameter will always contain the whole argument or 169 | * option including the parameter if exists. A two-argument option 170 | * ("-x foo") is always converted to single arguemnt option of the 171 | * form "-xfoo" before this function is called. 172 | * 173 | * Options of the form '-ofoo' are passed to this function without the 174 | * '-o' prefix. 175 | * 176 | * The return value of this function determines whether this argument 177 | * is to be inserted into the output argument vector, or discarded. 178 | * 179 | * @param data is the user data passed to the fuse_opt_parse() function 180 | * @param arg is the whole argument or option 181 | * @param key determines why the processing function was called 182 | * @param outargs the current output argument list 183 | * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept 184 | */ 185 | typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, 186 | struct fuse_args *outargs); 187 | 188 | /** 189 | * Option parsing function 190 | * 191 | * If 'args' was returned from a previous call to fuse_opt_parse() or 192 | * it was constructed from 193 | * 194 | * A NULL 'args' is equivalent to an empty argument vector 195 | * 196 | * A NULL 'opts' is equivalent to an 'opts' array containing a single 197 | * end marker 198 | * 199 | * A NULL 'proc' is equivalent to a processing function always 200 | * returning '1' 201 | * 202 | * @param args is the input and output argument list 203 | * @param data is the user data 204 | * @param opts is the option description array 205 | * @param proc is the processing function 206 | * @return -1 on error, 0 on success 207 | */ 208 | int fuse_opt_parse(struct fuse_args *args, void *data, 209 | const struct fuse_opt opts[], fuse_opt_proc_t proc); 210 | 211 | /** 212 | * Add an option to a comma separated option list 213 | * 214 | * @param opts is a pointer to an option list, may point to a NULL value 215 | * @param opt is the option to add 216 | * @return -1 on allocation error, 0 on success 217 | */ 218 | int fuse_opt_add_opt(char **opts, const char *opt); 219 | 220 | /** 221 | * Add an argument to a NULL terminated argument vector 222 | * 223 | * @param args is the structure containing the current argument list 224 | * @param arg is the new argument to add 225 | * @return -1 on allocation error, 0 on success 226 | */ 227 | int fuse_opt_add_arg(struct fuse_args *args, const char *arg); 228 | 229 | /** 230 | * Add an argument at the specified position in a NULL terminated 231 | * argument vector 232 | * 233 | * Adds the argument to the N-th position. This is useful for adding 234 | * options at the beggining of the array which must not come after the 235 | * special '--' option. 236 | * 237 | * @param args is the structure containing the current argument list 238 | * @param pos is the position at which to add the argument 239 | * @param arg is the new argument to add 240 | * @return -1 on allocation error, 0 on success 241 | */ 242 | int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg); 243 | 244 | /** 245 | * Free the contents of argument list 246 | * 247 | * The structure itself is not freed 248 | * 249 | * @param args is the structure containing the argument list 250 | */ 251 | void fuse_opt_free_args(struct fuse_args *args); 252 | 253 | 254 | /** 255 | * Check if an option matches 256 | * 257 | * @param opts is the option description array 258 | * @param opt is the option to match 259 | * @return 1 if a match is found, 0 if not 260 | */ 261 | int fuse_opt_match(const struct fuse_opt opts[], const char *opt); 262 | 263 | #ifdef __cplusplus 264 | } 265 | #endif 266 | 267 | #endif /* _FUSE_OPT_H_ */ 268 | -------------------------------------------------------------------------------- /dokan_fuse/include/fuse_sem_fix.h: -------------------------------------------------------------------------------- 1 | #ifndef FUSE_SEM_FIX_H 2 | #define FUSE_SEM_FIX_H 3 | 4 | #ifdef __CYGWIN__ 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | int my_sem_init(sem_t *sem, int pshared, int initial); 12 | int my_sem_destroy(sem_t *sem); 13 | int my_sem_post (sem_t * sem); 14 | int my_sem_wait (sem_t * sem); 15 | #define sem_init my_sem_init 16 | #define sem_destroy my_sem_destroy 17 | #define sem_wait my_sem_wait 18 | #define sem_post my_sem_post 19 | 20 | #ifdef __cplusplus 21 | }; 22 | #endif 23 | 24 | 25 | #endif 26 | 27 | #endif //FUSE_SEM_FIX_H 28 | -------------------------------------------------------------------------------- /dokan_fuse/include/fuse_win.h: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------- * 2 | * Win32 helper functions * 3 | * Compilation on MSVC requires /Zc:wchar_t compiler option * 4 | * ----------------------------------------------------------- */ 5 | #ifndef _FUSE_WIN_H_ 6 | #define _FUSE_WIN_H_ 7 | 8 | #include 9 | #include 10 | 11 | #ifdef _MSC_VER 12 | #include 13 | #endif 14 | 15 | /** Only use the latest version on Windows */ 16 | #ifndef FUSE_USE_VERSION 17 | #define FUSE_USE_VERSION 27 18 | #endif 19 | 20 | #ifndef DEFAULT_FUSE_VOLUME_NAME 21 | #define DEFAULT_FUSE_VOLUME_NAME "DOKAN" 22 | #endif 23 | 24 | #ifndef DEFAULT_FUSE_FILESYSTEM_NAME 25 | #define DEFAULT_FUSE_FILESYSTEM_NAME "Dokan user-level file system" 26 | #endif 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | int ntstatus_error_to_errno(int win_res); 32 | int errno_to_ntstatus_error(int err); 33 | 34 | // This stuff is useful only on Windows in MSVC 35 | #ifdef _MSC_VER 36 | char **convert_args(int argc, wchar_t *argv[]); 37 | void free_converted_args(int argc, char **argv); 38 | #endif 39 | 40 | #ifdef __cplusplus 41 | }; 42 | #endif 43 | 44 | extern wchar_t *Dokan_filesystem_name; 45 | extern wchar_t *Dokan_volume_name; 46 | 47 | ///////////////////////////////////////////////////////////////////// 48 | ////// Type definitions for MINGW32 49 | ///////////////////////////////////////////////////////////////////// 50 | #if defined(__MINGW32__) && !defined(UID_GID_DEF) 51 | typedef unsigned int gid_t; 52 | typedef unsigned int uid_t; 53 | #endif 54 | 55 | #if !defined(HAVE_STRUCT_TIMESPEC) && !defined(__CYGWIN__) && \ 56 | !defined(_TIMESPEC_DEFINED) && \ 57 | defined(_CRT_NO_TIME_T) /* win32 pthread.h time.h defines it */ 58 | /* POSIX.1b structure for a time value. This is like a `struct timeval' but 59 | has nanoseconds instead of microseconds. */ 60 | #define HAVE_STRUCT_TIMESPEC 1 61 | #define _TIMESPEC_DEFINED 62 | struct timespec { 63 | time_t tv_sec; /* Seconds. */ 64 | long int tv_nsec; /* Nanoseconds. */ 65 | }; 66 | #endif 67 | 68 | #if defined(__MINGW32__) 69 | /** Use 64 bit offsets */ 70 | #define __USE_FILE_OFFSET64 71 | // Block sizes 72 | typedef unsigned __int64 fsfilcnt64_t; 73 | typedef unsigned __int64 fsblkcnt64_t; 74 | typedef struct timespec timestruc_t; 75 | typedef unsigned short nlink_t; 76 | typedef unsigned __int64 uint64_t; 77 | typedef unsigned int blksize_t; 78 | typedef unsigned __int64 blkcnt_t; 79 | 80 | /** Transplanted from */ 81 | /* 82 | struct statvfs 83 | { 84 | unsigned long int f_bsize; 85 | unsigned long int f_frsize; 86 | fsblkcnt64_t f_blocks; 87 | fsblkcnt64_t f_bfree; 88 | fsblkcnt64_t f_bavail; 89 | fsfilcnt64_t f_files; 90 | fsfilcnt64_t f_ffree; 91 | fsfilcnt64_t f_favail; 92 | unsigned long int f_fsid; 93 | unsigned long int f_flag; 94 | unsigned long int f_namemax; 95 | };*/ 96 | struct flock { 97 | short l_type; 98 | short l_whence; 99 | off_t l_start; 100 | off_t l_len; 101 | pid_t l_pid; 102 | }; 103 | 104 | #endif 105 | 106 | ///////////////////////////////////////////////////////////////////// 107 | ////// Type definitions for MSVC 108 | ///////////////////////////////////////////////////////////////////// 109 | #if defined(_MSC_VER) 110 | // UNIX compatibility 111 | typedef struct timespec timestruc_t; 112 | typedef unsigned int mode_t; 113 | typedef unsigned short nlink_t; 114 | typedef unsigned int pid_t; 115 | typedef unsigned int gid_t; 116 | typedef unsigned int uid_t; 117 | typedef unsigned int blksize_t; 118 | typedef unsigned __int64 blkcnt_t; 119 | typedef unsigned int uint32_t; 120 | typedef unsigned __int64 uint64_t; 121 | typedef __int64 int64_t; 122 | 123 | // OCTAL constants! 124 | #define S_IFLNK 0120000 125 | #define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) 126 | 127 | /** Use 64 bit offsets */ 128 | #define __USE_FILE_OFFSET64 129 | // Block sizes 130 | typedef unsigned __int64 fsfilcnt64_t; 131 | typedef unsigned __int64 fsblkcnt64_t; 132 | 133 | /** Transplanted from */ 134 | /* 135 | struct statvfs { 136 | unsigned long int f_bsize; 137 | unsigned long int f_frsize; 138 | fsblkcnt64_t f_blocks; 139 | fsblkcnt64_t f_bfree; 140 | fsblkcnt64_t f_bavail; 141 | fsfilcnt64_t f_files; 142 | fsfilcnt64_t f_ffree; 143 | fsfilcnt64_t f_favail; 144 | unsigned long int f_fsid; 145 | unsigned long int f_flag; 146 | unsigned long int f_namemax; 147 | };*/ 148 | 149 | struct flock { 150 | short l_type; 151 | short l_whence; 152 | __int64 l_start; 153 | __int64 l_len; 154 | pid_t l_pid; 155 | }; 156 | 157 | #endif 158 | 159 | // We have a choice between CRT-compatible 32-bit off_t definition 160 | // and a custom 64-bit definition 161 | #define WIDE_OFF_T 1 162 | #ifndef WIDE_OFF_T 163 | #define FUSE_OFF_T off_t 164 | #define FUSE_STAT stat 165 | 166 | #else 167 | #define FUSE_OFF_T __int64 168 | // #define FUSE_STAT _stati64 169 | // use stat from cygwin instead for having more members and 170 | // being more compatible 171 | // stat ported from cygwin sys/stat.h 172 | /* 173 | struct stat64_cygwin { 174 | dev_t st_dev; 175 | uint64_t st_ino; 176 | mode_t st_mode; 177 | nlink_t st_nlink; 178 | uid_t st_uid; 179 | gid_t st_gid; 180 | dev_t st_rdev; 181 | FUSE_OFF_T st_size; 182 | timestruc_t st_atim; 183 | timestruc_t st_mtim; 184 | timestruc_t st_ctim; 185 | blksize_t st_blksize; 186 | blkcnt_t st_blocks; 187 | timestruc_t st_birthtim; 188 | };*/ 189 | /* The following breaks struct stat definiton in native Windows stats.h 190 | * So whenever referencing st_atime|st_ctime|st_mtime, replacing is needed. 191 | */ 192 | /* 193 | #define st_atime st_atim.tv_sec 194 | #define st_ctime st_ctim.tv_sec 195 | #define st_mtime st_mtim.tv_sec 196 | */ 197 | //#define FUSE_STAT stat 198 | #if 0 199 | struct stat64 { 200 | dev_t st_dev; 201 | ino_t st_ino; 202 | unsigned short st_mode; 203 | short st_nlink; 204 | short st_uid; 205 | short st_gid; 206 | dev_t st_rdev; 207 | FUSE_OFF_T st_size; 208 | time_t st_atime; 209 | time_t st_mtime; 210 | time_t st_ctime; 211 | }; 212 | #endif 213 | #endif 214 | 215 | #define F_WRLCK 1 216 | #define F_UNLCK 2 217 | #define F_SETLK 6 218 | 219 | #endif //_FUSE_WIN_H_ 220 | -------------------------------------------------------------------------------- /dokan_fuse/include/fusemain.h: -------------------------------------------------------------------------------- 1 | #ifndef FUSEMAIN_H 2 | #define FUSEMAIN_H 3 | 4 | #include "dokan.h" 5 | #include "fuse.h" 6 | #include "utils.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define CHECKED(arg) \ 13 | if (0) \ 14 | ; \ 15 | else { \ 16 | int __res = arg; \ 17 | if (__res < 0) \ 18 | return __res; \ 19 | } 20 | #define MAX_READ_SIZE (65536) 21 | 22 | class impl_fuse_context; 23 | struct impl_chain_link; 24 | 25 | class impl_file_handle; 26 | class impl_file_lock; 27 | 28 | class impl_file_locks { 29 | private: 30 | typedef std::map file_locks_t; 31 | file_locks_t file_locks; 32 | CRITICAL_SECTION lock; 33 | 34 | public: 35 | impl_file_locks() { InitializeCriticalSection(&lock); } 36 | ~impl_file_locks() { DeleteCriticalSection(&lock); }; 37 | int get_file(const std::string &name, bool is_dir, DWORD access_mode, 38 | DWORD shared_mode, std::unique_ptr &out); 39 | void renamed_file(const std::string &name, const std::string &new_name); 40 | void remove_file(const std::string &name); 41 | }; 42 | 43 | struct impl_chain_link { 44 | impl_chain_link *prev_link_; 45 | fuse_context call_ctx_; 46 | impl_chain_link() : prev_link_(nullptr) { 47 | memset(&call_ctx_, 0, sizeof(call_ctx_)); 48 | } 49 | }; 50 | 51 | /* 52 | This class pushes the impl_fuse_context frame on a thread-local stack, 53 | this allows to have reentrant FUSE filesystem (if anyone really wants 54 | it one day...) 55 | */ 56 | class impl_chain_guard { 57 | impl_chain_link link; 58 | 59 | public: 60 | impl_chain_guard(impl_fuse_context *ctx, int caller_pid); 61 | ~impl_chain_guard(); 62 | }; 63 | 64 | class win_error { 65 | public: 66 | win_error(int _err) : err(errno_to_ntstatus_error(_err)) {} 67 | win_error(int _err, bool) : err(_err) {} 68 | operator int() { return err; } 69 | 70 | private: 71 | int err; 72 | }; 73 | /* 74 | FUSE filesystem context 75 | */ 76 | class impl_fuse_context { 77 | friend class impl_chain_guard; 78 | 79 | struct fuse_operations ops_; 80 | fuse_conn_info conn_info_; 81 | void *user_data_; 82 | bool debug_; 83 | 84 | unsigned int filemask_; 85 | unsigned int dirmask_; 86 | const char *fsname_, *volname_; 87 | 88 | impl_file_locks file_locks; 89 | 90 | public: 91 | impl_fuse_context(const struct fuse_operations *ops, void *user_data, 92 | bool debug, unsigned int filemask, unsigned int dirmask, 93 | const char *fsname, const char *volname); 94 | 95 | bool debug() const { return debug_; } 96 | 97 | ////////////////////////////////////Methods/////////////////////////////// 98 | static int cast_from_longlong(LONGLONG src, FUSE_OFF_T *res); 99 | 100 | int do_open_dir(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo); 101 | 102 | int do_open_file(LPCWSTR FileName, DWORD share_mode, DWORD Flags, 103 | PDOKAN_FILE_INFO DokanFileInfo); 104 | 105 | int do_create_file(LPCWSTR FileName, DWORD Disposition, DWORD share_mode, 106 | DWORD Flags, PDOKAN_FILE_INFO DokanFileInfo); 107 | 108 | int do_delete_directory(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 109 | 110 | int do_delete_file(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 111 | 112 | int convert_flags(DWORD Flags); 113 | 114 | int resolve_symlink(const std::string &name, std::string *res); 115 | int check_and_resolve(std::string *name); 116 | 117 | struct walk_data { 118 | impl_fuse_context *ctx; 119 | std::string dirname; 120 | PDOKAN_FILE_INFO DokanFileInfo; 121 | PFillFindData delegate; 122 | std::vector getdir_data; // Used only in 123 | // walk_directory_getdir() 124 | }; 125 | static int walk_directory(void *buf, const char *name, 126 | const struct stat *stbuf, FUSE_OFF_T off); 127 | static int walk_directory_getdir(fuse_dirh_t hndl, const char *name, int type, 128 | ino_t ino); 129 | 130 | ///////////////////////////////////Delegates////////////////////////////// 131 | int find_files(LPCWSTR file_name, PFillFindData fill_find_data, 132 | PDOKAN_FILE_INFO dokan_file_info); 133 | 134 | int open_directory(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 135 | 136 | int cleanup(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 137 | 138 | int create_directory(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 139 | 140 | int delete_directory(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 141 | 142 | win_error create_file(LPCWSTR file_name, DWORD access_mode, DWORD share_mode, 143 | DWORD creation_disposition, DWORD flags_and_attributes, 144 | PDOKAN_FILE_INFO dokan_file_info); 145 | 146 | int close_file(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 147 | 148 | int read_file(LPCWSTR file_name, LPVOID buffer, DWORD num_bytes_to_read, 149 | LPDWORD read_bytes, LONGLONG offset, 150 | PDOKAN_FILE_INFO dokan_file_info); 151 | 152 | int write_file(LPCWSTR file_name, LPCVOID buffer, DWORD num_bytes_to_write, 153 | LPDWORD num_bytes_written, LONGLONG offset, 154 | PDOKAN_FILE_INFO dokan_file_info); 155 | 156 | int flush_file_buffers(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 157 | 158 | int get_file_information(LPCWSTR file_name, 159 | LPBY_HANDLE_FILE_INFORMATION handle_file_information, 160 | PDOKAN_FILE_INFO dokan_file_info); 161 | 162 | int delete_file(LPCWSTR file_name, PDOKAN_FILE_INFO dokan_file_info); 163 | 164 | int move_file(LPCWSTR file_name, LPCWSTR new_file_name, BOOL replace_existing, 165 | PDOKAN_FILE_INFO dokan_file_info); 166 | 167 | int lock_file(LPCWSTR file_name, LONGLONG byte_offset, LONGLONG length, 168 | PDOKAN_FILE_INFO dokan_file_info); 169 | 170 | int unlock_file(LPCWSTR file_name, LONGLONG byte_offset, LONGLONG length, 171 | PDOKAN_FILE_INFO dokan_file_info); 172 | 173 | int set_end_of_file(LPCWSTR file_name, LONGLONG byte_offset, 174 | PDOKAN_FILE_INFO dokan_file_info); 175 | 176 | int set_file_attributes(LPCWSTR file_name, DWORD file_attributes, 177 | PDOKAN_FILE_INFO dokan_file_info); 178 | 179 | int helper_set_time_struct(const FILETIME *filetime, const time_t backup, 180 | time_t *dest); 181 | 182 | int set_file_time(PCWSTR file_name, const FILETIME *creation_time, 183 | const FILETIME *last_access_time, 184 | const FILETIME *last_write_time, 185 | PDOKAN_FILE_INFO dokan_file_info); 186 | 187 | int get_disk_free_space(PULONGLONG free_bytes_available, 188 | PULONGLONG number_of_bytes, 189 | PULONGLONG number_of_free_bytes, 190 | PDOKAN_FILE_INFO dokan_file_info); 191 | 192 | int get_volume_information(LPWSTR volume_name_buffer, DWORD volume_name_size, 193 | LPWSTR file_system_name_buffer, 194 | DWORD file_system_name_size, 195 | PDOKAN_FILE_INFO dokan_file_info, 196 | LPDWORD volume_flags); 197 | 198 | int mounted(PDOKAN_FILE_INFO DokanFileInfo); 199 | 200 | int unmounted(PDOKAN_FILE_INFO DokanFileInfo); 201 | }; 202 | 203 | class impl_file_lock { 204 | friend class impl_file_handle; 205 | friend class impl_file_locks; 206 | std::string name_; 207 | impl_file_locks *locks; 208 | impl_file_handle *first; 209 | CRITICAL_SECTION lock; 210 | 211 | void add_file_unlocked(impl_file_handle *file); 212 | int lock_file(impl_file_handle *file, long long start, long long len, 213 | bool mark = true); 214 | int unlock_file(impl_file_handle *file, long long start, long long len); 215 | 216 | public: 217 | impl_file_lock(impl_file_locks *_locks, const std::string &name) 218 | : locks(_locks), name_(name), first(NULL) { 219 | InitializeCriticalSection(&lock); 220 | } 221 | ~impl_file_lock() { DeleteCriticalSection(&lock); }; 222 | void remove_file(impl_file_handle *file); 223 | const std::string &get_name() const { return name_; } 224 | }; 225 | 226 | class impl_file_handle { 227 | friend class impl_file_lock; 228 | friend class impl_file_locks; 229 | bool is_dir_; 230 | uint64_t fh_; 231 | impl_file_handle *next_file; 232 | impl_file_lock *file_lock; 233 | DWORD shared_mode_; 234 | typedef std::map locks_t; 235 | locks_t locks; 236 | impl_file_handle(bool is_dir, DWORD shared_mode); 237 | 238 | public: 239 | ~impl_file_handle(); 240 | 241 | bool is_dir() const { return is_dir_; } 242 | int close(const struct fuse_operations *ops); 243 | fuse_file_info make_finfo(); 244 | const std::string &get_name() const { return file_lock->get_name(); } 245 | void set_finfo(const fuse_file_info &finfo) { fh_ = finfo.fh; }; 246 | int check_lock(long long start, long long len) { 247 | return file_lock->lock_file(this, start, len, false); 248 | } 249 | int lock(long long start, long long len) { 250 | return file_lock->lock_file(this, start, len); 251 | } 252 | int unlock(long long start, long long len) { 253 | return file_lock->unlock_file(this, start, len); 254 | } 255 | }; 256 | 257 | #endif // FUSEMAIN_H 258 | -------------------------------------------------------------------------------- /dokan_fuse/include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | #include 5 | #include 6 | #include "fuse.h" 7 | 8 | /*#ifdef _MSC_VER 9 | #define DLLLOCAL 10 | #else 11 | #define DLLLOCAL __attribute__ ((visibility("hidden"))) 12 | #endif*/ 13 | 14 | void utf8_to_wchar_buf_old(const char *src, wchar_t *res, int maxlen); 15 | void utf8_to_wchar_buf(const char *src, wchar_t *res, int maxlen); 16 | std::string wchar_to_utf8_cstr(const wchar_t *str); 17 | 18 | std::string unixify(const std::string &str); 19 | std::string extract_file_name(const std::string &str); 20 | std::string extract_dir_name(const std::string &str); 21 | 22 | FILETIME unixTimeToFiletime(time_t t); 23 | time_t filetimeToUnixTime(const FILETIME *ft); 24 | bool is_filetime_set(const FILETIME *ft); 25 | 26 | template void convertStatlikeBuf(const struct stat *stbuf, const std::string &name, 27 | T * find_data) 28 | { 29 | if (stbuf==NULL) return; 30 | 31 | if ((stbuf->st_mode&S_IFDIR)==S_IFDIR) 32 | find_data->dwFileAttributes=FILE_ATTRIBUTE_DIRECTORY; 33 | else 34 | find_data->dwFileAttributes=FILE_ATTRIBUTE_NORMAL; 35 | 36 | #ifndef WIDE_OFF_T 37 | find_data->nFileSizeLow=stbuf->st_size; 38 | #else 39 | //Support 64 sizes 40 | find_data->nFileSizeLow=(DWORD) stbuf->st_size; 41 | find_data->nFileSizeHigh=stbuf->st_size>>32; 42 | #endif 43 | if (stbuf->st_ctim.tv_sec!=0) 44 | find_data->ftCreationTime=unixTimeToFiletime(stbuf->st_ctim.tv_sec); 45 | if (stbuf->st_atim.tv_sec!=0) 46 | find_data->ftLastAccessTime=unixTimeToFiletime(stbuf->st_atim.tv_sec); 47 | if (stbuf->st_mtim.tv_sec!=0) 48 | find_data->ftLastWriteTime=unixTimeToFiletime(stbuf->st_mtim.tv_sec); 49 | 50 | //Partial support for read-only files - currently done for a files without write permission only 51 | if (!(stbuf->st_mode&0222)) 52 | find_data->dwFileAttributes|=FILE_ATTRIBUTE_READONLY; 53 | //TODO: add full support for read-only files - try to derive it from file's owner? 54 | std::string fname=extract_file_name(name); 55 | if (!fname.empty() && fname.at(0)=='.') //UNIX hidden files 56 | find_data->dwFileAttributes|=FILE_ATTRIBUTE_HIDDEN; 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /dokan_fuse/src/docanfuse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utils.h" 3 | #include "fusemain.h" 4 | #include "ScopeGuard.h" 5 | #include "docanfuse.h" 6 | //#include "../../dokan/dokani.h" 7 | #include 8 | 9 | #ifdef __CYGWIN__ 10 | #define FWPRINTF dummy_fwprintf 11 | int dummy_fwprintf(FILE *, const wchar_t *, ...) { return 0; } 12 | #elif defined(__GNUC__) 13 | #define FWPRINTF(f, args...) \ 14 | do { \ 15 | fwprintf(f, args); \ 16 | fflush(f); \ 17 | } while (0) 18 | #else 19 | #define FWPRINTF fwprintf 20 | #endif 21 | 22 | #define the_impl \ 23 | reinterpret_cast( \ 24 | DokanFileInfo->DokanOptions->GlobalContext) 25 | 26 | HINSTANCE hFuseDllInstance; 27 | 28 | extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, 29 | LPVOID lpReserved) { 30 | if (dwReason == DLL_PROCESS_ATTACH) { 31 | hFuseDllInstance = hInstance; 32 | DisableThreadLibraryCalls(hInstance); 33 | } 34 | return TRUE; 35 | } 36 | 37 | static NTSTATUS DOKAN_CALLBACK 38 | FuseFindFiles(LPCWSTR FileName, 39 | PFillFindData FillFindData, // function pointer 40 | PDOKAN_FILE_INFO DokanFileInfo) { 41 | impl_fuse_context *impl = the_impl; 42 | if (impl->debug()) 43 | FWPRINTF(stderr, L"FindFiles :%s\n", FileName); 44 | 45 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 46 | return errno_to_ntstatus_error( 47 | impl->find_files(FileName, FillFindData, DokanFileInfo)); 48 | } 49 | 50 | static void DOKAN_CALLBACK FuseCleanup(LPCWSTR FileName, 51 | PDOKAN_FILE_INFO DokanFileInfo) { 52 | impl_fuse_context *impl = the_impl; 53 | if (impl->debug()) 54 | FWPRINTF(stderr, L"Cleanup: %s\n\n", FileName); 55 | 56 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 57 | impl->cleanup(FileName, DokanFileInfo); 58 | } 59 | 60 | static NTSTATUS DOKAN_CALLBACK 61 | FuseDeleteDirectory(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo) { 62 | impl_fuse_context *impl = the_impl; 63 | if (impl->debug()) 64 | FWPRINTF(stderr, L"DeleteDirectory %s\n", FileName); 65 | 66 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 67 | return errno_to_ntstatus_error( 68 | impl->delete_directory(FileName, DokanFileInfo)); 69 | } 70 | 71 | struct Constant { 72 | DWORD value; 73 | const char *name; 74 | }; 75 | 76 | #define CONST_START(name) Constant name[] = { 77 | #define CONST_VAL(val) \ 78 | { val, #val } \ 79 | , 80 | #define CONST_END(name) \ 81 | { 0, NULL } \ 82 | } \ 83 | ; 84 | 85 | CONST_START(cAccessMode) 86 | CONST_VAL(GENERIC_READ) 87 | CONST_VAL(GENERIC_WRITE) 88 | CONST_VAL(GENERIC_ALL) 89 | CONST_VAL(GENERIC_EXECUTE) 90 | CONST_VAL(DELETE) 91 | CONST_VAL(READ_CONTROL) 92 | CONST_VAL(WRITE_DAC) 93 | CONST_VAL(WRITE_OWNER) 94 | CONST_VAL(SYNCHRONIZE) 95 | CONST_VAL(FILE_GENERIC_EXECUTE) 96 | CONST_VAL(FILE_GENERIC_READ) 97 | CONST_VAL(FILE_GENERIC_WRITE) 98 | CONST_VAL(FILE_EXECUTE) 99 | CONST_VAL(FILE_READ_ATTRIBUTES) 100 | CONST_VAL(STANDARD_RIGHTS_EXECUTE) 101 | CONST_VAL(FILE_READ_ATTRIBUTES) 102 | CONST_VAL(FILE_READ_DATA) 103 | CONST_VAL(FILE_READ_EA) 104 | CONST_VAL(STANDARD_RIGHTS_READ) 105 | CONST_VAL(FILE_APPEND_DATA) 106 | CONST_VAL(FILE_WRITE_ATTRIBUTES) 107 | CONST_VAL(FILE_WRITE_DATA) 108 | CONST_VAL(FILE_WRITE_EA) 109 | CONST_VAL(STANDARD_RIGHTS_WRITE) 110 | CONST_VAL(FILE_ADD_FILE) 111 | CONST_VAL(FILE_ADD_SUBDIRECTORY) 112 | CONST_VAL(FILE_ALL_ACCESS) 113 | CONST_VAL(FILE_APPEND_DATA) 114 | CONST_VAL(FILE_CREATE_PIPE_INSTANCE) 115 | CONST_VAL(FILE_DELETE_CHILD) 116 | CONST_VAL(FILE_LIST_DIRECTORY) 117 | CONST_VAL(FILE_TRAVERSE) 118 | CONST_END(cAccessMode) 119 | 120 | CONST_START(cShareMode) 121 | CONST_VAL(FILE_SHARE_DELETE) 122 | CONST_VAL(FILE_SHARE_READ) 123 | CONST_VAL(FILE_SHARE_WRITE) 124 | CONST_END(cShareMode) 125 | 126 | CONST_START(cDisposition) 127 | CONST_VAL(FILE_SUPERSEDE) 128 | CONST_VAL(FILE_CREATE) 129 | CONST_VAL(FILE_OPEN) 130 | CONST_VAL(FILE_OPEN_IF) 131 | CONST_VAL(FILE_OVERWRITE) 132 | CONST_VAL(FILE_OVERWRITE_IF) 133 | CONST_END(cDisposition) 134 | 135 | void DebugConstant(const char *name, DWORD value, Constant *c) { 136 | while (c->name != NULL && c->value != value) 137 | ++c; 138 | fprintf(stderr, "%s: %s (%lu)\n", name, c->name ? c->name : "unknown!", 139 | value); 140 | } 141 | 142 | void DebugConstantBit(const char *name, DWORD value, Constant *cs) { 143 | // check sorted and sort 144 | for (Constant *c = cs; c[1].name;) { 145 | if (c[0].value < c[1].value) { 146 | std::swap(c[0], c[1]); 147 | c = cs; 148 | continue; 149 | } 150 | ++c; 151 | } 152 | 153 | DWORD left = value; 154 | bool started = false; 155 | const char *sep = ""; 156 | fprintf(stderr, "%s: ", name); 157 | for (Constant *c = cs; c->name; ++c) { 158 | if ((value & c->value) == c->value && (left & c->value) != 0) { 159 | fprintf(stderr, "%s%s", sep, c->name); 160 | sep = "|"; 161 | left &= ~c->value; 162 | started = true; 163 | } 164 | } 165 | if (left || !started) 166 | fprintf(stderr, "%s0x%lX", sep, (long unsigned)left); 167 | fprintf(stderr, "\n"); 168 | } 169 | 170 | static NTSTATUS DOKAN_CALLBACK 171 | FuseCreateFile(LPCWSTR FileName, PDOKAN_IO_SECURITY_CONTEXT SecurityContext, 172 | ACCESS_MASK DesiredAccess, ULONG FileAttributes, 173 | ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, 174 | PDOKAN_FILE_INFO DokanFileInfo) { 175 | impl_fuse_context *impl = the_impl; 176 | 177 | if (impl->debug()) { 178 | FWPRINTF(stderr, L"CreateFile : %s\n", FileName); 179 | DebugConstantBit("\tDesiredAccess", DesiredAccess, cAccessMode); 180 | DebugConstantBit("\tShareAccess", ShareAccess, cShareMode); 181 | DebugConstant("\tDisposition", CreateDisposition, cDisposition); 182 | FWPRINTF(stderr, L"\tAttributes: %u (0x%x)\n", FileAttributes, 183 | FileAttributes); 184 | FWPRINTF(stderr, L"\tOptions: %u (0x%x)\n", CreateOptions, CreateOptions); 185 | fflush(stderr); 186 | } 187 | 188 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 189 | 190 | if ((CreateOptions & FILE_DIRECTORY_FILE) == FILE_DIRECTORY_FILE) { 191 | 192 | if (CreateDisposition == FILE_CREATE || CreateDisposition == FILE_OPEN_IF) { 193 | return errno_to_ntstatus_error( 194 | impl->create_directory(FileName, DokanFileInfo)); 195 | } else if (CreateDisposition == FILE_OPEN) { 196 | 197 | return errno_to_ntstatus_error( 198 | impl->open_directory(FileName, DokanFileInfo)); 199 | } 200 | } 201 | 202 | return impl->create_file(FileName, DesiredAccess, ShareAccess, 203 | CreateDisposition, FileAttributes, DokanFileInfo); 204 | } 205 | 206 | static void DOKAN_CALLBACK FuseCloseFile(LPCWSTR FileName, 207 | PDOKAN_FILE_INFO DokanFileInfo) { 208 | impl_fuse_context *impl = the_impl; 209 | if (impl->debug()) 210 | FWPRINTF(stderr, L"Close: %s\n\n", FileName); 211 | 212 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 213 | impl->close_file(FileName, DokanFileInfo); 214 | } 215 | 216 | static NTSTATUS DOKAN_CALLBACK FuseReadFile(LPCWSTR FileName, LPVOID Buffer, 217 | DWORD BufferLength, 218 | LPDWORD ReadLength, LONGLONG Offset, 219 | PDOKAN_FILE_INFO DokanFileInfo) { 220 | impl_fuse_context *impl = the_impl; 221 | if (impl->debug()) 222 | FWPRINTF(stderr, L"ReadFile : %s from %I64d len %u\n", FileName, 223 | (__int64)Offset, (unsigned)BufferLength); 224 | 225 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 226 | return errno_to_ntstatus_error(impl->read_file( 227 | FileName, Buffer, BufferLength, ReadLength, Offset, DokanFileInfo)); 228 | } 229 | 230 | static NTSTATUS DOKAN_CALLBACK FuseWriteFile(LPCWSTR FileName, LPCVOID Buffer, 231 | DWORD NumberOfBytesToWrite, 232 | LPDWORD NumberOfBytesWritten, 233 | LONGLONG Offset, 234 | PDOKAN_FILE_INFO DokanFileInfo) { 235 | impl_fuse_context *impl = the_impl; 236 | if (impl->debug()) 237 | FWPRINTF(stderr, L"WriteFile : %s, offset %I64d, length %lu\n", FileName, 238 | Offset, NumberOfBytesToWrite); 239 | 240 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 241 | return errno_to_ntstatus_error( 242 | impl->write_file(FileName, Buffer, NumberOfBytesToWrite, 243 | NumberOfBytesWritten, Offset, DokanFileInfo)); 244 | } 245 | 246 | static NTSTATUS DOKAN_CALLBACK 247 | FuseFlushFileBuffers(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo) { 248 | impl_fuse_context *impl = the_impl; 249 | if (impl->debug()) 250 | FWPRINTF(stderr, L"FlushFileBuffers : %s\n", FileName); 251 | 252 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 253 | return errno_to_ntstatus_error( 254 | impl->flush_file_buffers(FileName, DokanFileInfo)); 255 | } 256 | 257 | static NTSTATUS DOKAN_CALLBACK FuseGetFileInformation( 258 | LPCWSTR FileName, LPBY_HANDLE_FILE_INFORMATION HandleFileInformation, 259 | PDOKAN_FILE_INFO DokanFileInfo) { 260 | impl_fuse_context *impl = the_impl; 261 | if (impl->debug()) 262 | FWPRINTF(stderr, L"GetFileInfo : %s\n", FileName); 263 | 264 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 265 | return errno_to_ntstatus_error(impl->get_file_information( 266 | FileName, HandleFileInformation, DokanFileInfo)); 267 | } 268 | 269 | static NTSTATUS DOKAN_CALLBACK FuseDeleteFile(LPCWSTR FileName, 270 | PDOKAN_FILE_INFO DokanFileInfo) { 271 | impl_fuse_context *impl = the_impl; 272 | if (impl->debug()) 273 | FWPRINTF(stderr, L"DeleteFile %s\n", FileName); 274 | 275 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 276 | return errno_to_ntstatus_error(impl->delete_file(FileName, DokanFileInfo)); 277 | } 278 | 279 | static NTSTATUS DOKAN_CALLBACK 280 | FuseMoveFile(LPCWSTR FileName, // existing file name 281 | LPCWSTR NewFileName, BOOL ReplaceIfExisting, 282 | PDOKAN_FILE_INFO DokanFileInfo) { 283 | impl_fuse_context *impl = the_impl; 284 | if (impl->debug()) 285 | FWPRINTF(stderr, L"MoveFile %s -> %s\n\n", FileName, NewFileName); 286 | 287 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 288 | return errno_to_ntstatus_error( 289 | impl->move_file(FileName, NewFileName, ReplaceIfExisting, DokanFileInfo)); 290 | } 291 | 292 | static NTSTATUS DOKAN_CALLBACK FuseLockFile(LPCWSTR FileName, 293 | LONGLONG ByteOffset, 294 | LONGLONG Length, 295 | PDOKAN_FILE_INFO DokanFileInfo) { 296 | impl_fuse_context *impl = the_impl; 297 | if (impl->debug()) 298 | FWPRINTF(stderr, L"LockFile %s\n", FileName); 299 | 300 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 301 | return errno_to_ntstatus_error( 302 | impl->lock_file(FileName, ByteOffset, Length, DokanFileInfo)); 303 | } 304 | 305 | static NTSTATUS DOKAN_CALLBACK FuseUnlockFile(LPCWSTR FileName, 306 | LONGLONG ByteOffset, 307 | LONGLONG Length, 308 | PDOKAN_FILE_INFO DokanFileInfo) { 309 | impl_fuse_context *impl = the_impl; 310 | if (impl->debug()) 311 | FWPRINTF(stderr, L"UnlockFile %s\n", FileName); 312 | 313 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 314 | return errno_to_ntstatus_error( 315 | impl->unlock_file(FileName, ByteOffset, Length, DokanFileInfo)); 316 | } 317 | 318 | static NTSTATUS DOKAN_CALLBACK FuseSetEndOfFile( 319 | LPCWSTR FileName, LONGLONG ByteOffset, PDOKAN_FILE_INFO DokanFileInfo) { 320 | impl_fuse_context *impl = the_impl; 321 | if (impl->debug()) 322 | FWPRINTF(stderr, L"SetEndOfFile %s, %I64d\n", FileName, ByteOffset); 323 | 324 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 325 | return errno_to_ntstatus_error( 326 | impl->set_end_of_file(FileName, ByteOffset, DokanFileInfo)); 327 | } 328 | 329 | static NTSTATUS DOKAN_CALLBACK FuseSetAllocationSize( 330 | LPCWSTR FileName, LONGLONG ByteOffset, PDOKAN_FILE_INFO DokanFileInfo) { 331 | impl_fuse_context *impl = the_impl; 332 | if (impl->debug()) 333 | FWPRINTF(stderr, L"SetAllocationSize %s, %I64d\n", FileName, ByteOffset); 334 | 335 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 336 | 337 | BY_HANDLE_FILE_INFORMATION byHandleFileInfo; 338 | ZeroMemory(&byHandleFileInfo, sizeof(BY_HANDLE_FILE_INFORMATION)); 339 | 340 | NTSTATUS ret = errno_to_ntstatus_error( 341 | impl->get_file_information(FileName, &byHandleFileInfo, DokanFileInfo)); 342 | 343 | LARGE_INTEGER fileSize; 344 | fileSize.LowPart = byHandleFileInfo.nFileSizeLow; 345 | fileSize.HighPart = byHandleFileInfo.nFileSizeHigh; 346 | 347 | if (ret != 0) { 348 | return ret; 349 | } else if (ByteOffset < fileSize.QuadPart) { 350 | /* https://msdn.microsoft.com/en-us/library/windows/hardware/ff540232(v=vs.85).aspx 351 | * The end-of-file position must always be less than or equal to the 352 | * allocation size. If the allocation size is set to a value that is 353 | * less than the end - of - file position, the end - of - file position 354 | * is automatically adjusted to match the allocation size.*/ 355 | return errno_to_ntstatus_error( 356 | impl->set_end_of_file(FileName, ByteOffset, DokanFileInfo)); 357 | } else { 358 | return 0; 359 | } 360 | } 361 | 362 | static NTSTATUS DOKAN_CALLBACK FuseSetFileAttributes( 363 | LPCWSTR FileName, DWORD FileAttributes, PDOKAN_FILE_INFO DokanFileInfo) { 364 | impl_fuse_context *impl = the_impl; 365 | if (impl->debug()) 366 | FWPRINTF(stderr, L"SetFileAttributes %s\n", FileName); 367 | 368 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 369 | return errno_to_ntstatus_error( 370 | impl->set_file_attributes(FileName, FileAttributes, DokanFileInfo)); 371 | } 372 | 373 | static NTSTATUS DOKAN_CALLBACK FuseSetFileTime(LPCWSTR FileName, 374 | CONST FILETIME *CreationTime, 375 | CONST FILETIME *LastAccessTime, 376 | CONST FILETIME *LastWriteTime, 377 | PDOKAN_FILE_INFO DokanFileInfo) { 378 | impl_fuse_context *impl = the_impl; 379 | if (impl->debug()) 380 | FWPRINTF(stderr, L"SetFileTime %s\n", FileName); 381 | 382 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 383 | return errno_to_ntstatus_error(impl->set_file_time( 384 | FileName, CreationTime, LastAccessTime, LastWriteTime, DokanFileInfo)); 385 | } 386 | 387 | static NTSTATUS DOKAN_CALLBACK FuseGetDiskFreeSpace( 388 | PULONGLONG FreeBytesAvailable, PULONGLONG TotalNumberOfBytes, 389 | PULONGLONG TotalNumberOfFreeBytes, PDOKAN_FILE_INFO DokanFileInfo) { 390 | impl_fuse_context *impl = the_impl; 391 | if (impl->debug()) 392 | FWPRINTF(stderr, L"GetDiskFreeSpace\n"); 393 | 394 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 395 | return errno_to_ntstatus_error( 396 | impl->get_disk_free_space(FreeBytesAvailable, TotalNumberOfBytes, 397 | TotalNumberOfFreeBytes, DokanFileInfo)); 398 | } 399 | 400 | static NTSTATUS DOKAN_CALLBACK 401 | GetVolumeInformation(LPWSTR VolumeNameBuffer, DWORD VolumeNameSize, 402 | LPDWORD VolumeSerialNumber, LPDWORD MaximumComponentLength, 403 | LPDWORD FileSystemFlags, LPWSTR FileSystemNameBuffer, 404 | DWORD FileSystemNameSize, PDOKAN_FILE_INFO DokanFileInfo) { 405 | impl_fuse_context *impl = the_impl; 406 | if (impl->debug()) 407 | FWPRINTF(stderr, L"GetVolumeInformation\n"); 408 | 409 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 410 | *VolumeSerialNumber = 0; 411 | *MaximumComponentLength = 255; 412 | return errno_to_ntstatus_error(impl->get_volume_information( 413 | VolumeNameBuffer, VolumeNameSize, FileSystemNameBuffer, 414 | FileSystemNameSize, DokanFileInfo, FileSystemFlags)); 415 | } 416 | 417 | static NTSTATUS DOKAN_CALLBACK FuseMounted(PDOKAN_FILE_INFO DokanFileInfo) { 418 | impl_fuse_context *impl = the_impl; 419 | if (impl->debug()) 420 | FWPRINTF(stderr, L"Mounted\n"); 421 | 422 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 423 | return errno_to_ntstatus_error(impl->mounted(DokanFileInfo)); 424 | } 425 | 426 | static NTSTATUS DOKAN_CALLBACK FuseUnmounted(PDOKAN_FILE_INFO DokanFileInfo) { 427 | impl_fuse_context *impl = the_impl; 428 | if (impl->debug()) 429 | FWPRINTF(stderr, L"Unmount\n"); 430 | 431 | impl_chain_guard guard(impl, DokanFileInfo->ProcessId); 432 | return errno_to_ntstatus_error(impl->unmounted(DokanFileInfo)); 433 | } 434 | 435 | int fuse_interrupted(void) { 436 | return 0; // TODO: fix this 437 | } 438 | 439 | static DOKAN_OPERATIONS dokanOperations = { 440 | FuseCreateFile, 441 | FuseCleanup, 442 | FuseCloseFile, 443 | FuseReadFile, 444 | FuseWriteFile, 445 | FuseFlushFileBuffers, 446 | FuseGetFileInformation, 447 | FuseFindFiles, 448 | NULL, // FindFilesWithPattern 449 | FuseSetFileAttributes, 450 | FuseSetFileTime, 451 | FuseDeleteFile, 452 | FuseDeleteDirectory, 453 | FuseMoveFile, 454 | FuseSetEndOfFile, 455 | FuseSetAllocationSize, 456 | FuseLockFile, 457 | FuseUnlockFile, 458 | FuseGetDiskFreeSpace, 459 | GetVolumeInformation, 460 | FuseMounted, 461 | FuseUnmounted, 462 | NULL, // GetFileSecurity 463 | NULL, // SetFileSecurity 464 | }; 465 | 466 | int do_fuse_loop(struct fuse *fs, bool mt) { 467 | if (!fs->ch.get() || fs->ch->mountpoint.empty()) 468 | return -1; 469 | 470 | // Calculate umasks 471 | int umask = fs->conf.umask; 472 | if (umask == 0) 473 | umask = 0777; // It's OCTAL! Really! 474 | int dirumask = fs->conf.dirumask; 475 | if (dirumask == 0) 476 | dirumask = umask; 477 | int fileumask = fs->conf.fileumask; 478 | if (fileumask == 0) 479 | fileumask = umask; 480 | 481 | impl_fuse_context impl(&fs->ops, fs->user_data, fs->conf.debug != 0, 482 | fileumask, dirumask, fs->conf.fsname, 483 | fs->conf.volname); 484 | 485 | // Parse Dokan options 486 | PDOKAN_OPTIONS dokanOptions = (PDOKAN_OPTIONS)malloc(sizeof(DOKAN_OPTIONS)); 487 | if (dokanOptions == NULL) { 488 | return -1; 489 | } 490 | ZeroMemory(dokanOptions, sizeof(DOKAN_OPTIONS)); 491 | dokanOptions->Options |= DOKAN_OPTION_REMOVABLE; 492 | dokanOptions->GlobalContext = reinterpret_cast(&impl); 493 | 494 | wchar_t mount[MAX_PATH + 1]; 495 | mbstowcs(mount, fs->ch->mountpoint.c_str(), MAX_PATH); 496 | 497 | dokanOptions->Version = DOKAN_VERSION; 498 | dokanOptions->MountPoint = mount; 499 | dokanOptions->ThreadCount = mt ? FUSE_THREAD_COUNT : 1; 500 | dokanOptions->Timeout = fs->conf.timeoutInSec * 1000; 501 | 502 | // Debug 503 | if (fs->conf.debug) 504 | dokanOptions->Options |= DOKAN_OPTION_DEBUG | DOKAN_OPTION_STDERR; 505 | 506 | // Load Dokan DLL 507 | if (!fs->ch->init()) { 508 | free(dokanOptions); 509 | return -1; // Couldn't load DLL. TODO: UGLY!! 510 | } 511 | 512 | // The main loop! 513 | fs->within_loop = true; 514 | int res = fs->ch->ResolvedDokanMain(dokanOptions, &dokanOperations); 515 | fs->within_loop = false; 516 | return res; 517 | } 518 | 519 | bool fuse_chan::init() { 520 | dokanDll = LoadLibraryW(DOKAN_DLL); 521 | if (!dokanDll) 522 | return false; 523 | 524 | // check version 525 | typedef ULONG(__stdcall * DokanVersionType)(); 526 | DokanVersionType ResolvedDokanVersion; 527 | ResolvedDokanVersion = 528 | (DokanVersionType)GetProcAddress(dokanDll, "DokanVersion"); 529 | if (!ResolvedDokanVersion || ResolvedDokanVersion() < DOKAN_VERSION) 530 | return false; 531 | 532 | ResolvedDokanMain = (DokanMainType)GetProcAddress(dokanDll, "DokanMain"); 533 | ResolvedDokanUnmount = 534 | (DokanUnmountType)GetProcAddress(dokanDll, "DokanUnmount"); 535 | ResolvedDokanRemoveMountPoint = (DokanRemoveMountPointType)GetProcAddress( 536 | dokanDll, "DokanRemoveMountPoint"); 537 | 538 | if (!ResolvedDokanMain || !ResolvedDokanUnmount || 539 | !ResolvedDokanRemoveMountPoint) 540 | return false; 541 | return true; 542 | } 543 | 544 | fuse_chan::~fuse_chan() { 545 | if (dokanDll) 546 | FreeLibrary(dokanDll); 547 | } 548 | 549 | /////////////////////////////////////////////////////////////////////////////////////// 550 | ////// This are just "emulators" of native FUSE api for the sake of 551 | ///compatibility 552 | /////////////////////////////////////////////////////////////////////////////////////// 553 | #define FUSE_LIB_OPT(t, p, v) \ 554 | { t, offsetof(struct fuse_config, p), v } 555 | 556 | enum { KEY_HELP }; 557 | 558 | static const struct fuse_opt fuse_lib_opts[] = { 559 | FUSE_OPT_KEY("-h", KEY_HELP), 560 | FUSE_OPT_KEY("--help", KEY_HELP), 561 | FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), 562 | FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), 563 | FUSE_LIB_OPT("debug", debug, 1), 564 | FUSE_LIB_OPT("-d", debug, 1), 565 | FUSE_LIB_OPT("umask=%o", umask, 0), 566 | FUSE_LIB_OPT("fileumask=%o", fileumask, 0), 567 | FUSE_LIB_OPT("dirumask=%o", dirumask, 0), 568 | FUSE_LIB_OPT("fsname=%s", fsname, 0), 569 | FUSE_LIB_OPT("volname=%s", volname, 0), 570 | FUSE_LIB_OPT("setsignals=%s", setsignals, 0), 571 | FUSE_LIB_OPT("daemon_timeout=%d", timeoutInSec, 0), 572 | FUSE_OPT_END}; 573 | 574 | static void fuse_lib_help(void) { 575 | fprintf( 576 | stderr, 577 | " -o umask=M set file and directory permissions (octal)\n" 578 | " -o fileumask=M set file permissions (octal)\n" 579 | " -o dirumask=M set directory permissions (octal)\n" 580 | " -o fsname=M set filesystem name\n" 581 | " -o volname=M set volume name\n" 582 | " -o setsignals=M set signal usage (1 to use)\n" 583 | " -o daemon_timeout=M set timeout in seconds\n" 584 | "\n"); 585 | } 586 | 587 | static int fuse_lib_opt_proc(void *data, const char *arg, int key, 588 | struct fuse_args *outargs) { 589 | (void)arg; 590 | (void)outargs; 591 | 592 | if (key == KEY_HELP) { 593 | struct fuse_config *conf = (struct fuse_config *)data; 594 | fuse_lib_help(); 595 | conf->help = 1; 596 | } 597 | 598 | return 1; 599 | } 600 | 601 | int fuse_is_lib_option(const char *opt) { 602 | return fuse_opt_match(fuse_lib_opts, opt); 603 | } 604 | 605 | int fuse_loop_mt(struct fuse *f) { return do_fuse_loop(f, true); } 606 | 607 | int fuse_loop(struct fuse *f) { return do_fuse_loop(f, false); } 608 | 609 | struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) { 610 | if (mountpoint == NULL || mountpoint[0] == '\0') 611 | return NULL; 612 | 613 | std::unique_ptr chan(new fuse_chan()); 614 | // NOTE: we used to do chan->init() here to check that Dokan DLLs can be 615 | // loaded. 616 | // However, this does not live well with Cygwin. It's common for filesystem 617 | // drivers 618 | // to daemon()ize themselves (which involves fork() call) and forking doesn't 619 | // work 620 | // with Dokan. So defer loading until the main loop. 621 | 622 | chan->mountpoint = mountpoint; 623 | return chan.release(); 624 | } 625 | 626 | void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) { 627 | if (mountpoint == NULL || mountpoint[0] == '\0') 628 | return; 629 | 630 | fuse_chan chan; 631 | if (!ch) { 632 | ch = &chan; 633 | ch->init(); 634 | ch->mountpoint = mountpoint; 635 | } 636 | 637 | // Unmount attached FUSE filesystem 638 | if (ch->ResolvedDokanRemoveMountPoint) { 639 | wchar_t wmountpoint[MAX_PATH + 1]; 640 | mbstowcs(wmountpoint, mountpoint, MAX_PATH); 641 | wchar_t &last = wmountpoint[wcslen(wmountpoint) - 1]; 642 | if (last == L'\\' || last == L'/') 643 | last = L'\0'; 644 | ch->ResolvedDokanRemoveMountPoint(wmountpoint); 645 | return; 646 | } 647 | if (ch->ResolvedDokanUnmount) 648 | ch->ResolvedDokanUnmount(mountpoint[0]); // Ugly :( 649 | } 650 | 651 | // Used from fuse_helpers.c 652 | extern "C" int fuse_session_exit(struct fuse_session *se) { 653 | fuse_unmount(se->ch->mountpoint.c_str(), se->ch); 654 | return 0; 655 | } 656 | 657 | struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, 658 | const struct fuse_operations *op, size_t op_size, 659 | void *user_data) { 660 | std::unique_ptr res(new fuse()); 661 | res->sess.ch = ch; 662 | res->ch.reset(ch); // Attach channel 663 | res->user_data = user_data; 664 | 665 | // prepare 'safe' options 666 | fuse_operations safe_ops = {0}; 667 | memcpy(&safe_ops, op, 668 | op_size > sizeof(safe_ops) ? sizeof(safe_ops) : op_size); 669 | res->ops = safe_ops; 670 | 671 | // Get debug param and filesystem name 672 | if (fuse_opt_parse(args, &res->conf, fuse_lib_opts, fuse_lib_opt_proc) == -1) 673 | return NULL; 674 | // res->conf.debug=1; 675 | 676 | return res.release(); 677 | } 678 | 679 | void fuse_exit(struct fuse *f) { 680 | // A hack - unmount the attached filesystem, it will cause the loop to end 681 | if (f == NULL || !f->ch.get() || f->ch->mountpoint.empty()) 682 | return; 683 | // Unmount attached FUSE filesystem 684 | f->ch->ResolvedDokanUnmount(f->ch->mountpoint.at(0)); // Ugly :( 685 | } 686 | 687 | void fuse_destroy(struct fuse *f) { delete f; } 688 | 689 | struct fuse *fuse_setup(int argc, char *argv[], 690 | const struct fuse_operations *op, size_t op_size, 691 | char **mountpoint, int *multithreaded, 692 | void *user_data) { 693 | struct fuse_args args = FUSE_ARGS_INIT(argc, argv); 694 | struct fuse_chan *ch = NULL; 695 | struct fuse *fuse; 696 | int foreground; 697 | int res; 698 | 699 | res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground); 700 | if (res == -1) 701 | return NULL; 702 | 703 | ch = fuse_mount(*mountpoint, &args); 704 | 705 | fuse = fuse_new(ch, &args, op, op_size, user_data); 706 | fuse_opt_free_args(&args); 707 | if (fuse == NULL || ch == NULL) 708 | goto err_unmount; 709 | 710 | res = fuse_daemonize(foreground); 711 | if (res == -1) 712 | goto err_unmount; 713 | 714 | if (fuse->conf.setsignals) { 715 | res = fuse_set_signal_handlers(fuse_get_session(fuse)); 716 | if (res == -1) 717 | goto err_unmount; 718 | } 719 | 720 | return fuse; 721 | 722 | err_unmount: 723 | fuse_unmount(*mountpoint, ch); 724 | if (fuse) 725 | fuse_destroy(fuse); 726 | free(*mountpoint); 727 | return NULL; 728 | } 729 | 730 | void fuse_teardown(struct fuse *fuse, char *mountpoint) { 731 | struct fuse_session *se = fuse_get_session(fuse); 732 | struct fuse_chan *ch = se->ch; 733 | if (fuse->conf.setsignals) 734 | fuse_remove_signal_handlers(se); 735 | fuse_unmount(mountpoint, ch); 736 | fuse_destroy(fuse); 737 | free(mountpoint); 738 | } 739 | 740 | int fuse_exited(struct fuse *f) { return !f->within_loop; } 741 | 742 | struct fuse_session *fuse_get_session(struct fuse *f) { 743 | return &f->sess; 744 | } 745 | 746 | int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, 747 | size_t op_size, void *user_data) { 748 | struct fuse *fuse; 749 | char *mountpoint; 750 | int multithreaded; 751 | int res; 752 | 753 | fuse = fuse_setup(argc, argv, op, op_size, &mountpoint, &multithreaded, 754 | user_data); 755 | if (fuse == NULL) 756 | return 1; 757 | 758 | // MT loops are only supported on MSVC 759 | if (multithreaded) 760 | res = fuse_loop_mt(fuse); 761 | else 762 | res = fuse_loop(fuse); 763 | 764 | fuse_teardown(fuse, mountpoint); 765 | if (res < 0) 766 | return 1; 767 | 768 | return 0; 769 | } 770 | -------------------------------------------------------------------------------- /dokan_fuse/src/dokanfuse.def: -------------------------------------------------------------------------------- 1 | LIBRARY dokanfuse1 2 | 3 | EXPORTS 4 | 5 | ; Optionals 6 | fuse_opt_parse 7 | fuse_opt_add_opt 8 | fuse_opt_add_arg 9 | fuse_opt_insert_arg 10 | fuse_opt_free_args 11 | fuse_opt_match 12 | 13 | ; Main FUSE 14 | fuse_new 15 | fuse_destroy 16 | fuse_loop 17 | fuse_exit 18 | fuse_is_lib_option 19 | fuse_loop_mt 20 | fuse_get_context 21 | fuse_interrupted 22 | fuse_main_real 23 | 24 | fuse_setup 25 | fuse_teardown 26 | fuse_get_session 27 | 28 | ; Stacking 29 | ;fuse_fs_getattr 30 | ;fuse_fs_fgetattr 31 | ;fuse_fs_rename 32 | ;fuse_fs_unlink 33 | ;fuse_fs_rmdir 34 | ;fuse_fs_symlink 35 | ;fuse_fs_link 36 | ;fuse_fs_release 37 | ;fuse_fs_open 38 | ;fuse_fs_read 39 | ;fuse_fs_write 40 | ;fuse_fs_fsync 41 | ;fuse_fs_flush 42 | ;fuse_fs_statfs 43 | ;fuse_fs_opendir 44 | ;fuse_fs_readdir 45 | ;fuse_fs_fsyncdir 46 | ;fuse_fs_releasedir 47 | ;fuse_fs_create 48 | ;fuse_fs_lock 49 | ;fuse_fs_chmod 50 | ;fuse_fs_chown 51 | ;fuse_fs_truncate 52 | ;fuse_fs_ftruncate 53 | ;fuse_fs_utimens 54 | ;fuse_fs_access 55 | ;fuse_fs_readlink 56 | ;fuse_fs_mknod 57 | ;fuse_fs_mkdir 58 | ;fuse_fs_setxattr 59 | ;fuse_fs_getxattr 60 | ;fuse_fs_listxattr 61 | ;fuse_fs_removexattr 62 | ;fuse_fs_bmap 63 | ;fuse_fs_init 64 | ;fuse_fs_destroy 65 | 66 | ; Modules 67 | ;fuse_fs_new 68 | ;fuse_register_module 69 | 70 | ; Fuse Common 71 | fuse_mount 72 | fuse_unmount 73 | fuse_parse_cmdline 74 | fuse_daemonize 75 | fuse_version 76 | fuse_set_signal_handlers 77 | fuse_remove_signal_handlers 78 | 79 | ; Win32 Helpers 80 | ntstatus_error_to_errno 81 | errno_to_ntstatus_error 82 | convert_args 83 | free_converted_args 84 | 85 | ; Utils 86 | utf8_to_wchar_buf_old 87 | utf8_to_wchar_buf 88 | wchar_to_utf8_cstr 89 | 90 | unixify 91 | extract_file_name 92 | extract_dir_name 93 | 94 | unixTimeToFiletime 95 | filetimeToUnixTime 96 | is_filetime_set -------------------------------------------------------------------------------- /dokan_fuse/src/dokanfuse.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #define APSTUDIO_READONLY_SYMBOLS 4 | ///////////////////////////////////////////////////////////////////////////// 5 | // 6 | // Generated from the TEXTINCLUDE 2 resource. 7 | // 8 | #include "winres.h" 9 | 10 | ///////////////////////////////////////////////////////////////////////////// 11 | #undef APSTUDIO_READONLY_SYMBOLS 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | // 15 | // Version 16 | // 17 | 18 | VS_VERSION_INFO VERSIONINFO 19 | FILEVERSION 1,0,0,0 20 | PRODUCTVERSION 1,0,0,0 21 | FILEFLAGSMASK 0x3fL 22 | #ifdef _DEBUG 23 | FILEFLAGS 0x1L 24 | #else 25 | FILEFLAGS 0x0L 26 | #endif 27 | FILEOS 0x4L 28 | FILETYPE 0x2L 29 | FILESUBTYPE 0x0L 30 | BEGIN 31 | BLOCK "StringFileInfo" 32 | BEGIN 33 | BLOCK "000004e3" 34 | BEGIN 35 | VALUE "CompanyName", "Dokan Project" 36 | VALUE "FileDescription", "Dokan Fuse library" 37 | VALUE "FileVersion", "1.0.0.0" 38 | VALUE "InternalName", "dokanfuse.dll" 39 | VALUE "LegalCopyright", "Copyright (C) 2016" 40 | VALUE "OriginalFilename", "dokanfuse.dll" 41 | VALUE "ProductName", "Dokan" 42 | VALUE "ProductVersion", "1.0.0.0" 43 | END 44 | END 45 | BLOCK "VarFileInfo" 46 | BEGIN 47 | VALUE "Translation", 0x0, 1251 48 | END 49 | END 50 | -------------------------------------------------------------------------------- /dokan_fuse/src/fuse_helpers.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "fuse.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef __CYGWIN__ 13 | #define _BSD_SOURCE 14 | #include 15 | #include 16 | #endif 17 | 18 | enum { 19 | KEY_HELP, 20 | KEY_HELP_NOHEADER, 21 | KEY_VERSION, 22 | }; 23 | 24 | struct helper_opts { 25 | int singlethread; 26 | int foreground; 27 | int fsname; 28 | char *mountpoint; 29 | }; 30 | 31 | extern "C" int fuse_session_exit(struct fuse_session *se); 32 | 33 | #ifdef _MSC_VER 34 | static char *realpath(const char *file_name, char *resolved_name) { 35 | strcpy(resolved_name, file_name); 36 | return resolved_name; 37 | } 38 | #endif 39 | 40 | #define FUSE_HELPER_OPT(t, p) \ 41 | { t, offsetof(struct helper_opts, p), 1 } 42 | 43 | static const struct fuse_opt fuse_helper_opts[] = { 44 | FUSE_HELPER_OPT("-d", foreground), 45 | FUSE_HELPER_OPT("debug", foreground), 46 | FUSE_HELPER_OPT("-f", foreground), 47 | FUSE_HELPER_OPT("-s", singlethread), 48 | FUSE_HELPER_OPT("fsname=", fsname), 49 | 50 | FUSE_OPT_KEY("-h", KEY_HELP), 51 | FUSE_OPT_KEY("--help", KEY_HELP), 52 | FUSE_OPT_KEY("-ho", KEY_HELP_NOHEADER), 53 | FUSE_OPT_KEY("-V", KEY_VERSION), 54 | FUSE_OPT_KEY("--version", KEY_VERSION), 55 | FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), 56 | FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), 57 | FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP), 58 | FUSE_OPT_END}; 59 | 60 | static void usage(const char *progname) { 61 | fprintf(stderr, "usage: %s mountpoint [options]\n\n", progname); 62 | fprintf(stderr, "general options:\n" 63 | " -o opt,[opt...] mount options\n" 64 | " -h --help print help\n" 65 | " -V --version print version\n" 66 | "\n"); 67 | } 68 | 69 | static void helper_help(void) { 70 | fprintf(stderr, 71 | "FUSE options:\n" 72 | " -d -o debug enable debug output (implies -f)\n" 73 | " -f foreground operation\n" 74 | " -s disable multi-threaded operation\n" 75 | "\n"); 76 | } 77 | 78 | static void helper_version(void) { 79 | fprintf(stderr, "FUSE library version: %d.%d\n", FUSE_MAJOR_VERSION, 80 | FUSE_MINOR_VERSION); 81 | } 82 | 83 | static int fuse_helper_opt_proc(void *data, const char *arg, int key, 84 | struct fuse_args *outargs) { 85 | struct helper_opts *hopts = (struct helper_opts *)data; 86 | 87 | switch (key) { 88 | case KEY_HELP: 89 | usage(outargs->argv[0]); 90 | /* fall through */ 91 | 92 | case KEY_HELP_NOHEADER: 93 | helper_help(); 94 | return fuse_opt_add_arg(outargs, "-h"); 95 | 96 | case KEY_VERSION: 97 | helper_version(); 98 | return 1; 99 | 100 | case FUSE_OPT_KEY_NONOPT: 101 | if (!hopts->mountpoint) { 102 | char mountpoint[MAX_PATH]; 103 | /* We have to short-circuit realpath, because Cygwin's notion of paths 104 | is not compatible with Dokan's. TODO: fix this! 105 | */ 106 | /*if (realpath(arg, mountpoint) == NULL) { 107 | fprintf(stderr, "fuse: bad mount point `%s': %s\n", arg, 108 | strerror(errno)); 109 | return -1; 110 | }*/ 111 | ZeroMemory(mountpoint, sizeof(mountpoint)); 112 | strncpy(mountpoint, arg, sizeof(mountpoint) - 1); 113 | return fuse_opt_add_opt(&hopts->mountpoint, mountpoint); 114 | } else { 115 | fprintf(stderr, "fuse: invalid argument `%s'\n", arg); 116 | return -1; 117 | } 118 | 119 | default: 120 | return 1; 121 | } 122 | } 123 | 124 | static int add_default_fsname(const char *progname, struct fuse_args *args) { 125 | int res; 126 | char *fsname_opt; 127 | const char *basename = strrchr(progname, '/'); 128 | if (basename == NULL) 129 | basename = progname; 130 | else if (basename[1] != '\0') 131 | basename++; 132 | 133 | fsname_opt = (char *)malloc(strlen(basename) + 64); 134 | if (fsname_opt == NULL) { 135 | fprintf(stderr, "fuse: memory allocation failed\n"); 136 | return -1; 137 | } 138 | sprintf(fsname_opt, "-ofsname=%s", basename); 139 | res = fuse_opt_add_arg(args, fsname_opt); 140 | free(fsname_opt); 141 | return res; 142 | } 143 | 144 | int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, 145 | int *multithreaded, int *foreground) { 146 | int res; 147 | struct helper_opts hopts; 148 | 149 | memset(&hopts, 0, sizeof(hopts)); 150 | res = fuse_opt_parse(args, &hopts, fuse_helper_opts, fuse_helper_opt_proc); 151 | if (res == -1) 152 | return -1; 153 | 154 | if (!hopts.fsname) { 155 | res = add_default_fsname(args->argv[0], args); 156 | if (res == -1) 157 | goto err; 158 | } 159 | if (mountpoint) 160 | *mountpoint = hopts.mountpoint; 161 | else 162 | free(hopts.mountpoint); 163 | 164 | if (multithreaded) 165 | *multithreaded = !hopts.singlethread; 166 | if (foreground) 167 | *foreground = hopts.foreground; 168 | return 0; 169 | 170 | err: 171 | free(hopts.mountpoint); 172 | return -1; 173 | } 174 | 175 | int fuse_daemonize(int foreground) { 176 | /** No daemons on Windows */ 177 | #ifdef __CYGWIN__ 178 | if (!foreground) { 179 | int res = daemon(0, 0); 180 | if (res == -1) { 181 | perror("fuse: failed to daemonize program\n"); 182 | return -1; 183 | } 184 | } 185 | #endif 186 | return 0; 187 | } 188 | 189 | int fuse_version(void) { return FUSE_VERSION; } 190 | 191 | #ifdef __CYGWIN__ 192 | static struct fuse_session *fuse_instance = NULL; 193 | 194 | static void exit_handler(int sig) { 195 | (void)sig; 196 | if (fuse_instance) 197 | fuse_session_exit(fuse_instance); 198 | } 199 | 200 | static int set_one_signal_handler(int sig, void (*handler)(int)) { 201 | struct sigaction sa; 202 | struct sigaction old_sa; 203 | 204 | memset(&sa, 0, sizeof(struct sigaction)); 205 | sa.sa_handler = handler; 206 | sigemptyset(&(sa.sa_mask)); 207 | sa.sa_flags = 0; 208 | 209 | if (sigaction(sig, NULL, &old_sa) == -1) { 210 | perror("fuse: cannot get old signal handler"); 211 | return -1; 212 | } 213 | 214 | if (old_sa.sa_handler == SIG_DFL && sigaction(sig, &sa, NULL) == -1) { 215 | perror("fuse: cannot set signal handler"); 216 | return -1; 217 | } 218 | 219 | return 0; 220 | } 221 | 222 | int fuse_set_signal_handlers(struct fuse_session *se) { 223 | if (set_one_signal_handler(SIGHUP, exit_handler) == -1 || 224 | set_one_signal_handler(SIGINT, exit_handler) == -1 || 225 | set_one_signal_handler(SIGTERM, exit_handler) == -1 || 226 | set_one_signal_handler(SIGPIPE, SIG_IGN) == -1) 227 | return -1; 228 | 229 | fuse_instance = se; 230 | return 0; 231 | } 232 | 233 | void fuse_remove_signal_handlers(struct fuse_session *se) { 234 | 235 | if (fuse_instance != se) 236 | fprintf(stderr, "fuse: fuse_remove_signal_handlers: unknown session\n"); 237 | else 238 | fuse_instance = NULL; 239 | 240 | set_one_signal_handler(SIGHUP, SIG_DFL); 241 | set_one_signal_handler(SIGINT, SIG_DFL); 242 | set_one_signal_handler(SIGTERM, SIG_DFL); 243 | set_one_signal_handler(SIGPIPE, SIG_DFL); 244 | } 245 | 246 | int my_sem_init(sem_t *sem, int pshared, int initial) { 247 | *sem = (sem_t)CreateSemaphore(NULL, initial, SEM_VALUE_MAX, NULL); 248 | return *sem == NULL ? -1 : 0; 249 | } 250 | 251 | int my_sem_destroy(sem_t *sem) { 252 | if (CloseHandle(*sem) > 0) 253 | return 0; 254 | return -1; 255 | } 256 | 257 | int my_sem_post(sem_t *sem) { 258 | if (ReleaseSemaphore((HANDLE)*sem, 1, NULL) > 0) 259 | return 0; 260 | return -1; 261 | } 262 | 263 | int my_sem_wait(sem_t *sem) { 264 | if (WaitForSingleObject((HANDLE)*sem, INFINITE) == WAIT_OBJECT_0) 265 | return 0; 266 | return -1; 267 | } 268 | 269 | #else 270 | 271 | int fuse_set_signal_handlers(struct fuse_session *se) { return 0; } 272 | 273 | void fuse_remove_signal_handlers(struct fuse_session *se) {} 274 | 275 | #endif // CYGWIN 276 | -------------------------------------------------------------------------------- /dokan_fuse/src/fuse_opt.c: -------------------------------------------------------------------------------- 1 | /* 2 | FUSE: Filesystem in Userspace 3 | Copyright (C) 2001-2007 Miklos Szeredi 4 | 5 | This program can be distributed under the terms of the GNU LGPL. 6 | See the file COPYING.LIB 7 | */ 8 | 9 | #include "fuse_opt.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | struct fuse_opt_context { 17 | void *data; 18 | const struct fuse_opt *opt; 19 | fuse_opt_proc_t proc; 20 | int argctr; 21 | int argc; 22 | char **argv; 23 | struct fuse_args outargs; 24 | char *opts; 25 | int nonopt; 26 | }; 27 | 28 | void fuse_opt_free_args(struct fuse_args *args) 29 | { 30 | if (args && args->argv && args->allocated) { 31 | int i; 32 | for (i = 0; i < args->argc; i++) 33 | free(args->argv[i]); 34 | free(args->argv); 35 | args->argv = NULL; 36 | args->allocated = 0; 37 | } 38 | } 39 | 40 | static int alloc_failed(void) 41 | { 42 | fprintf(stderr, "fuse: memory allocation failed\n"); 43 | return -1; 44 | } 45 | 46 | int fuse_opt_add_arg(struct fuse_args *args, const char *arg) 47 | { 48 | char **newargv = NULL; 49 | char *newarg; 50 | 51 | assert(!args->argv || args->allocated); 52 | 53 | newargv = (char **)realloc(args->argv, (args->argc + 2) * sizeof(char *)); 54 | newarg = newargv ? STRDUP(arg) : NULL; 55 | if (!newargv || !newarg) 56 | { 57 | if (newargv) 58 | free(newargv); 59 | return alloc_failed(); 60 | } 61 | 62 | args->argv = newargv; 63 | args->allocated = 1; 64 | args->argv[args->argc++] = newarg; 65 | args->argv[args->argc] = NULL; 66 | return 0; 67 | } 68 | 69 | int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) 70 | { 71 | assert(pos <= args->argc); 72 | if (fuse_opt_add_arg(args, arg) == -1) 73 | return -1; 74 | 75 | if (pos != args->argc - 1) { 76 | char *newarg = args->argv[args->argc - 1]; 77 | memmove(&args->argv[pos + 1], &args->argv[pos], 78 | sizeof(char *) * (args->argc - pos - 1)); 79 | args->argv[pos] = newarg; 80 | } 81 | return 0; 82 | } 83 | 84 | static int next_arg(struct fuse_opt_context *ctx, const char *opt) 85 | { 86 | if (ctx->argctr + 1 >= ctx->argc) { 87 | fprintf(stderr, "fuse: missing argument after `%s'\n", opt); 88 | return -1; 89 | } 90 | ctx->argctr++; 91 | return 0; 92 | } 93 | 94 | static int add_arg(struct fuse_opt_context *ctx, const char *arg) 95 | { 96 | return fuse_opt_add_arg(&ctx->outargs, arg); 97 | } 98 | 99 | int fuse_opt_add_opt(char **opts, const char *opt) 100 | { 101 | char *newopts; 102 | if (!*opts) 103 | newopts = STRDUP(opt); 104 | else { 105 | size_t oldlen = strlen(*opts); 106 | newopts = (char *)realloc(*opts, oldlen + 1 + strlen(opt) + 1); 107 | if (newopts) { 108 | newopts[oldlen] = ','; 109 | strcpy(newopts + oldlen + 1, opt); 110 | } 111 | } 112 | if (!newopts) 113 | return alloc_failed(); 114 | 115 | *opts = newopts; 116 | return 0; 117 | } 118 | 119 | static int add_opt(struct fuse_opt_context *ctx, const char *opt) 120 | { 121 | return fuse_opt_add_opt(&ctx->opts, opt); 122 | } 123 | 124 | static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key, 125 | int iso) 126 | { 127 | if (key == FUSE_OPT_KEY_DISCARD) 128 | return 0; 129 | 130 | if (key != FUSE_OPT_KEY_KEEP && ctx->proc) { 131 | int res = ctx->proc(ctx->data, arg, key, &ctx->outargs); 132 | if (res == -1 || !res) 133 | return res; 134 | } 135 | if (iso) 136 | return add_opt(ctx, arg); 137 | else 138 | return add_arg(ctx, arg); 139 | } 140 | 141 | static char match_template(const char *t, const char *arg, size_t *sepp) 142 | { 143 | size_t arglen = strlen(arg); 144 | const char *sep = strchr(t, '='); 145 | sep = sep ? sep : strchr(t, ' '); 146 | if (sep && (!sep[1] || sep[1] == '%')) { 147 | size_t tlen = sep - t; 148 | if (sep[0] == '=') 149 | tlen ++; 150 | if (arglen >= tlen && strncmp(arg, t, tlen) == 0) { 151 | *sepp = sep - t; 152 | return 1; 153 | } 154 | } 155 | if (strcmp(t, arg) == 0) { 156 | *sepp = 0; 157 | return 1; 158 | } 159 | return 0; 160 | } 161 | 162 | static const struct fuse_opt *find_opt(const struct fuse_opt *opt, 163 | const char *arg, size_t *sepp) 164 | { 165 | for (; opt && opt->templ; opt++) 166 | if (match_template(opt->templ, arg, sepp)) 167 | return opt; 168 | return NULL; 169 | } 170 | 171 | int fuse_opt_match(const struct fuse_opt *opts, const char *opt) 172 | { 173 | size_t dummy; 174 | return find_opt(opts, opt, &dummy) ? 1 : 0; 175 | } 176 | 177 | static int process_opt_param(void *var, const char *format, const char *param, 178 | const char *arg) 179 | { 180 | assert(format[0] == '%'); 181 | if (format[1] == 's') { 182 | char *copy = STRDUP(param); 183 | if (!copy) 184 | return alloc_failed(); 185 | 186 | *(char **) var = copy; 187 | } else { 188 | if (sscanf(param, format, var) != 1) { 189 | fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg); 190 | return -1; 191 | } 192 | } 193 | return 0; 194 | } 195 | 196 | static int process_opt(struct fuse_opt_context *ctx, 197 | const struct fuse_opt *opt, size_t sep, 198 | const char *arg, int iso) 199 | { 200 | if (opt->offset == (unsigned long)-1) { 201 | if (call_proc(ctx, arg, opt->value, iso) == -1) 202 | return -1; 203 | } else { 204 | void *var = ((unsigned char*)ctx->data) + opt->offset; 205 | if (sep && opt->templ[sep + 1]) { 206 | const char *param = arg + sep; 207 | if (opt->templ[sep] == '=') 208 | param ++; 209 | if (process_opt_param(var, opt->templ + sep + 1, 210 | param, arg) == -1) 211 | return -1; 212 | } else 213 | *(int *)var = opt->value; 214 | } 215 | return 0; 216 | } 217 | 218 | static int process_opt_sep_arg(struct fuse_opt_context *ctx, 219 | const struct fuse_opt *opt, size_t sep, 220 | const char *arg, int iso) 221 | { 222 | int res; 223 | char *newarg; 224 | char *param; 225 | 226 | if (next_arg(ctx, arg) == -1) 227 | return -1; 228 | 229 | param = ctx->argv[ctx->argctr]; 230 | newarg = (char *)malloc(sep + strlen(param) + 1); 231 | if (!newarg) 232 | return alloc_failed(); 233 | 234 | memcpy(newarg, arg, sep); 235 | strcpy(newarg + sep, param); 236 | res = process_opt(ctx, opt, sep, newarg, iso); 237 | free(newarg); 238 | 239 | return res; 240 | } 241 | 242 | static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso) 243 | { 244 | size_t sep; 245 | const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep); 246 | if (opt) { 247 | for (; opt; opt = find_opt(opt + 1, arg, &sep)) { 248 | int res; 249 | if (sep && opt->templ[sep] == ' ' && !arg[sep]) 250 | res = process_opt_sep_arg(ctx, opt, sep, arg, iso); 251 | else 252 | res = process_opt(ctx, opt, sep, arg, iso); 253 | if (res == -1) 254 | return -1; 255 | } 256 | return 0; 257 | } else 258 | return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso); 259 | } 260 | 261 | static int process_real_option_group(struct fuse_opt_context *ctx, char *opts) 262 | { 263 | char *sep; 264 | 265 | do { 266 | int res; 267 | sep = strchr(opts, ','); 268 | if (sep) 269 | *sep = '\0'; 270 | res = process_gopt(ctx, opts, 1); 271 | if (res == -1) 272 | return -1; 273 | opts = sep + 1; 274 | } while (sep); 275 | 276 | return 0; 277 | } 278 | 279 | static int process_option_group(struct fuse_opt_context *ctx, const char *opts) 280 | { 281 | int res; 282 | char *copy; 283 | const char *sep = strchr(opts, ','); 284 | if (!sep) 285 | return process_gopt(ctx, opts, 1); 286 | 287 | copy = STRDUP(opts); 288 | if (!copy) { 289 | fprintf(stderr, "fuse: memory allocation failed\n"); 290 | return -1; 291 | } 292 | res = process_real_option_group(ctx, copy); 293 | free(copy); 294 | return res; 295 | } 296 | 297 | static int process_one(struct fuse_opt_context *ctx, const char *arg) 298 | { 299 | if (ctx->nonopt || arg[0] != '-') 300 | return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0); 301 | else if (arg[1] == 'o') { 302 | if (arg[2]) 303 | return process_option_group(ctx, arg + 2); 304 | else { 305 | if (next_arg(ctx, arg) == -1) 306 | return -1; 307 | 308 | return process_option_group(ctx, ctx->argv[ctx->argctr]); 309 | } 310 | } else if (arg[1] == '-' && !arg[2]) { 311 | if (add_arg(ctx, arg) == -1) 312 | return -1; 313 | ctx->nonopt = ctx->outargs.argc; 314 | return 0; 315 | } else 316 | return process_gopt(ctx, arg, 0); 317 | } 318 | 319 | static int opt_parse(struct fuse_opt_context *ctx) 320 | { 321 | if (ctx->argc) { 322 | if (add_arg(ctx, ctx->argv[0]) == -1) 323 | return -1; 324 | } 325 | 326 | for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) 327 | if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) 328 | return -1; 329 | 330 | if (ctx->opts) { 331 | if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 || 332 | fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) 333 | return -1; 334 | } 335 | if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc) { 336 | free(ctx->outargs.argv[ctx->outargs.argc - 1]); 337 | ctx->outargs.argv[--ctx->outargs.argc] = NULL; 338 | } 339 | 340 | return 0; 341 | } 342 | 343 | int fuse_opt_parse(struct fuse_args *args, void *data, 344 | const struct fuse_opt opts[], fuse_opt_proc_t proc) 345 | { 346 | int res; 347 | struct fuse_opt_context ctx={0}; 348 | ctx.data = data; 349 | ctx.opt = opts; 350 | ctx.proc = proc; 351 | 352 | if (!args || !args->argv || !args->argc) 353 | return 0; 354 | 355 | ctx.argc = args->argc; 356 | ctx.argv = args->argv; 357 | 358 | res = opt_parse(&ctx); 359 | if (res != -1) { 360 | struct fuse_args tmp = *args; 361 | *args = ctx.outargs; 362 | ctx.outargs = tmp; 363 | } 364 | free(ctx.opts); 365 | fuse_opt_free_args(&ctx.outargs); 366 | return res; 367 | } 368 | -------------------------------------------------------------------------------- /dokan_fuse/src/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by dokanfuse.rc 4 | // 5 | #define IDR_VERSION2 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1000 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /dokan_fuse/src/utils.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_NO_STATUS 2 | #include 3 | #undef WIN32_NO_STATUS 4 | #include 5 | #include 6 | #include 7 | #include "utils.h" 8 | 9 | typedef unsigned int ICONV_CHAR; 10 | 11 | #if defined(__GNUC__) && __GNUC__ >= 3 12 | #define unlikely(x) __builtin_expect(!!(x), 0) 13 | #else 14 | #define unlikely(x) (x) 15 | #endif 16 | 17 | #define GET_A2(p) (*((unsigned short *)(p))) 18 | #define PUT_A2(buf, c) \ 19 | do { \ 20 | *((unsigned short *)(buf)) = (c); \ 21 | } while (0) 22 | 23 | static const unsigned char utf8_lengths[256] = { 24 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 25 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29 | 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33 | 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34 | 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0, 35 | }; 36 | 37 | static const unsigned char utf8_masks[7] = {0, 0x7f, 0x1f, 0x0f, 38 | 0x07, 0x03, 0x01}; 39 | 40 | static size_t get_utf8(const unsigned char *p, size_t len, ICONV_CHAR *out) { 41 | ICONV_CHAR uc; 42 | size_t l; 43 | 44 | l = utf8_lengths[p[0]]; 45 | if (unlikely(l == 0)) 46 | return -EILSEQ; 47 | if (unlikely(len < l)) 48 | return -EINVAL; 49 | 50 | len = l; 51 | uc = *p++ & utf8_masks[l]; 52 | while (--l) 53 | uc = (uc << 6) | (*p++ & 0x3f); 54 | *out = uc; 55 | return len; 56 | } 57 | 58 | static size_t put_utf8(unsigned char *buf, ICONV_CHAR c) { 59 | #define MASK(n) ((0xffffffffu << (n)) & 0xffffffffu) 60 | size_t o_len; 61 | unsigned mask; 62 | 63 | if ((c & MASK(7)) == 0) { 64 | *buf = (unsigned char)c; 65 | return 1; 66 | } 67 | 68 | o_len = 2; 69 | for (;;) { 70 | if ((c & MASK(11)) == 0) 71 | break; 72 | ++o_len; 73 | if ((c & MASK(16)) == 0) 74 | break; 75 | ++o_len; 76 | if ((c & MASK(21)) == 0) 77 | break; 78 | ++o_len; 79 | if ((c & MASK(26)) == 0) 80 | break; 81 | ++o_len; 82 | if ((c & MASK(31)) != 0) 83 | return -EINVAL; 84 | } 85 | 86 | buf += o_len; 87 | mask = 0xff80; 88 | for (;;) { 89 | *--buf = 0x80 | (c & 0x3f); 90 | c >>= 6; 91 | mask >>= 1; 92 | if (c < 0x40) { 93 | *--buf = mask | c; 94 | break; 95 | } 96 | } 97 | return o_len; 98 | } 99 | 100 | static size_t get_utf16(const unsigned char *p, size_t len, ICONV_CHAR *out) { 101 | ICONV_CHAR c; 102 | 103 | if (len < 2) 104 | return -EINVAL; 105 | c = GET_A2(p); 106 | if ((c & 0xfc00) == 0xd800 && len >= 4) { 107 | ICONV_CHAR c2 = GET_A2(p + 2); 108 | if ((c2 & 0xfc00) == 0xdc00) { 109 | *out = (c << 10) + c2 - ((0xd800 << 10) + 0xdc00 - 0x10000); 110 | return 4; 111 | } 112 | } 113 | *out = c; 114 | return 2; 115 | } 116 | 117 | static size_t put_utf16(unsigned char *buf, ICONV_CHAR c) { 118 | if (c >= 0x110000u) 119 | return -EILSEQ; 120 | if (c < 0x10000u) { 121 | PUT_A2(buf, c); 122 | return 2; 123 | } 124 | c -= 0x10000u; 125 | PUT_A2(buf, 0xd800 + (c >> 10)); 126 | PUT_A2(buf + 2, 0xdc00 + (c & 0x3ffu)); 127 | return 4; 128 | } 129 | 130 | typedef size_t (*get_conver_t)(const unsigned char *p, size_t len, 131 | ICONV_CHAR *out); 132 | typedef size_t (*put_convert_t)(unsigned char *buf, ICONV_CHAR c); 133 | 134 | static size_t convert_char(get_conver_t get_func, put_convert_t put_func, 135 | const void *src, size_t src_len, void *dest) { 136 | size_t il = src_len; 137 | const unsigned char *ib = (const unsigned char *)src; 138 | unsigned char *ob = (unsigned char *)dest; 139 | size_t total = 0; 140 | 141 | while (il) { 142 | ICONV_CHAR out_c; 143 | size_t readed = get_func(ib, il, &out_c); 144 | if (unlikely(readed < 0)) 145 | return -1; 146 | il -= readed; 147 | ib += readed; 148 | 149 | unsigned char dummy[8] = {0}; 150 | size_t written = put_func(ob ? ob : dummy, out_c); 151 | if (unlikely(written < 0)) 152 | return -1; 153 | 154 | if (ob) 155 | ob += written; 156 | total += written; 157 | } 158 | return total; 159 | } 160 | 161 | static char *wchar_to_utf8(const wchar_t *str) { 162 | if (str == NULL) 163 | return NULL; 164 | 165 | // Determine required length 166 | size_t ln = convert_char(get_utf16, put_utf8, str, 167 | (wcslen(str) + 1) * sizeof(wchar_t), NULL); 168 | if (ln <= 0) 169 | return NULL; 170 | char *res = (char *)malloc(sizeof(char) * ln); 171 | if (res == NULL) 172 | return NULL; 173 | 174 | // Convert to Unicode 175 | convert_char(get_utf16, put_utf8, str, (wcslen(str) + 1) * sizeof(wchar_t), 176 | res); 177 | return res; 178 | } 179 | 180 | void utf8_to_wchar_buf(const char *src, wchar_t *res, int maxlen) { 181 | if (res == NULL || maxlen == 0) 182 | return; 183 | 184 | size_t ln = convert_char(get_utf8, put_utf16, src, strlen(src) + 1, 185 | NULL); /* | raise_w32_error()*/ 186 | ; 187 | if (ln <= 0 || ln / sizeof(wchar_t) > (size_t)maxlen) { 188 | *res = L'\0'; 189 | return; 190 | } 191 | convert_char(get_utf8, put_utf16, src, strlen(src) + 1, 192 | res); /* | raise_w32_error()*/ 193 | ; 194 | } 195 | 196 | void utf8_to_wchar_buf_old(const char *src, wchar_t *res, int maxlen) { 197 | if (res == NULL || maxlen == 0) 198 | return; 199 | 200 | int ln = 201 | MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0) /* | raise_w32_error()*/; 202 | if (ln >= maxlen) { 203 | *res = L'\0'; 204 | return; 205 | } 206 | MultiByteToWideChar(CP_ACP, 0, src, -1, res, 207 | (int)(strlen(src) + 1)) /* | raise_w32_error()*/; 208 | } 209 | 210 | std::string wchar_to_utf8_cstr(const wchar_t *str) { 211 | char *utf = wchar_to_utf8(str); 212 | std::string res(utf); 213 | free(utf); 214 | return res; 215 | } 216 | 217 | std::string unixify(const std::string &str) { 218 | // Replace slashes 219 | std::string res = str; 220 | for (size_t f = 0; f < res.size(); ++f) { 221 | char ch = res[f]; 222 | if (ch == '\\') 223 | res[f] = '/'; 224 | } 225 | // Remove the trailing slash 226 | if (res.size() > 1 && res[res.size() - 1] == '/') 227 | res.resize(res.size() - 1); 228 | 229 | return res; 230 | } 231 | 232 | FILETIME unixTimeToFiletime(time_t t) { 233 | // Note that LONGLONG is a 64-bit value 234 | LONGLONG ll; 235 | 236 | ll = Int32x32To64(t, 10000000) + 116444736000000000LL; 237 | FILETIME res; 238 | res.dwLowDateTime = (DWORD)ll; 239 | res.dwHighDateTime = (DWORD)(ll >> 32); 240 | return res; 241 | } 242 | 243 | bool is_filetime_set(const FILETIME *ft) { 244 | if (ft == 0 || (ft->dwHighDateTime == 0 && ft->dwLowDateTime == 0)) 245 | return false; 246 | return true; 247 | } 248 | 249 | time_t filetimeToUnixTime(const FILETIME *ft) { 250 | if (!is_filetime_set(ft)) 251 | return 0; 252 | 253 | ULONGLONG ll = (ULONGLONG(ft->dwHighDateTime) << 32) + ft->dwLowDateTime; 254 | return time_t((ll - 116444736000000000LL) / 10000000LL); 255 | } 256 | 257 | /////////////////////////////////////////////////////////////////////////////////////// 258 | ////// Error mapping and arguments conversion 259 | /////////////////////////////////////////////////////////////////////////////////////// 260 | struct errentry { 261 | NTSTATUS oscode; /* OS return value */ 262 | int errnocode; /* System V error code */ 263 | }; 264 | 265 | static const struct errentry errtable[] = { 266 | {STATUS_NOT_IMPLEMENTED, EINVAL}, /* 1 */ 267 | {STATUS_OBJECT_NAME_NOT_FOUND, ENOENT}, /* 2 */ 268 | {STATUS_OBJECT_PATH_NOT_FOUND, ENOENT}, /* 3 */ 269 | {STATUS_TOO_MANY_OPENED_FILES, EMFILE}, /* 4 */ 270 | {STATUS_ACCESS_DENIED, EACCES}, /* 5 */ 271 | {STATUS_INVALID_HANDLE, EBADF}, /* 6 */ 272 | {STATUS_DISK_CORRUPT_ERROR, ENOMEM}, /* 7 */ 273 | {STATUS_NO_MEMORY, ENOMEM}, /* 8 */ 274 | {STATUS_INVALID_ADDRESS, ENOMEM}, /* 9 */ 275 | {STATUS_VARIABLE_NOT_FOUND, E2BIG}, /* 10 */ 276 | //{ ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */ Need to convert it 277 | //to NTSTATUS 278 | //{ ERROR_INVALID_ACCESS, EINVAL }, /* 12 */ 279 | //{ ERROR_INVALID_DATA, EINVAL }, /* 13 */ 280 | //{ ERROR_INVALID_DRIVE, ENOENT }, /* 15 */ 281 | //{ ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */ 282 | {STATUS_NOT_SAME_DEVICE, EXDEV}, /* 17 */ 283 | {STATUS_NO_MORE_FILES, ENOENT}, /* 18 */ 284 | {STATUS_FILE_LOCK_CONFLICT, EACCES}, /* 33 */ 285 | {STATUS_BAD_NETWORK_PATH, ENOENT}, /* 53 */ 286 | {STATUS_NETWORK_ACCESS_DENIED, EACCES}, /* 65 */ 287 | {STATUS_BAD_NETWORK_NAME, ENOENT}, /* 67 */ 288 | {STATUS_OBJECT_NAME_COLLISION, EEXIST}, /* 183 */ 289 | {STATUS_OBJECT_NAME_COLLISION, EEXIST}, /* 80 */ 290 | {STATUS_CANNOT_MAKE, EACCES}, /* 82 */ 291 | //{ ERROR_FAIL_I24, EACCES }, /* 83 */ 292 | {STATUS_INVALID_PARAMETER, EINVAL}, /* 87 */ 293 | //{ ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */ 294 | //{ ERROR_DRIVE_LOCKED, EACCES }, /* 108 */ 295 | {STATUS_PIPE_BROKEN, EPIPE}, /* 109 */ 296 | {STATUS_DISK_FULL, ENOSPC}, /* 112 */ 297 | //{ ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */ 298 | {STATUS_INVALID_HANDLE, EINVAL}, /* 124 */ 299 | {STATUS_NOT_FOUND, ECHILD}, /* 128 */ 300 | //{ ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */ 301 | //{ ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */ 302 | //{ ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */ 303 | //{ ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */ 304 | {STATUS_DIRECTORY_NOT_EMPTY, ENOTEMPTY}, /* 145 */ 305 | {STATUS_NOT_LOCKED, EACCES}, /* 158 */ 306 | {STATUS_OBJECT_PATH_SYNTAX_BAD, ENOENT}, /* 161 */ 307 | //{ ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */ 308 | {STATUS_LOCK_NOT_GRANTED, EACCES}, /* 167 */ 309 | {STATUS_NAME_TOO_LONG, ENOENT}, /* 206 */ 310 | //{ ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */ 311 | {STATUS_QUOTA_EXCEEDED, ENOMEM} /* 1816 */ 312 | }; 313 | const int errtable_size = sizeof(errtable) / sizeof(errtable[0]); 314 | 315 | extern "C" int ntstatus_error_to_errno(int win_res) { 316 | if (win_res == 0) 317 | return 0; // No error 318 | 319 | if (win_res < 0) 320 | win_res = -win_res; 321 | for (int f = 0; f < errtable_size; ++f) 322 | if (errtable[f].oscode == win_res) 323 | return errtable[f].errnocode; 324 | return EINVAL; 325 | } 326 | 327 | extern "C" int errno_to_ntstatus_error(int err) { 328 | if (err == 0) 329 | return 0; // No error 330 | 331 | if (err < 0) 332 | err = -err; 333 | for (int f = 0; f < errtable_size; ++f) 334 | if (errtable[f].errnocode == err) 335 | return errtable[f].oscode; 336 | return ERROR_INVALID_FUNCTION; 337 | } 338 | 339 | extern "C" char **convert_args(int argc, wchar_t *argv[]) { 340 | char **arr = (char **)malloc(sizeof(char *) * (argc + 1)); 341 | if (arr == NULL) 342 | return NULL; 343 | for (int f = 0; f < argc; ++f) 344 | arr[f] = wchar_to_utf8(argv[f]); 345 | arr[argc] = NULL; 346 | return arr; 347 | } 348 | 349 | extern "C" void free_converted_args(int argc, char **argv) { 350 | for (int f = 0; f < argc; ++f) 351 | free(argv[f]); 352 | free(argv); 353 | } 354 | 355 | std::string extract_file_name(const std::string &str) { 356 | std::string extracted; 357 | 358 | for (std::string::const_reverse_iterator f = str.rbegin(), en = str.rend(); 359 | f != en; ++f) 360 | if (*f == '/') { 361 | extracted = str.substr(en - f - 1); 362 | break; 363 | } 364 | 365 | if (extracted.empty()) 366 | return str; 367 | if (extracted[0] == '/') 368 | return extracted.substr(1); 369 | return extracted; 370 | } 371 | 372 | std::string extract_dir_name(const std::string &str) { 373 | for (std::string::const_reverse_iterator f = str.rbegin(), en = str.rend(); 374 | f != en; ++f) 375 | if (*f == '/') 376 | return str.substr(0, en - f); 377 | return str; 378 | } 379 | -------------------------------------------------------------------------------- /include/CL/cl_d3d10.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | **********************************************************************************/ 23 | 24 | /* $Revision: 10911 $ on $Date: 2010-04-06 03:11:26 +0530 (Tue, 06 Apr 2010) $ */ 25 | 26 | #ifndef __OPENCL_CL_D3D10_H 27 | #define __OPENCL_CL_D3D10_H 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /****************************************************************************** 38 | * cl_khr_d3d10_sharing */ 39 | #define cl_khr_d3d10_sharing 1 40 | 41 | typedef cl_uint cl_d3d10_device_source_khr; 42 | typedef cl_uint cl_d3d10_device_set_khr; 43 | 44 | /******************************************************************************/ 45 | 46 | // Error Codes 47 | #define CL_INVALID_D3D10_DEVICE_KHR -1002 48 | #define CL_INVALID_D3D10_RESOURCE_KHR -1003 49 | #define CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR -1004 50 | #define CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR -1005 51 | 52 | // cl_d3d10_device_source_nv 53 | #define CL_D3D10_DEVICE_KHR 0x4010 54 | #define CL_D3D10_DXGI_ADAPTER_KHR 0x4011 55 | 56 | // cl_d3d10_device_set_nv 57 | #define CL_PREFERRED_DEVICES_FOR_D3D10_KHR 0x4012 58 | #define CL_ALL_DEVICES_FOR_D3D10_KHR 0x4013 59 | 60 | // cl_context_info 61 | #define CL_CONTEXT_D3D10_DEVICE_KHR 0x4014 62 | #define CL_CONTEXT_D3D10_PREFER_SHARED_RESOURCES_KHR 0x402C 63 | 64 | // cl_mem_info 65 | #define CL_MEM_D3D10_RESOURCE_KHR 0x4015 66 | 67 | // cl_image_info 68 | #define CL_IMAGE_D3D10_SUBRESOURCE_KHR 0x4016 69 | 70 | // cl_command_type 71 | #define CL_COMMAND_ACQUIRE_D3D10_OBJECTS_KHR 0x4017 72 | #define CL_COMMAND_RELEASE_D3D10_OBJECTS_KHR 0x4018 73 | 74 | /******************************************************************************/ 75 | 76 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D10KHR_fn)( 77 | cl_platform_id platform, 78 | cl_d3d10_device_source_khr d3d_device_source, 79 | void * d3d_object, 80 | cl_d3d10_device_set_khr d3d_device_set, 81 | cl_uint num_entries, 82 | cl_device_id * devices, 83 | cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0; 84 | 85 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10BufferKHR_fn)( 86 | cl_context context, 87 | cl_mem_flags flags, 88 | ID3D10Buffer * resource, 89 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 90 | 91 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture2DKHR_fn)( 92 | cl_context context, 93 | cl_mem_flags flags, 94 | ID3D10Texture2D * resource, 95 | UINT subresource, 96 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 97 | 98 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture3DKHR_fn)( 99 | cl_context context, 100 | cl_mem_flags flags, 101 | ID3D10Texture3D * resource, 102 | UINT subresource, 103 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 104 | 105 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D10ObjectsKHR_fn)( 106 | cl_command_queue command_queue, 107 | cl_uint num_objects, 108 | const cl_mem * mem_objects, 109 | cl_uint num_events_in_wait_list, 110 | const cl_event * event_wait_list, 111 | cl_event * event) CL_API_SUFFIX__VERSION_1_0; 112 | 113 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D10ObjectsKHR_fn)( 114 | cl_command_queue command_queue, 115 | cl_uint num_objects, 116 | cl_mem * mem_objects, 117 | cl_uint num_events_in_wait_list, 118 | const cl_event * event_wait_list, 119 | cl_event * event) CL_API_SUFFIX__VERSION_1_0; 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | 125 | #endif // __OPENCL_CL_D3D10_H 126 | 127 | -------------------------------------------------------------------------------- /include/CL/cl_d3d10_ext.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | **********************************************************************************/ 23 | 24 | #ifndef __OPENCL_CL_D3D10_EXT_H 25 | #define __OPENCL_CL_D3D10_EXT_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /****************************************************************************** 36 | * cl_nv_d3d10_sharing */ 37 | 38 | typedef cl_uint cl_d3d10_device_source_nv; 39 | typedef cl_uint cl_d3d10_device_set_nv; 40 | 41 | /******************************************************************************/ 42 | 43 | // Error Codes 44 | #define CL_INVALID_D3D10_DEVICE_NV -1002 45 | #define CL_INVALID_D3D10_RESOURCE_NV -1003 46 | #define CL_D3D10_RESOURCE_ALREADY_ACQUIRED_NV -1004 47 | #define CL_D3D10_RESOURCE_NOT_ACQUIRED_NV -1005 48 | 49 | // cl_d3d10_device_source_nv 50 | #define CL_D3D10_DEVICE_NV 0x4010 51 | #define CL_D3D10_DXGI_ADAPTER_NV 0x4011 52 | 53 | // cl_d3d10_device_set_nv 54 | #define CL_PREFERRED_DEVICES_FOR_D3D10_NV 0x4012 55 | #define CL_ALL_DEVICES_FOR_D3D10_NV 0x4013 56 | 57 | // cl_context_info 58 | #define CL_CONTEXT_D3D10_DEVICE_NV 0x4014 59 | 60 | // cl_mem_info 61 | #define CL_MEM_D3D10_RESOURCE_NV 0x4015 62 | 63 | // cl_image_info 64 | #define CL_IMAGE_D3D10_SUBRESOURCE_NV 0x4016 65 | 66 | // cl_command_type 67 | #define CL_COMMAND_ACQUIRE_D3D10_OBJECTS_NV 0x4017 68 | #define CL_COMMAND_RELEASE_D3D10_OBJECTS_NV 0x4018 69 | 70 | /******************************************************************************/ 71 | 72 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D10NV_fn)( 73 | cl_platform_id platform, 74 | cl_d3d10_device_source_nv d3d_device_source, 75 | void * d3d_object, 76 | cl_d3d10_device_set_nv d3d_device_set, 77 | cl_uint num_entries, 78 | cl_device_id * devices, 79 | cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0; 80 | 81 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10BufferNV_fn)( 82 | cl_context context, 83 | cl_mem_flags flags, 84 | ID3D10Buffer * resource, 85 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 86 | 87 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture2DNV_fn)( 88 | cl_context context, 89 | cl_mem_flags flags, 90 | ID3D10Texture2D * resource, 91 | UINT subresource, 92 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 93 | 94 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D10Texture3DNV_fn)( 95 | cl_context context, 96 | cl_mem_flags flags, 97 | ID3D10Texture3D * resource, 98 | UINT subresource, 99 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 100 | 101 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D10ObjectsNV_fn)( 102 | cl_command_queue command_queue, 103 | cl_uint num_objects, 104 | const cl_mem * mem_objects, 105 | cl_uint num_events_in_wait_list, 106 | const cl_event * event_wait_list, 107 | cl_event * event) CL_API_SUFFIX__VERSION_1_0; 108 | 109 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D10ObjectsNV_fn)( 110 | cl_command_queue command_queue, 111 | cl_uint num_objects, 112 | cl_mem * mem_objects, 113 | cl_uint num_events_in_wait_list, 114 | const cl_event * event_wait_list, 115 | cl_event * event) CL_API_SUFFIX__VERSION_1_0; 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | 121 | #endif // __OPENCL_CL_D3D10_H 122 | 123 | -------------------------------------------------------------------------------- /include/CL/cl_d3d11_ext.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | **********************************************************************************/ 23 | 24 | #ifndef __OPENCL_CL_D3D11_EXT_H 25 | #define __OPENCL_CL_D3D11_EXT_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /****************************************************************************** 36 | * cl_nv_d3d11_sharing */ 37 | 38 | typedef cl_uint cl_d3d11_device_source_nv; 39 | typedef cl_uint cl_d3d11_device_set_nv; 40 | 41 | /******************************************************************************/ 42 | 43 | // Error Codes 44 | #define CL_INVALID_D3D11_DEVICE_NV -1006 45 | #define CL_INVALID_D3D11_RESOURCE_NV -1007 46 | #define CL_D3D11_RESOURCE_ALREADY_ACQUIRED_NV -1008 47 | #define CL_D3D11_RESOURCE_NOT_ACQUIRED_NV -1009 48 | 49 | // cl_d3d11_device_source_nv 50 | #define CL_D3D11_DEVICE_NV 0x4019 51 | #define CL_D3D11_DXGI_ADAPTER_NV 0x401A 52 | 53 | // cl_d3d11_device_set_nv 54 | #define CL_PREFERRED_DEVICES_FOR_D3D11_NV 0x401B 55 | #define CL_ALL_DEVICES_FOR_D3D11_NV 0x401C 56 | 57 | // cl_context_info 58 | #define CL_CONTEXT_D3D11_DEVICE_NV 0x401D 59 | 60 | // cl_mem_info 61 | #define CL_MEM_D3D11_RESOURCE_NV 0x401E 62 | 63 | // cl_image_info 64 | #define CL_IMAGE_D3D11_SUBRESOURCE_NV 0x401F 65 | 66 | // cl_command_type 67 | #define CL_COMMAND_ACQUIRE_D3D11_OBJECTS_NV 0x4020 68 | #define CL_COMMAND_RELEASE_D3D11_OBJECTS_NV 0x4021 69 | 70 | /******************************************************************************/ 71 | 72 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D11NV_fn)( 73 | cl_platform_id platform, 74 | cl_d3d11_device_source_nv d3d_device_source, 75 | void * d3d_object, 76 | cl_d3d11_device_set_nv d3d_device_set, 77 | cl_uint num_entries, 78 | cl_device_id * devices, 79 | cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0; 80 | 81 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11BufferNV_fn)( 82 | cl_context context, 83 | cl_mem_flags flags, 84 | ID3D11Buffer * resource, 85 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 86 | 87 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture2DNV_fn)( 88 | cl_context context, 89 | cl_mem_flags flags, 90 | ID3D11Texture2D * resource, 91 | UINT subresource, 92 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 93 | 94 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D11Texture3DNV_fn)( 95 | cl_context context, 96 | cl_mem_flags flags, 97 | ID3D11Texture3D * resource, 98 | UINT subresource, 99 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 100 | 101 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D11ObjectsNV_fn)( 102 | cl_command_queue command_queue, 103 | cl_uint num_objects, 104 | const cl_mem * mem_objects, 105 | cl_uint num_events_in_wait_list, 106 | const cl_event * event_wait_list, 107 | cl_event * event) CL_API_SUFFIX__VERSION_1_0; 108 | 109 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D11ObjectsNV_fn)( 110 | cl_command_queue command_queue, 111 | cl_uint num_objects, 112 | cl_mem * mem_objects, 113 | cl_uint num_events_in_wait_list, 114 | const cl_event * event_wait_list, 115 | cl_event * event) CL_API_SUFFIX__VERSION_1_0; 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | 121 | #endif // __OPENCL_CL_D3D11_H 122 | 123 | -------------------------------------------------------------------------------- /include/CL/cl_d3d9_ext.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | **********************************************************************************/ 23 | 24 | #ifndef __OPENCL_CL_D3D9_EXT_H 25 | #define __OPENCL_CL_D3D9_EXT_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /****************************************************************************** 36 | * cl_nv_d3d9_sharing */ 37 | 38 | typedef cl_uint cl_d3d9_device_source_nv; 39 | typedef cl_uint cl_d3d9_device_set_nv; 40 | 41 | /******************************************************************************/ 42 | 43 | // Error Codes 44 | #define CL_INVALID_D3D9_DEVICE_NV -1010 45 | #define CL_INVALID_D3D9_RESOURCE_NV -1011 46 | #define CL_D3D9_RESOURCE_ALREADY_ACQUIRED_NV -1012 47 | #define CL_D3D9_RESOURCE_NOT_ACQUIRED_NV -1013 48 | 49 | // cl_d3d9_device_source_nv 50 | #define CL_D3D9_DEVICE_NV 0x4022 51 | #define CL_D3D9_ADAPTER_NAME_NV 0x4023 52 | 53 | // cl_d3d9_device_set_nv 54 | #define CL_PREFERRED_DEVICES_FOR_D3D9_NV 0x4024 55 | #define CL_ALL_DEVICES_FOR_D3D9_NV 0x4025 56 | 57 | // cl_context_info 58 | #define CL_CONTEXT_D3D9_DEVICE_NV 0x4026 59 | 60 | // cl_mem_info 61 | #define CL_MEM_D3D9_RESOURCE_NV 0x4027 62 | 63 | // cl_image_info 64 | #define CL_IMAGE_D3D9_FACE_NV 0x4028 65 | #define CL_IMAGE_D3D9_LEVEL_NV 0x4029 66 | 67 | // cl_command_type 68 | #define CL_COMMAND_ACQUIRE_D3D9_OBJECTS_NV 0x402A 69 | #define CL_COMMAND_RELEASE_D3D9_OBJECTS_NV 0x402B 70 | 71 | /******************************************************************************/ 72 | 73 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetDeviceIDsFromD3D9NV_fn)( 74 | cl_platform_id platform, 75 | cl_d3d9_device_source_nv d3d_device_source, 76 | void * d3d_object, 77 | cl_d3d9_device_set_nv d3d_device_set, 78 | cl_uint num_entries, 79 | cl_device_id * devices, 80 | cl_uint * num_devices) CL_API_SUFFIX__VERSION_1_0; 81 | 82 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D9VertexBufferNV_fn)( 83 | cl_context context, 84 | cl_mem_flags flags, 85 | IDirect3DVertexBuffer9 * resource, 86 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 87 | 88 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D9IndexBufferNV_fn)( 89 | cl_context context, 90 | cl_mem_flags flags, 91 | IDirect3DIndexBuffer9 * resource, 92 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 93 | 94 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D9SurfaceNV_fn)( 95 | cl_context context, 96 | cl_mem_flags flags, 97 | IDirect3DSurface9 * resource, 98 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 99 | 100 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D9TextureNV_fn)( 101 | cl_context context, 102 | cl_mem_flags flags, 103 | IDirect3DTexture9 *resource, 104 | UINT miplevel, 105 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 106 | 107 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D9CubeTextureNV_fn)( 108 | cl_context context, 109 | cl_mem_flags flags, 110 | IDirect3DCubeTexture9 * resource, 111 | D3DCUBEMAP_FACES facetype, 112 | UINT miplevel, 113 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 114 | 115 | typedef CL_API_ENTRY cl_mem (CL_API_CALL *clCreateFromD3D9VolumeTextureNV_fn)( 116 | cl_context context, 117 | cl_mem_flags flags, 118 | IDirect3DVolumeTexture9 * resource, 119 | UINT miplevel, 120 | cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0; 121 | 122 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueAcquireD3D9ObjectsNV_fn)( 123 | cl_command_queue command_queue, 124 | cl_uint num_objects, 125 | const cl_mem *mem_objects, 126 | cl_uint num_events_in_wait_list, 127 | const cl_event *event_wait_list, 128 | cl_event *event) CL_API_SUFFIX__VERSION_1_0; 129 | 130 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clEnqueueReleaseD3D9ObjectsNV_fn)( 131 | cl_command_queue command_queue, 132 | cl_uint num_objects, 133 | cl_mem *mem_objects, 134 | cl_uint num_events_in_wait_list, 135 | const cl_event *event_wait_list, 136 | cl_event *event) CL_API_SUFFIX__VERSION_1_0; 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | #endif // __OPENCL_CL_D3D9_H 143 | 144 | -------------------------------------------------------------------------------- /include/CL/cl_ext.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | ******************************************************************************/ 23 | 24 | /* $Revision: 11187 $ on $Date: 2010-04-28 03:25:05 +0530 (Wed, 28 Apr 2010) $ */ 25 | 26 | /* cl_ext.h contains OpenCL extensions which don't have external */ 27 | /* (OpenGL, D3D) dependencies. */ 28 | 29 | #ifndef __CL_EXT_H 30 | #define __CL_EXT_H 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #ifdef __APPLE__ 37 | #include 38 | #else 39 | #include 40 | #endif 41 | 42 | /* cl_khr_fp64 extension - no extension #define since it has no functions */ 43 | #define CL_DEVICE_DOUBLE_FP_CONFIG 0x1032 44 | 45 | 46 | /* cl_khr_fp16 extension - no extension #define since it has no functions */ 47 | #define CL_DEVICE_HALF_FP_CONFIG 0x1033 48 | 49 | 50 | /* cl_khr_icd extension */ 51 | #define cl_khr_icd 1 52 | 53 | /* cl_platform_info */ 54 | #define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920 55 | 56 | /* Additional Error Codes */ 57 | #define CL_PLATFORM_NOT_FOUND_KHR -1001 58 | 59 | extern CL_API_ENTRY cl_int CL_API_CALL 60 | clIcdGetPlatformIDsKHR(cl_uint /* num_entries */, 61 | cl_platform_id * /* platforms */, 62 | cl_uint * /* num_platforms */); 63 | 64 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clIcdGetPlatformIDsKHR_fn)( 65 | cl_uint num_entries, 66 | cl_platform_id * platforms, 67 | cl_uint * num_platforms); 68 | 69 | /* cl_khr_icd extension */ 70 | #define cl_khr_icd 1 71 | 72 | /* cl_amd_device_attribute_query - no extension #define since it has no functions */ 73 | #define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036 74 | 75 | /* cl_nv_device_attribute_query extension - no extension #define since it has no functions */ 76 | #define CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV 0x4000 77 | #define CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV 0x4001 78 | #define CL_DEVICE_REGISTERS_PER_BLOCK_NV 0x4002 79 | #define CL_DEVICE_WARP_SIZE_NV 0x4003 80 | #define CL_DEVICE_GPU_OVERLAP_NV 0x4004 81 | #define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005 82 | #define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | 88 | 89 | #endif /* __CL_EXT_H */ 90 | -------------------------------------------------------------------------------- /include/CL/cl_gl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | **********************************************************************************/ 23 | 24 | /* $Revision: 11042 $ on $Date: 2010-04-14 23:26:05 +0530 (Wed, 14 Apr 2010) $ */ 25 | 26 | /* 27 | * cl_gl.h contains Khronos-approved (KHR) OpenCL extensions which have 28 | * OpenGL dependencies. The application is responsible for #including 29 | * OpenGL or OpenGL ES headers before #including cl_gl.h. 30 | */ 31 | 32 | #ifndef __OPENCL_CL_GL_H 33 | #define __OPENCL_CL_GL_H 34 | 35 | #ifdef __APPLE__ 36 | #include 37 | #include 38 | #else 39 | #include 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | typedef cl_uint cl_gl_object_type; 47 | typedef cl_uint cl_gl_texture_info; 48 | typedef cl_uint cl_gl_platform_info; 49 | typedef struct __GLsync *cl_GLsync; 50 | 51 | /* cl_gl_object_type */ 52 | #define CL_GL_OBJECT_BUFFER 0x2000 53 | #define CL_GL_OBJECT_TEXTURE2D 0x2001 54 | #define CL_GL_OBJECT_TEXTURE3D 0x2002 55 | #define CL_GL_OBJECT_RENDERBUFFER 0x2003 56 | 57 | /* cl_gl_texture_info */ 58 | #define CL_GL_TEXTURE_TARGET 0x2004 59 | #define CL_GL_MIPMAP_LEVEL 0x2005 60 | 61 | extern CL_API_ENTRY cl_mem CL_API_CALL 62 | clCreateFromGLBuffer(cl_context /* context */, 63 | cl_mem_flags /* flags */, 64 | cl_GLuint /* bufobj */, 65 | int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; 66 | 67 | extern CL_API_ENTRY cl_mem CL_API_CALL 68 | clCreateFromGLTexture2D(cl_context /* context */, 69 | cl_mem_flags /* flags */, 70 | cl_GLenum /* target */, 71 | cl_GLint /* miplevel */, 72 | cl_GLuint /* texture */, 73 | cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; 74 | 75 | extern CL_API_ENTRY cl_mem CL_API_CALL 76 | clCreateFromGLTexture3D(cl_context /* context */, 77 | cl_mem_flags /* flags */, 78 | cl_GLenum /* target */, 79 | cl_GLint /* miplevel */, 80 | cl_GLuint /* texture */, 81 | cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; 82 | 83 | extern CL_API_ENTRY cl_mem CL_API_CALL 84 | clCreateFromGLRenderbuffer(cl_context /* context */, 85 | cl_mem_flags /* flags */, 86 | cl_GLuint /* renderbuffer */, 87 | cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0; 88 | 89 | extern CL_API_ENTRY cl_int CL_API_CALL 90 | clGetGLObjectInfo(cl_mem /* memobj */, 91 | cl_gl_object_type * /* gl_object_type */, 92 | cl_GLuint * /* gl_object_name */) CL_API_SUFFIX__VERSION_1_0; 93 | 94 | extern CL_API_ENTRY cl_int CL_API_CALL 95 | clGetGLTextureInfo(cl_mem /* memobj */, 96 | cl_gl_texture_info /* param_name */, 97 | size_t /* param_value_size */, 98 | void * /* param_value */, 99 | size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; 100 | 101 | extern CL_API_ENTRY cl_int CL_API_CALL 102 | clEnqueueAcquireGLObjects(cl_command_queue /* command_queue */, 103 | cl_uint /* num_objects */, 104 | const cl_mem * /* mem_objects */, 105 | cl_uint /* num_events_in_wait_list */, 106 | const cl_event * /* event_wait_list */, 107 | cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; 108 | 109 | extern CL_API_ENTRY cl_int CL_API_CALL 110 | clEnqueueReleaseGLObjects(cl_command_queue /* command_queue */, 111 | cl_uint /* num_objects */, 112 | const cl_mem * /* mem_objects */, 113 | cl_uint /* num_events_in_wait_list */, 114 | const cl_event * /* event_wait_list */, 115 | cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0; 116 | 117 | /* cl_khr_gl_sharing extension */ 118 | 119 | #define cl_khr_gl_sharing 1 120 | 121 | typedef cl_uint cl_gl_context_info; 122 | 123 | /* Additional Error Codes */ 124 | #define CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR -1000 125 | 126 | /* cl_gl_context_info */ 127 | #define CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR 0x2006 128 | #define CL_DEVICES_FOR_GL_CONTEXT_KHR 0x2007 129 | 130 | /* Additional cl_context_properties */ 131 | #define CL_GL_CONTEXT_KHR 0x2008 132 | #define CL_EGL_DISPLAY_KHR 0x2009 133 | #define CL_GLX_DISPLAY_KHR 0x200A 134 | #define CL_WGL_HDC_KHR 0x200B 135 | #define CL_CGL_SHAREGROUP_KHR 0x200C 136 | 137 | extern CL_API_ENTRY cl_int CL_API_CALL 138 | clGetGLContextInfoKHR(const cl_context_properties * /* properties */, 139 | cl_gl_context_info /* param_name */, 140 | size_t /* param_value_size */, 141 | void * /* param_value */, 142 | size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; 143 | 144 | typedef CL_API_ENTRY cl_int (CL_API_CALL *clGetGLContextInfoKHR_fn)( 145 | const cl_context_properties * properties, 146 | cl_gl_context_info param_name, 147 | size_t param_value_size, 148 | void * param_value, 149 | size_t * param_value_size_ret); 150 | 151 | #ifdef __cplusplus 152 | } 153 | #endif 154 | 155 | #endif /* __OPENCL_CL_GL_H */ 156 | -------------------------------------------------------------------------------- /include/CL/cl_gl_ext.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************** 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | **********************************************************************************/ 23 | 24 | /* $Revision: 11044 $ on $Date: 2010-04-14 23:41:21 +0530 (Wed, 14 Apr 2010) $ */ 25 | 26 | /* cl_gl_ext.h contains vendor (non-KHR) OpenCL extensions which have */ 27 | /* OpenGL dependencies. */ 28 | 29 | #ifndef __OPENCL_CL_GL_EXT_H 30 | #define __OPENCL_CL_GL_EXT_H 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #ifdef __APPLE__ 37 | #include 38 | #else 39 | #include 40 | #endif 41 | 42 | /* 43 | * For each extension, follow this template 44 | * cl_VEN_extname extension 45 | * #define cl_VEN_extname 1 46 | * ... define new types, if any 47 | * ... define new tokens, if any 48 | * ... define new APIs, if any 49 | * 50 | * If you need GLtypes here, mirror them with a cl_GLtype, rather than including a GL header 51 | * This allows us to avoid having to decide whether to include GL headers or GLES here. 52 | */ 53 | 54 | /* 55 | * cl_khr_gl_event extension 56 | * See section 9.9 in the OpenCL 1.1 spec for more information 57 | */ 58 | #define CL_COMMAND_GL_FENCE_SYNC_OBJECT_KHR 0x200D 59 | 60 | extern CL_API_ENTRY cl_event CL_API_CALL 61 | clCreateEventFromGLsyncKHR(cl_context /* context */, 62 | cl_GLsync /* cl_GLsync */, 63 | cl_int * /* errcode_ret */) CL_EXT_SUFFIX__VERSION_1_1; 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif /* __OPENCL_CL_GL_EXT_H */ 70 | -------------------------------------------------------------------------------- /include/CL/debugcl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VRAM_DEBUGCL_HPP 2 | #define VRAM_DEBUGCL_HPP 3 | 4 | /* 5 | * Minimal OpenCL implementation for better debugging with valgrind 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define CL_CALLBACK 13 | 14 | const int CL_MEM_READ_WRITE = 0; 15 | const int CL_SUCCESS = 0; 16 | const int CL_DEVICE_TYPE_GPU = 0; 17 | const int CL_COMPLETE = 0; 18 | 19 | typedef int cl_event; 20 | typedef int cl_int; 21 | 22 | typedef CL_CALLBACK void (*callback_fn)(cl_event, cl_int, void*); 23 | 24 | namespace cl { 25 | class Device { 26 | 27 | }; 28 | 29 | class Platform { 30 | public: 31 | static void getDevices(int type, std::vector* devices) { 32 | devices->push_back(Device()); 33 | } 34 | 35 | static void get(std::vector* platforms) { 36 | platforms->push_back(Platform()); 37 | } 38 | }; 39 | 40 | class Context { 41 | public: 42 | Context() {} 43 | Context(std::vector& devices) {} 44 | }; 45 | 46 | class Buffer { 47 | public: 48 | Buffer() { 49 | data = std::make_shared>(); 50 | } 51 | 52 | Buffer(Context& ctx, int flags, int64_t size, void* host_ptr = nullptr, int* err = nullptr) { 53 | data = std::make_shared>(); 54 | data->resize(size); 55 | if (err) *err = CL_SUCCESS; 56 | } 57 | 58 | std::shared_ptr> data; 59 | }; 60 | 61 | class Event { 62 | public: 63 | void setCallback(int flag, callback_fn cb, void* userdata) { 64 | cb(0, 0, userdata); 65 | } 66 | 67 | void wait() {} 68 | }; 69 | 70 | class CommandQueue { 71 | public: 72 | CommandQueue() {} 73 | CommandQueue(Context& ctx, Device& device) {} 74 | 75 | int enqueueFillBuffer(const Buffer& buf, int pattern, int off, int size, std::vector* events, cl::Event* event) { 76 | memset(&buf.data->operator[](off), 0, size); 77 | return CL_SUCCESS; 78 | } 79 | 80 | int enqueueCopyBuffer(const Buffer& src, Buffer& dst, int offSrc, int offDst, int size, std::vector* events, cl::Event* event) { 81 | memcpy(&dst.data->operator[](offDst), &src.data->operator[](offSrc), size); 82 | return CL_SUCCESS; 83 | } 84 | 85 | int enqueueReadBuffer(const Buffer& buf, bool block, int off, int size, void* out, std::vector* events, cl::Event* event) { 86 | memcpy(out, &buf.data->operator[](off), size); 87 | return CL_SUCCESS; 88 | } 89 | 90 | int enqueueWriteBuffer(const Buffer& buf, bool block, int off, int size, const void* in, std::vector* events, cl::Event* event) { 91 | memcpy(&buf.data->operator[](off), in, size); 92 | return CL_SUCCESS; 93 | } 94 | 95 | int finish() { 96 | return CL_SUCCESS; 97 | } 98 | }; 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /include/CL/opencl.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2008-2009 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | ******************************************************************************/ 23 | 24 | /* $Revision: 10424 $ on $Date: 2010-02-18 04:04:49 +0530 (Thu, 18 Feb 2010) $ */ 25 | 26 | #ifndef __OPENCL_H 27 | #define __OPENCL_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #ifdef __APPLE__ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #else 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #endif 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* __OPENCL_H */ 54 | 55 | -------------------------------------------------------------------------------- /include/entry.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VRAM_ENTRY_HPP 2 | #define VRAM_ENTRY_HPP 3 | 4 | /* 5 | * Entry types 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "memory.hpp" 15 | #include "util.hpp" 16 | 17 | using std::string; 18 | using std::shared_ptr; 19 | 20 | namespace vram { 21 | namespace entry { 22 | // Types of references to entries 23 | class entry_t; 24 | class file_t; 25 | class dir_t; 26 | class symlink_t; 27 | 28 | typedef shared_ptr entry_ref; 29 | typedef shared_ptr file_ref; 30 | typedef shared_ptr dir_ref; 31 | typedef shared_ptr symlink_ref; 32 | 33 | typedef entry_t* entry_ptr; 34 | typedef file_t* file_ptr; 35 | typedef dir_t* dir_ptr; 36 | typedef symlink_t* symlink_ptr; 37 | 38 | // Type of entry, can be combined for filtering in find() 39 | namespace type { 40 | enum type_t { 41 | none = 0, 42 | file = 1, 43 | dir = 2, 44 | symlink = 4 45 | }; 46 | 47 | const int all = file | dir | symlink; 48 | } 49 | 50 | // Total entry count 51 | int count(); 52 | 53 | // Full description of entry 54 | class entry_t : public std::enable_shared_from_this { 55 | public: 56 | entry_t(const entry_t& other) = delete; 57 | 58 | dir_ptr parent() const; 59 | 60 | const string& name() const; 61 | 62 | virtual ~entry_t(); 63 | 64 | virtual type::type_t type() const = 0; 65 | 66 | virtual size_t size() const = 0; 67 | 68 | // Change file attributes (automatically updates change time) 69 | timespec atime() const; 70 | timespec mtime() const; 71 | timespec ctime() const; 72 | 73 | mode_t mode() const; 74 | uid_t user() const; 75 | gid_t group() const; 76 | 77 | void atime(timespec t); 78 | void mtime(timespec t); 79 | void ctime(timespec t); 80 | 81 | void mode(mode_t mode); 82 | void user(uid_t user); 83 | void group(gid_t group); 84 | 85 | // Remove link with parent directory 86 | void unlink(); 87 | 88 | // Move entry 89 | void move(dir_ptr new_parent, const string& new_name); 90 | 91 | protected: 92 | entry_t(); 93 | 94 | // Associate entry with a parent directory after construction 95 | void link(dir_ptr parent, const string& name); 96 | 97 | private: 98 | // Non-owning pointer, parent is guaranteed to exist if entry exists 99 | dir_ptr _parent = nullptr; 100 | 101 | string _name; 102 | 103 | mode_t _mode = 0; 104 | uid_t _user = 0; 105 | gid_t _group = 0; 106 | 107 | timespec _atime; 108 | timespec _mtime; 109 | timespec _ctime; 110 | }; 111 | 112 | // File entry 113 | class file_t : public entry_t { 114 | public: 115 | // Constructor that takes care of memory management 116 | static file_ref make(dir_ptr parent, const string& name); 117 | 118 | type::type_t type() const; 119 | 120 | size_t size() const; 121 | 122 | // Blocks beyond the new file size are immediately deallocated 123 | void size(size_t new_size); 124 | 125 | // Read data from file, returns total bytes read <= size 126 | // 127 | // The specified mutex is unlocked while blocking to read, because 128 | // that's a non-critical section. 129 | int read(off_t off, size_t size, char* data, std::mutex& wait_mutex); 130 | 131 | // Write data to file, returns -error or total bytes written 132 | int write(off_t off, size_t size, const char* data, bool async = true); 133 | 134 | // Sync writes to file 135 | void sync(); 136 | 137 | private: 138 | // Data blocks if this entry is a file 139 | std::map file_blocks; 140 | 141 | // Last block touched by write() 142 | memory::block_ref last_written_block; 143 | 144 | // File size 145 | size_t _size = 0; 146 | 147 | file_t(); 148 | 149 | // Get the OpenCL buffer of the block if it exists or a nullptr 150 | memory::block_ref get_block(off_t off) const; 151 | 152 | // Allocate new block, buf is only set on success (returning true) 153 | memory::block_ref alloc_block(off_t off); 154 | 155 | // Delete all blocks with a starting offset >= *off* 156 | void free_blocks(off_t off = 0); 157 | }; 158 | 159 | // Directory entry 160 | class dir_t : public entry_t { 161 | friend class entry_t; 162 | 163 | public: 164 | // Constructor that takes care of memory management 165 | static dir_ref make(dir_ptr parent, const string& name); 166 | 167 | type::type_t type() const; 168 | 169 | // Always returns size of 4096 170 | size_t size() const; 171 | 172 | // Not const, because it changes access time 173 | const std::unordered_map children(); 174 | 175 | // Find entry by path relative to this entry 176 | int find(const string& path, entry_ref& entry, int filter = type::all) const; 177 | 178 | protected: 179 | std::unordered_map _children; 180 | 181 | private: 182 | dir_t(); 183 | }; 184 | 185 | // Symlink entry 186 | class symlink_t : public entry_t { 187 | public: 188 | // Target of symlink 189 | const string target; 190 | 191 | // Constructor that takes care of memory management 192 | static symlink_ref make(dir_ptr parent, const string& name, const string& target); 193 | 194 | type::type_t type() const; 195 | 196 | size_t size() const; 197 | 198 | private: 199 | symlink_t(const string& target); 200 | }; 201 | } 202 | } 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /include/memory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VRAM_MEMORY_HPP 2 | #define VRAM_MEMORY_HPP 3 | 4 | /* 5 | * VRAM block allocation 6 | */ 7 | 8 | 9 | #ifdef DEBUG 10 | // Use minimal OpenCL implementation for better debugging with valgrind 11 | #include "CL/debugcl.hpp" 12 | #elif OPENCL_1_1 13 | // OpenCL 1.1 header uses deprecated APIs 14 | #define CL_USE_DEPRECATED_OPENCL_1_1_APIS 15 | #include 16 | #else 17 | #include 18 | #endif 19 | 20 | #include 21 | 22 | namespace vram { 23 | namespace memory { 24 | class block; 25 | typedef std::shared_ptr block_ref; 26 | 27 | // Check if current machine supports VRAM allocation 28 | bool is_available(); 29 | 30 | // Set the device to use 31 | void set_device(size_t num); 32 | 33 | // Returns a list of device names 34 | std::vector list_devices(); 35 | 36 | // Total blocks and blocks currently free 37 | int pool_size(); 38 | int pool_available(); 39 | 40 | // Allocate pool of memory blocks, returns actual amount allocated (in bytes) 41 | size_t increase_pool(size_t size); 42 | 43 | // Get a new block of memory from the pool, returns nullptr if pool is empty 44 | block_ref allocate(); 45 | 46 | /* 47 | * Block of allocated VRAM 48 | */ 49 | 50 | class block : public std::enable_shared_from_this { 51 | friend block_ref allocate(); 52 | 53 | public: 54 | // Best performance/size balance 55 | static const size_t size = 128 * 1024; 56 | 57 | block(const block& other) = delete; 58 | 59 | ~block(); 60 | 61 | void read(off_t offset, size_t size, void* data) const; 62 | 63 | // Data may be freed afterwards, even if called with async = true 64 | void write(off_t offset, size_t size, const void* data, bool async = false); 65 | 66 | // Wait for all writes to this block to complete 67 | void sync(); 68 | 69 | private: 70 | cl::Buffer buffer; 71 | cl::Event last_write; 72 | 73 | // True until first write (until then it contains leftover data from last use) 74 | bool dirty = true; 75 | 76 | block(); 77 | }; 78 | } 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /include/util.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VRAM_UTIL_HPP 2 | #define VRAM_UTIL_HPP 3 | 4 | /* 5 | * Utility functions 6 | */ 7 | 8 | #define FUSE_USE_VERSION 26 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | using std::string; 15 | 16 | namespace vram { 17 | namespace util { 18 | // Error function that can be combined with a return statement to return *ret* 19 | template T fatal_error(const string &error, T ret) { 20 | std::cerr << "error: " << error << std::endl; 21 | fuse_exit(fuse_get_context()->fuse); 22 | return ret; 23 | } 24 | 25 | // Get current time with nanosecond precision 26 | timespec time(); 27 | 28 | // Split path/to/file.txt into "path/to" and "file.txt" 29 | void split_file_path(const string &path, string &dir, string &file); 30 | } 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/vramfs.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VRAM_TYPES_HPP 2 | #define VRAM_TYPES_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.hpp" 9 | #include "memory.hpp" 10 | #include "entry.hpp" 11 | 12 | using std::lock_guard; 13 | using std::mutex; 14 | using std::string; 15 | using std::dynamic_pointer_cast; 16 | 17 | namespace vram { 18 | // Data persistent in an open() and release() session 19 | struct file_session { 20 | entry::file_ref file; 21 | 22 | file_session(entry::file_ref file) : file(file) {} 23 | }; 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /lib/OpenCL.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzhiyi/vramfs-on-Windows/0fa8c392056147831fda595271abb48dd99c88b6/lib/OpenCL.dll -------------------------------------------------------------------------------- /mount.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/vramfs.exe Z: 512M -------------------------------------------------------------------------------- /src/dir.cpp: -------------------------------------------------------------------------------- 1 | #include "entry.hpp" 2 | #include "util.hpp" 3 | 4 | #include 5 | 6 | namespace vram { 7 | namespace entry { 8 | dir_ref dir_t::make(dir_ptr parent, const string& name) { 9 | auto dir = dir_ref(new dir_t()); 10 | dir->link(parent, name); 11 | return dir; 12 | } 13 | 14 | dir_t::dir_t() { 15 | mode(0755); 16 | } 17 | 18 | type::type_t dir_t::type() const { 19 | return type::dir; 20 | } 21 | 22 | size_t dir_t::size() const { 23 | return 4096; 24 | } 25 | 26 | const std::unordered_map dir_t::children() { 27 | atime(util::time()); 28 | 29 | return _children; 30 | } 31 | 32 | int dir_t::find(const string& path, entry_ref& entry, int filter) const { 33 | // If filter is empty, no entry will ever match 34 | if ((filter & type::all) == 0) return -ENOENT; 35 | 36 | // Traverse file system by hierarchically, starting from this entry 37 | entry = std::const_pointer_cast(shared_from_this()); 38 | 39 | std::stringstream stream(path.substr(1)); 40 | string part; 41 | 42 | // If the path is empty, assume the root directory 43 | while (getline(stream, part, '/')) { 44 | // If current entry isn't a directory, abort 45 | if (entry->type() != type::dir) return -ENOTDIR; 46 | 47 | // Navigate to next entry 48 | auto dir = std::dynamic_pointer_cast(entry); 49 | auto it = dir->_children.find(part); 50 | 51 | if (it != dir->_children.end()) { 52 | entry = it->second; 53 | } else { 54 | return -ENOENT; 55 | } 56 | } 57 | 58 | // If an undesired type of entry was found, return an appropriate error 59 | if (!(entry->type() & filter)) { 60 | if (entry->type() == type::file) { 61 | if (filter & type::symlink) return -ENOENT; 62 | if (filter & type::dir) return -EISDIR; 63 | } else if (entry->type() == entry::type::dir) { 64 | if (filter & type::file) return -ENOTDIR; 65 | if (filter & type::symlink) return -EPERM; 66 | } else { 67 | return -EPERM; 68 | } 69 | } 70 | 71 | return 0; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/entry.cpp: -------------------------------------------------------------------------------- 1 | #include "entry.hpp" 2 | #include "util.hpp" 3 | 4 | namespace vram { 5 | namespace entry { 6 | int entry_count = 0; 7 | 8 | int count() { 9 | return entry_count; 10 | } 11 | 12 | entry_t::entry_t() { 13 | auto t = util::time(); 14 | 15 | _atime = t; 16 | _mtime = t; 17 | _ctime = t; 18 | 19 | entry_count++; 20 | } 21 | 22 | entry_t::~entry_t() { 23 | entry_count--; 24 | } 25 | 26 | void entry_t::link(dir_ptr parent, const string& name) { 27 | _parent = parent; 28 | _name = name; 29 | 30 | if (parent) { 31 | parent->_children[name] = shared_from_this(); 32 | parent->mtime(util::time()); 33 | } 34 | } 35 | 36 | dir_ptr entry_t::parent() const { 37 | return _parent; 38 | } 39 | 40 | const string& entry_t::name() const { 41 | return _name; 42 | } 43 | 44 | timespec entry_t::atime() const { 45 | return _atime; 46 | } 47 | 48 | timespec entry_t::mtime() const { 49 | return _mtime; 50 | } 51 | 52 | timespec entry_t::ctime() const { 53 | return _ctime; 54 | } 55 | 56 | mode_t entry_t::mode() const { 57 | return _mode; 58 | } 59 | 60 | uid_t entry_t::user() const { 61 | return _user; 62 | } 63 | 64 | gid_t entry_t::group() const { 65 | return _group; 66 | } 67 | 68 | void entry_t::atime(timespec t) { 69 | _atime = t; 70 | ctime(util::time()); 71 | } 72 | 73 | void entry_t::mtime(timespec t) { 74 | _mtime = t; 75 | ctime(util::time()); 76 | } 77 | 78 | void entry_t::ctime(timespec t) { 79 | _ctime = t; 80 | } 81 | 82 | void entry_t::mode(mode_t mode) { 83 | _mode = mode; 84 | ctime(util::time()); 85 | } 86 | 87 | void entry_t::user(uid_t user) { 88 | _user = user; 89 | ctime(util::time()); 90 | } 91 | 92 | void entry_t::group(gid_t group) { 93 | _group = group; 94 | ctime(util::time()); 95 | } 96 | 97 | void entry_t::unlink() { 98 | if (_parent) { 99 | _parent->_children.erase(_name); 100 | _parent->mtime(util::time()); 101 | } 102 | } 103 | 104 | void entry_t::move(dir_ptr new_parent, const string& new_name) { 105 | if (_parent) { 106 | _parent->_children.erase(_name); 107 | _parent->mtime(util::time()); 108 | } 109 | 110 | _parent = new_parent; 111 | _name = new_name; 112 | 113 | ctime(util::time()); 114 | 115 | new_parent->_children[new_name] = shared_from_this(); 116 | new_parent->mtime(util::time()); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/file.cpp: -------------------------------------------------------------------------------- 1 | #include "entry.hpp" 2 | #include "util.hpp" 3 | 4 | namespace vram { 5 | namespace entry { 6 | file_ref file_t::make(dir_ptr parent, const string& name) { 7 | auto file = file_ref(new file_t()); 8 | file->link(parent, name); 9 | return file; 10 | } 11 | 12 | file_t::file_t() { 13 | mode(0644); 14 | } 15 | 16 | type::type_t file_t::type() const { 17 | return type::file; 18 | } 19 | 20 | size_t file_t::size() const { 21 | return _size; 22 | } 23 | 24 | void file_t::size(size_t new_size) { 25 | if (new_size < _size) { 26 | free_blocks(new_size); 27 | } 28 | 29 | _size = new_size; 30 | 31 | mtime(util::time()); 32 | } 33 | 34 | int file_t::read(off_t off, size_t size, char* data, std::mutex& wait_mutex) { 35 | if ((size_t) off >= _size) return 0; 36 | size = std::min(_size - off, size); 37 | 38 | // Walk over blocks in read region 39 | off_t end_pos = off + size; 40 | size_t total_read = size; 41 | 42 | while (off < end_pos) { 43 | // Find block corresponding to current offset 44 | off_t block_start = (off / memory::block::size) * memory::block::size; 45 | off_t block_off = off - block_start; 46 | size_t read_size = std::min(memory::block::size - block_off, size); 47 | 48 | auto block = get_block(block_start); 49 | 50 | // Allow multiple threads to block for reading simultaneously 51 | wait_mutex.unlock(); 52 | if (block) { 53 | block->read(block_off, read_size, data); 54 | } else { 55 | // Non-written part of file 56 | memset(data, 0, read_size); 57 | } 58 | wait_mutex.lock(); 59 | 60 | data += read_size; 61 | off += read_size; 62 | size -= read_size; 63 | } 64 | 65 | atime(util::time()); 66 | 67 | return total_read; 68 | } 69 | 70 | int file_t::write(off_t off, size_t size, const char* data, bool async) { 71 | // Walk over blocks in write region 72 | off_t end_pos = off + size; 73 | size_t total_write = size; 74 | 75 | while (off < end_pos) { 76 | // Find block corresponding to current offset 77 | off_t block_start = (off / memory::block::size) * memory::block::size; 78 | off_t block_off = off - block_start; 79 | size_t write_size = std::min(memory::block::size - block_off, size); 80 | 81 | auto block = get_block(block_start); 82 | 83 | if (!block) { 84 | block = alloc_block(block_start); 85 | 86 | // Failed to allocate buffer, likely out of VRAM 87 | if (!block) break; 88 | } 89 | 90 | block->write(block_off, write_size, data, async); 91 | 92 | last_written_block = block; 93 | 94 | data += write_size; 95 | off += write_size; 96 | size -= write_size; 97 | } 98 | 99 | if (_size < (size_t) off) { 100 | _size = off; 101 | } 102 | mtime(util::time()); 103 | 104 | if (off < end_pos) { 105 | return -ENOSPC; 106 | } else { 107 | return total_write; 108 | } 109 | } 110 | 111 | void file_t::sync() { 112 | // Waits for all asynchronous writes to finish, because they must 113 | // complete before the last write does (OpenCL guarantee) 114 | last_written_block->sync(); 115 | } 116 | 117 | memory::block_ref file_t::get_block(off_t off) const { 118 | auto it = file_blocks.find(off); 119 | 120 | if (it != file_blocks.end()) { 121 | return it->second; 122 | } else { 123 | return nullptr; 124 | } 125 | } 126 | 127 | memory::block_ref file_t::alloc_block(off_t off) { 128 | auto block = memory::allocate(); 129 | 130 | if (block) { 131 | file_blocks[off] = block; 132 | } 133 | 134 | return block; 135 | } 136 | 137 | void file_t::free_blocks(off_t off) { 138 | // Determine first block just beyond the range 139 | off_t start_off = (off / memory::block::size) * memory::block::size; 140 | if (off % memory::block::size != 0) start_off += memory::block::size; 141 | 142 | for (auto it = file_blocks.find(start_off); it != file_blocks.end();) { 143 | it = file_blocks.erase(it); 144 | } 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.hpp" 2 | 3 | namespace vram { 4 | namespace memory { 5 | // Connection with OpenCL 6 | bool ready = false; 7 | bool has_fillbuffer = 8 | false; // supports the FillBuffer API (platform is version 1.2 or higher) 9 | cl::Context context; 10 | cl::Device device; 11 | cl::CommandQueue queue; 12 | 13 | cl::Buffer zero_buffer; // used to clear buffers on pre-1.2 platforms 14 | 15 | std::vector pool; 16 | int total_blocks = 0; 17 | 18 | size_t device_num = 0; 19 | 20 | // Fill buffer with zeros 21 | static int clear_buffer(const cl::Buffer &buf) { 22 | #ifdef CL_VERSION_1_2 23 | if (has_fillbuffer) 24 | return queue.enqueueFillBuffer(buf, 0, 0, block::size, nullptr, nullptr); 25 | else 26 | #endif 27 | return queue.enqueueCopyBuffer(zero_buffer, buf, 0, 0, block::size, nullptr, 28 | nullptr); 29 | } 30 | 31 | // Find platform with OpenCL capable GPU 32 | static bool init_opencl() { 33 | if (ready) 34 | return true; 35 | 36 | std::vector platforms; 37 | cl::Platform::get(&platforms); 38 | if (platforms.size() == 0) 39 | return false; 40 | 41 | for (auto &platform : platforms) { 42 | std::vector gpu_devices; 43 | platform.getDevices(CL_DEVICE_TYPE_CPU, &gpu_devices); 44 | if (gpu_devices.size() == 0) 45 | continue; 46 | 47 | device = gpu_devices[device_num]; 48 | context = cl::Context(gpu_devices); 49 | queue = cl::CommandQueue(context, device); 50 | 51 | #ifdef CL_VERSION_1_2 52 | cl_uint version = cl::detail::getPlatformVersion(platform()); 53 | 54 | if (version >= (1 << 16 | 2)) 55 | has_fillbuffer = true; 56 | #endif 57 | 58 | if (!has_fillbuffer) { 59 | char zero_data[block::size] = {}; 60 | int r; 61 | zero_buffer = cl::Buffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, 62 | block::size, zero_data, &r); 63 | if (r != CL_SUCCESS) 64 | return false; 65 | } 66 | 67 | return true; 68 | } 69 | 70 | return false; 71 | } 72 | 73 | // Called for asynchronous writes to clean up the data copy 74 | static CL_CALLBACK void async_write_dealloc(cl_event, cl_int, void *data) { 75 | delete[] reinterpret_cast(data); 76 | } 77 | 78 | bool is_available() { return (ready = init_opencl()); } 79 | 80 | void set_device(size_t device) { device_num = device; } 81 | 82 | std::vector list_devices() { 83 | std::vector device_names; 84 | 85 | std::vector platforms; 86 | cl::Platform::get(&platforms); 87 | 88 | for (auto &platform : platforms) { 89 | std::vector gpu_devices; 90 | platform.getDevices(CL_DEVICE_TYPE_CPU, &gpu_devices); 91 | if (gpu_devices.size() == 0) 92 | continue; 93 | 94 | for (auto &device : gpu_devices) { 95 | device_names.push_back(device.getInfo()); 96 | } 97 | 98 | break; 99 | } 100 | 101 | return device_names; 102 | } 103 | 104 | int pool_size() { return total_blocks; } 105 | 106 | int pool_available() { return pool.size(); } 107 | 108 | size_t increase_pool(size_t size) { 109 | int block_count = 1 + (size - 1) / block::size; 110 | int r; 111 | 112 | for (int i = 0; i < block_count; i++) { 113 | cl::Buffer buf(context, CL_MEM_READ_WRITE, block::size, nullptr, &r); 114 | 115 | if (r == CL_SUCCESS && clear_buffer(buf) == CL_SUCCESS) { 116 | pool.push_back(buf); 117 | total_blocks++; 118 | } else { 119 | return i * block::size; 120 | } 121 | } 122 | 123 | return block_count * block::size; 124 | } 125 | 126 | block_ref allocate() { 127 | if (pool.size() != 0) { 128 | return block_ref(new block()); 129 | } else { 130 | return nullptr; 131 | } 132 | } 133 | 134 | block::block() { 135 | buffer = pool.back(); 136 | pool.pop_back(); 137 | } 138 | 139 | block::~block() { pool.push_back(buffer); } 140 | 141 | void block::read(off_t offset, size_t size, void *data) const { 142 | if (dirty) { 143 | memset(data, 0, size); 144 | } else { 145 | // Queue is configured for in-order execution, so writes before this 146 | // are guaranteed to be completed first 147 | queue.enqueueReadBuffer(buffer, true, offset, size, data, nullptr, nullptr); 148 | } 149 | } 150 | 151 | void block::write(off_t offset, size_t size, const void *data, bool async) { 152 | // If this block has not been written to yet, and this call doesn't 153 | // overwrite the entire block, clear with zeros first 154 | if (dirty && size != block::size) { 155 | clear_buffer(buffer); 156 | } 157 | 158 | if (async) { 159 | char *data_copy = new char[size]; 160 | memcpy(data_copy, data, size); 161 | data = data_copy; 162 | } 163 | 164 | cl::Event event; 165 | queue.enqueueWriteBuffer(buffer, !async, offset, size, data, nullptr, &event); 166 | 167 | if (async) { 168 | event.setCallback(CL_COMPLETE, async_write_dealloc, 169 | const_cast(data)); 170 | } 171 | 172 | last_write = event; 173 | dirty = false; 174 | } 175 | 176 | void block::sync() { last_write.wait(); } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/symlink.cpp: -------------------------------------------------------------------------------- 1 | #include "entry.hpp" 2 | #include "util.hpp" 3 | 4 | namespace vram { 5 | namespace entry { 6 | symlink_ref symlink_t::make(dir_ptr parent, const string& name, const string& target) { 7 | auto symlink = symlink_ref(new symlink_t(target)); 8 | symlink->link(parent, name); 9 | return symlink; 10 | } 11 | 12 | symlink_t::symlink_t(const string& target) : target(target) {} 13 | 14 | type::type_t symlink_t::type() const { 15 | return type::symlink; 16 | } 17 | 18 | size_t symlink_t::size() const { 19 | return target.size(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | namespace vram { 4 | namespace util { 5 | timespec time() { 6 | timespec tv; 7 | clock_gettime(CLOCK_REALTIME, &tv); 8 | return tv; 9 | } 10 | 11 | void split_file_path(const string &path, string &dir, string &file) { 12 | size_t p = path.rfind("/"); 13 | 14 | if (p == string::npos) { 15 | dir = ""; 16 | file = path; 17 | } else { 18 | dir = path.substr(0, p); 19 | file = path.substr(p + 1); 20 | } 21 | 22 | if (dir.size() == 0) 23 | dir = "/"; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/vramfs.cpp: -------------------------------------------------------------------------------- 1 | // Third-party libraries 2 | #define FUSE_USE_VERSION 26 3 | #include 4 | #include 5 | 6 | // Standard library 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // Internal dependencies 14 | #include "vramfs.hpp" 15 | 16 | using namespace vram; 17 | 18 | /* 19 | * Globals 20 | */ 21 | 22 | // Lock to prevent multiple threads from manipulating the file system index and 23 | // OpenCL buffers simultaneously. The tiny overhead is worth not having to deal 24 | // with the uncountable amount of race conditions that would otherwise occur. 25 | static std::mutex fsmutex; 26 | 27 | // File system root that links to the rest 28 | static entry::dir_ref root_entry; 29 | 30 | /* 31 | * Initialisation 32 | */ 33 | 34 | static void *vram_init(fuse_conn_info *conn) { 35 | root_entry = entry::dir_t::make(nullptr, ""); 36 | root_entry->user(geteuid()); 37 | root_entry->group(getegid()); 38 | 39 | std::cout << "mounted." << std::endl; 40 | 41 | return nullptr; 42 | } 43 | 44 | /* 45 | * File system info 46 | */ 47 | 48 | static int vram_statfs(const char *, struct statvfs *vfs) { 49 | vfs->f_bsize = memory::block::size; 50 | vfs->f_blocks = memory::pool_size(); 51 | vfs->f_bfree = memory::pool_available(); 52 | vfs->f_bavail = memory::pool_available(); 53 | vfs->f_files = entry::count(); 54 | vfs->f_ffree = std::numeric_limits::max(); 55 | vfs->f_namemax = std::numeric_limits::max(); 56 | 57 | return 0; 58 | } 59 | 60 | /* 61 | * Entry attributes 62 | */ 63 | 64 | static int vram_getattr(const char *path, struct stat *stbuf) { 65 | lock_guard local_lock(fsmutex); 66 | 67 | // Look up entry 68 | entry::entry_ref entry; 69 | int err = root_entry->find(path, entry); 70 | if (err != 0) 71 | return err; 72 | 73 | memset(stbuf, 0, sizeof(struct stat)); 74 | 75 | if (entry->type() == entry::type::dir) { 76 | stbuf->st_mode = S_IFDIR | entry->mode(); 77 | stbuf->st_nlink = 2; 78 | } else if (entry->type() == entry::type::file) { 79 | stbuf->st_mode = S_IFREG | entry->mode(); 80 | stbuf->st_nlink = 1; 81 | stbuf->st_blksize = memory::block::size; 82 | 83 | if (entry->size() > 0) { 84 | stbuf->st_blocks = 1 + (entry->size() - 1) / memory::block::size; 85 | } 86 | } else { 87 | stbuf->st_mode = S_IFLNK | 0777; 88 | stbuf->st_nlink = 1; 89 | } 90 | 91 | stbuf->st_uid = entry->user(); 92 | stbuf->st_gid = entry->group(); 93 | stbuf->st_size = entry->size(); 94 | stbuf->st_atim = entry->atime(); 95 | stbuf->st_mtim = entry->mtime(); 96 | stbuf->st_ctim = entry->ctime(); 97 | 98 | return 0; 99 | } 100 | 101 | /* 102 | * Get target of link 103 | */ 104 | 105 | static int vram_readlink(const char *path, char *buf, size_t size) { 106 | lock_guard local_lock(fsmutex); 107 | 108 | entry::entry_ref entry; 109 | int err = root_entry->find(path, entry, entry::type::symlink); 110 | if (err != 0) 111 | return err; 112 | 113 | auto symlink = dynamic_pointer_cast(entry); 114 | strncpy(buf, symlink->target.c_str(), size); 115 | 116 | return 0; 117 | } 118 | 119 | /* 120 | * Set the mode bits of an entry 121 | */ 122 | 123 | static int vram_chmod(const char *path, mode_t mode) { 124 | lock_guard local_lock(fsmutex); 125 | 126 | entry::entry_ref entry; 127 | int err = root_entry->find(path, entry, entry::type::file | entry::type::dir); 128 | if (err != 0) 129 | return err; 130 | 131 | entry->mode(mode); 132 | 133 | return 0; 134 | } 135 | 136 | /* 137 | * Change the owner/group of an entry 138 | */ 139 | 140 | static int vram_chown(const char *path, uid_t user, gid_t group) { 141 | lock_guard lock_lock(fsmutex); 142 | 143 | entry::entry_ref entry; 144 | int err = root_entry->find(path, entry, entry::type::file | entry::type::dir); 145 | if (err != 0) 146 | return err; 147 | 148 | entry->user(user); 149 | entry->group(group); 150 | 151 | return 0; 152 | } 153 | 154 | /* 155 | * Set the last access and last modified times of an entry 156 | */ 157 | 158 | static int vram_utimens(const char *path, const timespec tv[2]) { 159 | lock_guard local_lock(fsmutex); 160 | 161 | entry::entry_ref entry; 162 | int err = root_entry->find(path, entry, entry::type::file | entry::type::dir); 163 | if (err != 0) 164 | return err; 165 | 166 | entry->atime(tv[0]); 167 | entry->mtime(tv[1]); 168 | 169 | return 0; 170 | } 171 | 172 | /* 173 | * Directory listing 174 | */ 175 | 176 | static int vram_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 177 | off_t, fuse_file_info *) { 178 | lock_guard local_lock(fsmutex); 179 | 180 | // Look up directory 181 | entry::entry_ref entry; 182 | int err = root_entry->find(path, entry, entry::type::dir); 183 | if (err != 0) 184 | return err; 185 | auto dir = dynamic_pointer_cast(entry); 186 | 187 | // Required default entries 188 | filler(buf, ".", nullptr, 0); 189 | filler(buf, "..", nullptr, 0); 190 | 191 | for (auto &pair : dir->children()) { 192 | filler(buf, pair.second->name().c_str(), nullptr, 0); 193 | } 194 | 195 | return 0; 196 | } 197 | 198 | /* 199 | * Create file 200 | */ 201 | 202 | static int vram_create(const char *path, mode_t, struct fuse_file_info *fi) { 203 | lock_guard local_lock(fsmutex); 204 | 205 | // Truncate any existing file entry or fail if it's another type 206 | entry::entry_ref entry; 207 | int err = root_entry->find(path, entry, entry::type::file); 208 | if (err == -EISDIR) 209 | return err; 210 | else if (err == 0) 211 | entry->unlink(); 212 | 213 | string dir, name; 214 | util::split_file_path(path, dir, name); 215 | 216 | // Check if parent directory exists 217 | err = root_entry->find(dir, entry, entry::type::dir); 218 | if (err != 0) 219 | return err; 220 | auto parent = dynamic_pointer_cast(entry); 221 | 222 | // Create new entry with appropriate owner/group 223 | auto file = entry::file_t::make(parent.get(), name); 224 | 225 | auto context = fuse_get_context(); 226 | file->user(context->uid); 227 | file->group(context->gid); 228 | 229 | // Open it by assigning new file handle 230 | fi->fh = reinterpret_cast(new file_session(file)); 231 | 232 | return 0; 233 | } 234 | 235 | /* 236 | * Create directory 237 | */ 238 | 239 | static int vram_mkdir(const char *path, mode_t) { 240 | lock_guard local_lock(fsmutex); 241 | 242 | // Fail if entry with that name already exists 243 | entry::entry_ref entry; 244 | int err = root_entry->find(path, entry); 245 | if (err == 0) 246 | return -EEXIST; 247 | 248 | string dir, name; 249 | util::split_file_path(path, dir, name); 250 | 251 | // Check if parent directory exists 252 | err = root_entry->find(dir, entry, entry::type::dir); 253 | if (err != 0) 254 | return err; 255 | auto parent = dynamic_pointer_cast(entry); 256 | 257 | // Create new directory with appropriate owner/group 258 | auto new_dir = entry::dir_t::make(parent.get(), name); 259 | 260 | auto context = fuse_get_context(); 261 | new_dir->user(context->uid); 262 | new_dir->group(context->gid); 263 | 264 | return 0; 265 | } 266 | 267 | /* 268 | * Create symlink 269 | */ 270 | 271 | static int vram_symlink(const char *target, const char *path) { 272 | lock_guard local_lock(fsmutex); 273 | 274 | // Fail if an entry with that name already exists 275 | entry::entry_ref entry; 276 | int err = root_entry->find(path, entry); 277 | if (err == 0) 278 | return -EEXIST; 279 | 280 | // Split path in parent directory and new symlink name 281 | string dir, name; 282 | util::split_file_path(path, dir, name); 283 | 284 | // Check if parent directory exists 285 | err = root_entry->find(dir, entry, entry::type::dir); 286 | if (err != 0) 287 | return err; 288 | auto parent = dynamic_pointer_cast(entry); 289 | 290 | // Create new symlink with appropriate owner/group 291 | auto symlink = entry::symlink_t::make(parent.get(), name, target); 292 | 293 | auto context = fuse_get_context(); 294 | symlink->user(context->uid); 295 | symlink->group(context->gid); 296 | 297 | return 0; 298 | } 299 | 300 | /* 301 | * Delete file 302 | */ 303 | 304 | static int vram_unlink(const char *path) { 305 | lock_guard local_lock(fsmutex); 306 | 307 | entry::entry_ref entry; 308 | int err = 309 | root_entry->find(path, entry, entry::type::symlink | entry::type::file); 310 | if (err != 0) 311 | return err; 312 | 313 | entry->unlink(); 314 | 315 | return 0; 316 | } 317 | 318 | /* 319 | * Delete directory 320 | */ 321 | 322 | static int vram_rmdir(const char *path) { 323 | lock_guard local_lock(fsmutex); 324 | 325 | // Fail if entry doesn't exist or is not a directory 326 | entry::entry_ref entry; 327 | int err = root_entry->find(path, entry, entry::type::dir); 328 | if (err != 0) 329 | return err; 330 | auto dir = dynamic_pointer_cast(entry); 331 | 332 | // Check if directory is empty 333 | if (dir->children().size() != 0) { 334 | return -ENOTEMPTY; 335 | } 336 | 337 | dir->unlink(); 338 | 339 | return 0; 340 | } 341 | 342 | /* 343 | * Rename entry 344 | */ 345 | 346 | static int vram_rename(const char *path, const char *new_path) { 347 | lock_guard local_lock(fsmutex); 348 | 349 | // Look up entry 350 | entry::entry_ref entry; 351 | int err = root_entry->find(path, entry); 352 | if (err != 0) 353 | return err; 354 | 355 | // Check if destination directory exists 356 | string dir, new_name; 357 | util::split_file_path(new_path, dir, new_name); 358 | 359 | entry::entry_ref parent_entry; 360 | err = root_entry->find(dir, parent_entry, entry::type::dir); 361 | if (err != 0) 362 | return err; 363 | auto parent = dynamic_pointer_cast(parent_entry); 364 | 365 | // If the destination entry already exists, then delete it 366 | entry::entry_ref dest_entry; 367 | err = root_entry->find(new_path, dest_entry); 368 | if (err == 0) 369 | dest_entry->unlink(); 370 | 371 | entry->move(parent.get(), new_name); 372 | 373 | return 0; 374 | } 375 | 376 | /* 377 | * Open file 378 | */ 379 | 380 | static int vram_open(const char *path, fuse_file_info *fi) { 381 | lock_guard local_lock(fsmutex); 382 | 383 | entry::entry_ref entry; 384 | int err = root_entry->find(path, entry, entry::type::file); 385 | if (err != 0) 386 | return err; 387 | auto file = dynamic_pointer_cast(entry); 388 | 389 | fi->fh = reinterpret_cast(new file_session(file)); 390 | 391 | return 0; 392 | } 393 | 394 | /* 395 | * Read file 396 | */ 397 | 398 | static int vram_read(const char *path, char *buf, size_t size, off_t off, 399 | fuse_file_info *fi) { 400 | lock_guard local_lock(fsmutex); 401 | 402 | file_session *session = reinterpret_cast(fi->fh); 403 | return session->file->read(off, size, buf, fsmutex); 404 | } 405 | 406 | /* 407 | * Write file 408 | */ 409 | 410 | static int vram_write(const char *path, const char *buf, size_t size, off_t off, 411 | fuse_file_info *fi) { 412 | lock_guard local_lock(fsmutex); 413 | 414 | file_session *session = reinterpret_cast(fi->fh); 415 | return session->file->write(off, size, buf); 416 | } 417 | 418 | /* 419 | * Sync writes to file 420 | */ 421 | 422 | static int vram_fsync(const char *path, int, fuse_file_info *fi) { 423 | lock_guard local_lock(fsmutex); 424 | 425 | file_session *session = reinterpret_cast(fi->fh); 426 | session->file->sync(); 427 | 428 | return 0; 429 | } 430 | 431 | /* 432 | * Close file 433 | */ 434 | 435 | static int vram_release(const char *path, fuse_file_info *fi) { 436 | lock_guard local_lock(fsmutex); 437 | 438 | delete reinterpret_cast(fi->fh); 439 | 440 | return 0; 441 | } 442 | 443 | /* 444 | * Change file size 445 | */ 446 | 447 | static int vram_truncate(const char *path, off_t size) { 448 | lock_guard local_lock(fsmutex); 449 | 450 | entry::entry_ref entry; 451 | int err = root_entry->find(path, entry, entry::type::file); 452 | if (err != 0) 453 | return err; 454 | auto file = dynamic_pointer_cast(entry); 455 | 456 | file->size(size); 457 | 458 | return 0; 459 | } 460 | 461 | /* 462 | * FUSE setup 463 | */ 464 | 465 | static struct vram_operations : fuse_operations { 466 | vram_operations() { 467 | init = vram_init; 468 | statfs = vram_statfs; 469 | getattr = vram_getattr; 470 | readlink = vram_readlink; 471 | utimens = vram_utimens; 472 | chmod = vram_chmod; 473 | chown = vram_chown; 474 | readdir = vram_readdir; 475 | create = vram_create; 476 | mkdir = vram_mkdir; 477 | symlink = vram_symlink; 478 | unlink = vram_unlink; 479 | rmdir = vram_rmdir; 480 | rename = vram_rename; 481 | open = vram_open; 482 | read = vram_read; 483 | write = vram_write; 484 | fsync = vram_fsync; 485 | release = vram_release; 486 | truncate = vram_truncate; 487 | } 488 | } operations; 489 | 490 | static int print_help() { 491 | std::cerr << "usage: vramfs [-d ] [-f]\n\n" 492 | " mountdir - directory to mount file system, must be empty\n" 493 | " size - size of the disk in bytes\n" 494 | " -d - specifies identifier of device to use\n" 495 | " -f - flag that forces mounting, with a smaller size " 496 | "if needed\n\n" 497 | "The size may be followed by one of the following " 498 | "multiplicative suffixes: " 499 | "K=1024, KB=1000, M=1024*1024, MB=1000*1000, G=1024*1024*1024, " 500 | "GB=1000*1000*1000. " 501 | "It's rounded up to the nearest multiple of the block size.\n" 502 | << std::endl; 503 | 504 | auto devices = memory::list_devices(); 505 | 506 | if (!devices.empty()) { 507 | std::cerr << "device list: \n"; 508 | 509 | for (size_t i = 0; i < devices.size(); ++i) { 510 | std::cerr << " " << i << ": " << devices[i] << "\n"; 511 | } 512 | std::cerr << std::endl; 513 | } else { 514 | std::cerr << "No suitable devices found." << std::endl; 515 | } 516 | 517 | return 1; 518 | } 519 | 520 | static std::regex size_regex("^([0-9]+)([KMG]B?)?$"); 521 | 522 | static size_t parse_size(const string ¶m) { 523 | std::smatch groups; 524 | std::regex_search(param, groups, size_regex); 525 | 526 | size_t size = strtoul(groups[1].str().c_str(), 0, 10); 527 | 528 | if (groups[2] == "K") 529 | size *= 1024UL; 530 | else if (groups[2] == "KB") 531 | size *= 1000UL; 532 | else if (groups[2] == "M") 533 | size *= 1024UL * 1024UL; 534 | else if (groups[2] == "MB") 535 | size *= 1000UL * 1000UL; 536 | else if (groups[2] == "G") 537 | size *= 1024UL * 1024UL * 1024UL; 538 | else if (groups[2] == "GB") 539 | size *= 1000UL * 1000UL * 1000UL; 540 | 541 | return size; 542 | } 543 | 544 | int main(int argc, char *argv[]) { 545 | // Check parameter and parse parameters 546 | if (argc < 3 || argc > 6) 547 | return print_help(); 548 | if (!std::regex_match(argv[2], size_regex)) 549 | return print_help(); 550 | if (argc == 4 && strcmp(argv[3], "-f") != 0) 551 | return print_help(); 552 | if (argc == 5 && strcmp(argv[3], "-d") != 0) 553 | return print_help(); 554 | if (argc == 6) { 555 | if (strcmp(argv[3], "-d") != 0 && strcmp(argv[5], "-f") != 0) { 556 | return print_help(); 557 | } 558 | } 559 | 560 | size_t disk_size = parse_size(argv[2]); 561 | bool force_allocate = (argc == 4 || argc == 6); 562 | 563 | if (argc == 5 || argc == 6) { 564 | memory::set_device(atoi(argv[4])); 565 | std::cout << "device set to:" << atoi(argv[4]) << std::endl; 566 | } /* else { 567 | memory::set_device(0); 568 | }*/ 569 | 570 | // Check for OpenCL supported GPU and allocate memory 571 | if (!memory::is_available()) { 572 | std::cerr << "no opencl capable gpu found" << std::endl; 573 | return 1; 574 | } else { 575 | std::cout << "allocating vram..." << std::endl; 576 | 577 | size_t actual_size = memory::increase_pool(disk_size); 578 | 579 | if (actual_size < disk_size) { 580 | if (force_allocate) { 581 | std::cerr << "warning: only allocated " << actual_size << " bytes" 582 | << std::endl; 583 | } else { 584 | std::cerr << "error: could not allocate more than " << actual_size 585 | << " bytes" << std::endl; 586 | std::cerr << "cleaning up..." << std::endl; 587 | return 1; 588 | } 589 | } 590 | } 591 | 592 | // Pass mount point parameter to FUSE 593 | struct fuse_args args = FUSE_ARGS_INIT(2, argv); 594 | 595 | fuse_opt_parse(&args, nullptr, nullptr, nullptr); 596 | 597 | // Allow up to 128K writes 598 | fuse_opt_add_arg(&args, "-obig_writes"); 599 | 600 | // Properly unmount even on crash 601 | fuse_opt_add_arg(&args, "-oauto_unmount"); 602 | 603 | // Let FUSE and the kernel deal with permissions handling 604 | fuse_opt_add_arg(&args, "-odefault_permissions"); 605 | 606 | // OpenCL driver acts funky if program doesn't keep running in foreground 607 | fuse_opt_add_arg(&args, "-f"); 608 | 609 | fuse_opt_add_arg(&args, "-o daemon_timeout=1000"); 610 | // debug 611 | fuse_opt_add_arg(&args, "-d"); 612 | 613 | return fuse_main(args.argc, args.argv, &operations, nullptr); 614 | } 615 | --------------------------------------------------------------------------------