Local file backup WIP

This commit is contained in:
Martin 2020-12-17 21:25:56 +01:00
parent 94aa8a243e
commit 8324f9c3a1
230 changed files with 129584 additions and 219 deletions

6
.gitignore vendored
View File

@ -268,3 +268,9 @@ blockalign/x64/*
/blockalign/Debug/*
/luaplugin/Debug/*
/urbackupserver/www/templates/post/*
/blockalign_src/Release/*
/btrfs/btrfsplugin/x64/*
/btrfs/fuse/oslib/x64/*
/btrfs/fuse/x64/*
/luaplugin/Release/*
/urbackup/data_*

View File

@ -22,33 +22,34 @@
<ProjectGuid>{F8E6B10F-B0A5-4DEB-BEB1-B6BC221153C0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SQLGen</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@ -176,6 +177,7 @@
<ClCompile Include="..\OutputStream.cpp" />
<ClCompile Include="..\PipeThrottler.cpp" />
<ClCompile Include="..\Query.cpp" />
<ClCompile Include="..\SChannelPipe.cpp" />
<ClCompile Include="..\SelectThread.cpp" />
<ClCompile Include="..\Server.cpp" />
<ClCompile Include="..\ServerWin32.cpp" />

View File

@ -135,6 +135,9 @@
<ClCompile Include="..\Condition_std.cpp">
<Filter>Server</Filter>
</ClCompile>
<ClCompile Include="..\SChannelPipe.cpp">
<Filter>Server</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Database.h">

View File

@ -264,6 +264,10 @@ std::map<std::string, std::string> parseAnnotations(const std::string& data)
content += ch;
state = 3;
}
else if (ch == '*' && state == 3)
{
content += ch;
}
else if (ch == '/' && state == 3)
{
state = 0;

View File

@ -1424,25 +1424,8 @@ struct SThreadInfo
void thread_helper_f2(IThread* t)
{
#ifndef _DEBUG
try
{
#endif
(*t)();
Server->destroyDatabases(Server->getThreadID());
#ifndef _DEBUG
}
catch (std::exception& e)
{
Server->Log(std::string("Thread exit with unhandled std::exception ") + e.what(), LL_ERROR);
throw;
}
catch (...)
{
Server->Log(std::string("Thread exit with unhandled C++ exception "), LL_ERROR);
throw;
}
#endif
(*t)();
Server->destroyDatabases(Server->getThreadID());
}
DWORD WINAPI thread_helper_f(LPVOID param)

View File

@ -29,150 +29,322 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blockalign", "blockalign_sr
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luaplugin", "luaplugin\luaplugin.vcxproj", "{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "btrfsfuse", "btrfs\fuse\fuse.vcxproj", "{B6ED0533-D4DB-4571-BE69-EDF0A1655064}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oslib", "btrfs\fuse\oslib\oslib.vcxproj", "{EA09B289-492C-4F30-813B-9928994FB21B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "btrfsplugin", "btrfs\btrfsplugin\btrfsplugin.vcxproj", "{8F901558-A663-4EA8-A52D-E6577ABEB2D1}"
ProjectSection(ProjectDependencies) = postProject
{B6ED0533-D4DB-4571-BE69-EDF0A1655064} = {B6ED0533-D4DB-4571-BE69-EDF0A1655064}
{EA09B289-492C-4F30-813B-9928994FB21B} = {EA09B289-492C-4F30-813B-9928994FB21B}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release Service|ARM = Release Service|ARM
Release Service|ARM64 = Release Service|ARM64
Release Service|Win32 = Release Service|Win32
Release Service|x64 = Release Service|x64
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Debug|ARM.ActiveCfg = Debug|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Debug|ARM64.ActiveCfg = Debug|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Debug|Win32.ActiveCfg = Debug|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Debug|Win32.Build.0 = Debug|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Debug|x64.ActiveCfg = Debug|x64
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Debug|x64.Build.0 = Debug|x64
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|ARM.ActiveCfg = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|ARM.Build.0 = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|ARM64.ActiveCfg = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|ARM64.Build.0 = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|Win32.ActiveCfg = Release|x64
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|x64.ActiveCfg = Release|x64
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release Service|x64.Build.0 = Release|x64
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release|ARM.ActiveCfg = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release|ARM64.ActiveCfg = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release|Win32.ActiveCfg = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release|Win32.Build.0 = Release|Win32
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release|x64.ActiveCfg = Release|x64
{B1F1AF2E-E544-45F7-864A-883461A4B574}.Release|x64.Build.0 = Release|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Debug|ARM.ActiveCfg = Debug|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Debug|ARM64.ActiveCfg = Debug|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Debug|Win32.ActiveCfg = Debug|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Debug|Win32.Build.0 = Debug|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Debug|x64.ActiveCfg = Debug|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Debug|x64.Build.0 = Debug|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|ARM.ActiveCfg = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|ARM.Build.0 = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|ARM64.ActiveCfg = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|ARM64.Build.0 = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|Win32.ActiveCfg = Release|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|x64.ActiveCfg = Release|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release Service|x64.Build.0 = Release|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release|ARM.ActiveCfg = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release|ARM64.ActiveCfg = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release|Win32.ActiveCfg = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release|Win32.Build.0 = Release|Win32
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release|x64.ActiveCfg = Release|x64
{20375DC0-38DA-4254-B479-EFA8028C29B1}.Release|x64.Build.0 = Release|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Debug|ARM.ActiveCfg = Debug|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Debug|ARM64.ActiveCfg = Debug|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Debug|Win32.ActiveCfg = Debug|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Debug|Win32.Build.0 = Debug|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Debug|x64.ActiveCfg = Debug|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Debug|x64.Build.0 = Debug|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|ARM.ActiveCfg = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|ARM.Build.0 = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|ARM64.ActiveCfg = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|ARM64.Build.0 = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|Win32.ActiveCfg = Release|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|x64.ActiveCfg = Release|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release Service|x64.Build.0 = Release|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release|ARM.ActiveCfg = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release|ARM64.ActiveCfg = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release|Win32.ActiveCfg = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release|Win32.Build.0 = Release|Win32
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release|x64.ActiveCfg = Release|x64
{3E6BBB51-77D4-4DC7-BF09-FC6F21CA04D5}.Release|x64.Build.0 = Release|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Debug|ARM.ActiveCfg = Debug|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Debug|ARM64.ActiveCfg = Debug|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Debug|Win32.ActiveCfg = Debug|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Debug|Win32.Build.0 = Debug|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Debug|x64.ActiveCfg = Debug|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Debug|x64.Build.0 = Debug|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|ARM.ActiveCfg = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|ARM.Build.0 = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|ARM64.ActiveCfg = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|ARM64.Build.0 = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|Win32.ActiveCfg = Release Server|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|x64.ActiveCfg = Release Server|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release Service|x64.Build.0 = Release Server|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|ARM.ActiveCfg = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|ARM.Build.0 = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|ARM64.ActiveCfg = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|ARM64.Build.0 = Release Server|Win32
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|Win32.ActiveCfg = Release Server|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|x64.ActiveCfg = Release Server|x64
{A4E2527B-4886-4163-9411-10BF66A931BE}.Release|x64.Build.0 = Release Server|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Debug|ARM.ActiveCfg = Debug|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Debug|ARM64.ActiveCfg = Debug|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Debug|Win32.ActiveCfg = Debug|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Debug|Win32.Build.0 = Debug|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Debug|x64.ActiveCfg = Debug|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Debug|x64.Build.0 = Debug|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|ARM.ActiveCfg = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|ARM.Build.0 = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|ARM64.ActiveCfg = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|ARM64.Build.0 = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|Win32.ActiveCfg = Release|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|Win32.Build.0 = Release|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|x64.ActiveCfg = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release Service|x64.Build.0 = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release|ARM.ActiveCfg = Release|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release|ARM64.ActiveCfg = Release|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release|Win32.ActiveCfg = Release|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release|Win32.Build.0 = Release|Win32
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release|x64.ActiveCfg = Release|x64
{28D66E10-BF1E-45E3-B4E0-77920126531B}.Release|x64.Build.0 = Release|x64
{8546D6E2-1872-418B-9766-E40F33689BE4}.Debug|ARM.ActiveCfg = Debug|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Debug|ARM64.ActiveCfg = Debug|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Debug|Win32.ActiveCfg = Debug|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Debug|Win32.Build.0 = Debug|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Debug|x64.ActiveCfg = Debug|x64
{8546D6E2-1872-418B-9766-E40F33689BE4}.Debug|x64.Build.0 = Debug|x64
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release Service|ARM.ActiveCfg = Release Service|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release Service|ARM64.ActiveCfg = Release Service|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release Service|Win32.ActiveCfg = Release Service|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release Service|Win32.Build.0 = Release Service|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release Service|x64.ActiveCfg = Release Service|x64
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release Service|x64.Build.0 = Release Service|x64
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release|ARM.ActiveCfg = Release|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release|ARM64.ActiveCfg = Release|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release|Win32.ActiveCfg = Release|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release|Win32.Build.0 = Release|Win32
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release|x64.ActiveCfg = Release|x64
{8546D6E2-1872-418B-9766-E40F33689BE4}.Release|x64.Build.0 = Release|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Debug|ARM.ActiveCfg = Debug|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Debug|ARM64.ActiveCfg = Debug|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Debug|Win32.ActiveCfg = Debug|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Debug|Win32.Build.0 = Debug|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Debug|x64.ActiveCfg = Debug|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Debug|x64.Build.0 = Debug|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|ARM.ActiveCfg = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|ARM.Build.0 = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|ARM64.ActiveCfg = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|ARM64.Build.0 = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|Win32.ActiveCfg = Release|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|x64.ActiveCfg = Release|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release Service|x64.Build.0 = Release|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release|ARM.ActiveCfg = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release|ARM64.ActiveCfg = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release|Win32.ActiveCfg = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release|Win32.Build.0 = Release|Win32
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release|x64.ActiveCfg = Release|x64
{A9B12FBF-84D8-4BB6-B4A3-DD57F06637B0}.Release|x64.Build.0 = Release|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Debug|ARM.ActiveCfg = Debug|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Debug|ARM64.ActiveCfg = Debug|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Debug|Win32.ActiveCfg = Debug|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Debug|Win32.Build.0 = Debug|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Debug|x64.ActiveCfg = Debug|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Debug|x64.Build.0 = Debug|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|ARM.ActiveCfg = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|ARM.Build.0 = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|ARM64.ActiveCfg = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|ARM64.Build.0 = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|Win32.ActiveCfg = Release|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|x64.ActiveCfg = Release|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release Service|x64.Build.0 = Release|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release|ARM.ActiveCfg = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release|ARM64.ActiveCfg = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release|Win32.ActiveCfg = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release|Win32.Build.0 = Release|Win32
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release|x64.ActiveCfg = Release|x64
{D1BF1BE4-1F36-4E19-8631-CB4C93B77E9B}.Release|x64.Build.0 = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Debug|ARM.ActiveCfg = Debug|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Debug|ARM64.ActiveCfg = Debug|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Debug|Win32.ActiveCfg = Debug|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Debug|Win32.Build.0 = Debug|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Debug|x64.ActiveCfg = Debug|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Debug|x64.Build.0 = Debug|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|ARM.ActiveCfg = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|ARM.Build.0 = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|ARM64.ActiveCfg = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|ARM64.Build.0 = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|Win32.ActiveCfg = Release|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|Win32.Build.0 = Release|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release Service|x64.ActiveCfg = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release|ARM.ActiveCfg = Release|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release|ARM64.ActiveCfg = Release|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release|Win32.ActiveCfg = Release|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release|Win32.Build.0 = Release|Win32
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release|x64.ActiveCfg = Release|x64
{09263E7C-F43C-4925-B672-22C1818D8CCD}.Release|x64.Build.0 = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Debug|ARM.ActiveCfg = Debug|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Debug|ARM64.ActiveCfg = Debug|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Debug|Win32.ActiveCfg = Debug|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Debug|x64.ActiveCfg = Debug|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Debug|x64.Build.0 = Debug|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|ARM.ActiveCfg = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|ARM.Build.0 = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|ARM64.ActiveCfg = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|ARM64.Build.0 = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|Win32.ActiveCfg = Release|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|Win32.Build.0 = Release|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release Service|x64.ActiveCfg = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release|ARM.ActiveCfg = Release|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release|ARM64.ActiveCfg = Release|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release|Win32.ActiveCfg = Release|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release|Win32.Build.0 = Release|Win32
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release|x64.ActiveCfg = Release|x64
{DC9628DB-0FBF-4E1C-944C-6F877E185FA7}.Release|x64.Build.0 = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Debug|ARM.ActiveCfg = Debug|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Debug|ARM64.ActiveCfg = Debug|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Debug|Win32.ActiveCfg = Debug|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Debug|Win32.Build.0 = Debug|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Debug|x64.ActiveCfg = Debug|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Debug|x64.Build.0 = Debug|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|ARM.ActiveCfg = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|ARM.Build.0 = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|ARM64.ActiveCfg = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|ARM64.Build.0 = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|Win32.ActiveCfg = Release|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|Win32.Build.0 = Release|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|x64.ActiveCfg = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release Service|x64.Build.0 = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release|ARM.ActiveCfg = Release|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release|ARM64.ActiveCfg = Release|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release|Win32.ActiveCfg = Release|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release|Win32.Build.0 = Release|Win32
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release|x64.ActiveCfg = Release|x64
{C2F8110F-6103-4669-9CA5-C332DC5FE228}.Release|x64.Build.0 = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Debug|ARM.ActiveCfg = Debug|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Debug|ARM64.ActiveCfg = Debug|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Debug|Win32.ActiveCfg = Debug|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Debug|Win32.Build.0 = Debug|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Debug|x64.ActiveCfg = Debug|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Debug|x64.Build.0 = Debug|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|ARM.ActiveCfg = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|ARM.Build.0 = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|ARM64.ActiveCfg = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|ARM64.Build.0 = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|Win32.ActiveCfg = Release|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|Win32.Build.0 = Release|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|x64.ActiveCfg = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release Service|x64.Build.0 = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release|ARM.ActiveCfg = Release|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release|ARM64.ActiveCfg = Release|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release|Win32.ActiveCfg = Release|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release|Win32.Build.0 = Release|Win32
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release|x64.ActiveCfg = Release|x64
{249B45EB-BDD2-4F47-B2F8-3F4E3B805ACC}.Release|x64.Build.0 = Release|x64
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Debug|ARM.ActiveCfg = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Debug|ARM64.ActiveCfg = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Debug|Win32.ActiveCfg = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Debug|Win32.Build.0 = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Debug|x64.ActiveCfg = Debug|x64
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Debug|x64.Build.0 = Debug|x64
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|ARM.ActiveCfg = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|ARM.Build.0 = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|ARM64.ActiveCfg = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|ARM64.Build.0 = Debug|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|Win32.ActiveCfg = Release|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|Win32.Build.0 = Release|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|x64.ActiveCfg = Release|x64
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release Service|x64.Build.0 = Release|x64
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release|ARM.ActiveCfg = Release|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release|ARM64.ActiveCfg = Release|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release|Win32.ActiveCfg = Release|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release|Win32.Build.0 = Release|Win32
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release|x64.ActiveCfg = Release|x64
{B6ED0533-D4DB-4571-BE69-EDF0A1655064}.Release|x64.Build.0 = Release|x64
{EA09B289-492C-4F30-813B-9928994FB21B}.Debug|ARM.ActiveCfg = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Debug|ARM64.ActiveCfg = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Debug|Win32.ActiveCfg = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Debug|Win32.Build.0 = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Debug|x64.ActiveCfg = Debug|x64
{EA09B289-492C-4F30-813B-9928994FB21B}.Debug|x64.Build.0 = Debug|x64
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|ARM.ActiveCfg = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|ARM.Build.0 = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|ARM64.ActiveCfg = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|ARM64.Build.0 = Debug|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|Win32.ActiveCfg = Release|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|Win32.Build.0 = Release|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|x64.ActiveCfg = Release|x64
{EA09B289-492C-4F30-813B-9928994FB21B}.Release Service|x64.Build.0 = Release|x64
{EA09B289-492C-4F30-813B-9928994FB21B}.Release|ARM.ActiveCfg = Release|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release|ARM64.ActiveCfg = Release|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release|Win32.ActiveCfg = Release|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release|Win32.Build.0 = Release|Win32
{EA09B289-492C-4F30-813B-9928994FB21B}.Release|x64.ActiveCfg = Release|x64
{EA09B289-492C-4F30-813B-9928994FB21B}.Release|x64.Build.0 = Release|x64
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Debug|ARM.ActiveCfg = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Debug|ARM64.ActiveCfg = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Debug|Win32.ActiveCfg = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Debug|Win32.Build.0 = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Debug|x64.ActiveCfg = Debug|x64
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Debug|x64.Build.0 = Debug|x64
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|ARM.ActiveCfg = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|ARM.Build.0 = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|ARM64.ActiveCfg = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|ARM64.Build.0 = Debug|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|Win32.ActiveCfg = Release|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|Win32.Build.0 = Release|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|x64.ActiveCfg = Release|x64
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release Service|x64.Build.0 = Release|x64
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release|ARM.ActiveCfg = Release|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release|ARM64.ActiveCfg = Release|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release|Win32.ActiveCfg = Release|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release|Win32.Build.0 = Release|Win32
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release|x64.ActiveCfg = Release|x64
{8F901558-A663-4EA8-A52D-E6577ABEB2D1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,53 @@
#include "BackupFileSystem.h"
BtrfsBackupFileSystem::BtrfsBackupFileSystem(const std::string& backing_path)
: btrfs(btrfs_fuse_open_disk_image(backing_path))
{
}
IFsFile* BtrfsBackupFileSystem::openFile(const std::string& path, int mode)
{
return btrfs->openFile(path, mode);
}
bool BtrfsBackupFileSystem::reflinkFile(const std::string& source, const std::string& dest)
{
return btrfs->reflink(source, dest);
}
bool BtrfsBackupFileSystem::createDir(const std::string& path)
{
return btrfs->createDir(path);
}
EFileType BtrfsBackupFileSystem::getFileType(const std::string& path)
{
int ft = static_cast<unsigned int>(btrfs->getFileType(path));
int ret = 0;
if (ft & static_cast<unsigned int>(BtrfsFuse::FileType::Directory))
{
ret |= EFileType_Directory;
}
else if (ft & static_cast<unsigned int>(BtrfsFuse::FileType::File))
{
ret |= EFileType_File;
}
return static_cast<EFileType>(ret);
}
bool BtrfsBackupFileSystem::hasError()
{
return btrfs.get()==nullptr;
}
bool BtrfsBackupFileSystem::Flush()
{
return btrfs->flush();
}
bool BtrfsBackupFileSystem::deleteFile(const std::string& path)
{
return btrfs->deleteFile(path);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IBackupFileSystem.h"
#include "../fuse/fuse.h"
class BtrfsBackupFileSystem : public IBackupFileSystem
{
public:
BtrfsBackupFileSystem(const std::string& backing_path);
virtual IFsFile* openFile(const std::string& path, int mode) override;
virtual bool reflinkFile(const std::string& source, const std::string& dest) override;
virtual bool createDir(const std::string& path) override;
virtual EFileType getFileType(const std::string& path) override;
virtual bool hasError() override;
virtual bool Flush() override;
virtual bool deleteFile(const std::string& path) override;
private:
std::unique_ptr<BtrfsFuse> btrfs;
};

View File

@ -0,0 +1,7 @@
#include "BtrfsFactory.h"
#include "BackupFileSystem.h"
IBackupFileSystem* BtrfsFactory::openBtrfsImage(const std::string& path)
{
return new BtrfsBackupFileSystem(path);
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "IBtrfsFactory.h"
class BtrfsFactory : public IBtrfsFactory
{
public:
virtual IBackupFileSystem* openBtrfsImage(const std::string& path) override;
};

View File

@ -0,0 +1,24 @@
#pragma once
#include "../../Interface/Object.h"
#include "../../Interface/File.h"
#include "../../urbackupcommon/os_functions.h"
class IBackupFileSystem : public IObject
{
public:
virtual bool hasError() = 0;
virtual IFsFile* openFile(const std::string& path, int mode) = 0;
virtual bool reflinkFile(const std::string& source, const std::string& dest) = 0;
virtual bool createDir(const std::string& path) = 0;
virtual bool deleteFile(const std::string& path) = 0;
virtual EFileType getFileType(const std::string& path) = 0;
virtual bool Flush() = 0;
};

View File

@ -0,0 +1,10 @@
#pragma once
#include "IBackupFileSystem.h"
#include "../../Interface/Plugin.h"
class IBtrfsFactory : public IPlugin
{
public:
virtual IBackupFileSystem* openBtrfsImage(const std::string& path) = 0;
};

View File

@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BackupFileSystem.cpp" />
<ClCompile Include="BtrfsFactory.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pluginmgr.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BackupFileSystem.h" />
<ClInclude Include="BtrfsFactory.h" />
<ClInclude Include="IBackupFileSystem.h" />
<ClInclude Include="IBtrfsFactory.h" />
<ClInclude Include="pluginmgr.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8f901558-a663-4ea8-a52d-e6577abeb2d1}</ProjectGuid>
<RootNamespace>btrfsplugin</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;BTRFSPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;BTRFSPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;BTRFSPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>btrfsfuse.lib;oslib.lib;legacy_stdio_definitions.lib;Synchronization.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;BTRFSPLUGIN_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="pluginmgr.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="BtrfsFactory.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="BackupFileSystem.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pluginmgr.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="BtrfsFactory.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="BackupFileSystem.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="IBtrfsFactory.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="IBackupFileSystem.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,104 @@
/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#ifdef _WIN32
#define DLLEXPORT extern "C" __declspec (dllexport)
#else
#define DLLEXPORT extern "C"
#endif
#include <iostream>
#include <memory.h>
#include <stdio.h>
#include <string>
#include <assert.h>
#ifndef STATIC_PLUGIN
#define DEF_SERVER
#endif
#include "../../Interface/Server.h"
#ifndef STATIC_PLUGIN
IServer* Server;
#else
#include "../StaticPluginRegistration.h"
extern IServer* Server;
#define LoadActions LoadActions_btrfsplugin
#define UnloadActions UnloadActions_btrfsplugin
#endif
#include <stdlib.h>
#include "pluginmgr.h"
#include "../fuse/fuse.h"
#include "IBackupFileSystem.h"
#include "IBtrfsFactory.h"
BtrfsPluginMgr* btrfspluginmgr;
DLLEXPORT void LoadActions(IServer* pServer)
{
Server = pServer;
btrfs_fuse_init();
btrfspluginmgr = new BtrfsPluginMgr;
if (!Server->getServerParameter("run_btrfs_test").empty())
{
str_map params;
IBtrfsFactory* fak = reinterpret_cast<IBtrfsFactory*>(btrfspluginmgr->createPluginInstance(params));
IBackupFileSystem* fs = fak->openBtrfsImage("D:\\tmp\\btrfs.img");
bool b = fs->deleteFile("test_dir2");
assert(b);
b = fs->createDir("test_dir2");
assert(b);
IFsFile* f = fs->openFile("test_file_5", MODE_WRITE);
std::string buf;
buf.resize(4096);
f->Write(buf);
f->Seek(0);
f->Read(4096);
f->Resize(4096);
assert(f->Size() == 4096);
b = fs->Flush();
assert(b);
exit(0);
}
Server->RegisterPluginThreadsafeModel(btrfspluginmgr, "btrfsplugin");
#ifndef STATIC_PLUGIN
Server->Log("Loaded -btrfsplugin- plugin", LL_INFO);
#endif
}
DLLEXPORT void UnloadActions(void)
{
}
#ifdef STATIC_PLUGIN
namespace
{
static RegisterPluginHelper register_plugin(LoadActions, UnloadActions, 0);
}
#endif

View File

@ -0,0 +1,12 @@
#include "pluginmgr.h"
#include "BtrfsFactory.h"
IPlugin* BtrfsPluginMgr::createPluginInstance(str_map& params)
{
return new BtrfsFactory;
}
void BtrfsPluginMgr::destroyPluginInstance(IPlugin* plugin)
{
delete static_cast<BtrfsFactory*>(plugin);
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "../../Interface/PluginMgr.h"
class BtrfsPluginMgr : public IPluginMgr
{
public:
IPlugin* createPluginInstance(str_map& params);
void destroyPluginInstance(IPlugin* plugin);
};

706
btrfs/fuse/fuse.cpp Normal file
View File

@ -0,0 +1,706 @@
#include <iostream>
#include <vector>
#include "os.h"
#include "../../utf8/utf8.h"
#include "fuse.h"
extern "C"
{
#include <ntifs.h>
#include <device.h>
#include "src/btrfsioctl.h"
NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
extern PDEVICE_OBJECT master_devobj;
typedef struct _DUPLICATE_EXTENTS_DATA {
HANDLE FileHandle;
LARGE_INTEGER SourceFileOffset;
LARGE_INTEGER TargetFileOffset;
LARGE_INTEGER ByteCount;
} DUPLICATE_EXTENTS_DATA, * PDUPLICATE_EXTENTS_DATA;
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)
}
namespace
{
std::vector<PDEVICE_OBJECT> new_disks;
std::unique_ptr<DRIVER_OBJECT> driver_object;
std::wstring ConvertToWchar(const std::string& input)
{
if (input.empty())
{
return std::wstring();
}
std::wstring ret;
try
{
if (sizeof(wchar_t) == 2)
{
utf8::utf8to16(&input[0], &input[input.size() - 1] + 1, back_inserter(ret));
}
else if (sizeof(wchar_t) == 4)
{
utf8::utf8to32(&input[0], &input[input.size() - 1] + 1, back_inserter(ret));
}
}
catch (...) {}
return ret;
}
}
void register_new_disk(PDEVICE_OBJECT disk)
{
new_disks.push_back(disk);
}
class UStr
{
public:
UStr(const std::wstring& wstr)
{
str.Buffer = new wchar_t[wstr.size() + 1];
str.Length = wstr.size()*sizeof(wchar_t);
str.MaximumLength = (wstr.size() + 1)*sizeof(wchar_t);
memcpy(str.Buffer, wstr.data(), str.MaximumLength);
}
~UStr()
{
delete[] str.Buffer;
}
PUNICODE_STRING getUstr()
{
return &str;
}
private:
UNICODE_STRING str;
};
int main()
{
btrfs_fuse_init();
std::unique_ptr<DEVICE_OBJECT> device_object = std::make_unique<DEVICE_OBJECT>();
std::unique_ptr<FILE_OBJECT> file_object = std::make_unique<FILE_OBJECT>();
device_object->DiskDevice = InitDiskDevice("D:\\tmp\\btrfs.img", 1LL * 1024 * 1024 * 1024, 1);
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
std::vector<char> moundev_name_buf;
std::wstring volname = L"VOL1";
IoRegisterDeviceObjectPointer(UStr(volname).getUstr(), file_object.get(), device_object.get());
moundev_name_buf.resize(sizeof(ULONG) + sizeof(WCHAR) * (volname.size()+1));
PMOUNTDEV_NAME mountdev_name = reinterpret_cast<PMOUNTDEV_NAME>(moundev_name_buf.data());
mountdev_name->NameLength = volname.size()*sizeof(WCHAR);
memcpy(mountdev_name->Name, volname.data(), volname.size() * sizeof(WCHAR));
irp->AssociatedIrp.SystemBuffer = mountdev_name;
irp->StackLocation.Parameters.DeviceIoControl.IoControlCode = IOCTL_BTRFS_PROBE_VOLUME;
irp->StackLocation.Parameters.DeviceIoControl.InputBufferLength = moundev_name_buf.size();
driver_object->MajorFunction[IRP_MJ_DEVICE_CONTROL](master_devobj, irp.get());
PDEVICE_OBJECT btrfs_disk = new_disks[new_disks.size() - 1];
for (PDEVICE_OBJECT disk : new_disks)
{
driver_object->DriverExtension->AddDevice(driver_object.get(), disk);
}
new_disks.clear();
irp->StackLocation.MinorFunction = IRP_MN_MOUNT_VOLUME;
irp->StackLocation.Parameters.MountVolume.DeviceObject = btrfs_disk;
PVPB vpb = new VPB;
irp->StackLocation.Parameters.MountVolume.Vpb = vpb;
vpb->DeviceObject = btrfs_disk;
vpb->RealDevice = device_object.get();
driver_object->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL](master_devobj, irp.get());
PFILE_OBJECT root_file = FsRtlNotifyGetLastVolumeEventsubject();
root_file->RelatedFileObject = NULL;
UStr root_path(L"\\");
root_file->FileName = *root_path.getUstr();
PDEVICE_OBJECT fs = vpb->DeviceObject;
irp = std::make_unique<IRP>();
std::unique_ptr<SECURITY_CONTEXT> security_context = std::make_unique<SECURITY_CONTEXT>();
std::unique_ptr<ACCESS_STATE> access_state = std::make_unique< ACCESS_STATE>();
security_context->AccessState = access_state.get();
irp->StackLocation.MajorFunction = IRP_MJ_CREATE;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.FileObject = root_file;
irp->StackLocation.Parameters.Create.Options = FILE_OPEN<<24;
irp->StackLocation.Parameters.Create.SecurityContext = security_context.get();
driver_object->MajorFunction[IRP_MJ_CREATE](fs, irp.get());
irp = std::make_unique<IRP>();
irp->StackLocation.MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
irp->StackLocation.MinorFunction = IRP_MN_QUERY_DIRECTORY;
irp->StackLocation.FileObject = root_file;
irp->StackLocation.Flags = SL_RESTART_SCAN;
std::vector<char> out_buf;
out_buf.resize(1024);
irp->UserBuffer = out_buf.data();
irp->StackLocation.Parameters.QueryDirectory.Length = out_buf.size();
irp->StackLocation.Parameters.QueryDirectory.FileInformationClass = FileBothDirectoryInformation;
driver_object->MajorFunction[IRP_MJ_DIRECTORY_CONTROL](fs, irp.get());
for (size_t i = 0; i +sizeof(FILE_BOTH_DIR_INFORMATION )-sizeof(WCHAR)< irp->IoStatus.Information;)
{
FILE_BOTH_DIR_INFORMATION* fni = reinterpret_cast<FILE_BOTH_DIR_INFORMATION*>(out_buf.data()+i);
std::wcout << std::wstring(fni->FileName, fni->FileNameLength/sizeof(WCHAR)) << std::endl;
if (fni->NextEntryOffset == 0)
break;
i += fni->NextEntryOffset;
}
irp = std::make_unique<IRP>();
security_context = std::make_unique<SECURITY_CONTEXT>();
access_state = std::make_unique< ACCESS_STATE>();
security_context->AccessState = access_state.get();
irp->StackLocation.MajorFunction = IRP_MJ_CREATE;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.Parameters.Create.Options = FILE_OPEN << 24;
irp->StackLocation.Parameters.Create.SecurityContext = security_context.get();
std::unique_ptr<FILE_OBJECT> test_file_obj = std::make_unique<FILE_OBJECT>();
test_file_obj->RelatedFileObject = root_file;
UStr test_file_path(L"test.file");
test_file_obj->FileName = *test_file_path.getUstr();
irp->StackLocation.FileObject = test_file_obj.get();
driver_object->MajorFunction[IRP_MJ_CREATE](fs, irp.get());
irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_READ;
irp->StackLocation.Parameters.Read.ByteOffset.QuadPart = 0;
irp->StackLocation.Parameters.Read.Length = 4096;
irp->StackLocation.FileObject = test_file_obj.get();
out_buf.resize(5000);
irp->UserBuffer = out_buf.data();
driver_object->MajorFunction[IRP_MJ_READ](fs, irp.get());
int abct = 5;
}
BtrfsFuse* open_disk_image(const std::string& path)
{
return nullptr;
}
struct FsData
{
std::string device_path;
std::unique_ptr<DEVICE_OBJECT> device_object;
std::unique_ptr<FILE_OBJECT> file_object;
PDEVICE_OBJECT btrfs_device;
PFILE_OBJECT root_file;
PDEVICE_OBJECT fs;
};
void btrfs_fuse_init()
{
init_windef();
driver_object = std::make_unique<DRIVER_OBJECT>();
driver_object->DriverExtension = new DRIVER_OBJECT_EXTENSION;
UStr reg_path(L"FOOBAR\\BAR");
DriverEntry(driver_object.get(), reg_path.getUstr());
}
BtrfsFuse* btrfs_fuse_open_disk_image(const std::string& path)
{
return new BtrfsFuse(path);
}
BtrfsFuse::BtrfsFuse(const std::string& path)
: fs_data(new FsData)
{
fs_data->device_path = path;
fs_data->device_object = std::make_unique<DEVICE_OBJECT>();
fs_data->file_object = std::make_unique<FILE_OBJECT>();
fs_data->device_object->DiskDevice = InitDiskDevice(path.c_str(), 1LL * 1024 * 1024 * 1024, 1);
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
std::vector<char> moundev_name_buf;
std::wstring volname = L"VOL1";
IoRegisterDeviceObjectPointer(UStr(volname).getUstr(), fs_data->file_object.get(), fs_data->device_object.get());
moundev_name_buf.resize(sizeof(ULONG) + sizeof(WCHAR) * (volname.size() + 1));
PMOUNTDEV_NAME mountdev_name = reinterpret_cast<PMOUNTDEV_NAME>(moundev_name_buf.data());
mountdev_name->NameLength = volname.size() * sizeof(WCHAR);
memcpy(mountdev_name->Name, volname.data(), volname.size() * sizeof(WCHAR));
irp->AssociatedIrp.SystemBuffer = mountdev_name;
irp->StackLocation.Parameters.DeviceIoControl.IoControlCode = IOCTL_BTRFS_PROBE_VOLUME;
irp->StackLocation.Parameters.DeviceIoControl.InputBufferLength = moundev_name_buf.size();
driver_object->MajorFunction[IRP_MJ_DEVICE_CONTROL](master_devobj, irp.get());
PDEVICE_OBJECT btrfs_disk = new_disks[new_disks.size() - 1];
for (PDEVICE_OBJECT disk : new_disks)
{
driver_object->DriverExtension->AddDevice(driver_object.get(), disk);
fs_data->btrfs_device = disk->AttachedDevice;
}
new_disks.clear();
irp->StackLocation.MinorFunction = IRP_MN_MOUNT_VOLUME;
irp->StackLocation.Parameters.MountVolume.DeviceObject = btrfs_disk;
PVPB vpb = new VPB;
irp->StackLocation.Parameters.MountVolume.Vpb = vpb;
vpb->DeviceObject = btrfs_disk;
vpb->RealDevice = fs_data->device_object.get();
driver_object->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL](master_devobj, irp.get());
fs_data->fs = vpb->DeviceObject;
PFILE_OBJECT tmp_root_file = FsRtlNotifyGetLastVolumeEventsubject();
fs_data->root_file = nullptr;
fs_data->root_file = openFileInt("\\", MODE_READ, false, false).release();
/*fs_data->root_file = FsRtlNotifyGetLastVolumeEventsubject();
fs_data->root_file->RelatedFileObject = NULL;
UStr root_path(L"\\");
fs_data->root_file->FileName = *root_path.getUstr();
irp = std::make_unique<IRP>();
std::unique_ptr<SECURITY_CONTEXT> security_context = std::make_unique<SECURITY_CONTEXT>();
std::unique_ptr<ACCESS_STATE> access_state = std::make_unique< ACCESS_STATE>();
security_context->AccessState = access_state.get();
irp->StackLocation.MajorFunction = IRP_MJ_CREATE;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.FileObject = fs_data->root_file;
irp->StackLocation.Parameters.Create.Options = FILE_OPEN << 24;
irp->StackLocation.Parameters.Create.SecurityContext = security_context.get();
driver_object->MajorFunction[IRP_MJ_CREATE](fs_data->fs, irp.get());*/
}
BtrfsFuse::~BtrfsFuse()
{
}
bool BtrfsFuse::createDir(const std::string& path)
{
std::unique_ptr<_FILE_OBJECT> file_obj = openFileInt(path, MODE_WRITE, true, false);
if (file_obj.get() == nullptr)
return false;
return closeFile(std::move(file_obj));
}
bool BtrfsFuse::deleteFile(const std::string& path)
{
std::unique_ptr<_FILE_OBJECT> file_obj = openFileInt(path, MODE_RW, false, true);
if (file_obj.get() == nullptr)
return false;
return closeFile(std::move(file_obj));
}
class BtrfsFuseFile : public IFsFile
{
public:
BtrfsFuseFile(FsData* fs_data, std::unique_ptr<FILE_OBJECT> file_obj, const std::string& path)
: fs_data(fs_data), path(path), file_obj(std::move(file_obj)), pos(0)
{
}
~BtrfsFuseFile()
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->StackLocation.MajorFunction = IRP_MJ_CLOSE;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.FileObject = file_obj.get();
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_CLOSE](fs_data->fs, irp.get());
}
virtual std::string Read(_u32 tr, bool* has_error = NULL) override
{
std::string ret= Read(pos, tr, has_error);
pos += ret.size();
return ret;
}
virtual std::string Read(int64 spos, _u32 tr, bool* has_error = NULL) override
{
std::string str;
str.resize(tr);
_u32 read = Read(spos, &str[0], tr, has_error);
if (read != tr)
str.resize(read);
return str;
}
virtual _u32 Read(char* buffer, _u32 bsize, bool* has_error = NULL) override
{
_u32 read = Read(pos, buffer, bsize, has_error);
pos += read;
return read;
}
virtual _u32 Read(int64 spos, char* buffer, _u32 bsize, bool* has_error = NULL) override
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_READ;
irp->StackLocation.Parameters.Read.ByteOffset.QuadPart = spos;
irp->StackLocation.Parameters.Read.Length = bsize;
irp->StackLocation.FileObject = file_obj.get();
irp->UserBuffer = buffer;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_READ](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
errno = rc;
if(has_error!=nullptr)
*has_error = true;
return 0;
}
return static_cast<_u32>(irp->IoStatus.Information);
}
virtual _u32 Write(const std::string& tw, bool* has_error = NULL) override
{
return Write(tw.data(), tw.size(), has_error);
}
virtual _u32 Write(int64 spos, const std::string& tw, bool* has_error = NULL) override
{
return Write(spos, tw.data(), tw.size(), has_error);
}
virtual _u32 Write(const char* buffer, _u32 bsiz, bool* has_error = NULL) override
{
_u32 written = Write(pos, buffer, bsiz, has_error);
pos += written;
return written;
}
virtual _u32 Write(int64 spos, const char* buffer, _u32 bsize, bool* has_error = NULL) override
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_WRITE;
irp->StackLocation.Parameters.Write.ByteOffset.QuadPart = spos;
irp->StackLocation.Parameters.Write.Length = bsize;
irp->StackLocation.FileObject = file_obj.get();
irp->UserBuffer = const_cast<char*>(buffer);
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_WRITE](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
errno = rc;
if (has_error != nullptr)
*has_error = true;
return 0;
}
return static_cast<_u32>(irp->IoStatus.Information);
}
virtual bool Seek(_i64 spos) override
{
pos = spos;
return true;
}
virtual _i64 Size(void) override
{
FILE_STANDARD_INFORMATION fsi;
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_QUERY_INFORMATION;
irp->StackLocation.Parameters.QueryFile.FileInformationClass = FileStandardInformation;
irp->StackLocation.Parameters.QueryFile.Length = sizeof(fsi);
irp->StackLocation.FileObject = file_obj.get();
irp->AssociatedIrp.SystemBuffer = &fsi;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_QUERY_INFORMATION](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
return -1;
}
return fsi.EndOfFile.QuadPart;
}
virtual _i64 RealSize() override
{
return Size();
}
virtual bool PunchHole(_i64 spos, _i64 size) override
{
return false;
}
virtual bool Sync() override
{
return false;
}
virtual std::string getFilename(void) override
{
return path;
}
virtual void resetSparseExtentIter() override
{
}
virtual SSparseExtent nextSparseExtent() override
{
return SSparseExtent();
}
virtual bool Resize(int64 new_size, bool set_sparse = true) override
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_SET_INFORMATION;
irp->StackLocation.Parameters.SetFile.FileInformationClass = FileAllocationInformation;
FILE_END_OF_FILE_INFORMATION eofi;
eofi.EndOfFile.QuadPart = new_size;
irp->StackLocation.Parameters.SetFile.Length = sizeof(eofi);
irp->StackLocation.FileObject = file_obj.get();
irp->AssociatedIrp.SystemBuffer = &eofi;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_SET_INFORMATION](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
return false;
}
return true;
}
virtual std::vector<SFileExtent> getFileExtents(int64 starting_offset, int64 block_size, bool& more_data) override
{
return std::vector<SFileExtent>();
}
virtual IVdlVolCache* createVdlVolCache() override
{
return nullptr;
}
virtual int64 getValidDataLength(IVdlVolCache* vol_cache) override
{
return int64();
}
virtual os_file_handle getOsHandle(bool release_handle = false) override
{
return os_file_handle();
}
private:
FsData* fs_data;
std::string path;
std::unique_ptr<_FILE_OBJECT> file_obj;
int64 pos;
};
IFsFile* BtrfsFuse::openFile(const std::string& path, int mode)
{
std::unique_ptr<_FILE_OBJECT> file_obj = openFileInt(path, mode, false, false);
if (file_obj.get() == nullptr)
return nullptr;
return new BtrfsFuseFile(fs_data.get(), std::move(file_obj), path);
}
BtrfsFuse::FileType BtrfsFuse::getFileType(const std::string& path)
{
std::unique_ptr<_FILE_OBJECT> file_obj = openFileInt(path, MODE_READ, false, false);
if (file_obj.get() == nullptr)
return FileType::None;
BtrfsFuse::FileType ret = FileType::None;
FILE_STANDARD_INFORMATION fsi;
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_QUERY_INFORMATION;
irp->StackLocation.Parameters.QueryFile.FileInformationClass = FileStandardInformation;
irp->StackLocation.Parameters.QueryFile.Length = sizeof(fsi);
irp->StackLocation.FileObject = file_obj.get();
irp->AssociatedIrp.SystemBuffer = &fsi;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_QUERY_INFORMATION](fs_data->fs, irp.get());
if (NT_SUCCESS(rc))
{
if (fsi.Directory)
{
ret = FileType::Directory;
}
else
{
ret = FileType::File;
}
}
closeFile(std::move(file_obj));
return ret;
}
bool BtrfsFuse::reflink(const std::string& src_path, const std::string& dest_path)
{
std::unique_ptr<_FILE_OBJECT> dest_file_obj = openFileInt(dest_path, MODE_WRITE, false, false);
if (dest_file_obj.get() == nullptr)
return false;
std::unique_ptr<_FILE_OBJECT> src_file_obj = openFileInt(src_path, MODE_WRITE, false, false);
if (src_file_obj.get() == nullptr)
return false;
int64 source_size = fileSize(src_file_obj.get());
if (source_size < 0)
return false;
if (source_size == 0)
return true;
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
irp->StackLocation.MinorFunction = IRP_MN_USER_FS_REQUEST;
irp->StackLocation.Parameters.FileSystemControl.FsControlCode = FSCTL_DUPLICATE_EXTENTS_TO_FILE;
DUPLICATE_EXTENTS_DATA ded;
irp->AssociatedIRP = irp.get();
irp->UserBuffer = &ded;
irp->StackLocation.Parameters.FileSystemControl.InputBufferLength = sizeof(ded);
irp->StackLocation.Parameters.FileSystemControl.OutputBufferLength = 0;
irp->StackLocation.FileObject = dest_file_obj.get();
HANDLE hSrc = ObRegisterHandle(src_file_obj.get());
ded.FileHandle = hSrc;
ded.SourceFileOffset.QuadPart = 0;
ded.TargetFileOffset.QuadPart = 0;
ded.ByteCount.QuadPart = source_size;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL](fs_data->fs, irp.get());
bool ret = false;
if (NT_SUCCESS(rc))
{
ret = true;
}
ObDeregisterHandle(hSrc);
closeFile(std::move(dest_file_obj));
closeFile(std::move(src_file_obj));
return ret;
}
bool BtrfsFuse::flush()
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_POWER;
irp->StackLocation.MinorFunction = IRP_MN_QUERY_POWER;
irp->StackLocation.Parameters.Power.Type = SystemPowerState;
irp->StackLocation.Parameters.Power.State.SystemState = PowerSystemNone;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_POWER](fs_data->btrfs_device, irp.get());
if (!NT_SUCCESS(rc))
{
return false;
}
return true;
}
std::unique_ptr<_FILE_OBJECT> BtrfsFuse::openFileInt(const std::string& path, int mode, bool openDirectory, bool deleteFile)
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
std::unique_ptr<SECURITY_CONTEXT> security_context = std::make_unique<SECURITY_CONTEXT>();
std::unique_ptr<ACCESS_STATE> access_state = std::make_unique< ACCESS_STATE>();
security_context->AccessState = access_state.get();
irp->StackLocation.MajorFunction = IRP_MJ_CREATE;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.Parameters.Create.Options = FILE_OPEN << 24;
if (mode == MODE_WRITE)
{
irp->StackLocation.Parameters.Create.Options |= (FILE_CREATE << 24);
}
if (deleteFile)
{
irp->StackLocation.Parameters.Create.Options |= FILE_DELETE_ON_CLOSE;
}
if (openDirectory)
{
irp->StackLocation.Parameters.Create.Options |= FILE_DIRECTORY_FILE;
}
irp->StackLocation.Parameters.Create.SecurityContext = security_context.get();
std::unique_ptr<_FILE_OBJECT> file_obj = std::make_unique<_FILE_OBJECT>();
file_obj->RelatedFileObject = fs_data->root_file;
UStr test_file_path(ConvertToWchar(path));
file_obj->FileName = *test_file_path.getUstr();
irp->StackLocation.FileObject = file_obj.get();
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_CREATE](fs_data->fs, irp.get());
if (rc != 0)
{
errno = rc;
return std::unique_ptr<_FILE_OBJECT>();
}
return std::move(file_obj);
}
bool BtrfsFuse::closeFile(std::unique_ptr<_FILE_OBJECT> file_object)
{
return closeFile(file_object.get());
}
bool BtrfsFuse::closeFile(PFILE_OBJECT file_object)
{
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
/*irp->StackLocation.MajorFunction = IRP_MJ_CLOSE;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.FileObject = file_object;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_CLOSE](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
errno = rc;
return false;
}*/
irp->StackLocation.MajorFunction = IRP_MJ_CLEANUP;
irp->StackLocation.MinorFunction = IRP_MN_NORMAL;
irp->StackLocation.FileObject = file_object;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_CLEANUP](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
errno = rc;
return false;
}
return true;
}
int64 BtrfsFuse::fileSize(PFILE_OBJECT file_object)
{
FILE_STANDARD_INFORMATION fsi;
std::unique_ptr<IRP> irp = std::make_unique<IRP>();
irp->Flags = IRP_NOCACHE;
irp->StackLocation.MajorFunction = IRP_MJ_QUERY_INFORMATION;
irp->StackLocation.Parameters.QueryFile.FileInformationClass = FileStandardInformation;
irp->StackLocation.Parameters.QueryFile.Length = sizeof(fsi);
irp->StackLocation.FileObject = file_object;
irp->AssociatedIrp.SystemBuffer = &fsi;
NTSTATUS rc = driver_object->MajorFunction[IRP_MJ_QUERY_INFORMATION](fs_data->fs, irp.get());
if (!NT_SUCCESS(rc))
{
return -1;
}
return fsi.EndOfFile.QuadPart;
}

52
btrfs/fuse/fuse.h Normal file
View File

@ -0,0 +1,52 @@
#pragma once
#include <string>
#include "../../Interface/File.h"
#include <memory>
struct _DEVICE_OBJECT;
typedef struct _DEVICE_OBJECT* PDEVICE_OBJECT;
struct _FILE_OBJECT;
typedef struct _FILE_OBJECT* PFILE_OBJECT;
int main();
void register_new_disk(PDEVICE_OBJECT disk);
struct FsData;
class BtrfsFuse
{
public:
BtrfsFuse(const std::string& path);
~BtrfsFuse();
bool createDir(const std::string& path);
bool deleteFile(const std::string& path);
IFsFile* openFile(const std::string& path, int mode);
enum class FileType
{
None = 0,
File = 1,
Directory = 2,
Symlink = 4
};
FileType getFileType(const std::string& path);
bool reflink(const std::string& src_path,
const std::string& dest_path);
bool flush();
private:
std::unique_ptr<_FILE_OBJECT> openFileInt(const std::string& path, int mode, bool openDirectory, bool deleteFile);
bool closeFile(std::unique_ptr<_FILE_OBJECT> file_object);
bool closeFile(PFILE_OBJECT file_object);
int64 fileSize(PFILE_OBJECT file_object);
std::unique_ptr<FsData> fs_data;
};
void btrfs_fuse_init();
BtrfsFuse* btrfs_fuse_open_disk_image(const std::string& path);

243
btrfs/fuse/fuse.vcxproj Normal file
View File

@ -0,0 +1,243 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{B6ED0533-D4DB-4571-BE69-EDF0A1655064}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>fuse</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>btrfsfuse</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>nt;oslib;$(SolutionDir)/external/btrfs</AdditionalIncludeDirectories>
<PreprocessToFile>false</PreprocessToFile>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(SolutionDir)$(Platform)\$(Configuration)\oslib.lib;legacy_stdio_definitions.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;BTRFS_FUSE%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)nt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\external\btrfs\src\balance.c" />
<ClCompile Include="..\..\external\btrfs\src\blake2b-ref.c" />
<ClCompile Include="..\..\external\btrfs\src\boot.c" />
<ClCompile Include="..\..\external\btrfs\src\btrfs.c" />
<ClCompile Include="..\..\external\btrfs\src\cache.c" />
<ClCompile Include="..\..\external\btrfs\src\calcthread.c" />
<ClCompile Include="..\..\external\btrfs\src\compress.c" />
<ClCompile Include="..\..\external\btrfs\src\crc32c.c" />
<ClCompile Include="..\..\external\btrfs\src\create.c" />
<ClCompile Include="..\..\external\btrfs\src\devctrl.c" />
<ClCompile Include="..\..\external\btrfs\src\dirctrl.c" />
<ClCompile Include="..\..\external\btrfs\src\extent-tree.c" />
<ClCompile Include="..\..\external\btrfs\src\fastio.c" />
<ClCompile Include="..\..\external\btrfs\src\fileinfo.c" />
<ClCompile Include="..\..\external\btrfs\src\flushthread.c" />
<ClCompile Include="..\..\external\btrfs\src\free-space.c" />
<ClCompile Include="..\..\external\btrfs\src\fsctl.c" />
<ClCompile Include="..\..\external\btrfs\src\fsrtl.c" />
<ClCompile Include="..\..\external\btrfs\src\galois.c" />
<ClCompile Include="..\..\external\btrfs\src\pnp.c" />
<ClCompile Include="..\..\external\btrfs\src\read.c" />
<ClCompile Include="..\..\external\btrfs\src\registry.c" />
<ClCompile Include="..\..\external\btrfs\src\reparse.c" />
<ClCompile Include="..\..\external\btrfs\src\scrub.c" />
<ClCompile Include="..\..\external\btrfs\src\search.c" />
<ClCompile Include="..\..\external\btrfs\src\security.c" />
<ClCompile Include="..\..\external\btrfs\src\send.c" />
<ClCompile Include="..\..\external\btrfs\src\sha256.c" />
<ClCompile Include="..\..\external\btrfs\src\treefuncs.c" />
<ClCompile Include="..\..\external\btrfs\src\volume.c" />
<ClCompile Include="..\..\external\btrfs\src\worker-thread.c" />
<ClCompile Include="..\..\external\btrfs\src\write.c" />
<ClCompile Include="..\..\external\btrfs\src\xxhash.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\adler32.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\deflate.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\inffast.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\inflate.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\inftrees.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\trees.c" />
<ClCompile Include="..\..\external\btrfs\src\zlib\zutil.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\entropy_common.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\error_private.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\fse_compress.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\fse_decompress.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\hist.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\huf_compress.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\huf_decompress.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_common.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_compress.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_decompress.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_double_fast.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_fast.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_lazy.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_ldm.c" />
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_opt.c" />
<ClCompile Include="fuse.cpp" />
<ClCompile Include="nt\device.cpp" />
<ClCompile Include="nt\resource.cpp" />
<ClCompile Include="nt\windef.cpp" />
<ClCompile Include="nt\workqueue.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="fuse.h" />
<ClInclude Include="nt\ata.h" />
<ClInclude Include="nt\device.h" />
<ClInclude Include="nt\guiddef.h" />
<ClInclude Include="nt\mountdev.h" />
<ClInclude Include="nt\mountmgr.h" />
<ClInclude Include="nt\ntdddisk.h" />
<ClInclude Include="nt\ntddk.h" />
<ClInclude Include="nt\ntddscsi.h" />
<ClInclude Include="nt\ntddvol.h" />
<ClInclude Include="nt\ntddstor.h" />
<ClInclude Include="nt\ntdef.h" />
<ClInclude Include="nt\ntifs.h" />
<ClInclude Include="nt\ntstatus.h" />
<ClInclude Include="nt\ntstrsafe.h" />
<ClInclude Include="nt\os.h\Header.h" />
<ClInclude Include="nt\resource.h" />
<ClInclude Include="nt\wdm.h" />
<ClInclude Include="nt\windef.h" />
<ClInclude Include="nt\Windows.h" />
<ClInclude Include="nt\winnt.h" />
<ClInclude Include="nt\workqueue.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,279 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="btrfs">
<UniqueIdentifier>{71c5887e-07aa-43dd-9f01-bef959a55f26}</UniqueIdentifier>
</Filter>
<Filter Include="nt">
<UniqueIdentifier>{690387f0-0463-482c-9f9d-43557212fc08}</UniqueIdentifier>
</Filter>
<Filter Include="btrfs\zstd">
<UniqueIdentifier>{394cd095-b22c-4ba5-ab51-5d8408724d78}</UniqueIdentifier>
</Filter>
<Filter Include="btrfs\zlib">
<UniqueIdentifier>{d31f708a-d5c4-4c76-a8c4-e51296eb9a02}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="fuse.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="nt\resource.cpp">
<Filter>nt</Filter>
</ClCompile>
<ClCompile Include="nt\windef.cpp">
<Filter>nt</Filter>
</ClCompile>
<ClCompile Include="nt\workqueue.cpp">
<Filter>nt</Filter>
</ClCompile>
<ClCompile Include="nt\device.cpp">
<Filter>nt</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\balance.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\blake2b-ref.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\boot.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\btrfs.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\cache.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\calcthread.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\compress.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\crc32c.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\create.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\devctrl.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\dirctrl.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\extent-tree.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\fastio.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\fileinfo.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\flushthread.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\free-space.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\fsctl.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\fsrtl.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\galois.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\pnp.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\read.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\registry.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\reparse.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\scrub.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\search.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\security.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\send.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\sha256.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\treefuncs.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\volume.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\worker-thread.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\write.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\xxhash.c">
<Filter>btrfs</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\entropy_common.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\error_private.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\fse_compress.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\fse_decompress.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\hist.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\huf_compress.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\huf_decompress.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_common.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_compress.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_decompress.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_double_fast.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_fast.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_lazy.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_ldm.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zstd\zstd_opt.c">
<Filter>btrfs\zstd</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\adler32.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\deflate.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\inffast.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\inflate.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\inftrees.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\trees.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
<ClCompile Include="..\..\external\btrfs\src\zlib\zutil.c">
<Filter>btrfs\zlib</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="nt\ntifs.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ata.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\mountmgr.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntddk.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntstrsafe.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\wdm.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\windef.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\winnt.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntddscsi.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntdddisk.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntddvol.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\guiddef.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntddstor.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\resource.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntstatus.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\os.h\Header.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\workqueue.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\mountdev.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\ntdef.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="fuse.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="nt\device.h">
<Filter>nt</Filter>
</ClInclude>
<ClInclude Include="nt\Windows.h">
<Filter>nt</Filter>
</ClInclude>
</ItemGroup>
</Project>

3
btrfs/fuse/nt/Windows.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "windef.h"

0
btrfs/fuse/nt/ata.h Normal file
View File

188
btrfs/fuse/nt/device.cpp Normal file
View File

@ -0,0 +1,188 @@
extern "C"
{
#include "device.h"
}
#include "vol.h"
namespace
{
NTSTATUS __stdcall vol_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID conptr,
DWORD errorCode, DWORD bytesTransferred)
{
Irp->IoStatus.Status = errorCode;
Irp->IoStatus.Information = bytesTransferred;
return Irp->CompletionRoutine(DeviceObject, Irp, conptr);
}
class DiskDevice
{
public:
DiskDevice() {}
void Init(const char* path, ULONGLONG DiskLength, ULONG DiskNumber)
{
disk_length = DiskLength;
disk_vol = std::make_unique<vol>(path);
}
NTSTATUS InternalDeviceControl(PIRP Irp)
{
switch (Irp->StackLocation.Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_DISK_UPDATE_PROPERTIES:
return STATUS_SUCCESS;
case IOCTL_DISK_GET_DRIVE_LAYOUT_EX:
{
PDRIVE_LAYOUT_INFORMATION_EX layout_info = reinterpret_cast<PDRIVE_LAYOUT_INFORMATION_EX>(Irp->AssociatedIrp.SystemBuffer);
layout_info->PartitionCount = 0;
Irp->IoStatus.Information = sizeof(DRIVE_LAYOUT_INFORMATION_EX);
return STATUS_SUCCESS;
}
case IOCTL_DISK_GET_LENGTH_INFO:
{
PGET_LENGTH_INFORMATION length_info = reinterpret_cast<PGET_LENGTH_INFORMATION>(Irp->AssociatedIrp.SystemBuffer);
length_info->Length.QuadPart = disk_length;
Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
return STATUS_SUCCESS;
}
case IOCTL_STORAGE_GET_DEVICE_NUMBER:
{
PSTORAGE_DEVICE_NUMBER device_number = reinterpret_cast<PSTORAGE_DEVICE_NUMBER>(Irp->AssociatedIrp.SystemBuffer);
device_number->DeviceNumber = disk_number;
device_number->PartitionNumber = 0;
device_number->DeviceType = 0;
Irp->IoStatus.Information = sizeof(STORAGE_DEVICE_NUMBER);
return STATUS_SUCCESS;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
{
PDISK_GEOMETRY disk_geom = reinterpret_cast<PDISK_GEOMETRY>(Irp->AssociatedIrp.SystemBuffer);
memset(disk_geom, 0, sizeof(DISK_GEOMETRY));
disk_geom->BytesPerSector = 4096;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
return STATUS_SUCCESS;
}
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
{
PMOUNTDEV_NAME mountdev_name = reinterpret_cast<PMOUNTDEV_NAME>(Irp->AssociatedIrp.SystemBuffer);
std::wstring name = L"\\Device\\Btrfs{foobar}";
mountdev_name->NameLength = (name.size() + 1)*sizeof(wchar_t);
if (Irp->StackLocation.Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG) + (name.size() + 1) * sizeof(wchar_t))
{
memcpy(mountdev_name->Name, name.data(), sizeof(wchar_t) * (name.size() + 1));
return STATUS_SUCCESS;
}
else
{
return STATUS_BUFFER_OVERFLOW;
}
}
}
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS Read(PIRP Irp, PDEVICE_OBJECT DeviceObject)
{
vol::completion_args completion;
completion.CompletionRoutine = vol_completion;
completion.Context = Irp->CompletionRoutineContext;
completion.DeviceObject = DeviceObject;
completion.Irp = Irp;
disk_vol->read(Irp->StackLocation.Parameters.Read.ByteOffset.QuadPart,
reinterpret_cast<char*>(Irp->UserBuffer), Irp->StackLocation.Parameters.Read.Length,
completion);
return STATUS_PENDING;
}
NTSTATUS Write(PIRP Irp, PDEVICE_OBJECT DeviceObject)
{
vol::completion_args completion;
completion.CompletionRoutine = vol_completion;
completion.Context = Irp->CompletionRoutineContext;
completion.DeviceObject = DeviceObject;
completion.Irp = Irp;
disk_vol->write(Irp->StackLocation.Parameters.Write.ByteOffset.QuadPart,
reinterpret_cast<char*>(Irp->UserBuffer), Irp->StackLocation.Parameters.Write.Length,
completion);
return STATUS_PENDING;
}
NTSTATUS DeviceControl(PIRP Irp, PDEVICE_OBJECT DeviceObject)
{
if (Irp->StackLocation.Parameters.DeviceIoControl.IoControlCode != IOCTL_ATA_PASS_THROUGH)
{
return STATUS_NOT_IMPLEMENTED;
}
if (Irp->StackLocation.Parameters.DeviceIoControl.InputBufferLength != sizeof(ATA_PASS_THROUGH_EX))
return STATUS_INVALID_PARAMETER;
ATA_PASS_THROUGH_EX* ata = static_cast<ATA_PASS_THROUGH_EX*>(Irp->UserBuffer);
if (ata->CurrentTaskFile[6] == IDE_COMMAND_FLUSH_CACHE)
{
bool b = disk_vol->flush();
Irp->IoStatus.Status = b ? STATUS_SUCCESS : STATUS_UNEXPECTED_IO_ERROR;
Irp->CompletionRoutine(DeviceObject, Irp, Irp->CompletionRoutineContext);
return STATUS_SUCCESS;
}
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS Call(PIRP Irp, PDEVICE_OBJECT DeviceObject)
{
switch (Irp->StackLocation.MajorFunction)
{
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
return InternalDeviceControl(Irp);
case IRP_MJ_READ:
return Read(Irp, DeviceObject);
case IRP_MJ_WRITE:
return Write(Irp, DeviceObject);
case IRP_MJ_DEVICE_CONTROL:
return DeviceControl(Irp, DeviceObject);
}
return STATUS_NOT_IMPLEMENTED;
}
bool Flush()
{
return disk_vol->flush();
}
private:
ULONGLONG disk_length;
ULONG disk_number;
std::unique_ptr<vol> disk_vol;
};
}
struct _DISK_DEVICE
{
DiskDevice disk_device;
};
NTSTATUS DiskDeviceCall(PDISK_DEVICE DiskDevice, PIRP Irp, PDEVICE_OBJECT DeviceObject)
{
return DiskDevice->disk_device.Call(Irp, DeviceObject);
}
PDISK_DEVICE InitDiskDevice(const char* path, ULONGLONG Length, ULONG Number)
{
PDISK_DEVICE ret = new _DISK_DEVICE;
ret->disk_device.Init(path, Length, Number);
return ret;
}
NTSTATUS FlushDiskDevice(PDISK_DEVICE DiskDevice)
{
if (DiskDevice->disk_device.Flush())
{
return STATUS_SUCCESS;
}
return STATUS_UNEXPECTED_IO_ERROR;
}

12
btrfs/fuse/nt/device.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <windef.h>
struct _DISK_DEVICE;
typedef struct _DISK_DEVICE* PDISK_DEVICE;
struct _DEVICE_OBJECT;
typedef struct _DEVICE_OBJECT* PDEVICE_OBJECT;
NTSTATUS DiskDeviceCall(PDISK_DEVICE DiskDevice, PIRP Irp, PDEVICE_OBJECT DeviceObject);
PDISK_DEVICE InitDiskDevice(const char* path, ULONGLONG Length, ULONG Number);
NTSTATUS FlushDiskDevice(PDISK_DEVICE DiskDevice);

18
btrfs/fuse/nt/guiddef.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[8];
} GUID;
typedef GUID* LPGUID;
typedef GUID* PGUID;
#define DEFINE_GUID(gname, data1, data2, data3, data4a, data4b, data4c, data4d, data4e, data4f, data4g, data4h) static GUID gname = { data1, data2, data3, {data4a, data4b, data4c, data4d, data4e, data4f, data4g, data4h} };
DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, 0x3eee337e, 0xd03b, 0x4980, 0xa8, 0xed, 0x8c, 0x40, 0x6d, 0x68, 0xf3, 0xf0);
DEFINE_GUID(GUID_DEVINTERFACE_HIDDEN_VOLUME, 0x3eee337e, 0xd03b, 0x4980, 0xa8, 0xed, 0x8c, 0x40, 0x6d, 0x68, 0xf3, 0xf1);
DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x3eee337e, 0xd03b, 0x4980, 0xa8, 0xed, 0x8c, 0x40, 0x6d, 0x68, 0xf3, 0xf2);

1
btrfs/fuse/nt/mountdev.h Normal file
View File

@ -0,0 +1 @@
#pragma once

0
btrfs/fuse/nt/mountmgr.h Normal file
View File

1
btrfs/fuse/nt/ntdddisk.h Normal file
View File

@ -0,0 +1 @@
#pragma once

0
btrfs/fuse/nt/ntddk.h Normal file
View File

1
btrfs/fuse/nt/ntddscsi.h Normal file
View File

@ -0,0 +1 @@
#pragma once

1
btrfs/fuse/nt/ntddstor.h Normal file
View File

@ -0,0 +1 @@
#pragma once

1
btrfs/fuse/nt/ntddvol.h Normal file
View File

@ -0,0 +1 @@
#pragma once

3
btrfs/fuse/nt/ntdef.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "windef.h"

3
btrfs/fuse/nt/ntifs.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "windef.h"

59
btrfs/fuse/nt/ntstatus.h Normal file
View File

@ -0,0 +1,59 @@
#pragma once
#define STATUS_SUCCESS 0
#define STATUS_MORE_PROCESSING_REQUIRED 1
#define STATUS_INVALID_PARAMETER 2
#define STATUS_PENDING 3
#define STATUS_BUFFER_OVERFLOW 4
#define STATUS_SOME_NOT_MAPPED 5
#define STATUS_NOT_IMPLEMENTED 6
#define STATUS_INSUFFICIENT_RESOURCES 7
#define STATUS_INTERNAL_ERROR 8
#define STATUS_BUFFER_TOO_SMALL 9
#define STATUS_INVALID_VOLUME_LABEL 10
#define STATUS_MEDIA_WRITE_PROTECTED 11
#define STATUS_ACCESS_DENIED 12
#define STATUS_TOO_LATE 13
#define STATUS_UNRECOGNIZED_VOLUME 14
#define STATUS_NOT_FOUND 15
#define STATUS_INVALID_DEVICE_REQUEST 16
#define STATUS_DEVICE_NOT_READY 17
#define STATUS_WRONG_VOLUME 18
#define STATUS_NOT_SUPPORTED 19
#define STATUS_DISK_FULL 20
#define STATUS_PRIVILEGE_NOT_HELD 21
#define STATUS_CANNOT_DELETE 22
#define STATUS_CRC_ERROR 23
#define STATUS_UNEXPECTED_IO_ERROR 24
#define STATUS_OBJECT_NAME_COLLISION 25
#define STATUS_END_OF_FILE 26
#define STATUS_OBJECT_NAME_NOT_FOUND 27
#define STATUS_OBJECT_NAME_INVALID 28
#define STATUS_OBJECT_PATH_NOT_FOUND 29
#define STATUS_REPARSE 30
#define STATUS_USER_MAPPED_FILE 31
#define STATUS_DELETE_PENDING 32
#define STATUS_FILE_IS_A_DIRECTORY 33
#define STATUS_NOT_A_DIRECTORY 34
#define STATUS_SHARING_VIOLATION 35
#define STATUS_VERIFY_REQUIRED 36
#define STATUS_NO_MORE_FILES 37
#define STATUS_NO_SUCH_FILE 38
#define STATUS_CANT_WAIT 39
#define STATUS_DIRECTORY_NOT_EMPTY 40
#define STATUS_FILE_CLOSED 41
#define STATUS_INFO_LENGTH_MISMATCH 42
#define STATUS_TOO_MANY_LINKS 43
#define STATUS_NONEXISTENT_EA_ENTRY 44
#define STATUS_FILE_DELETED 45
#define STATUS_NOT_LOCKED 46
#define STATUS_INVALID_USER_BUFFER 47
#define STATUS_FILE_LOCK_CONFLICT 48
#define STATUS_IO_REPARSE_DATA_INVALID 49
#define STATUS_IO_REPARSE_TAG_INVALID 50
#define STATUS_UNSUCCESSFUL 51
#define STATUS_NO_MORE_ENTRIES 52
#define STATUS_NOT_A_REPARSE_POINT 53
#define STATUS_INVALID_BUFFER_SIZE 64
#define IO_ERR_INTERNAL_ERROR 1001

View File

132
btrfs/fuse/nt/resource.cpp Normal file
View File

@ -0,0 +1,132 @@
#include "resource.h"
#include <mutex>
#include <condition_variable>
#include <atomic>
struct ERESOURCE_INT {
ERESOURCE_INT()
: shared_lock(0), owner(std::thread::id()),
excl_count(0) {}
std::mutex mutex;
std::condition_variable cond;
int shared_lock;
std::thread::id owner;
int excl_count;
};
BOOLEAN ExAcquireResourceSharedLite(PERESOURCE Resource, BOOLEAN Wait)
{
std::unique_lock<std::mutex> lock(Resource->res->mutex);
if (Resource->res->owner == std::this_thread::get_id())
{
++Resource->res->excl_count;
return TRUE;
}
if (Resource->res->owner == std::thread::id())
{
++Resource->res->shared_lock;
return TRUE;
}
if (!Wait)
{
return FALSE;
}
while (Resource->res->owner == std::thread::id())
{
Resource->res->cond.wait(lock);
}
++Resource->res->shared_lock;
return TRUE;
}
BOOLEAN ExAcquireResourceExclusiveLite(PERESOURCE Resource, BOOLEAN Wait)
{
std::unique_lock<std::mutex> lock(Resource->res->mutex);
if (Resource->res->owner == std::this_thread::get_id())
{
++Resource->res->excl_count;
return TRUE;
}
if (!Resource->res->shared_lock &&
Resource->res->owner == std::thread::id())
{
Resource->res->owner = std::this_thread::get_id();
Resource->res->excl_count = 1;
return TRUE;
}
if (!Wait)
{
return FALSE;
}
while (Resource->res->shared_lock &&
Resource->res->owner != std::thread::id())
{
Resource->res->cond.wait(lock);
}
Resource->res->owner = std::this_thread::get_id();
Resource->res->excl_count = 1;
return TRUE;
}
BOOLEAN ExReleaseResourceLite(PERESOURCE Resource)
{
std::unique_lock<std::mutex> lock(Resource->res->mutex);
if (Resource->res->owner == std::this_thread::get_id())
{
if (Resource->res->excl_count > 1)
{
--Resource->res->excl_count;
}
else
{
Resource->res->owner = std::thread::id();
Resource->res->excl_count = 0;
Resource->res->cond.notify_one();
}
}
else
{
--Resource->res->shared_lock;
if (Resource->res->shared_lock == 0)
{
Resource->res->cond.notify_one();
}
}
return TRUE;
}
void ExConvertExclusiveToSharedLite(PERESOURCE Res)
{
std::unique_lock<std::mutex> lock(Res->res->mutex);
Res->res->owner = std::thread::id();
Res->res->excl_count = 0;
++Res->res->shared_lock;
}
BOOLEAN ExDeleteResourceLite(PERESOURCE Resource)
{
delete Resource->res;
return TRUE;
}
BOOLEAN ExInitializeResourceLite(PERESOURCE Resource)
{
Resource->res = new ERESOURCE_INT;
return TRUE;
}

32
btrfs/fuse/nt/resource.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include "windef.h"
#ifdef __cplusplus
extern "C" {
#endif
struct ERESOURCE_INT;
typedef struct _ERESOURCE {
struct ERESOURCE_INT* res;
} ERESOURCE;
typedef ERESOURCE* PERESOURCE;
BOOLEAN ExAcquireResourceSharedLite(PERESOURCE Resource, BOOLEAN Wait);
BOOLEAN ExAcquireResourceExclusiveLite(PERESOURCE Resource, BOOLEAN Wait);
BOOLEAN ExReleaseResourceLite(PERESOURCE Resource);
BOOLEAN ExDeleteResourceLite(PERESOURCE Resource);
BOOLEAN ExInitializeResourceLite(PERESOURCE Resource);
void ExConvertExclusiveToSharedLite(PERESOURCE Res);
#ifdef __cplusplus
}
#endif

0
btrfs/fuse/nt/wdm.h Normal file
View File

1797
btrfs/fuse/nt/windef.cpp Normal file

File diff suppressed because it is too large Load Diff

2571
btrfs/fuse/nt/windef.h Normal file

File diff suppressed because it is too large Load Diff

0
btrfs/fuse/nt/winnt.h Normal file
View File

View File

@ -0,0 +1,47 @@
extern "C"
{
#include <workqueue.h>
}
#include <queue>
namespace
{
struct SWorkItem
{
PIO_WORKITEM WorkItem;
PIO_WORKITEM_ROUTINE Routine;
PVOID Context;
};
std::queue<SWorkItem> work;
}
PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
{
PIO_WORKITEM ret = new IO_WORKITEM;
ret->DeviceObject = DeviceObject;
return ret;
}
void IoQueueWorkItem(PIO_WORKITEM WorkItem, PIO_WORKITEM_ROUTINE Routine, WORK_QUEUE_TYPE QueueType, PVOID Context)
{
Routine(WorkItem->DeviceObject, Context);
/*
SWorkItem item;
item.WorkItem = WorkItem;
item.Routine = Routine;
item.Context = Context;
work.push(item);*/
}
void IoFreeWorkItem(PIO_WORKITEM WorkItem)
{
delete WorkItem;
}
void ExQueueWorkItem(PWORK_QUEUE_ITEM Wqi, WORK_QUEUE_TYPE Type)
{
}

23
btrfs/fuse/nt/workqueue.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "windef.h"
typedef struct _IO_WORKITEM {
PDEVICE_OBJECT DeviceObject;
} IO_WORKITEM;
typedef IO_WORKITEM* PIO_WORKITEM;
typedef void(IO_WORKITEM_ROUTINE)(PDEVICE_OBJECT DeviceObject, PVOID Context);
typedef IO_WORKITEM_ROUTINE* PIO_WORKITEM_ROUTINE;
typedef enum _WORK_QUEUE_TYPE {
DelayedWorkQueue
} WORK_QUEUE_TYPE;
PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject);
void IoQueueWorkItem(PIO_WORKITEM WorkItem, PIO_WORKITEM_ROUTINE Routine, WORK_QUEUE_TYPE QueueType, PVOID Context);
void IoFreeWorkItem(PIO_WORKITEM WorkItem);
void ExQueueWorkItem(PWORK_QUEUE_ITEM Wqi, WORK_QUEUE_TYPE Type);

View File

@ -0,0 +1,33 @@
#include "event.h"
#include <Windows.h>
HANDLE create_event(bool state)
{
return CreateEventEx(NULL, NULL, state ? CREATE_EVENT_INITIAL_SET : 0, EVENT_ALL_ACCESS);
}
bool event_wait(HANDLE hEvent, DWORD ms)
{
DWORD rc = WaitForSingleObjectEx(hEvent, ms, TRUE);
return rc == WAIT_OBJECT_0 || rc==WAIT_IO_COMPLETION;
}
bool event_set(HANDLE hEvent)
{
return SetEvent(hEvent) == TRUE;
}
bool event_reset(HANDLE hEvent)
{
return ResetEvent(hEvent) == TRUE;
}
void event_destroy(HANDLE hEvent)
{
CloseHandle(hEvent);
}
bool event_pulse(HANDLE hEvent)
{
return PulseEvent(hEvent) == TRUE;
}

16
btrfs/fuse/oslib/event.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
typedef void* HANDLE;
typedef unsigned long DWORD;
HANDLE create_event(bool state);
bool event_wait(HANDLE hEvent, DWORD ms);
bool event_set(HANDLE hEvent);
bool event_reset(HANDLE hEvent);
void event_destroy(HANDLE hEvent);
bool event_pulse(HANDLE hEvent);

156
btrfs/fuse/oslib/file.h Normal file
View File

@ -0,0 +1,156 @@
#ifndef FILE_H
#define FILE_H
#include "../../../Interface/File.h"
const int MODE_TEMP = 4;
//#define MODE_STL //No 64bit
#ifdef _WIN32
# define MODE_WIN
#elif LINUX
# define MODE_LIN
#else
# define MODE_STL
# warning "using STL file access files>4GB are not supported"
#endif
#ifdef MODE_STL
# include <fstream>
#endif
#ifdef MODE_WIN
# include <Windows.h>
#endif
#ifdef MODE_LIN
#if !defined(_LARGEFILE64_SOURCE) && !defined(__APPLE__)
# define _LARGEFILE64_SOURCE
#endif
# include <fcntl.h>
# include <sys/stat.h>
# include <stdlib.h>
# include <unistd.h>
# define _unlink unlink
#if defined(__FreeBSD__) || defined(__APPLE__)
#define off64_t off_t
#endif
#endif
#include <vector>
#include <string>
class alignas(16) File
{
public:
#pragma pack(push)
struct SSparseExtent
{
SSparseExtent()
: offset(-1), size(-1)
{
}
SSparseExtent(int64 offset, int64 size)
: offset(offset), size(size)
{
}
bool operator<(const SSparseExtent& other) const
{
return offset < other.offset;
}
int64 offset;
int64 size;
};
#pragma pack(pop)
struct SFileExtent
{
enum class Flags
{
None = 0,
Shared = 1
};
SFileExtent()
: offset(-1), size(-1), volume_offset(-1), flags(Flags::None)
{}
int64 offset;
int64 size;
int64 volume_offset;
Flags flags;
};
enum class FiemapFlag
{
None = 0,
Physical = 8,
Noshared = 16
};
#ifdef _WIN32
typedef void* os_file_handle;
#else
typedef int os_file_handle;
#endif
File();
~File();
bool Open(std::string pfn, int mode=MODE_READ);
bool Open(void *handle, const std::string& pFilename);
std::string Read(_u32 tr, bool *has_error=NULL);
std::string Read(int64 spos, _u32 tr, bool *has_error = NULL);
_u32 Read(char* buffer, _u32 bsize, bool *has_error=NULL);
_u32 Read(int64 spos, char* buffer, _u32 bsize, bool *has_error = NULL);
_u32 Write(const std::string &tw, bool *has_error=NULL);
_u32 Write(int64 spos, const std::string &tw, bool *has_error = NULL);
_u32 Write(const char* buffer, _u32 bsize, bool *has_error=NULL);
_u32 Write(int64 spos, const char* buffer, _u32 bsize, bool *has_error = NULL);
bool Seek(_i64 spos);
_i64 Size(void);
_i64 RealSize();
void Close();
bool PunchHole( _i64 spos, _i64 size );
bool Sync();
bool Resize(int64 new_size, bool set_sparse=true);
void resetSparseExtentIter();
SSparseExtent nextSparseExtent();
std::vector<SFileExtent> getFileExtents(int64 starting_offset, int64 block_size, bool& more_data);
os_file_handle getOsHandle(bool release_handle = false);
std::string getFilename(void);
private:
#ifdef MODE_STL
std::fstream fi;
#endif
#ifdef MODE_WIN
HANDLE hfile;
bool is_sparse;
#endif
#ifdef MODE_LIN
int fd;
#endif
std::string fn;
#ifdef _WIN32
bool setSparse();
bool more_extents;
std::vector<FILE_ALLOCATED_RANGE_BUFFER> res_extent_buffer;
size_t curr_extent;
int64 last_sparse_pos;
#else
off64_t last_sparse_pos;
#endif
};
bool DeleteFileInt(std::string pFilename);
#endif //FILE_H

View File

@ -0,0 +1,40 @@
/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "file.h"
#include <string>
#include "utf8.h"
File::~File()
{
Close();
}
std::string File::getFilename(void)
{
return fn;
}
bool DeleteFileInt(std::string pFilename)
{
#ifndef _WIN32
return _unlink((pFilename).c_str()) == 0 ? true : false;
#else
return DeleteFileW(ConvertToWchar(pFilename).c_str()) != 0;
#endif
}

View File

@ -0,0 +1,557 @@
/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "Server.h"
#include "file.h"
#include "types.h"
#include "stringtools.h"
#ifdef MODE_LIN
#include "config.h"
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef __linux__
#ifdef HAVE_LINUX_FIEMAP_H
#include <linux/fiemap.h>
#else
namespace
{
struct fiemap_extent
{
uint64 fe_logical;
uint64 fe_physical;
uint64 fe_length;
uint64 fe_reserved64[2];
unsigned int fe_flags;
unsigned int fe_reserved[3];
};
struct fiemap
{
uint64 fm_start;
uint64 fm_length;
unsigned int fm_flags;
unsigned int fm_mapped_extents;
unsigned int fm_extent_count;
unsigned int fm_reserved;
struct fiemap_extent fm_extents[0];
};
#define FIEMAP_MAX_OFFSET (~0ULL)
#define FIEMAP_EXTENT_LAST 0x00000001
#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap)
}
#endif
#ifndef FALLOC_FL_KEEP_SIZE
#define FALLOC_FL_KEEP_SIZE 0x1
#endif
#ifndef FALLOC_FL_PUNCH_HOLE
#define FALLOC_FL_PUNCH_HOLE 0x2
#endif
#ifndef SEEK_DATA
#define SEEK_DATA 3
#endif
#ifndef SEEK_HOLE
#define SEEK_HOLE 4
#endif
#endif //__linux__
#if defined(__FreeBSD__) || defined(__APPLE__)
#define open64 open
#define off64_t off_t
#define lseek64 lseek
#define O_LARGEFILE 0
#define stat64 stat
#define fstat64 fstat
#define ftruncate64 ftruncate
#define fallocate64 fallocate
#define pwrite64 pwrite
#define pread64 pread
#else
#include <linux/fs.h>
#if !defined(BLKGETSIZE64) && defined(__i386__) && defined(__x86_64__)
#define BLKGETSIZE64 _IOR(0x12,114,size_t)
#endif
#endif
#if defined(__FreeBSD__)
//2017-05-12: Make illegal. Performance problems with ZFS on FreeBSD
#undef SEEK_HOLE
#define SEEK_HOLE 400
#endif
File::File()
: fd(-1), last_sparse_pos(0)
{
}
bool File::Open(std::string pfn, int mode)
{
if (mode == MODE_RW_RESTORE)
{
mode = MODE_RW;
}
if (mode == MODE_RW_CREATE_RESTORE)
{
mode = MODE_RW_CREATE;
}
if (mode == MODE_RW_CREATE_DEVICE
|| mode == MODE_RW_CREATE_DELETE )
{
mode = MODE_RW_CREATE;
}
if (mode == MODE_READ_DEVICE_OVERLAPPED)
{
mode = MODE_READ_DEVICE;
}
fn=pfn;
int flags=0;
mode_t imode=S_IRWXU|S_IRWXG;
if( mode==MODE_READ
|| mode==MODE_READ_DEVICE
|| mode==MODE_READ_SEQUENTIAL
|| mode==MODE_READ_SEQUENTIAL_BACKUP)
{
flags=O_RDONLY;
}
else if( mode==MODE_WRITE )
{
DeleteFileInt(pfn);
flags=O_WRONLY|O_CREAT;
}
else if( mode==MODE_APPEND )
{
flags=O_RDWR | O_APPEND;
}
else if( mode==MODE_RW
|| mode==MODE_RW_SEQUENTIAL
|| mode==MODE_RW_CREATE
|| mode==MODE_RW_READNONE
|| mode==MODE_RW_DEVICE
|| mode==MODE_RW_DELETE
|| mode==MODE_RW_DIRECT
|| mode==MODE_RW_CREATE_DIRECT)
{
flags=O_RDWR;
if( mode==MODE_RW_CREATE
|| mode==MODE_RW_CREATE_DIRECT )
{
flags|=O_CREAT;
}
}
#ifdef __linux__
if( mode==MODE_RW_CREATE_DIRECT
|| mode==MODE_RW_DIRECT )
{
flags|=O_DIRECT;
}
#endif
struct stat buf;
if(stat((fn).c_str(), &buf)==0)
{
if(S_ISDIR(buf.st_mode) )
return false;
}
#if defined(O_CLOEXEC)
flags |= O_CLOEXEC;
#endif
#if defined(O_NOATIME)
if (mode == MODE_READ_SEQUENTIAL_BACKUP)
{
flags |= O_NOATIME;
}
#endif
fd=open64((fn).c_str(), flags|O_LARGEFILE, imode);
#ifdef __linux__
if(mode==MODE_READ_SEQUENTIAL
|| mode==MODE_READ_SEQUENTIAL_BACKUP
|| mode==MODE_RW_SEQUENTIAL)
{
posix_fadvise64(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
}
if( mode==MODE_RW_READNONE )
{
posix_fadvise64(fd, 0, 0, POSIX_FADV_DONTNEED);
}
#endif
if( fd!=-1 )
{
return true;
}
else
return false;
}
bool File::OpenTemporaryFile(const std::string &dir, bool first_try)
{
char *tmpdir=getenv("TMPDIR");
std::string stmpdir;
if(tmpdir==NULL )
stmpdir="/tmp";
else
stmpdir=tmpdir;
stmpdir=stmpdir+"/cps.XXXXXX";
mode_t cur_umask = umask(S_IRWXO | S_IRWXG);
fd=mkstemp((char*)stmpdir.c_str());
umask(cur_umask);
fn=(stmpdir);
if( fd==-1 )
return false;
else
return true;
}
bool File::Open(void *handle, const std::string& pFilename)
{
fd=(int)((intptr_t)handle);
fn = pFilename;
return true;
}
std::string File::Read(_u32 tr, bool *has_error)
{
std::string ret;
ret.resize(tr);
_u32 gc=Read((char*)ret.c_str(), tr, has_error);
if( gc<tr )
ret.resize( gc );
return ret;
}
std::string File::Read(int64 spos, _u32 tr, bool *has_error)
{
std::string ret;
ret.resize(tr);
_u32 gc=Read(spos, (char*)ret.c_str(), tr, has_error);
if( gc<tr )
ret.resize( gc );
return ret;
}
_u32 File::Read(char* buffer, _u32 bsize, bool *has_error)
{
ssize_t r=read(fd, buffer, bsize);
if( r<0 )
{
if(has_error) *has_error=true;
r=0;
}
return (_u32)r;
}
_u32 File::Read(int64 spos, char* buffer, _u32 bsize, bool *has_error)
{
ssize_t r=pread64(fd, buffer, bsize, spos);
if (r < 0)
{
if (has_error) *has_error = true;
r = 0;
}
return (_u32)r;
}
_u32 File::Write(const std::string &tw, bool *has_error)
{
return Write( tw.c_str(), (_u32)tw.size(), has_error);
}
_u32 File::Write(int64 spos, const std::string &tw, bool *has_error)
{
return Write(spos, tw.c_str(), (_u32)tw.size(), has_error);
}
_u32 File::Write(const char* buffer, _u32 bsize, bool *has_error)
{
ssize_t w=write(fd, buffer, bsize);
if( w<0 )
{
Server->Log("Write failed. errno="+convert(errno), LL_DEBUG);
if (has_error) *has_error = true;
w=0;
}
return (_u32)w;
}
_u32 File::Write(int64 spos, const char* buffer, _u32 bsize, bool *has_error)
{
ssize_t w=pwrite64(fd, buffer, bsize, spos);
if( w<0 )
{
Server->Log("Write failed. errno="+convert(errno), LL_DEBUG);
if(has_error) *has_error=true;
w=0;
}
return (_u32)w;
}
bool File::Seek(_i64 spos)
{
off64_t ot=lseek64(fd, spos, SEEK_SET);
if( ot==(off64_t)-1 )
{
return false;
}
else
{
return true;
}
}
_i64 File::Size(void)
{
struct stat64 stat_buf;
int rc = fstat64(fd, &stat_buf);
if(rc==0)
{
#if defined(BLKGETSIZE64)
if(S_ISBLK(stat_buf.st_mode))
{
_i64 ret;
rc = ioctl(fd, BLKGETSIZE64, &ret);
if(rc==0)
{
return ret;
}
}
#endif
return stat_buf.st_size;
}
else
{
return -1;
}
}
_i64 File::RealSize(void)
{
struct stat64 stat_buf;
fstat64(fd, &stat_buf);
return stat_buf.st_blocks*512;
}
void File::Close()
{
if( fd!=-1 )
{
close( fd );
fd=-1;
}
}
bool File::PunchHole(_i64 spos, _i64 size)
{
#ifdef __APPLE__
return false;
#elif __FreeBSD__
/* Does not exist yet...
struct flock64 s;
s.l_whence = SEEK_SET;
s.l_start = spos;
s.l_len = size;
int rc = fcntl(fd, F_FREESP64, &s);
return rc == 0;*/
return false;
#elif defined(HAVE_FALLOCATE64)
int rc = fallocate64(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, spos, size);
return rc == 0;
#else
return false;
#endif
}
bool File::Sync()
{
return fsync(fd)==0;
}
bool File::Resize(int64 new_size, bool set_sparse)
{
return ftruncate64(fd, new_size) == 0;
}
void File::resetSparseExtentIter()
{
last_sparse_pos = 0;
}
namespace
{
class ResetCur
{
public:
ResetCur(int fd, off64_t pos)
: fd(fd), pos(pos)
{}
~ResetCur()
{
lseek64(fd, pos, SEEK_SET);
}
private:
int fd;
off64_t pos;
};
}
IFsFile::SSparseExtent File::nextSparseExtent()
{
#ifdef SEEK_HOLE
if (last_sparse_pos == -1)
{
return SSparseExtent();
}
off64_t curr_pos = lseek64(fd, 0, SEEK_CUR);
if (curr_pos == -1)
{
return SSparseExtent();
}
ResetCur reset_cur(fd, curr_pos);
off64_t next_hole_start = lseek64(fd, last_sparse_pos, SEEK_HOLE);
if (next_hole_start == -1)
{
last_sparse_pos = -1;
return SSparseExtent();
}
_i64 fsize = Size();
if (next_hole_start == fsize)
{
last_sparse_pos = -1;
return SSparseExtent();
}
last_sparse_pos = lseek64(fd, next_hole_start, SEEK_DATA);
if (last_sparse_pos == -1)
{
return SSparseExtent(next_hole_start, fsize - next_hole_start);
}
if(next_hole_start == last_sparse_pos)
{
last_sparse_pos = -1;
return SSparseExtent();
}
return SSparseExtent(next_hole_start, last_sparse_pos - next_hole_start);
#else //SEEK_HOLE
return SSparseExtent();
#endif
}
std::vector<IFsFile::SFileExtent> File::getFileExtents(int64 starting_offset, int64 block_size, bool& more_data)
{
#ifdef __linux__
std::vector<char> buf;
buf.resize(4096 * 4);
struct fiemap* fiemap = reinterpret_cast<struct fiemap*>(buf.data());
fiemap->fm_extent_count = (buf.size() - sizeof(struct fiemap)) / sizeof(struct fiemap_extent);
fiemap->fm_start = starting_offset;
fiemap->fm_length = FIEMAP_MAX_OFFSET - starting_offset;
fiemap->fm_flags = 0;
if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0)
{
return std::vector<SFileExtent>();
}
std::vector<SFileExtent> ret;
ret.resize(fiemap->fm_mapped_extents);
more_data = true;
for (_u32 i = 0; i < fiemap->fm_mapped_extents; ++i)
{
struct fiemap_extent& ext = fiemap->fm_extents[i];
if (i + 1 >= fiemap->fm_mapped_extents)
{
if (ext.fe_flags & FIEMAP_EXTENT_LAST)
{
more_data = false;
}
}
ret[i].offset = ext.fe_logical;
ret[i].size = ext.fe_length;
ret[i].volume_offset = ext.fe_physical;
}
if (starting_offset == 0
&& fiemap->fm_mapped_extents == 0)
{
more_data = false;
}
return ret;
#else
return std::vector<SFileExtent>();
#endif
}
IFsFile::os_file_handle File::getOsHandle(bool release_handle)
{
int ret = fd;
if (release_handle)
{
fd = -1;
}
return ret;
}
#endif

View File

@ -0,0 +1,505 @@
/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "file.h"
#include <sstream>
#include "utf8.h"
#include <string>
#ifdef MODE_WIN
File::File()
: hfile(INVALID_HANDLE_VALUE), is_sparse(false), more_extents(true), curr_extent(0), last_sparse_pos(0)
{
}
bool File::Open(std::string pfn, int mode)
{
if(mode==MODE_RW_DIRECT)
mode = MODE_RW;
if(mode==MODE_RW_CREATE_DIRECT)
mode = MODE_RW_CREATE;
fn=pfn;
DWORD dwCreationDisposition;
DWORD dwDesiredAccess;
DWORD dwShareMode=FILE_SHARE_READ;
if( mode==MODE_READ
|| mode==MODE_READ_DEVICE
|| mode==MODE_READ_SEQUENTIAL
|| mode==MODE_READ_SEQUENTIAL_BACKUP
|| mode== MODE_READ_DEVICE_OVERLAPPED)
{
dwCreationDisposition=OPEN_EXISTING;
dwDesiredAccess=GENERIC_READ;
}
else if( mode==MODE_WRITE )
{
DeleteFileInt(pfn);
dwCreationDisposition=CREATE_NEW;
dwDesiredAccess=GENERIC_WRITE;
}
else if( mode==MODE_APPEND )
{
dwCreationDisposition=OPEN_EXISTING;
dwDesiredAccess=GENERIC_WRITE | GENERIC_READ;
}
else if( mode==MODE_TEMP )
{
dwCreationDisposition=CREATE_NEW;
dwDesiredAccess=GENERIC_WRITE | GENERIC_READ;
}
else if( mode==MODE_RW
|| mode==MODE_RW_SEQUENTIAL
|| mode==MODE_RW_CREATE
|| mode==MODE_RW_READNONE
|| mode== MODE_RW_DEVICE
|| mode==MODE_RW_RESTORE
|| mode==MODE_RW_CREATE_RESTORE
|| mode== MODE_RW_CREATE_DEVICE
|| mode== MODE_RW_CREATE_DELETE
|| mode==MODE_RW_DELETE)
{
if(mode==MODE_RW
|| mode==MODE_RW_SEQUENTIAL
|| mode==MODE_RW_READNONE
|| mode== MODE_RW_DEVICE
|| mode==MODE_RW_RESTORE
|| mode==MODE_RW_DELETE)
{
dwCreationDisposition=OPEN_EXISTING;
}
else
{
dwCreationDisposition=OPEN_ALWAYS;
}
dwDesiredAccess=GENERIC_WRITE | GENERIC_READ;
}
if(mode==MODE_READ_DEVICE
|| mode== MODE_RW_DEVICE
|| mode== MODE_RW_DELETE
|| mode== MODE_RW_CREATE_DEVICE
|| mode== MODE_RW_CREATE_DELETE
|| mode== MODE_READ_DEVICE_OVERLAPPED)
{
dwShareMode|=FILE_SHARE_WRITE;
}
if (mode == MODE_RW_CREATE_DELETE
|| mode == MODE_RW_DELETE)
{
dwShareMode |= FILE_SHARE_DELETE;
}
DWORD flags=FILE_ATTRIBUTE_NORMAL;
if(mode==MODE_READ_SEQUENTIAL
|| mode==MODE_READ_SEQUENTIAL_BACKUP
|| mode==MODE_RW_SEQUENTIAL)
{
flags|=FILE_FLAG_SEQUENTIAL_SCAN;
}
if(mode==MODE_READ_SEQUENTIAL_BACKUP
|| mode==MODE_RW_RESTORE
|| mode==MODE_RW_CREATE_RESTORE)
{
flags|=FILE_FLAG_BACKUP_SEMANTICS;
}
if (mode == MODE_READ_DEVICE_OVERLAPPED)
{
flags |= FILE_FLAG_OVERLAPPED| FILE_FLAG_NO_BUFFERING;
}
hfile=CreateFileW( ConvertToWchar(fn).c_str(), dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, flags, NULL );
if( hfile!=INVALID_HANDLE_VALUE )
{
if( mode==MODE_APPEND )
{
Seek( Size() );
}
return true;
}
else
{
DWORD err = GetLastError();
return false;
}
}
bool File::Open(void *handle, const std::string& pFilename)
{
hfile=(HANDLE)handle;
fn = pFilename;
if( hfile!=INVALID_HANDLE_VALUE )
{
return true;
}
else
{
return false;
}
}
std::string File::Read(_u32 tr, bool *has_error)
{
std::string ret;
ret.resize(tr);
_u32 gc=Read((char*)ret.c_str(), tr, has_error);
if( gc<tr )
ret.resize( gc );
return ret;
}
std::string File::Read(int64 spos, _u32 tr, bool *has_error)
{
std::string ret;
ret.resize(tr);
_u32 gc=Read(spos, (char*)ret.c_str(), tr, has_error);
if( gc<tr )
ret.resize( gc );
return ret;
}
_u32 File::Read(char* buffer, _u32 bsize, bool *has_error)
{
DWORD read;
BOOL b=ReadFile(hfile, buffer, bsize, &read, NULL );
if(b==FALSE)
{
if(has_error)
{
*has_error=true;
}
}
return (_u32)read;
}
_u32 File::Read(int64 spos, char* buffer, _u32 bsize, bool *has_error)
{
OVERLAPPED overlapped = {};
LARGE_INTEGER li;
li.QuadPart = spos;
overlapped.Offset = li.LowPart;
overlapped.OffsetHigh = li.HighPart;
DWORD read;
BOOL b=ReadFile(hfile, buffer, bsize, &read, &overlapped );
if(b==FALSE)
{
if (has_error)
{
*has_error = true;
}
}
return (_u32)read;
}
_u32 File::Write(const std::string &tw, bool *has_error)
{
return Write( tw.c_str(), (_u32)tw.size(), has_error );
}
_u32 File::Write(int64 spos, const std::string &tw, bool *has_error)
{
return Write(spos, tw.c_str(), (_u32)tw.size(), has_error);
}
_u32 File::Write(const char* buffer, _u32 bsize, bool *has_error)
{
DWORD written;
if (WriteFile(hfile, buffer, bsize, &written, NULL) == FALSE)
{
if (has_error)
{
*has_error = true;
}
}
return written;
}
_u32 File::Write(int64 spos, const char* buffer, _u32 bsize, bool *has_error)
{
OVERLAPPED overlapped = {};
LARGE_INTEGER li;
li.QuadPart = spos;
overlapped.Offset = li.LowPart;
overlapped.OffsetHigh = li.HighPart;
DWORD written;
if (WriteFile(hfile, buffer, bsize, &written, &overlapped) == FALSE)
{
if (has_error)
{
*has_error = true;
}
}
return written;
}
bool File::Seek(_i64 spos)
{
LARGE_INTEGER tmp;
tmp.QuadPart=spos;
if( SetFilePointerEx(hfile, tmp, NULL, FILE_BEGIN) == FALSE )
{
int err=GetLastError();
return false;
}
else
return true;
}
_i64 File::Size(void)
{
LARGE_INTEGER fs;
GetFileSizeEx(hfile, &fs);
return fs.QuadPart;
}
_i64 File::RealSize()
{
return Size();
}
void File::Close()
{
if( hfile!=INVALID_HANDLE_VALUE )
{
BOOL b=CloseHandle( hfile );
hfile=INVALID_HANDLE_VALUE;
}
}
File::os_file_handle File::getOsHandle(bool release_handle)
{
HANDLE ret = hfile;
if (release_handle)
{
hfile = INVALID_HANDLE_VALUE;
}
return ret;
}
bool File::setSparse()
{
if (!is_sparse)
{
FILE_SET_SPARSE_BUFFER buf = { TRUE };
DWORD ret_bytes;
BOOL b = DeviceIoControl(hfile, FSCTL_SET_SPARSE, &buf,
static_cast<DWORD>(sizeof(buf)), NULL, 0, &ret_bytes, NULL);
if (!b)
{
return false;
}
is_sparse = true;
}
return true;
}
bool File::PunchHole( _i64 spos, _i64 size )
{
if (!setSparse())
{
return false;
}
FILE_ZERO_DATA_INFORMATION zdi;
zdi.FileOffset.QuadPart = spos;
zdi.BeyondFinalZero.QuadPart = spos + size;
DWORD ret_bytes;
BOOL b = DeviceIoControl(hfile, FSCTL_SET_ZERO_DATA, &zdi,
static_cast<DWORD>(sizeof(zdi)), NULL, 0, &ret_bytes, 0);
if(!b)
{
return false;
}
else
{
return true;
}
}
bool File::Sync()
{
return FlushFileBuffers(hfile)!=0;
}
bool File::Resize(int64 new_size, bool set_sparse)
{
int64 fsize = Size();
if (new_size > fsize
&& set_sparse)
{
if (!setSparse())
{
return false;
}
}
LARGE_INTEGER tmp;
tmp.QuadPart = 0;
LARGE_INTEGER curr_pos;
if (SetFilePointerEx(hfile, tmp, &curr_pos, FILE_CURRENT) == FALSE)
{
return false;
}
tmp.QuadPart = new_size;
if (SetFilePointerEx(hfile, tmp, NULL, FILE_BEGIN) == FALSE)
{
return false;
}
BOOL ret = SetEndOfFile(hfile);
SetFilePointerEx(hfile, curr_pos, NULL, FILE_BEGIN);
return ret == TRUE;
}
void File::resetSparseExtentIter()
{
res_extent_buffer.clear();
more_extents = true;
curr_extent = 0;
}
File::SSparseExtent File::nextSparseExtent()
{
while (!res_extent_buffer.empty()
&& curr_extent<res_extent_buffer.size())
{
if (res_extent_buffer[curr_extent].FileOffset.QuadPart != last_sparse_pos)
{
File::SSparseExtent ret(last_sparse_pos, res_extent_buffer[curr_extent].FileOffset.QuadPart - last_sparse_pos);
last_sparse_pos = res_extent_buffer[curr_extent].FileOffset.QuadPart + res_extent_buffer[curr_extent].Length.QuadPart;
++curr_extent;
return ret;
}
last_sparse_pos = res_extent_buffer[curr_extent].FileOffset.QuadPart + res_extent_buffer[curr_extent].Length.QuadPart;
++curr_extent;
}
if (!more_extents)
{
int64 fsize = Size();
if (last_sparse_pos!=-1 && last_sparse_pos != fsize)
{
File::SSparseExtent ret = File::SSparseExtent(last_sparse_pos, fsize - last_sparse_pos);
last_sparse_pos = fsize;
return ret;
}
return File::SSparseExtent();
}
int64 fsize = Size();
FILE_ALLOCATED_RANGE_BUFFER query_range;
query_range.FileOffset.QuadPart = last_sparse_pos;
query_range.Length.QuadPart = fsize- last_sparse_pos;
if (res_extent_buffer.empty())
{
res_extent_buffer.resize(10);
}
else
{
res_extent_buffer.resize(100);
}
DWORD output_bytes;
BOOL b = DeviceIoControl(hfile, FSCTL_QUERY_ALLOCATED_RANGES,
&query_range, sizeof(query_range), res_extent_buffer.data(), static_cast<DWORD>(res_extent_buffer.size()*sizeof(FILE_ALLOCATED_RANGE_BUFFER)),
&output_bytes, NULL);
more_extents = (!b && GetLastError() == ERROR_MORE_DATA);
if (more_extents || b)
{
res_extent_buffer.resize(output_bytes / sizeof(FILE_ALLOCATED_RANGE_BUFFER));
curr_extent = 0;
}
else
{
res_extent_buffer.clear();
more_extents = false;
curr_extent = 0;
last_sparse_pos = -1;
}
return nextSparseExtent();
}
std::vector<File::SFileExtent> File::getFileExtents(int64 starting_offset, int64 block_size, bool& more_data)
{
std::vector<File::SFileExtent> ret;
STARTING_VCN_INPUT_BUFFER starting_vcn;
starting_vcn.StartingVcn.QuadPart = starting_offset / block_size;
std::vector<char> buf;
buf.resize(4096);
DWORD retBytes;
BOOL b = DeviceIoControl(hfile, FSCTL_GET_RETRIEVAL_POINTERS,
&starting_vcn, sizeof(starting_vcn),
buf.data(), buf.size(), &retBytes, NULL);
more_data = (!b && GetLastError() == ERROR_MORE_DATA);
if (more_data || b)
{
PRETRIEVAL_POINTERS_BUFFER pbuf = reinterpret_cast<PRETRIEVAL_POINTERS_BUFFER>(buf.data());
LARGE_INTEGER last_vcn = pbuf->StartingVcn;
for (DWORD i = 0; i < pbuf->ExtentCount; ++i)
{
if (pbuf->Extents[i].Lcn.QuadPart != -1)
{
int64 count = pbuf->Extents[i].NextVcn.QuadPart - last_vcn.QuadPart;
File::SFileExtent ext;
ext.offset = last_vcn.QuadPart * block_size;
ext.size = count * block_size;
ext.volume_offset = pbuf->Extents[i].Lcn.QuadPart * block_size;
ret.push_back(ext);
}
last_vcn = pbuf->Extents[i].NextVcn;
}
}
return ret;
}
#endif

54
btrfs/fuse/oslib/os.cpp Normal file
View File

@ -0,0 +1,54 @@
#include <Windows.h>
#include "os.h"
size_t os_get_num_cpus()
{
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return system_info.dwNumberOfProcessors;
}
wchar_t os_toupper(wchar_t ch)
{
return towupper(ch);
}
LONG os_interlocked_increment(long volatile* val)
{
return InterlockedIncrement(val);
}
long long os_interlocked_increment64(long long volatile* val)
{
return InterlockedIncrement64(val);
}
LONG os_interlocked_decrement(long volatile* val)
{
return InterlockedDecrement(val);
}
long os_interlocked_add(long volatile* val, long add)
{
return InterlockedAdd(val, add);
}
void os_sleep(unsigned int sleepms)
{
SleepEx(sleepms, TRUE);
}
long os_interlocked_compare_exchange(long volatile* dest, long change, long comp)
{
return InterlockedCompareExchange(dest, change, comp);
}
bool os_wait_on_address(volatile void* address, void* compare_address, size_t address_size, unsigned int waitms)
{
return WaitOnAddress(address, compare_address, address_size, waitms) ? true : false;
}
void os_wake_by_address_single(void* address)
{
WakeByAddressSingle(address);
}

21
btrfs/fuse/oslib/os.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
size_t os_get_num_cpus();
wchar_t os_toupper(wchar_t ch);
long os_interlocked_increment(long volatile* val);
long long os_interlocked_increment64(long long volatile* val);
long os_interlocked_decrement(long volatile* val);
long os_interlocked_add(long volatile* val, long add);
void os_sleep(unsigned int sleepms);
long os_interlocked_compare_exchange(long volatile* dest, long change, long comp);
bool os_wait_on_address(volatile void* address, void* compare_address, size_t address_size, unsigned int waitms);
void os_wake_by_address_single(void* address);

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="event.cpp" />
<ClCompile Include="file_common.cpp" />
<ClCompile Include="file_win.cpp" />
<ClCompile Include="os.cpp" />
<ClCompile Include="utf8.cpp" />
<ClCompile Include="vol.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="event.h" />
<ClInclude Include="file.h" />
<ClInclude Include="os.h" />
<ClInclude Include="utf8.h" />
<ClInclude Include="vol.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{EA09B289-492C-4F30-813B-9928994FB21B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>oslib</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Lib>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="os.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="vol.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="event.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="file_common.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="file_win.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="utf8.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="os.h">
<Filter>Quelldateien</Filter>
</ClInclude>
<ClInclude Include="vol.h">
<Filter>Quelldateien</Filter>
</ClInclude>
<ClInclude Include="event.h">
<Filter>Quelldateien</Filter>
</ClInclude>
<ClInclude Include="file.h">
<Filter>Quelldateien</Filter>
</ClInclude>
<ClInclude Include="utf8.h">
<Filter>Quelldateien</Filter>
</ClInclude>
</ItemGroup>
</Project>

51
btrfs/fuse/oslib/utf8.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "utf8.h"
#include "utf8/utf8.h"
std::wstring ConvertToWchar(const std::string& input)
{
if (input.empty())
{
return std::wstring();
}
std::wstring ret;
try
{
if (sizeof(wchar_t) == 2)
{
utf8::utf8to16(&input[0], &input[input.size() - 1] + 1, back_inserter(ret));
}
else if (sizeof(wchar_t) == 4)
{
utf8::utf8to32(&input[0], &input[input.size() - 1] + 1, back_inserter(ret));
}
}
catch (...) {}
return ret;
}
std::string ConvertFromWchar(const std::wstring& input)
{
if (input.empty())
{
return std::string();
}
std::string ret;
try
{
if (sizeof(wchar_t) == 2)
{
utf8::utf16to8(&input[0], &input[input.size() - 1] + 1, back_inserter(ret));
}
else if (sizeof(wchar_t) == 4)
{
utf8::utf32to8(&input[0], &input[input.size() - 1] + 1, back_inserter(ret));
}
}
catch (...) {}
return ret;
}

6
btrfs/fuse/oslib/utf8.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <string>
std::wstring ConvertToWchar(const std::string& input);
std::string ConvertFromWchar(const std::wstring& input);

View File

@ -0,0 +1,34 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "utf8/checked.h"
#include "utf8/unchecked.h"
#endif // header guard

View File

@ -0,0 +1,318 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
#include <stdexcept>
namespace utf8
{
// Exceptions that may be thrown from the library functions.
class invalid_code_point : public std::exception {
uint32_t cp;
public:
invalid_code_point(uint32_t cp) : cp(cp) {}
virtual const char* what() const throw() { return "Invalid code point"; }
uint32_t code_point() const {return cp;}
};
class invalid_utf8 : public std::exception {
uint8_t u8;
public:
invalid_utf8 (uint8_t u) : u8(u) {}
virtual const char* what() const throw() { return "Invalid UTF-8"; }
uint8_t utf8_octet() const {return u8;}
};
class invalid_utf16 : public std::exception {
uint16_t u16;
public:
invalid_utf16 (uint16_t u) : u16(u) {}
virtual const char* what() const throw() { return "Invalid UTF-16"; }
uint16_t utf16_word() const {return u16;}
};
class not_enough_room : public std::exception {
public:
virtual const char* what() const throw() { return "Not enough space"; }
};
/// The library API - functions intended to be called by the users
template <typename octet_iterator, typename output_iterator>
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
{
while (start != end) {
octet_iterator sequence_start = start;
internal::utf_error err_code = internal::validate_next(start, end);
switch (err_code) {
case internal::OK :
for (octet_iterator it = sequence_start; it != start; ++it)
*out++ = *it;
break;
case internal::NOT_ENOUGH_ROOM:
throw not_enough_room();
case internal::INVALID_LEAD:
append (replacement, out);
++start;
break;
case internal::INCOMPLETE_SEQUENCE:
case internal::OVERLONG_SEQUENCE:
case internal::INVALID_CODE_POINT:
append (replacement, out);
++start;
// just one replacement mark for the sequence
while (internal::is_trail(*start) && start != end)
++start;
break;
}
}
return out;
}
template <typename octet_iterator, typename output_iterator>
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
{
static const uint32_t replacement_marker = internal::mask16(0xfffd);
return replace_invalid(start, end, out, replacement_marker);
}
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (!internal::is_code_point_valid(cp))
throw invalid_code_point(cp);
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>((cp >> 6) & 0x3f | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp <= internal::CODE_POINT_MAX) { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>((cp >> 12)& 0x3f | 0x80);
*(result++) = static_cast<uint8_t>((cp >> 6) & 0x3f | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else
throw invalid_code_point(cp);
return result;
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it, octet_iterator end)
{
uint32_t cp = 0;
internal::utf_error err_code = internal::validate_next(it, end, &cp);
switch (err_code) {
case internal::OK :
break;
case internal::NOT_ENOUGH_ROOM :
throw not_enough_room();
case internal::INVALID_LEAD :
case internal::INCOMPLETE_SEQUENCE :
case internal::OVERLONG_SEQUENCE :
throw invalid_utf8(*it);
case internal::INVALID_CODE_POINT :
throw invalid_code_point(cp);
}
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it, octet_iterator end)
{
return next(it, end);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it, octet_iterator start)
{
octet_iterator end = it;
while (internal::is_trail(*(--it)))
if (it < start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
octet_iterator temp = it;
return next(temp, end);
}
/// Deprecated in versions that include "prior"
template <typename octet_iterator>
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
{
octet_iterator end = it;
while (internal::is_trail(*(--it)))
if (it == pass_start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
octet_iterator temp = it;
return next(temp, end);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n, octet_iterator end)
{
for (distance_type i = 0; i < n; ++i)
next(it, end);
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
next(first, last);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = internal::mask16(*start++);
// Take care of surrogate pairs first
if (internal::is_surrogate(cp)) {
if (start != end) {
uint32_t trail_surrogate = internal::mask16(*start++);
if (trail_surrogate >= internal::TRAIL_SURROGATE_MIN && trail_surrogate <= internal::TRAIL_SURROGATE_MAX)
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
else
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
}
else
throw invalid_utf16(static_cast<uint16_t>(*start));
}
result = append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start != end) {
uint32_t cp = next(start, end);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start < end)
(*result++) = next(start, end);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
octet_iterator it;
octet_iterator range_start;
octet_iterator range_end;
public:
iterator () {};
explicit iterator (const octet_iterator& octet_it,
const octet_iterator& range_start,
const octet_iterator& range_end) :
it(octet_it), range_start(range_start), range_end(range_end)
{
if (it < range_start || it > range_end)
throw std::out_of_range("Invalid utf-8 iterator position");
}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return next(temp, range_end);
}
bool operator == (const iterator& rhs) const
{
if (range_start != rhs.range_start || range_end != rhs.range_end)
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
next(it, range_end);
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
next(it, range_end);
return temp;
}
iterator& operator -- ()
{
prior(it, range_start);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
prior(it, range_start);
return temp;
}
}; // class iterator
} // namespace utf8
#endif //header guard

View File

@ -0,0 +1,259 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include <iterator>
namespace utf8
{
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
// You may need to change them to match your system.
// These typedefs have the same names as ones from cstdint, or boost/cstdint
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Helper code - not intended to be directly called by the library users. May be changed at any time
namespace internal
{
// Unicode constants
// Leading (high) surrogates: 0xd800 - 0xdbff
// Trailing (low) surrogates: 0xdc00 - 0xdfff
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
// Maximum valid value for a Unicode code point
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
template<typename octet_type>
inline uint8_t mask8(octet_type oc)
{
return static_cast<uint8_t>(0xff & oc);
}
template<typename u16_type>
inline uint16_t mask16(u16_type oc)
{
return static_cast<uint16_t>(0xffff & oc);
}
template<typename octet_type>
inline bool is_trail(octet_type oc)
{
return ((mask8(oc) >> 6) == 0x2);
}
template <typename u16>
inline bool is_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u32>
inline bool is_code_point_valid(u32 cp)
{
return (cp <= CODE_POINT_MAX && !is_surrogate(cp) && cp != 0xfffe && cp != 0xffff);
}
template <typename octet_iterator>
inline typename std::iterator_traits<octet_iterator>::difference_type
sequence_length(octet_iterator lead_it)
{
uint8_t lead = mask8(*lead_it);
if (lead < 0x80)
return 1;
else if ((lead >> 5) == 0x6)
return 2;
else if ((lead >> 4) == 0xe)
return 3;
else if ((lead >> 3) == 0x1e)
return 4;
else
return 0;
}
enum utf_error {OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
template <typename octet_iterator>
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t* code_point)
{
uint32_t cp = mask8(*it);
// Check the lead octet
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
octet_difference_type length = sequence_length(it);
// "Shortcut" for ASCII characters
if (length == 1) {
if (end - it > 0) {
if (code_point)
*code_point = cp;
++it;
return OK;
}
else
return NOT_ENOUGH_ROOM;
}
// Do we have enough memory?
if (std::distance(it, end) < length)
return NOT_ENOUGH_ROOM;
// Check trail octets and calculate the code point
switch (length) {
case 0:
return INVALID_LEAD;
break;
case 2:
if (is_trail(*(++it))) {
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
}
else {
--it;
return INCOMPLETE_SEQUENCE;
}
break;
case 3:
if (is_trail(*(++it))) {
cp = ((cp << 12) & 0xffff) + ((mask8(*it) << 6) & 0xfff);
if (is_trail(*(++it))) {
cp += (*it) & 0x3f;
}
else {
std::advance(it, -2);
return INCOMPLETE_SEQUENCE;
}
}
else {
--it;
return INCOMPLETE_SEQUENCE;
}
break;
case 4:
if (is_trail(*(++it))) {
cp = ((cp << 18) & 0x1fffff) + ((mask8(*it) << 12) & 0x3ffff);
if (is_trail(*(++it))) {
cp += (mask8(*it) << 6) & 0xfff;
if (is_trail(*(++it))) {
cp += (*it) & 0x3f;
}
else {
std::advance(it, -3);
return INCOMPLETE_SEQUENCE;
}
}
else {
std::advance(it, -2);
return INCOMPLETE_SEQUENCE;
}
}
else {
--it;
return INCOMPLETE_SEQUENCE;
}
break;
}
// Is the code point valid?
if (!is_code_point_valid(cp)) {
for (octet_difference_type i = 0; i < length - 1; ++i)
--it;
return INVALID_CODE_POINT;
}
if (code_point)
*code_point = cp;
if (cp < 0x80) {
if (length != 1) {
std::advance(it, (int)(-(length-1)));
return OVERLONG_SEQUENCE;
}
}
else if (cp < 0x800) {
if (length != 2) {
std::advance(it, (int)(-(length-1)));
return OVERLONG_SEQUENCE;
}
}
else if (cp < 0x10000) {
if (length != 3) {
std::advance(it, (int)(-(length-1)));
return OVERLONG_SEQUENCE;
}
}
++it;
return OK;
}
template <typename octet_iterator>
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
return validate_next(it, end, 0);
}
} // namespace internal
/// The library API - functions intended to be called by the users
// Byte order mark
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
template <typename octet_iterator>
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
{
octet_iterator result = start;
while (result != end) {
internal::utf_error err_code = internal::validate_next(result, end);
if (err_code != internal::OK)
return result;
}
return result;
}
template <typename octet_iterator>
inline bool is_valid(octet_iterator start, octet_iterator end)
{
return (find_invalid(start, end) == end);
}
template <typename octet_iterator>
inline bool is_bom (octet_iterator it)
{
return (
(internal::mask8(*it++)) == bom[0] &&
(internal::mask8(*it++)) == bom[1] &&
(internal::mask8(*it)) == bom[2]
);
}
} // namespace utf8
#endif // header guard

View File

@ -0,0 +1,228 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
namespace utf8
{
namespace unchecked
{
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>((cp >> 6) & 0x3f | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>((cp >> 12)& 0x3f | 0x80);
*(result++) = static_cast<uint8_t>((cp >> 6) & 0x3f | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it)
{
uint32_t cp = internal::mask8(*it);
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
switch (length) {
case 1:
break;
case 2:
it++;
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
break;
case 3:
++it;
cp = ((cp << 12) & 0xffff) + ((internal::mask8(*it) << 6) & 0xfff);
++it;
cp += (*it) & 0x3f;
break;
case 4:
++it;
cp = ((cp << 18) & 0x1fffff) + ((internal::mask8(*it) << 12) & 0x3ffff);
++it;
cp += (internal::mask8(*it) << 6) & 0xfff;
++it;
cp += (*it) & 0x3f;
break;
}
++it;
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it)
{
return next(it);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it)
{
while (internal::is_trail(*(--it))) ;
octet_iterator temp = it;
return next(temp);
}
// Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
template <typename octet_iterator>
inline uint32_t previous(octet_iterator& it)
{
return prior(it);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n)
{
for (distance_type i = 0; i < n; ++i)
next(it);
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
next(first);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = internal::mask16(*start++);
// Take care of surrogate pairs first
if (internal::is_surrogate(cp)) {
uint32_t trail_surrogate = internal::mask16(*start++);
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
}
result = append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start != end) {
uint32_t cp = next(start);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start < end)
(*result++) = next(start);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
octet_iterator it;
public:
iterator () {};
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return next(temp);
}
bool operator == (const iterator& rhs) const
{
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
std::advance(it, internal::sequence_length(it));
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
std::advance(it, internal::sequence_length(it));
return temp;
}
iterator& operator -- ()
{
prior(it);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
prior(it);
return temp;
}
}; // class iterator
} // namespace utf8::unchecked
} // namespace utf8
#endif // header guard

134
btrfs/fuse/oslib/vol.cpp Normal file
View File

@ -0,0 +1,134 @@
#include "vol.h"
#include "vol.h"
#include <Windows.h>
#include <thread>
struct vol::vol_handle
{
HANDLE hvol;
};
namespace
{
struct overlapped_wrapper
{
OVERLAPPED ovl;
vol::completion_args completion;
};
void VolCompletion(
DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped
)
{
overlapped_wrapper* ovl = static_cast<overlapped_wrapper*>(lpOverlapped->hEvent);
ovl->completion.CompletionRoutine(ovl->completion.DeviceObject,
ovl->completion.Irp, ovl->completion.Context, dwErrorCode, dwNumberOfBytesTransfered);
delete ovl;
}
}
static void completion_port_thread(HANDLE completion_port)
{
while (true)
{
DWORD bytes_transferred;
ULONG_PTR key;
LPOVERLAPPED ovl;
BOOL b = GetQueuedCompletionStatus(completion_port,
&bytes_transferred, &key, &ovl, INFINITE);
if (b && ovl!=nullptr)
{
HANDLE hvol = reinterpret_cast<HANDLE>(key);
DWORD dwErrorCode = 0;
if (!GetOverlappedResult(hvol, ovl, &bytes_transferred, FALSE))
{
dwErrorCode = GetLastError();
}
overlapped_wrapper* ovl_w = reinterpret_cast<overlapped_wrapper*>(ovl);
ovl_w->completion.CompletionRoutine(ovl_w->completion.DeviceObject,
ovl_w->completion.Irp, ovl_w->completion.Context, dwErrorCode, bytes_transferred);
delete ovl_w;
}
}
}
vol::vol(const std::string& path)
: path(path),
hvol(std::make_unique<vol_handle>())
{
hvol->hvol =
CreateFileA(path.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED,
NULL);
completion_port = CreateIoCompletionPort(hvol->hvol,
NULL, reinterpret_cast<ULONG_PTR>(hvol->hvol), 0);
std::thread compl_thread([&]() {
completion_port_thread(completion_port);
});
compl_thread.detach();
Sleep(1000);
}
vol::~vol()
{
if (hvol->hvol != INVALID_HANDLE_VALUE)
{
CloseHandle(hvol->hvol);
}
}
bool vol::read(unsigned long long offset, char* buf, size_t buf_size, completion_args completion)
{
overlapped_wrapper* ovl = new overlapped_wrapper;
LARGE_INTEGER loff;
loff.QuadPart = offset;
ovl->ovl = {};
ovl->ovl.Offset = loff.LowPart;
ovl->ovl.OffsetHigh = loff.HighPart;
ovl->completion = completion;
BOOL b = ReadFile(hvol->hvol, buf, buf_size,
NULL, &ovl->ovl);
if (!b)
return false;
else
return true;
}
bool vol::write(unsigned long long offset, char* buf, size_t buf_size, completion_args completion)
{
overlapped_wrapper* ovl = new overlapped_wrapper;
LARGE_INTEGER loff;
loff.QuadPart = offset;
ovl->ovl = {};
ovl->ovl.Offset = loff.LowPart;
ovl->ovl.OffsetHigh = loff.HighPart;
ovl->completion = completion;
BOOL b = WriteFile(hvol->hvol, buf, buf_size,
NULL, &ovl->ovl);
if (!b)
return false;
else
return true;
}
bool vol::flush()
{
return FlushFileBuffers(hvol->hvol) == TRUE;
}

41
btrfs/fuse/oslib/vol.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include <memory>
#include <string>
struct _IRP;
typedef struct _IRP* PIRP;
struct _DEVICE_OBJECT;
typedef struct _DEVICE_OBJECT* PDEVICE_OBJECT;
typedef void* PVOID;
typedef long NTSTATUS;
typedef NTSTATUS(__stdcall VolIoCompletionRoutine)(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context, unsigned long errorCode, unsigned long bytesTransferred);
typedef VolIoCompletionRoutine VOL_IO_COMPLETION_ROUTINE;
typedef VolIoCompletionRoutine* PVOL_IO_COMPLETION_ROUTINE;
typedef void* HANDLE;
class vol
{
public:
vol(const std::string& path);
~vol();
struct completion_args
{
PVOL_IO_COMPLETION_ROUTINE CompletionRoutine;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PVOID Context;
};
bool read(unsigned long long offset, char* buf, size_t buf_size, completion_args completion);
bool write(unsigned long long offset, char* buf, size_t buf_size, completion_args completion);
bool flush();
private:
std::string path;
struct vol_handle;
std::unique_ptr<vol_handle> hvol;
HANDLE completion_port;
};

3919
external/btrfs/src/balance.c vendored Normal file

File diff suppressed because it is too large Load Diff

194
external/btrfs/src/blake2-impl.h vendored Normal file
View File

@ -0,0 +1,194 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#pragma once
#include <stdint.h>
#include <string.h>
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
#if defined(_MSC_VER)
#define BLAKE2_INLINE __inline
#elif defined(__GNUC__)
#define BLAKE2_INLINE __inline__
#else
#define BLAKE2_INLINE
#endif
#else
#define BLAKE2_INLINE inline
#endif
static BLAKE2_INLINE uint32_t load32( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8) |
(( uint32_t )( p[2] ) << 16) |
(( uint32_t )( p[3] ) << 24) ;
#endif
}
static BLAKE2_INLINE uint64_t load64( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) |
(( uint64_t )( p[6] ) << 48) |
(( uint64_t )( p[7] ) << 56) ;
#endif
}
static BLAKE2_INLINE uint16_t load16( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint16_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8));
#endif
}
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
#endif
}
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
#endif
}
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
p[6] = (uint8_t)(w >> 48);
p[7] = (uint8_t)(w >> 56);
#endif
}
static BLAKE2_INLINE uint64_t load48( const void *src )
{
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) ;
}
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
{
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
}
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 32 - c ) );
}
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 64 - c ) );
}
#if defined(_MSC_VER)
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
#define BLAKE2_PACKED(x) x __attribute__((packed))
#endif
enum blake2b_constant
{
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
};
typedef struct blake2b_state__
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2b_state;
BLAKE2_PACKED(struct blake2b_param__
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint32_t xof_length; /* 16 */
uint8_t node_depth; /* 17 */
uint8_t inner_length; /* 18 */
uint8_t reserved[14]; /* 32 */
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
});
typedef struct blake2b_param__ blake2b_param;

245
external/btrfs/src/blake2b-ref.c vendored Normal file
View File

@ -0,0 +1,245 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2-impl.h"
static const uint64_t blake2b_IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t blake2b_sigma[12][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
};
static int blake2b_update(blake2b_state* S, const void* in, size_t inlen);
static void blake2b_set_lastnode( blake2b_state *S )
{
S->f[1] = (uint64_t)-1;
}
/* Some helper functions, not necessarily useful */
static int blake2b_is_lastblock( const blake2b_state *S )
{
return S->f[0] != 0;
}
static void blake2b_set_lastblock( blake2b_state *S )
{
if( S->last_node ) blake2b_set_lastnode( S );
S->f[0] = (uint64_t)-1;
}
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
}
static void blake2b_init0( blake2b_state *S )
{
size_t i;
memset( S, 0, sizeof( blake2b_state ) );
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
}
/* init xors IV with input parameter block */
static void blake2b_init_param( blake2b_state *S, const blake2b_param *P )
{
const uint8_t *p = ( const uint8_t * )( P );
size_t i;
blake2b_init0( S );
/* IV XOR ParamBlock */
for( i = 0; i < 8; ++i )
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
S->outlen = P->digest_length;
}
static void blake2b_init( blake2b_state *S, size_t outlen )
{
blake2b_param P[1];
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
blake2b_init_param( S, P );
}
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
{
uint64_t m[16];
uint64_t v[16];
size_t i;
for( i = 0; i < 16; ++i ) {
m[i] = load64( block + i * sizeof( m[i] ) );
}
for( i = 0; i < 8; ++i ) {
v[i] = S->h[i];
}
v[ 8] = blake2b_IV[0];
v[ 9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5] ^ S->t[1];
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7] ^ S->f[1];
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
ROUND( 3 );
ROUND( 4 );
ROUND( 5 );
ROUND( 6 );
ROUND( 7 );
ROUND( 8 );
ROUND( 9 );
ROUND( 10 );
ROUND( 11 );
for( i = 0; i < 8; ++i ) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
}
#undef G
#undef ROUND
static int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
if( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = BLAKE2B_BLOCKBYTES - left;
if( inlen > fill )
{
S->buflen = 0;
memcpy( S->buf + left, in, fill ); /* Fill buffer */
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
blake2b_compress( S, S->buf ); /* Compress */
in += fill; inlen -= fill;
while(inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress( S, in );
in += BLAKE2B_BLOCKBYTES;
inlen -= BLAKE2B_BLOCKBYTES;
}
}
memcpy( S->buf + S->buflen, in, inlen );
S->buflen += inlen;
}
return 0;
}
static int blake2b_final( blake2b_state *S, void *out, size_t outlen )
{
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
size_t i;
if( out == NULL || outlen < S->outlen )
return -1;
if( blake2b_is_lastblock( S ) )
return -1;
blake2b_increment_counter( S, S->buflen );
blake2b_set_lastblock( S );
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
blake2b_compress( S, S->buf );
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
memcpy( out, buffer, S->outlen );
return 0;
}
/* inlen, at least, should be uint64_t. Others can be size_t. */
void blake2b( void *out, size_t outlen, const void *in, size_t inlen )
{
blake2b_state S[1];
blake2b_init( S, outlen );
blake2b_update( S, ( const uint8_t * )in, inlen );
blake2b_final( S, out, outlen );
}

598
external/btrfs/src/boot.c vendored Normal file
View File

@ -0,0 +1,598 @@
/* Copyright (c) Mark Harmstone 2019
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
#ifdef _MSC_VER
#include <ntstrsafe.h>
#endif
extern ERESOURCE pdo_list_lock;
extern LIST_ENTRY pdo_list;
extern ERESOURCE boot_lock;
extern PDRIVER_OBJECT drvobj;
BTRFS_UUID boot_uuid; // initialized to 0
uint64_t boot_subvol = 0;
#ifndef _MSC_VER
NTSTATUS RtlUnicodeStringPrintf(PUNICODE_STRING DestinationString, const WCHAR* pszFormat, ...); // not in mingw
#endif
// Not in any headers? Windbg knows about it though.
#define DOE_START_PENDING 0x10
// Just as much as we need - the version in mingw is truncated still further
typedef struct {
CSHORT Type;
USHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG PowerFlags;
void* Dope;
ULONG ExtensionFlags;
} DEVOBJ_EXTENSION2;
typedef enum {
system_root_unknown,
system_root_partition,
system_root_btrfs
} system_root_type;
typedef struct {
uint32_t disk_num;
uint32_t partition_num;
BTRFS_UUID uuid;
system_root_type type;
} system_root;
static void get_system_root(system_root* sr) {
NTSTATUS Status;
HANDLE h;
UNICODE_STRING us, target;
OBJECT_ATTRIBUTES objatt;
ULONG retlen = 0;
bool second_time = false;
static const WCHAR system_root[] = L"\\SystemRoot";
static const WCHAR boot_device[] = L"\\Device\\BootDevice";
static const WCHAR arc_prefix[] = L"\\ArcName\\multi(0)disk(0)rdisk(";
static const WCHAR arc_middle[] = L")partition(";
static const WCHAR arc_btrfs_prefix[] = L"\\ArcName\\btrfs(";
us.Buffer = (WCHAR*)system_root;
us.Length = us.MaximumLength = sizeof(system_root) - sizeof(WCHAR);
InitializeObjectAttributes(&objatt, &us, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
while (true) {
Status = ZwOpenSymbolicLinkObject(&h, GENERIC_READ, &objatt);
if (!NT_SUCCESS(Status)) {
ERR("ZwOpenSymbolicLinkObject returned %08lx\n", Status);
return;
}
target.Length = target.MaximumLength = 0;
Status = ZwQuerySymbolicLinkObject(h, &target, &retlen);
if (Status != STATUS_BUFFER_TOO_SMALL) {
ERR("ZwQuerySymbolicLinkObject returned %08lx\n", Status);
NtClose(h);
return;
}
if (retlen == 0) {
NtClose(h);
return;
}
target.Buffer = ExAllocatePoolWithTag(NonPagedPool, retlen, ALLOC_TAG);
if (!target.Buffer) {
ERR("out of memory\n");
NtClose(h);
return;
}
target.Length = target.MaximumLength = (USHORT)retlen;
Status = ZwQuerySymbolicLinkObject(h, &target, NULL);
if (!NT_SUCCESS(Status)) {
ERR("ZwQuerySymbolicLinkObject returned %08lx\n", Status);
NtClose(h);
ExFreePool(target.Buffer);
return;
}
NtClose(h);
if (second_time) {
TRACE("boot device is %.*S\n", (int)(target.Length / sizeof(WCHAR)), target.Buffer);
} else {
TRACE("system root is %.*S\n", (int)(target.Length / sizeof(WCHAR)), target.Buffer);
}
if (!second_time && target.Length >= sizeof(boot_device) - sizeof(WCHAR) &&
RtlCompareMemory(target.Buffer, boot_device, sizeof(boot_device) - sizeof(WCHAR)) == sizeof(boot_device) - sizeof(WCHAR)) {
ExFreePool(target.Buffer);
us.Buffer = (WCHAR*)boot_device;
us.Length = us.MaximumLength = sizeof(boot_device) - sizeof(WCHAR);
second_time = true;
} else
break;
}
sr->type = system_root_unknown;
if (target.Length >= sizeof(arc_prefix) - sizeof(WCHAR) &&
RtlCompareMemory(target.Buffer, arc_prefix, sizeof(arc_prefix) - sizeof(WCHAR)) == sizeof(arc_prefix) - sizeof(WCHAR)) {
WCHAR* s = &target.Buffer[(sizeof(arc_prefix) / sizeof(WCHAR)) - 1];
ULONG left = ((target.Length - sizeof(arc_prefix)) / sizeof(WCHAR)) + 1;
if (left == 0 || s[0] < '0' || s[0] > '9') {
ExFreePool(target.Buffer);
return;
}
sr->disk_num = 0;
while (left > 0 && s[0] >= '0' && s[0] <= '9') {
sr->disk_num *= 10;
sr->disk_num += s[0] - '0';
s++;
left--;
}
if (left <= (sizeof(arc_middle) / sizeof(WCHAR)) - 1 ||
RtlCompareMemory(s, arc_middle, sizeof(arc_middle) - sizeof(WCHAR)) != sizeof(arc_middle) - sizeof(WCHAR)) {
ExFreePool(target.Buffer);
return;
}
s = &s[(sizeof(arc_middle) / sizeof(WCHAR)) - 1];
left -= (sizeof(arc_middle) / sizeof(WCHAR)) - 1;
if (left == 0 || s[0] < '0' || s[0] > '9') {
ExFreePool(target.Buffer);
return;
}
sr->partition_num = 0;
while (left > 0 && s[0] >= '0' && s[0] <= '9') {
sr->partition_num *= 10;
sr->partition_num += s[0] - '0';
s++;
left--;
}
sr->type = system_root_partition;
} else if (target.Length >= sizeof(arc_btrfs_prefix) - sizeof(WCHAR) &&
RtlCompareMemory(target.Buffer, arc_btrfs_prefix, sizeof(arc_btrfs_prefix) - sizeof(WCHAR)) == sizeof(arc_btrfs_prefix) - sizeof(WCHAR)) {
WCHAR* s = &target.Buffer[(sizeof(arc_btrfs_prefix) / sizeof(WCHAR)) - 1];
for (unsigned int i = 0; i < 16; i++) {
if (*s >= '0' && *s <= '9')
sr->uuid.uuid[i] = (*s - '0') << 4;
else if (*s >= 'a' && *s <= 'f')
sr->uuid.uuid[i] = (*s - 'a' + 0xa) << 4;
else if (*s >= 'A' && *s <= 'F')
sr->uuid.uuid[i] = (*s - 'A' + 0xa) << 4;
else {
ExFreePool(target.Buffer);
return;
}
s++;
if (*s >= '0' && *s <= '9')
sr->uuid.uuid[i] |= *s - '0';
else if (*s >= 'a' && *s <= 'f')
sr->uuid.uuid[i] |= *s - 'a' + 0xa;
else if (*s >= 'A' && *s <= 'F')
sr->uuid.uuid[i] |= *s - 'A' + 0xa;
else {
ExFreePool(target.Buffer);
return;
}
s++;
if (i == 3 || i == 5 || i == 7 || i == 9) {
if (*s != '-') {
ExFreePool(target.Buffer);
return;
}
s++;
}
}
if (*s != ')') {
ExFreePool(target.Buffer);
return;
}
sr->type = system_root_btrfs;
}
ExFreePool(target.Buffer);
}
static void change_symlink(uint32_t disk_num, uint32_t partition_num, BTRFS_UUID* uuid) {
NTSTATUS Status;
UNICODE_STRING us, us2;
WCHAR symlink[60], target[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) + 36], *w;
us.Buffer = symlink;
us.Length = 0;
us.MaximumLength = sizeof(symlink);
Status = RtlUnicodeStringPrintf(&us, L"\\Device\\Harddisk%u\\Partition%u", disk_num, partition_num);
if (!NT_SUCCESS(Status)) {
ERR("RtlUnicodeStringPrintf returned %08lx\n", Status);
return;
}
Status = IoDeleteSymbolicLink(&us);
if (!NT_SUCCESS(Status))
ERR("IoDeleteSymbolicLink returned %08lx\n", Status);
RtlCopyMemory(target, BTRFS_VOLUME_PREFIX, sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR));
w = &target[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1];
for (unsigned int i = 0; i < 16; i++) {
*w = hex_digit(uuid->uuid[i] >> 4); w++;
*w = hex_digit(uuid->uuid[i] & 0xf); w++;
if (i == 3 || i == 5 || i == 7 || i == 9) {
*w = L'-';
w++;
}
}
*w = L'}';
us2.Buffer = target;
us2.Length = us2.MaximumLength = sizeof(target);
Status = IoCreateSymbolicLink(&us, &us2);
if (!NT_SUCCESS(Status))
ERR("IoCreateSymbolicLink returned %08lx\n", Status);
}
static void mountmgr_notification(BTRFS_UUID* uuid) {
UNICODE_STRING mmdevpath;
NTSTATUS Status;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT mountmgr;
ULONG mmtnlen;
MOUNTMGR_TARGET_NAME* mmtn;
WCHAR* w;
RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME);
Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &FileObject, &mountmgr);
if (!NT_SUCCESS(Status)) {
ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
return;
}
mmtnlen = offsetof(MOUNTMGR_TARGET_NAME, DeviceName[0]) + sizeof(BTRFS_VOLUME_PREFIX) + (36 * sizeof(WCHAR));
mmtn = ExAllocatePoolWithTag(NonPagedPool, mmtnlen, ALLOC_TAG);
if (!mmtn) {
ERR("out of memory\n");
return;
}
mmtn->DeviceNameLength = sizeof(BTRFS_VOLUME_PREFIX) + (36 * sizeof(WCHAR));
RtlCopyMemory(mmtn->DeviceName, BTRFS_VOLUME_PREFIX, sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR));
w = &mmtn->DeviceName[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1];
for (unsigned int i = 0; i < 16; i++) {
*w = hex_digit(uuid->uuid[i] >> 4); w++;
*w = hex_digit(uuid->uuid[i] & 0xf); w++;
if (i == 3 || i == 5 || i == 7 || i == 9) {
*w = L'-';
w++;
}
}
*w = L'}';
Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, mmtn, mmtnlen, NULL, 0, false, NULL);
if (!NT_SUCCESS(Status)) {
ERR("IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION returned %08lx\n", Status);
ExFreePool(mmtn);
return;
}
ExFreePool(mmtn);
}
static void check_boot_options() {
NTSTATUS Status;
WCHAR* s;
static const WCHAR pathw[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control";
static const WCHAR namew[] = L"SystemStartOptions";
static const WCHAR subvol[] = L"SUBVOL=";
try {
HANDLE control;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING path;
ULONG kvfilen = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + (255 * sizeof(WCHAR));
KEY_VALUE_FULL_INFORMATION* kvfi;
UNICODE_STRING name;
WCHAR* options;
path.Buffer = (WCHAR*)pathw;
path.Length = path.MaximumLength = sizeof(pathw) - sizeof(WCHAR);
InitializeObjectAttributes(&oa, &path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenKey(&control, KEY_QUERY_VALUE, &oa);
if (!NT_SUCCESS(Status)) {
ERR("ZwOpenKey returned %08lx\n", Status);
return;
}
// FIXME - don't fail if value too long (can we query for the length?)
kvfi = ExAllocatePoolWithTag(PagedPool, kvfilen, ALLOC_TAG);
if (!kvfi) {
ERR("out of memory\n");
NtClose(control);
return;
}
name.Buffer = (WCHAR*)namew;
name.Length = name.MaximumLength = sizeof(namew) - sizeof(WCHAR);
Status = ZwQueryValueKey(control, &name, KeyValueFullInformation, kvfi,
kvfilen, &kvfilen);
if (!NT_SUCCESS(Status)) {
ERR("ZwQueryValueKey returned %08lx\n", Status);
NtClose(control);
return;
}
NtClose(control);
options = (WCHAR*)((uint8_t*)kvfi + kvfi->DataOffset);
options[kvfi->DataLength / sizeof(WCHAR)] = 0; // FIXME - make sure buffer long enough to allow this
s = wcsstr(options, subvol);
if (!s)
return;
s += (sizeof(subvol) / sizeof(WCHAR)) - 1;
boot_subvol = 0;
while (true) {
if (*s >= '0' && *s <= '9') {
boot_subvol <<= 4;
boot_subvol |= *s - '0';
} else if (*s >= 'a' && *s <= 'f') {
boot_subvol <<= 4;
boot_subvol |= *s - 'a' + 0xa;
} else if (*s >= 'A' && *s <= 'F') {
boot_subvol <<= 4;
boot_subvol |= *s - 'A' + 0xa;
} else
break;
s++;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
return;
}
if (boot_subvol != 0) {
TRACE("passed subvol %I64x in boot options\n", boot_subvol);
}
}
void boot_add_device(DEVICE_OBJECT* pdo) {
pdo_device_extension* pdode = pdo->DeviceExtension;
AddDevice(drvobj, pdo);
// To stop Windows sneakily setting DOE_START_PENDING
pdode->dont_report = true;
if (pdo->DeviceObjectExtension) {
((DEVOBJ_EXTENSION2*)pdo->DeviceObjectExtension)->ExtensionFlags &= ~DOE_START_PENDING;
if (pdode && pdode->vde && pdode->vde->device)
((DEVOBJ_EXTENSION2*)pdode->vde->device->DeviceObjectExtension)->ExtensionFlags &= ~DOE_START_PENDING;
}
mountmgr_notification(&pdode->uuid);
}
/* If booting from Btrfs, Windows will pass the device object for the raw partition to
* mount_vol - which is no good to us, as we only use the \Device\Btrfs{} devices we
* create so that RAID works correctly.
* At the time check_system_root gets called, \SystemRoot is a symlink to the ARC device,
* e.g. \ArcName\multi(0)disk(0)rdisk(0)partition(1)\Windows. We can't change the symlink,
* as it gets clobbered by IopReassignSystemRoot shortly afterwards, and we can't touch
* the \ArcName symlinks as they haven't been created yet. Instead, we need to change the
* symlink \Device\HarddiskX\PartitionY, which is what the ArcName symlink will shortly
* point to.
*/
void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULONG Count) {
system_root sr;
LIST_ENTRY* le;
bool done = false;
PDEVICE_OBJECT pdo_to_add = NULL;
volume_child* boot_vc = NULL;
TRACE("(%p, %p, %lu)\n", DriverObject, Context, Count);
// wait for any PNP notifications in progress to finish
ExAcquireResourceExclusiveLite(&boot_lock, TRUE);
ExReleaseResourceLite(&boot_lock);
get_system_root(&sr);
if (sr.type == system_root_partition) {
TRACE("system boot partition is disk %u, partition %u\n", sr.disk_num, sr.partition_num);
ExAcquireResourceSharedLite(&pdo_list_lock, true);
le = pdo_list.Flink;
while (le != &pdo_list) {
LIST_ENTRY* le2;
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
ExAcquireResourceSharedLite(&pdode->child_lock, true);
le2 = pdode->children.Flink;
while (le2 != &pdode->children) {
volume_child* vc = CONTAINING_RECORD(le2, volume_child, list_entry);
if (vc->disk_num == sr.disk_num && vc->part_num == sr.partition_num) {
change_symlink(sr.disk_num, sr.partition_num, &pdode->uuid);
done = true;
vc->boot_volume = true;
boot_uuid = pdode->uuid;
if (!pdode->vde)
pdo_to_add = pdode->pdo;
boot_vc = vc;
break;
}
le2 = le2->Flink;
}
if (done) {
le2 = pdode->children.Flink;
while (le2 != &pdode->children) {
volume_child* vc = CONTAINING_RECORD(le2, volume_child, list_entry);
/* On Windows 7 we need to clear the DO_SYSTEM_BOOT_PARTITION flag of
* all of our underlying partition objects - otherwise IopMountVolume
* will bugcheck with UNMOUNTABLE_BOOT_VOLUME when it tries and fails
* to mount one. */
if (vc->devobj) {
PDEVICE_OBJECT dev = vc->devobj;
ObReferenceObject(dev);
while (dev) {
PDEVICE_OBJECT dev2 = IoGetLowerDeviceObject(dev);
dev->Flags &= ~DO_SYSTEM_BOOT_PARTITION;
ObDereferenceObject(dev);
dev = dev2;
}
}
le2 = le2->Flink;
}
ExReleaseResourceLite(&pdode->child_lock);
break;
}
ExReleaseResourceLite(&pdode->child_lock);
le = le->Flink;
}
ExReleaseResourceLite(&pdo_list_lock);
} else if (sr.type == system_root_btrfs) {
boot_uuid = sr.uuid;
ExAcquireResourceSharedLite(&pdo_list_lock, true);
le = pdo_list.Flink;
while (le != &pdo_list) {
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
if (RtlCompareMemory(&pdode->uuid, &sr.uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
if (!pdode->vde)
pdo_to_add = pdode->pdo;
break;
}
le = le->Flink;
}
ExReleaseResourceLite(&pdo_list_lock);
}
if (boot_vc) {
NTSTATUS Status;
UNICODE_STRING name;
/* On Windows 8, mountmgr!MountMgrFindBootVolume returns the first volume in its database
* with the DO_SYSTEM_BOOT_PARTITION flag set. We've cleared the bit on the underlying devices,
* but as it caches it we need to disable and re-enable the volume so mountmgr receives a PNP
* notification to refresh its list. */
static const WCHAR prefix[] = L"\\??";
name.Length = name.MaximumLength = boot_vc->pnp_name.Length + sizeof(prefix) - sizeof(WCHAR);
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
if (!name.Buffer)
ERR("out of memory\n");
else {
RtlCopyMemory(name.Buffer, prefix, sizeof(prefix) - sizeof(WCHAR));
RtlCopyMemory(&name.Buffer[(sizeof(prefix) / sizeof(WCHAR)) - 1], boot_vc->pnp_name.Buffer, boot_vc->pnp_name.Length);
Status = IoSetDeviceInterfaceState(&name, false);
if (!NT_SUCCESS(Status))
ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
Status = IoSetDeviceInterfaceState(&name, true);
if (!NT_SUCCESS(Status))
ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
ExFreePool(name.Buffer);
}
}
if (sr.type == system_root_btrfs || boot_vc)
check_boot_options();
// If our FS depends on volumes that aren't there when we do our IoRegisterPlugPlayNotification calls
// in DriverEntry, bus_query_device_relations won't get called until it's too late. We need to do our
// own call to AddDevice here as a result. We need to clear the DOE_START_PENDING bits, or NtOpenFile
// will return STATUS_NO_SUCH_DEVICE.
if (pdo_to_add)
boot_add_device(pdo_to_add);
}

6385
external/btrfs/src/btrfs.c vendored Normal file

File diff suppressed because it is too large Load Diff

599
external/btrfs/src/btrfs.h vendored Normal file
View File

@ -0,0 +1,599 @@
/* btrfs.h
* Generic btrfs header file. Thanks to whoever it was who wrote
* https://btrfs.wiki.kernel.org/index.php/On-disk_Format - you saved me a lot of time!
*
* I release this file, and this file only, into the public domain - do whatever
* you want with it. You don't have to, but I'd appreciate if you let me know if you
* use it anything cool - mark@harmstone.com. */
#pragma once
#include <stdint.h>
static const uint64_t superblock_addrs[] = { 0x10000, 0x4000000, 0x4000000000, 0x4000000000000, 0 };
#define BTRFS_MAGIC 0x4d5f53665248425f
#define MAX_LABEL_SIZE 0x100
#define SUBVOL_ROOT_INODE 0x100
#define TYPE_INODE_ITEM 0x01
#define TYPE_INODE_REF 0x0C
#define TYPE_INODE_EXTREF 0x0D
#define TYPE_XATTR_ITEM 0x18
#define TYPE_ORPHAN_INODE 0x30
#define TYPE_DIR_ITEM 0x54
#define TYPE_DIR_INDEX 0x60
#define TYPE_EXTENT_DATA 0x6C
#define TYPE_EXTENT_CSUM 0x80
#define TYPE_ROOT_ITEM 0x84
#define TYPE_ROOT_BACKREF 0x90
#define TYPE_ROOT_REF 0x9C
#define TYPE_EXTENT_ITEM 0xA8
#define TYPE_METADATA_ITEM 0xA9
#define TYPE_TREE_BLOCK_REF 0xB0
#define TYPE_EXTENT_DATA_REF 0xB2
#define TYPE_EXTENT_REF_V0 0xB4
#define TYPE_SHARED_BLOCK_REF 0xB6
#define TYPE_SHARED_DATA_REF 0xB8
#define TYPE_BLOCK_GROUP_ITEM 0xC0
#define TYPE_FREE_SPACE_INFO 0xC6
#define TYPE_FREE_SPACE_EXTENT 0xC7
#define TYPE_FREE_SPACE_BITMAP 0xC8
#define TYPE_DEV_EXTENT 0xCC
#define TYPE_DEV_ITEM 0xD8
#define TYPE_CHUNK_ITEM 0xE4
#define TYPE_TEMP_ITEM 0xF8
#define TYPE_DEV_STATS 0xF9
#define TYPE_SUBVOL_UUID 0xFB
#define TYPE_SUBVOL_REC_UUID 0xFC
#define BTRFS_ROOT_ROOT 1
#define BTRFS_ROOT_EXTENT 2
#define BTRFS_ROOT_CHUNK 3
#define BTRFS_ROOT_DEVTREE 4
#define BTRFS_ROOT_FSTREE 5
#define BTRFS_ROOT_TREEDIR 6
#define BTRFS_ROOT_CHECKSUM 7
#define BTRFS_ROOT_UUID 9
#define BTRFS_ROOT_FREE_SPACE 0xa
#define BTRFS_ROOT_DATA_RELOC 0xFFFFFFFFFFFFFFF7
#define BTRFS_COMPRESSION_NONE 0
#define BTRFS_COMPRESSION_ZLIB 1
#define BTRFS_COMPRESSION_LZO 2
#define BTRFS_COMPRESSION_ZSTD 3
#define BTRFS_ENCRYPTION_NONE 0
#define BTRFS_ENCODING_NONE 0
#define EXTENT_TYPE_INLINE 0
#define EXTENT_TYPE_REGULAR 1
#define EXTENT_TYPE_PREALLOC 2
#define BLOCK_FLAG_DATA 0x001
#define BLOCK_FLAG_SYSTEM 0x002
#define BLOCK_FLAG_METADATA 0x004
#define BLOCK_FLAG_RAID0 0x008
#define BLOCK_FLAG_RAID1 0x010
#define BLOCK_FLAG_DUPLICATE 0x020
#define BLOCK_FLAG_RAID10 0x040
#define BLOCK_FLAG_RAID5 0x080
#define BLOCK_FLAG_RAID6 0x100
#define BLOCK_FLAG_RAID1C3 0x200
#define BLOCK_FLAG_RAID1C4 0x400
#define FREE_SPACE_CACHE_ID 0xFFFFFFFFFFFFFFF5
#define EXTENT_CSUM_ID 0xFFFFFFFFFFFFFFF6
#define BALANCE_ITEM_ID 0xFFFFFFFFFFFFFFFC
#define BTRFS_INODE_NODATASUM 0x001
#define BTRFS_INODE_NODATACOW 0x002
#define BTRFS_INODE_READONLY 0x004
#define BTRFS_INODE_NOCOMPRESS 0x008
#define BTRFS_INODE_PREALLOC 0x010
#define BTRFS_INODE_SYNC 0x020
#define BTRFS_INODE_IMMUTABLE 0x040
#define BTRFS_INODE_APPEND 0x080
#define BTRFS_INODE_NODUMP 0x100
#define BTRFS_INODE_NOATIME 0x200
#define BTRFS_INODE_DIRSYNC 0x400
#define BTRFS_INODE_COMPRESS 0x800
#define BTRFS_SUBVOL_READONLY 0x1
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE 0x1
#define BTRFS_COMPAT_RO_FLAGS_FREE_SPACE_CACHE_VALID 0x2
#define BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF 0x0001
#define BTRFS_INCOMPAT_FLAGS_DEFAULT_SUBVOL 0x0002
#define BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS 0x0004
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_LZO 0x0008
#define BTRFS_INCOMPAT_FLAGS_COMPRESS_ZSTD 0x0010
#define BTRFS_INCOMPAT_FLAGS_BIG_METADATA 0x0020
#define BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF 0x0040
#define BTRFS_INCOMPAT_FLAGS_RAID56 0x0080
#define BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA 0x0100
#define BTRFS_INCOMPAT_FLAGS_NO_HOLES 0x0200
#define BTRFS_INCOMPAT_FLAGS_METADATA_UUID 0x0400
#define BTRFS_INCOMPAT_FLAGS_RAID1C34 0x0800
#define BTRFS_SUPERBLOCK_FLAGS_SEEDING 0x100000000
#define BTRFS_ORPHAN_INODE_OBJID 0xFFFFFFFFFFFFFFFB
#define CSUM_TYPE_CRC32C 0
#define CSUM_TYPE_XXHASH 1
#define CSUM_TYPE_SHA256 2
#define CSUM_TYPE_BLAKE2 3
#pragma pack(push, 1)
typedef struct {
uint8_t uuid[16];
} BTRFS_UUID;
typedef struct {
uint64_t obj_id;
uint8_t obj_type;
uint64_t offset;
} KEY;
#define HEADER_FLAG_WRITTEN 0x000000000000001
#define HEADER_FLAG_SHARED_BACKREF 0x000000000000002
#define HEADER_FLAG_MIXED_BACKREF 0x100000000000000
typedef struct {
uint8_t csum[32];
BTRFS_UUID fs_uuid;
uint64_t address;
uint64_t flags;
BTRFS_UUID chunk_tree_uuid;
uint64_t generation;
uint64_t tree_id;
uint32_t num_items;
uint8_t level;
} tree_header;
typedef struct {
KEY key;
uint32_t offset;
uint32_t size;
} leaf_node;
typedef struct {
KEY key;
uint64_t address;
uint64_t generation;
} internal_node;
typedef struct {
uint64_t dev_id;
uint64_t num_bytes;
uint64_t bytes_used;
uint32_t optimal_io_align;
uint32_t optimal_io_width;
uint32_t minimal_io_size;
uint64_t type;
uint64_t generation;
uint64_t start_offset;
uint32_t dev_group;
uint8_t seek_speed;
uint8_t bandwidth;
BTRFS_UUID device_uuid;
BTRFS_UUID fs_uuid;
} DEV_ITEM;
#define SYS_CHUNK_ARRAY_SIZE 0x800
#define BTRFS_NUM_BACKUP_ROOTS 4
typedef struct {
uint64_t root_tree_addr;
uint64_t root_tree_generation;
uint64_t chunk_tree_addr;
uint64_t chunk_tree_generation;
uint64_t extent_tree_addr;
uint64_t extent_tree_generation;
uint64_t fs_tree_addr;
uint64_t fs_tree_generation;
uint64_t dev_root_addr;
uint64_t dev_root_generation;
uint64_t csum_root_addr;
uint64_t csum_root_generation;
uint64_t total_bytes;
uint64_t bytes_used;
uint64_t num_devices;
uint64_t reserved[4];
uint8_t root_level;
uint8_t chunk_root_level;
uint8_t extent_root_level;
uint8_t fs_root_level;
uint8_t dev_root_level;
uint8_t csum_root_level;
uint8_t reserved2[10];
} superblock_backup;
typedef struct {
uint8_t checksum[32];
BTRFS_UUID uuid;
uint64_t sb_phys_addr;
uint64_t flags;
uint64_t magic;
uint64_t generation;
uint64_t root_tree_addr;
uint64_t chunk_tree_addr;
uint64_t log_tree_addr;
uint64_t log_root_transid;
uint64_t total_bytes;
uint64_t bytes_used;
uint64_t root_dir_objectid;
uint64_t num_devices;
uint32_t sector_size;
uint32_t node_size;
uint32_t leaf_size;
uint32_t stripe_size;
uint32_t n;
uint64_t chunk_root_generation;
uint64_t compat_flags;
uint64_t compat_ro_flags;
uint64_t incompat_flags;
uint16_t csum_type;
uint8_t root_level;
uint8_t chunk_root_level;
uint8_t log_root_level;
DEV_ITEM dev_item;
char label[MAX_LABEL_SIZE];
uint64_t cache_generation;
uint64_t uuid_tree_generation;
BTRFS_UUID metadata_uuid;
uint64_t reserved[28];
uint8_t sys_chunk_array[SYS_CHUNK_ARRAY_SIZE];
superblock_backup backup[BTRFS_NUM_BACKUP_ROOTS];
uint8_t reserved2[565];
} superblock;
#define BTRFS_TYPE_UNKNOWN 0
#define BTRFS_TYPE_FILE 1
#define BTRFS_TYPE_DIRECTORY 2
#define BTRFS_TYPE_CHARDEV 3
#define BTRFS_TYPE_BLOCKDEV 4
#define BTRFS_TYPE_FIFO 5
#define BTRFS_TYPE_SOCKET 6
#define BTRFS_TYPE_SYMLINK 7
#define BTRFS_TYPE_EA 8
typedef struct {
KEY key;
uint64_t transid;
uint16_t m;
uint16_t n;
uint8_t type;
char name[1];
} DIR_ITEM;
typedef struct {
uint64_t seconds;
uint32_t nanoseconds;
} BTRFS_TIME;
typedef struct {
uint64_t generation;
uint64_t transid;
uint64_t st_size;
uint64_t st_blocks;
uint64_t block_group;
uint32_t st_nlink;
uint32_t st_uid;
uint32_t st_gid;
uint32_t st_mode;
uint64_t st_rdev;
uint64_t flags;
uint64_t sequence;
uint8_t reserved[32];
BTRFS_TIME st_atime;
BTRFS_TIME st_ctime;
BTRFS_TIME st_mtime;
BTRFS_TIME otime;
} INODE_ITEM;
typedef struct {
INODE_ITEM inode;
uint64_t generation;
uint64_t objid;
uint64_t block_number;
uint64_t byte_limit;
uint64_t bytes_used;
uint64_t last_snapshot_generation;
uint64_t flags;
uint32_t num_references;
KEY drop_progress;
uint8_t drop_level;
uint8_t root_level;
uint64_t generation2;
BTRFS_UUID uuid;
BTRFS_UUID parent_uuid;
BTRFS_UUID received_uuid;
uint64_t ctransid;
uint64_t otransid;
uint64_t stransid;
uint64_t rtransid;
BTRFS_TIME ctime;
BTRFS_TIME otime;
BTRFS_TIME stime;
BTRFS_TIME rtime;
uint64_t reserved[8];
} ROOT_ITEM;
typedef struct {
uint64_t size;
uint64_t root_id;
uint64_t stripe_length;
uint64_t type;
uint32_t opt_io_alignment;
uint32_t opt_io_width;
uint32_t sector_size;
uint16_t num_stripes;
uint16_t sub_stripes;
} CHUNK_ITEM;
typedef struct {
uint64_t dev_id;
uint64_t offset;
BTRFS_UUID dev_uuid;
} CHUNK_ITEM_STRIPE;
typedef struct {
uint64_t generation;
uint64_t decoded_size;
uint8_t compression;
uint8_t encryption;
uint16_t encoding;
uint8_t type;
uint8_t data[1];
} EXTENT_DATA;
typedef struct {
uint64_t address;
uint64_t size;
uint64_t offset;
uint64_t num_bytes;
} EXTENT_DATA2;
typedef struct {
uint64_t index;
uint16_t n;
char name[1];
} INODE_REF;
typedef struct {
uint64_t dir;
uint64_t index;
uint16_t n;
char name[1];
} INODE_EXTREF;
#define EXTENT_ITEM_DATA 0x001
#define EXTENT_ITEM_TREE_BLOCK 0x002
#define EXTENT_ITEM_SHARED_BACKREFS 0x100
typedef struct {
uint64_t refcount;
uint64_t generation;
uint64_t flags;
} EXTENT_ITEM;
typedef struct {
KEY firstitem;
uint8_t level;
} EXTENT_ITEM2;
typedef struct {
uint32_t refcount;
} EXTENT_ITEM_V0;
typedef struct {
EXTENT_ITEM extent_item;
KEY firstitem;
uint8_t level;
} EXTENT_ITEM_TREE;
typedef struct {
uint64_t offset;
} TREE_BLOCK_REF;
typedef struct {
uint64_t root;
uint64_t objid;
uint64_t offset;
uint32_t count;
} EXTENT_DATA_REF;
typedef struct {
uint64_t used;
uint64_t chunk_tree;
uint64_t flags;
} BLOCK_GROUP_ITEM;
typedef struct {
uint64_t root;
uint64_t gen;
uint64_t objid;
uint32_t count;
} EXTENT_REF_V0;
typedef struct {
uint64_t offset;
} SHARED_BLOCK_REF;
typedef struct {
uint64_t offset;
uint32_t count;
} SHARED_DATA_REF;
#define FREE_SPACE_EXTENT 1
#define FREE_SPACE_BITMAP 2
typedef struct {
uint64_t offset;
uint64_t size;
uint8_t type;
} FREE_SPACE_ENTRY;
typedef struct {
KEY key;
uint64_t generation;
uint64_t num_entries;
uint64_t num_bitmaps;
} FREE_SPACE_ITEM;
typedef struct {
uint64_t dir;
uint64_t index;
uint16_t n;
char name[1];
} ROOT_REF;
typedef struct {
uint64_t chunktree;
uint64_t objid;
uint64_t address;
uint64_t length;
BTRFS_UUID chunktree_uuid;
} DEV_EXTENT;
#define BALANCE_FLAGS_DATA 0x1
#define BALANCE_FLAGS_SYSTEM 0x2
#define BALANCE_FLAGS_METADATA 0x4
#define BALANCE_ARGS_FLAGS_PROFILES 0x001
#define BALANCE_ARGS_FLAGS_USAGE 0x002
#define BALANCE_ARGS_FLAGS_DEVID 0x004
#define BALANCE_ARGS_FLAGS_DRANGE 0x008
#define BALANCE_ARGS_FLAGS_VRANGE 0x010
#define BALANCE_ARGS_FLAGS_LIMIT 0x020
#define BALANCE_ARGS_FLAGS_LIMIT_RANGE 0x040
#define BALANCE_ARGS_FLAGS_STRIPES_RANGE 0x080
#define BALANCE_ARGS_FLAGS_CONVERT 0x100
#define BALANCE_ARGS_FLAGS_SOFT 0x200
#define BALANCE_ARGS_FLAGS_USAGE_RANGE 0x400
typedef struct {
uint64_t profiles;
union {
uint64_t usage;
struct {
uint32_t usage_start;
uint32_t usage_end;
};
};
uint64_t devid;
uint64_t drange_start;
uint64_t drange_end;
uint64_t vrange_start;
uint64_t vrange_end;
uint64_t convert;
uint64_t flags;
union {
uint64_t limit;
struct {
uint32_t limit_start;
uint32_t limit_end;
};
};
uint32_t stripes_start;
uint32_t stripes_end;
uint8_t reserved[48];
} BALANCE_ARGS;
typedef struct {
uint64_t flags;
BALANCE_ARGS data;
BALANCE_ARGS metadata;
BALANCE_ARGS system;
uint8_t reserved[32];
} BALANCE_ITEM;
#define BTRFS_FREE_SPACE_USING_BITMAPS 1
typedef struct {
uint32_t count;
uint32_t flags;
} FREE_SPACE_INFO;
#define BTRFS_DEV_STAT_WRITE_ERRORS 0
#define BTRFS_DEV_STAT_READ_ERRORS 1
#define BTRFS_DEV_STAT_FLUSH_ERRORS 2
#define BTRFS_DEV_STAT_CORRUPTION_ERRORS 3
#define BTRFS_DEV_STAT_GENERATION_ERRORS 4
#define BTRFS_SEND_CMD_SUBVOL 1
#define BTRFS_SEND_CMD_SNAPSHOT 2
#define BTRFS_SEND_CMD_MKFILE 3
#define BTRFS_SEND_CMD_MKDIR 4
#define BTRFS_SEND_CMD_MKNOD 5
#define BTRFS_SEND_CMD_MKFIFO 6
#define BTRFS_SEND_CMD_MKSOCK 7
#define BTRFS_SEND_CMD_SYMLINK 8
#define BTRFS_SEND_CMD_RENAME 9
#define BTRFS_SEND_CMD_LINK 10
#define BTRFS_SEND_CMD_UNLINK 11
#define BTRFS_SEND_CMD_RMDIR 12
#define BTRFS_SEND_CMD_SET_XATTR 13
#define BTRFS_SEND_CMD_REMOVE_XATTR 14
#define BTRFS_SEND_CMD_WRITE 15
#define BTRFS_SEND_CMD_CLONE 16
#define BTRFS_SEND_CMD_TRUNCATE 17
#define BTRFS_SEND_CMD_CHMOD 18
#define BTRFS_SEND_CMD_CHOWN 19
#define BTRFS_SEND_CMD_UTIMES 20
#define BTRFS_SEND_CMD_END 21
#define BTRFS_SEND_CMD_UPDATE_EXTENT 22
#define BTRFS_SEND_TLV_UUID 1
#define BTRFS_SEND_TLV_TRANSID 2
#define BTRFS_SEND_TLV_INODE 3
#define BTRFS_SEND_TLV_SIZE 4
#define BTRFS_SEND_TLV_MODE 5
#define BTRFS_SEND_TLV_UID 6
#define BTRFS_SEND_TLV_GID 7
#define BTRFS_SEND_TLV_RDEV 8
#define BTRFS_SEND_TLV_CTIME 9
#define BTRFS_SEND_TLV_MTIME 10
#define BTRFS_SEND_TLV_ATIME 11
#define BTRFS_SEND_TLV_OTIME 12
#define BTRFS_SEND_TLV_XATTR_NAME 13
#define BTRFS_SEND_TLV_XATTR_DATA 14
#define BTRFS_SEND_TLV_PATH 15
#define BTRFS_SEND_TLV_PATH_TO 16
#define BTRFS_SEND_TLV_PATH_LINK 17
#define BTRFS_SEND_TLV_OFFSET 18
#define BTRFS_SEND_TLV_DATA 19
#define BTRFS_SEND_TLV_CLONE_UUID 20
#define BTRFS_SEND_TLV_CLONE_CTRANSID 21
#define BTRFS_SEND_TLV_CLONE_PATH 22
#define BTRFS_SEND_TLV_CLONE_OFFSET 23
#define BTRFS_SEND_TLV_CLONE_LENGTH 24
#define BTRFS_SEND_MAGIC "btrfs-stream"
typedef struct {
uint8_t magic[13];
uint32_t version;
} btrfs_send_header;
typedef struct {
uint32_t length;
uint16_t cmd;
uint32_t csum;
} btrfs_send_command;
typedef struct {
uint16_t type;
uint16_t length;
} btrfs_send_tlv;
#pragma pack(pop)

129
external/btrfs/src/btrfs.inf vendored Normal file
View File

@ -0,0 +1,129 @@
;;;
;;; WinBtrfs
;;;
;;;
;;; Copyright (c) 2016-20 Mark Harmstone
;;;
[Version]
Signature = "$Windows NT$"
Class = Volume
ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
Provider = %Me%
DriverVer = 03/02/2020,1.7.1.0
CatalogFile = btrfs.cat
[DestinationDirs]
DefaultDestDir = 12
Btrfs.DriverFiles = 12 ;%windir%\system32\drivers
Btrfs.DllFiles = 11 ;%windir%\system32
;;
;; Default install sections
;;
[DefaultInstall]
OptionDesc = %ServiceDescription%
CopyFiles = Btrfs.DriverFiles,Btrfs.DllFiles
RegisterDlls = shellbtrfs
CopyINF = btrfs.inf
[DefaultInstall.Services]
AddService = %ServiceName%,0x802,Btrfs.Service
[Manufacturer]
%Me%=Standard,NTamd64,NTx86,NTarm,NTarm64
[Standard.NTamd64]
%VolumeName% = Btrfs_Install, BtrfsVolume
%ControllerName% = Btrfs_Install, ROOT\btrfs
[Standard.NTx86]
%VolumeName% = Btrfs_Install, BtrfsVolume
%ControllerName% = Btrfs_Install, ROOT\btrfs
[Standard.NTarm]
%VolumeName% = Btrfs_Install, BtrfsVolume
%ControllerName% = Btrfs_Install, ROOT\btrfs
[Standard.NTarm64]
%VolumeName% = Btrfs_Install, BtrfsVolume
%ControllerName% = Btrfs_Install, ROOT\btrfs
[Btrfs_Install]
OptionDesc = %ServiceDescription%
CopyFiles = Btrfs.DriverFiles,Btrfs.DllFiles
RegisterDlls = shellbtrfs
[Btrfs_Install.Services]
AddService = %ServiceName%,2,Btrfs.Service
;;
;; Default uninstall sections
;;
[DefaultUninstall]
UnregisterDlls = shellbtrfs
DelFiles = Btrfs.DriverFiles,Btrfs.DllFiles
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting
;
; Services Section
;
[Btrfs.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\
ServiceType = 1
StartType = 1 ;SERVICE_SYSTEM_START
ErrorControl = 1
LoadOrderGroup = "File System"
[shellbtrfs]
11,,shellbtrfs.dll,1
;
; Copy Files
;
[Btrfs.DriverFiles]
%DriverName%.sys
[Btrfs.DllFiles]
shellbtrfs.dll
ubtrfs.dll
mkbtrfs.exe
[SourceDisksFiles]
btrfs.sys = 1,,
shellbtrfs.dll = 1,,
ubtrfs.dll = 1,,
mkbtrfs.exe = 1,,
[SourceDisksNames.x86]
1 = %DiskId1%,,,\x86
[SourceDisksNames.amd64]
1 = %DiskId1%,,,\x64
[SourceDisksNames.arm]
1 = %DiskId1%,,,\arm
[SourceDisksNames.arm64]
1 = %DiskId1%,,,\aarch64
;;
;; String Section
;;
[Strings]
Me = "Mark Harmstone"
ServiceDescription = "Btrfs driver"
ServiceName = "btrfs"
DriverName = "btrfs"
DiskId1 = "Btrfs Device Installation Disk"
VolumeName = "Btrfs volume"
ControllerName = "Btrfs controller"

99
external/btrfs/src/btrfs.rc vendored Normal file
View File

@ -0,0 +1,99 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,1,0
PRODUCTVERSION 1,7,1,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileDescription", "WinBtrfs"
VALUE "FileVersion", "1.7.1"
VALUE "InternalName", "btrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20"
VALUE "OriginalFilename", "btrfs.sys"
VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "1.7.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

1925
external/btrfs/src/btrfs_drv.h vendored Normal file

File diff suppressed because it is too large Load Diff

281
external/btrfs/src/btrfsioctl.h vendored Normal file
View File

@ -0,0 +1,281 @@
// No copyright claimed in this file - do what you want with it.
#pragma once
#include "btrfs.h"
#define FSCTL_BTRFS_GET_FILE_IDS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x829, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_CREATE_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82a, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_CREATE_SNAPSHOT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82b, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_GET_INODE_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82c, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_SET_INODE_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82d, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_GET_DEVICES CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82e, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_GET_USAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x82f, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_START_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_QUERY_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x831, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_PAUSE_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x832, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_RESUME_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x833, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_STOP_BALANCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x834, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_ADD_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x835, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x836, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_BTRFS_QUERY_FILESYSTEMS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x837, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_GET_UUID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x838, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_START_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x839, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_QUERY_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83a, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_PAUSE_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83b, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_RESUME_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83c, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_STOP_SCRUB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83d, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_BTRFS_PROBE_VOLUME CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83e, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_RESET_STATS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83f, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_MKNOD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x840, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_RECEIVED_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x841, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_GET_XATTRS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x842, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_SET_XATTR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x843, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_RESERVE_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x844, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_FIND_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x845, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_SEND_SUBVOL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x846, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_READ_SEND_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x847, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define FSCTL_BTRFS_RESIZE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x848, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_BTRFS_UNLOAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x849, METHOD_NEITHER, FILE_ANY_ACCESS)
typedef struct {
uint64_t subvol;
uint64_t inode;
BOOL top;
} btrfs_get_file_ids;
typedef struct {
HANDLE subvol;
BOOL readonly;
BOOL posix;
uint16_t namelen;
WCHAR name[1];
} btrfs_create_snapshot;
typedef struct {
void* POINTER_32 subvol;
BOOL readonly;
BOOL posix;
uint16_t namelen;
WCHAR name[1];
} btrfs_create_snapshot32;
#define BTRFS_COMPRESSION_ANY 0
#define BTRFS_COMPRESSION_ZLIB 1
#define BTRFS_COMPRESSION_LZO 2
#define BTRFS_COMPRESSION_ZSTD 3
typedef struct {
uint64_t subvol;
uint64_t inode;
BOOL top;
uint8_t type;
uint32_t st_uid;
uint32_t st_gid;
uint32_t st_mode;
uint64_t st_rdev;
uint64_t flags;
uint32_t inline_length;
uint64_t disk_size_uncompressed;
uint64_t disk_size_zlib;
uint64_t disk_size_lzo;
uint8_t compression_type;
uint64_t disk_size_zstd;
uint64_t sparse_size;
uint32_t num_extents;
} btrfs_inode_info;
typedef struct {
uint64_t flags;
BOOL flags_changed;
uint32_t st_uid;
BOOL uid_changed;
uint32_t st_gid;
BOOL gid_changed;
uint32_t st_mode;
BOOL mode_changed;
uint8_t compression_type;
BOOL compression_type_changed;
} btrfs_set_inode_info;
typedef struct {
uint32_t next_entry;
uint64_t dev_id;
uint64_t size;
uint64_t max_size;
BOOL readonly;
BOOL missing;
ULONG device_number;
ULONG partition_number;
uint64_t stats[5];
USHORT namelen;
WCHAR name[1];
} btrfs_device;
typedef struct {
uint64_t dev_id;
uint64_t alloc;
} btrfs_usage_device;
typedef struct {
uint32_t next_entry;
uint64_t type;
uint64_t size;
uint64_t used;
uint64_t num_devices;
btrfs_usage_device devices[1];
} btrfs_usage;
#define BTRFS_BALANCE_OPTS_ENABLED 0x001
#define BTRFS_BALANCE_OPTS_PROFILES 0x002
#define BTRFS_BALANCE_OPTS_DEVID 0x004
#define BTRFS_BALANCE_OPTS_DRANGE 0x008
#define BTRFS_BALANCE_OPTS_VRANGE 0x010
#define BTRFS_BALANCE_OPTS_LIMIT 0x020
#define BTRFS_BALANCE_OPTS_STRIPES 0x040
#define BTRFS_BALANCE_OPTS_USAGE 0x080
#define BTRFS_BALANCE_OPTS_CONVERT 0x100
#define BTRFS_BALANCE_OPTS_SOFT 0x200
#define BLOCK_FLAG_SINGLE 0x1000000000000 // only used in balance
typedef struct {
uint64_t flags;
uint64_t profiles;
uint64_t devid;
uint64_t drange_start;
uint64_t drange_end;
uint64_t vrange_start;
uint64_t vrange_end;
uint64_t limit_start;
uint64_t limit_end;
uint16_t stripes_start;
uint16_t stripes_end;
uint8_t usage_start;
uint8_t usage_end;
uint64_t convert;
} btrfs_balance_opts;
#define BTRFS_BALANCE_STOPPED 0
#define BTRFS_BALANCE_RUNNING 1
#define BTRFS_BALANCE_PAUSED 2
#define BTRFS_BALANCE_REMOVAL 4
#define BTRFS_BALANCE_ERROR 8
#define BTRFS_BALANCE_SHRINKING 16
typedef struct {
uint32_t status;
uint64_t chunks_left;
uint64_t total_chunks;
NTSTATUS error;
btrfs_balance_opts data_opts;
btrfs_balance_opts metadata_opts;
btrfs_balance_opts system_opts;
} btrfs_query_balance;
typedef struct {
btrfs_balance_opts opts[3];
} btrfs_start_balance;
typedef struct {
uint8_t uuid[16];
BOOL missing;
USHORT name_length;
WCHAR name[1];
} btrfs_filesystem_device;
typedef struct {
uint32_t next_entry;
uint8_t uuid[16];
uint32_t num_devices;
btrfs_filesystem_device device;
} btrfs_filesystem;
#define BTRFS_SCRUB_STOPPED 0
#define BTRFS_SCRUB_RUNNING 1
#define BTRFS_SCRUB_PAUSED 2
typedef struct {
uint32_t next_entry;
uint64_t address;
uint64_t device;
BOOL recovered;
BOOL is_metadata;
BOOL parity;
union {
struct {
uint64_t subvol;
uint64_t offset;
uint16_t filename_length;
WCHAR filename[1];
} data;
struct {
uint64_t root;
uint8_t level;
KEY firstitem;
} metadata;
};
} btrfs_scrub_error;
typedef struct {
uint32_t status;
LARGE_INTEGER start_time;
LARGE_INTEGER finish_time;
uint64_t chunks_left;
uint64_t total_chunks;
uint64_t data_scrubbed;
uint64_t duration;
NTSTATUS error;
uint32_t num_errors;
btrfs_scrub_error errors;
} btrfs_query_scrub;
typedef struct {
uint64_t inode;
uint8_t type;
uint64_t st_rdev;
uint16_t namelen;
WCHAR name[1];
} btrfs_mknod;
typedef struct {
uint64_t generation;
BTRFS_UUID uuid;
} btrfs_received_subvol;
typedef struct {
USHORT namelen;
USHORT valuelen;
char data[1];
} btrfs_set_xattr;
typedef struct {
BOOL readonly;
BOOL posix;
USHORT namelen;
WCHAR name[1];
} btrfs_create_subvol;
typedef struct {
BTRFS_UUID uuid;
uint64_t ctransid;
} btrfs_find_subvol;
typedef struct {
HANDLE parent;
ULONG num_clones;
HANDLE clones[1];
} btrfs_send_subvol;
typedef struct {
void* POINTER_32 parent;
ULONG num_clones;
void* POINTER_32 clones[1];
} btrfs_send_subvol32;
typedef struct {
uint64_t device;
uint64_t size;
} btrfs_resize;

90
external/btrfs/src/cache.c vendored Normal file
View File

@ -0,0 +1,90 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
CACHE_MANAGER_CALLBACKS cache_callbacks;
static BOOLEAN __stdcall acquire_for_lazy_write(PVOID Context, BOOLEAN Wait) {
PFILE_OBJECT FileObject = Context;
fcb* fcb = FileObject->FsContext;
TRACE("(%p, %u)\n", Context, Wait);
if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait))
return false;
if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) {
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
return false;
}
fcb->lazy_writer_thread = KeGetCurrentThread();
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return true;
}
static void __stdcall release_from_lazy_write(PVOID Context) {
PFILE_OBJECT FileObject = Context;
fcb* fcb = FileObject->FsContext;
TRACE("(%p)\n", Context);
fcb->lazy_writer_thread = NULL;
ExReleaseResourceLite(fcb->Header.Resource);
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);
}
static BOOLEAN __stdcall acquire_for_read_ahead(PVOID Context, BOOLEAN Wait) {
PFILE_OBJECT FileObject = Context;
fcb* fcb = FileObject->FsContext;
TRACE("(%p, %u)\n", Context, Wait);
if (!ExAcquireResourceSharedLite(fcb->Header.Resource, Wait))
return false;
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return true;
}
static void __stdcall release_from_read_ahead(PVOID Context) {
PFILE_OBJECT FileObject = Context;
fcb* fcb = FileObject->FsContext;
TRACE("(%p)\n", Context);
ExReleaseResourceLite(fcb->Header.Resource);
if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);
}
void init_cache() {
cache_callbacks.AcquireForLazyWrite = acquire_for_lazy_write;
cache_callbacks.ReleaseFromLazyWrite = release_from_lazy_write;
cache_callbacks.AcquireForReadAhead = acquire_for_read_ahead;
cache_callbacks.ReleaseFromReadAhead = release_from_read_ahead;
}

313
external/btrfs/src/calcthread.c vendored Normal file
View File

@ -0,0 +1,313 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
#include "xxhash.h"
#include "crc32c.h"
void calc_thread_main(device_extension* Vcb, calc_job* cj) {
while (true) {
KIRQL irql;
calc_job* cj2;
uint8_t* src;
void* dest;
bool last_one = false;
KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
if (cj && cj->not_started == 0) {
KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
break;
}
if (cj)
cj2 = cj;
else {
if (IsListEmpty(&Vcb->calcthreads.job_list)) {
KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
break;
}
cj2 = CONTAINING_RECORD(Vcb->calcthreads.job_list.Flink, calc_job, list_entry);
}
src = cj2->in;
dest = cj2->out;
switch (cj2->type) {
case calc_thread_crc32c:
case calc_thread_xxhash:
case calc_thread_sha256:
case calc_thread_blake2:
cj2->in = (uint8_t*)cj2->in + Vcb->superblock.sector_size;
cj2->out = (uint8_t*)cj2->out + Vcb->csum_size;
break;
default:
break;
}
cj2->not_started--;
if (cj2->not_started == 0) {
RemoveEntryList(&cj2->list_entry);
last_one = true;
}
KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
switch (cj2->type) {
case calc_thread_crc32c:
*(uint32_t*)dest = ~calc_crc32c(0xffffffff, src, Vcb->superblock.sector_size);
break;
case calc_thread_xxhash:
*(uint64_t*)dest = XXH64(src, Vcb->superblock.sector_size, 0);
break;
case calc_thread_sha256:
calc_sha256(dest, src, Vcb->superblock.sector_size);
break;
case calc_thread_blake2:
blake2b(dest, BLAKE2_HASH_SIZE, src, Vcb->superblock.sector_size);
break;
case calc_thread_decomp_zlib:
cj2->Status = zlib_decompress(src, cj2->inlen, dest, cj2->outlen);
if (!NT_SUCCESS(cj2->Status))
ERR("zlib_decompress returned %08lx\n", cj2->Status);
break;
case calc_thread_decomp_lzo:
cj2->Status = lzo_decompress(src, cj2->inlen, dest, cj2->outlen, cj2->off);
if (!NT_SUCCESS(cj2->Status))
ERR("lzo_decompress returned %08lx\n", cj2->Status);
break;
case calc_thread_decomp_zstd:
cj2->Status = zstd_decompress(src, cj2->inlen, dest, cj2->outlen);
if (!NT_SUCCESS(cj2->Status))
ERR("zstd_decompress returned %08lx\n", cj2->Status);
break;
case calc_thread_comp_zlib:
cj2->Status = zlib_compress(src, cj2->inlen, dest, cj2->outlen, Vcb->options.zlib_level, &cj2->space_left);
if (!NT_SUCCESS(cj2->Status))
ERR("zlib_compress returned %08lx\n", cj2->Status);
break;
case calc_thread_comp_lzo:
cj2->Status = lzo_compress(src, cj2->inlen, dest, cj2->outlen, &cj2->space_left);
if (!NT_SUCCESS(cj2->Status))
ERR("lzo_compress returned %08lx\n", cj2->Status);
break;
case calc_thread_comp_zstd:
cj2->Status = zstd_compress(src, cj2->inlen, dest, cj2->outlen, Vcb->options.zstd_level, &cj2->space_left);
if (!NT_SUCCESS(cj2->Status))
ERR("zstd_compress returned %08lx\n", cj2->Status);
break;
}
if (InterlockedDecrement(&cj2->left) == 0)
KeSetEvent(&cj2->event, 0, false);
if (last_one)
break;
}
}
void do_calc_job(device_extension* Vcb, uint8_t* data, uint32_t sectors, void* csum) {
KIRQL irql;
calc_job cj;
cj.in = data;
cj.out = csum;
cj.left = cj.not_started = sectors;
switch (Vcb->superblock.csum_type) {
case CSUM_TYPE_CRC32C:
cj.type = calc_thread_crc32c;
break;
case CSUM_TYPE_XXHASH:
cj.type = calc_thread_xxhash;
break;
case CSUM_TYPE_SHA256:
cj.type = calc_thread_sha256;
break;
case CSUM_TYPE_BLAKE2:
cj.type = calc_thread_blake2;
break;
}
KeInitializeEvent(&cj.event, NotificationEvent, false);
KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
InsertTailList(&Vcb->calcthreads.job_list, &cj.list_entry);
KeSetEvent(&Vcb->calcthreads.event, 0, false);
KeClearEvent(&Vcb->calcthreads.event);
KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
calc_thread_main(Vcb, &cj);
KeWaitForSingleObject(&cj.event, Executive, KernelMode, false, NULL);
}
NTSTATUS add_calc_job_decomp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen,
void* out, unsigned int outlen, unsigned int off, calc_job** pcj) {
calc_job* cj;
KIRQL irql;
cj = ExAllocatePoolWithTag(NonPagedPool, sizeof(calc_job), ALLOC_TAG);
if (!cj) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
cj->in = in;
cj->inlen = inlen;
cj->out = out;
cj->outlen = outlen;
cj->off = off;
cj->left = cj->not_started = 1;
cj->Status = STATUS_SUCCESS;
switch (compression) {
case BTRFS_COMPRESSION_ZLIB:
cj->type = calc_thread_decomp_zlib;
break;
case BTRFS_COMPRESSION_LZO:
cj->type = calc_thread_decomp_lzo;
break;
case BTRFS_COMPRESSION_ZSTD:
cj->type = calc_thread_decomp_zstd;
break;
default:
ERR("unexpected compression type %x\n", compression);
ExFreePool(cj);
return STATUS_NOT_SUPPORTED;
}
KeInitializeEvent(&cj->event, NotificationEvent, false);
KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
KeSetEvent(&Vcb->calcthreads.event, 0, false);
KeClearEvent(&Vcb->calcthreads.event);
KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
*pcj = cj;
return STATUS_SUCCESS;
}
NTSTATUS add_calc_job_comp(device_extension* Vcb, uint8_t compression, void* in, unsigned int inlen,
void* out, unsigned int outlen, calc_job** pcj) {
calc_job* cj;
KIRQL irql;
cj = ExAllocatePoolWithTag(NonPagedPool, sizeof(calc_job), ALLOC_TAG);
if (!cj) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
cj->in = in;
cj->inlen = inlen;
cj->out = out;
cj->outlen = outlen;
cj->left = cj->not_started = 1;
cj->Status = STATUS_SUCCESS;
switch (compression) {
case BTRFS_COMPRESSION_ZLIB:
cj->type = calc_thread_comp_zlib;
break;
case BTRFS_COMPRESSION_LZO:
cj->type = calc_thread_comp_lzo;
break;
case BTRFS_COMPRESSION_ZSTD:
cj->type = calc_thread_comp_zstd;
break;
default:
ERR("unexpected compression type %x\n", compression);
ExFreePool(cj);
return STATUS_NOT_SUPPORTED;
}
KeInitializeEvent(&cj->event, NotificationEvent, false);
KeAcquireSpinLock(&Vcb->calcthreads.spinlock, &irql);
InsertTailList(&Vcb->calcthreads.job_list, &cj->list_entry);
KeSetEvent(&Vcb->calcthreads.event, 0, false);
KeClearEvent(&Vcb->calcthreads.event);
KeReleaseSpinLock(&Vcb->calcthreads.spinlock, irql);
*pcj = cj;
return STATUS_SUCCESS;
}
_Function_class_(KSTART_ROUTINE)
void __stdcall calc_thread(void* context) {
drv_calc_thread* thread = context;
device_extension* Vcb = thread->DeviceObject->DeviceExtension;
ObReferenceObject(thread->DeviceObject);
KeSetSystemAffinityThread((KAFFINITY)(1 << thread->number));
while (true) {
KeWaitForSingleObject(&Vcb->calcthreads.event, Executive, KernelMode, false, NULL);
calc_thread_main(Vcb, NULL);
if (thread->quit)
break;
}
ObDereferenceObject(thread->DeviceObject);
KeSetEvent(&thread->finished, 0, false);
PsTerminateSystemThread(STATUS_SUCCESS);
}

1192
external/btrfs/src/compress.c vendored Normal file

File diff suppressed because it is too large Load Diff

106
external/btrfs/src/crc32c-amd64-gas.S vendored Normal file
View File

@ -0,0 +1,106 @@
/* Copyright (c) Mark Harmstone 2020
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
.intel_syntax noprefix
.extern _crctable
.global _calc_crc32c_sw@12
/* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
_calc_crc32c_sw@12:
/* rax = crc / seed
* rdx = buf
* r8 = len
* rcx = tmp
* r10 = tmp2 */
mov rax, rcx
crcloop:
test r8, r8
jz crcend
mov rcx, rax
shr rcx, 8
mov r10b, byte ptr [rdx]
xor al, r10b
and rax, 255
shl rax, 2
mov rax, [_crctable + rax]
xor rax, rcx
inc rdx
dec r8
jmp crcloop
crcend:
ret
/****************************************************/
/* uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
_calc_crc32c_hw@12:
/* rax = crc / seed
* rdx = buf
* r8 = len */
mov rax, rcx
crchw_loop:
cmp r8, 8
jl crchw_stragglers
crc32 rax, qword ptr [rdx]
add rdx, 8
sub r8, 8
jmp crchw_loop
crchw_stragglers:
cmp r8, 4
jl crchw_stragglers2
crc32 eax, dword ptr [rdx]
add rdx, 4
sub r8, 4
crchw_stragglers2:
cmp r8, 2
jl crchw_stragglers3
crc32 eax, word ptr [rdx]
add rdx, 2
sub r8, 2
crchw_stragglers3:
test r8, r8
jz crchw_end
crc32 eax, byte ptr [rdx]
inc rdx
dec r8
jmp crchw_stragglers3
crchw_end:
ret

114
external/btrfs/src/crc32c-amd64-masm.S vendored Normal file
View File

@ -0,0 +1,114 @@
; Copyright (c) Mark Harmstone 2020
;
; This file is part of WinBtrfs.
;
; WinBtrfs is free software: you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public Licence as published by
; the Free Software Foundation, either version 3 of the Licence, or
; (at your option) any later version.
;
; WinBtrfs is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU Lesser General Public Licence for more details.
;
; You should have received a copy of the GNU Lesser General Public Licence
; along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>.
EXTERN crctable:qword
_TEXT SEGMENT
PUBLIC calc_crc32c_sw
; uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen);
calc_crc32c_sw:
; rax = crc / seed
; rdx = buf
; r8 = len
; rcx = tmp
; r10 = tmp2
mov rax, rcx
crcloop:
test r8, r8
jz crcend
mov rcx, rax
shr rcx, 8
mov r10b, byte ptr [rdx]
xor al, r10b
and rax, 255
shl rax, 2
mov r10, offset crctable
mov eax, dword ptr [r10 + rax]
xor rax, rcx
inc rdx
dec r8
jmp crcloop
crcend:
ret
; ****************************************************
; uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen);
PUBLIC calc_crc32c_hw
calc_crc32c_hw:
; rax = crc / seed
; rdx = buf
; r8 = len
mov rax, rcx
crchw_loop:
cmp r8, 8
jl crchw_stragglers
crc32 rax, qword ptr [rdx]
add rdx, 8
sub r8, 8
jmp crchw_loop
crchw_stragglers:
cmp r8, 4
jl crchw_stragglers2
crc32 eax, dword ptr [rdx]
add rdx, 4
sub r8, 4
crchw_stragglers2:
cmp r8, 2
jl crchw_stragglers3
crc32 eax, word ptr [rdx]
add rdx, 2
sub r8, 2
crchw_stragglers3:
test r8, r8
jz crchw_end
crc32 eax, byte ptr [rdx]
inc rdx
dec r8
jmp crchw_stragglers3
crchw_end:
ret
_TEXT ENDS
end

118
external/btrfs/src/crc32c-x86-gas.S vendored Normal file
View File

@ -0,0 +1,118 @@
/* Copyright (c) Mark Harmstone 2020
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
.intel_syntax noprefix
.extern _crctable
.global _calc_crc32c_sw@12
.global _calc_crc32c_hw@12
/* uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
_calc_crc32c_sw@12:
push ebp
mov ebp, esp
push esi
push ebx
mov eax, [ebp+8]
mov edx, [ebp+12]
mov ebx, [ebp+16]
/* eax = crc / seed
* ebx = len
* esi = tmp
* edx = buf
* ecx = tmp2 */
crcloop:
test ebx, ebx
jz crcend
mov esi, eax
shr esi, 8
mov cl, byte ptr [edx]
xor al, cl
and eax, 255
shl eax, 2
mov eax, [_crctable + eax]
xor eax, esi
inc edx
dec ebx
jmp crcloop
crcend:
pop ebx
pop esi
pop ebp
ret 12
/****************************************************/
/* uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen); */
_calc_crc32c_hw@12:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov edx, [ebp+12]
mov ecx, [ebp+16]
/* eax = crc / seed
* ecx = len
* edx = buf */
crchw_loop:
cmp ecx, 4
jl crchw_stragglers
crc32 eax, dword ptr [edx]
add edx, 4
sub ecx, 4
jmp crchw_loop
crchw_stragglers:
cmp ecx, 2
jl crchw_stragglers2
crc32 eax, word ptr [edx]
add edx, 2
sub ecx, 2
crchw_stragglers2:
test ecx, ecx
jz crchw_end
crc32 eax, byte ptr [edx]
inc edx
dec ecx
jmp crchw_stragglers2
crchw_end:
pop ebp
ret 12

126
external/btrfs/src/crc32c-x86-masm.S vendored Normal file
View File

@ -0,0 +1,126 @@
; Copyright (c) Mark Harmstone 2020
;
; This file is part of WinBtrfs.
;
; WinBtrfs is free software: you can redistribute it and/or modify
; it under the terms of the GNU Lesser General Public Licence as published by
; the Free Software Foundation, either version 3 of the Licence, or
; (at your option) any later version.
;
; WinBtrfs is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU Lesser General Public Licence for more details.
;
; You should have received a copy of the GNU Lesser General Public Licence
; along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>.
.686P
EXTERN _crctable:ABS
_TEXT SEGMENT
; uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen);
PUBLIC _calc_crc32c_sw@12
_calc_crc32c_sw@12:
push ebp
mov ebp, esp
push esi
push ebx
mov eax, [ebp+8]
mov edx, [ebp+12]
mov ebx, [ebp+16]
; eax = crc / seed
; ebx = len
; esi = tmp
; edx = buf
; ecx = tmp2
crcloop:
test ebx, ebx
jz crcend
mov esi, eax
shr esi, 8
mov cl, byte ptr [edx]
xor al, cl
and eax, 255
shl eax, 2
mov eax, [_crctable + eax]
xor eax, esi
inc edx
dec ebx
jmp crcloop
crcend:
pop ebx
pop esi
pop ebp
ret 12
; ****************************************************
; uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen);
PUBLIC _calc_crc32c_hw@12
_calc_crc32c_hw@12:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov edx, [ebp+12]
mov ecx, [ebp+16]
; eax = crc / seed
; ecx = len
; edx = buf
crchw_loop:
cmp ecx, 4
jl crchw_stragglers
crc32 eax, dword ptr [edx]
add edx, 4
sub ecx, 4
jmp crchw_loop
crchw_stragglers:
cmp ecx, 2
jl crchw_stragglers2
crc32 eax, word ptr [edx]
add edx, 2
sub ecx, 2
crchw_stragglers2:
test ecx, ecx
jz crchw_end
crc32 eax, byte ptr [edx]
inc edx
dec ecx
jmp crchw_stragglers2
crchw_end:
pop ebp
ret 12
_TEXT ENDS
end

71
external/btrfs/src/crc32c.c vendored Normal file
View File

@ -0,0 +1,71 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "crc32c.h"
#include <stdint.h>
#include <stdbool.h>
#include <sal.h>
crc_func calc_crc32c = calc_crc32c_sw;
const uint32_t crctable[] = {
0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
};
// x86 and amd64 versions live in asm files
#if !defined(_X86_) && !defined(_AMD64_)
uint32_t __stdcall calc_crc32c_sw(_In_ uint32_t seed, _In_reads_bytes_(msglen) uint8_t* msg, _In_ uint32_t msglen) {
uint32_t rem = seed;
for (uint32_t i = 0; i < msglen; i++) {
rem = crctable[(rem ^ msg[i]) & 0xff] ^ (rem >> 8);
}
return rem;
}
#endif

13
external/btrfs/src/crc32c.h vendored Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#if defined(_X86_) || defined(_AMD64_)
uint32_t __stdcall calc_crc32c_hw(uint32_t seed, uint8_t* msg, uint32_t msglen);
#endif
uint32_t __stdcall calc_crc32c_sw(uint32_t seed, uint8_t* msg, uint32_t msglen);
typedef uint32_t (__stdcall *crc_func)(uint32_t seed, uint8_t* msg, uint32_t msglen);
extern crc_func calc_crc32c;

4951
external/btrfs/src/create.c vendored Normal file

File diff suppressed because it is too large Load Diff

322
external/btrfs/src/devctrl.c vendored Normal file
View File

@ -0,0 +1,322 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
#include <ntdddisk.h>
#include <mountdev.h>
#include <diskguid.h>
extern PDRIVER_OBJECT drvobj;
extern LIST_ENTRY VcbList;
extern ERESOURCE global_loading_lock;
static NTSTATUS mountdev_query_stable_guid(device_extension* Vcb, PIRP Irp) {
MOUNTDEV_STABLE_GUID* msg = Irp->UserBuffer;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
TRACE("IOCTL_MOUNTDEV_QUERY_STABLE_GUID\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_STABLE_GUID))
return STATUS_INVALID_PARAMETER;
RtlCopyMemory(&msg->StableGuid, &Vcb->superblock.uuid, sizeof(GUID));
Irp->IoStatus.Information = sizeof(MOUNTDEV_STABLE_GUID);
return STATUS_SUCCESS;
}
static NTSTATUS is_writable(device_extension* Vcb) {
TRACE("IOCTL_DISK_IS_WRITABLE\n");
return Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_SUCCESS;
}
static NTSTATUS query_filesystems(void* data, ULONG length) {
NTSTATUS Status;
LIST_ENTRY *le, *le2;
btrfs_filesystem* bfs = NULL;
ULONG itemsize;
ExAcquireResourceSharedLite(&global_loading_lock, true);
if (IsListEmpty(&VcbList)) {
if (length < sizeof(btrfs_filesystem)) {
Status = STATUS_BUFFER_OVERFLOW;
goto end;
} else {
RtlZeroMemory(data, sizeof(btrfs_filesystem));
Status = STATUS_SUCCESS;
goto end;
}
}
le = VcbList.Flink;
while (le != &VcbList) {
device_extension* Vcb = CONTAINING_RECORD(le, device_extension, list_entry);
btrfs_filesystem_device* bfd;
if (bfs) {
bfs->next_entry = itemsize;
bfs = (btrfs_filesystem*)((uint8_t*)bfs + itemsize);
} else
bfs = data;
if (length < offsetof(btrfs_filesystem, device)) {
Status = STATUS_BUFFER_OVERFLOW;
goto end;
}
itemsize = offsetof(btrfs_filesystem, device);
length -= offsetof(btrfs_filesystem, device);
bfs->next_entry = 0;
RtlCopyMemory(&bfs->uuid, &Vcb->superblock.uuid, sizeof(BTRFS_UUID));
ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
bfs->num_devices = (uint32_t)Vcb->superblock.num_devices;
bfd = NULL;
le2 = Vcb->devices.Flink;
while (le2 != &Vcb->devices) {
device* dev = CONTAINING_RECORD(le2, device, list_entry);
MOUNTDEV_NAME mdn;
if (bfd)
bfd = (btrfs_filesystem_device*)((uint8_t*)bfd + offsetof(btrfs_filesystem_device, name[0]) + bfd->name_length);
else
bfd = &bfs->device;
if (length < offsetof(btrfs_filesystem_device, name[0])) {
ExReleaseResourceLite(&Vcb->tree_lock);
Status = STATUS_BUFFER_OVERFLOW;
goto end;
}
itemsize += (ULONG)offsetof(btrfs_filesystem_device, name[0]);
length -= (ULONG)offsetof(btrfs_filesystem_device, name[0]);
RtlCopyMemory(&bfd->uuid, &dev->devitem.device_uuid, sizeof(BTRFS_UUID));
if (dev->devobj) {
Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &mdn, sizeof(MOUNTDEV_NAME), true, NULL);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
ExReleaseResourceLite(&Vcb->tree_lock);
ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
goto end;
}
if (mdn.NameLength > length) {
ExReleaseResourceLite(&Vcb->tree_lock);
Status = STATUS_BUFFER_OVERFLOW;
goto end;
}
Status = dev_ioctl(dev->devobj, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &bfd->name_length, (ULONG)offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength, true, NULL);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
ExReleaseResourceLite(&Vcb->tree_lock);
ERR("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME returned %08lx\n", Status);
goto end;
}
itemsize += bfd->name_length;
length -= bfd->name_length;
} else {
bfd->missing = true;
bfd->name_length = 0;
}
le2 = le2->Flink;
}
ExReleaseResourceLite(&Vcb->tree_lock);
le = le->Flink;
}
Status = STATUS_SUCCESS;
end:
ExReleaseResourceLite(&global_loading_lock);
return Status;
}
static NTSTATUS probe_volume(void* data, ULONG length, KPROCESSOR_MODE processor_mode) {
MOUNTDEV_NAME* mdn = (MOUNTDEV_NAME*)data;
UNICODE_STRING path, pnp_name;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
const GUID* guid;
if (length < sizeof(MOUNTDEV_NAME))
return STATUS_INVALID_PARAMETER;
if (length < offsetof(MOUNTDEV_NAME, Name[0]) + mdn->NameLength)
return STATUS_INVALID_PARAMETER;
TRACE("%.*S\n", (int)(mdn->NameLength / sizeof(WCHAR)), mdn->Name);
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE), processor_mode))
return STATUS_PRIVILEGE_NOT_HELD;
path.Buffer = mdn->Name;
path.Length = path.MaximumLength = mdn->NameLength;
Status = IoGetDeviceObjectPointer(&path, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject);
if (!NT_SUCCESS(Status)) {
ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
return Status;
}
Status = get_device_pnp_name(DeviceObject, &pnp_name, &guid);
if (!NT_SUCCESS(Status)) {
ERR("get_device_pnp_name returned %08lx\n", Status);
ObDereferenceObject(FileObject);
return Status;
}
if (RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) {
Status = dev_ioctl(DeviceObject, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, true, NULL);
if (!NT_SUCCESS(Status))
WARN("IOCTL_DISK_UPDATE_PROPERTIES returned %08lx\n", Status);
}
ObDereferenceObject(FileObject);
volume_removal(drvobj, &pnp_name);
if (RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID))
disk_arrival(drvobj, &pnp_name);
else
volume_arrival(drvobj, &pnp_name);
return STATUS_SUCCESS;
}
static NTSTATUS ioctl_unload(PIRP Irp) {
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE), Irp->RequestorMode)) {
ERR("insufficient privileges\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
do_shutdown(Irp);
return STATUS_SUCCESS;
}
static NTSTATUS control_ioctl(PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_BTRFS_QUERY_FILESYSTEMS:
Status = query_filesystems(map_user_buffer(Irp, NormalPagePriority), IrpSp->Parameters.FileSystemControl.OutputBufferLength);
break;
case IOCTL_BTRFS_PROBE_VOLUME:
Status = probe_volume(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.FileSystemControl.InputBufferLength, Irp->RequestorMode);
break;
case IOCTL_BTRFS_UNLOAD:
Status = ioctl_unload(Irp);
break;
default:
TRACE("unhandled ioctl %lx\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
return Status;
}
_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS __stdcall drv_device_control(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
device_extension* Vcb = DeviceObject->DeviceExtension;
bool top_level;
FsRtlEnterFileSystem();
top_level = is_top_level(Irp);
Irp->IoStatus.Information = 0;
if (Vcb) {
if (Vcb->type == VCB_TYPE_CONTROL) {
Status = control_ioctl(Irp);
goto end;
} else if (Vcb->type == VCB_TYPE_VOLUME) {
Status = vol_device_control(DeviceObject, Irp);
goto end;
} else if (Vcb->type != VCB_TYPE_FS) {
Status = STATUS_INVALID_PARAMETER;
goto end;
}
} else {
Status = STATUS_INVALID_PARAMETER;
goto end;
}
if (!IrpSp->FileObject || IrpSp->FileObject->FsContext != Vcb->volume_fcb) {
Status = STATUS_INVALID_PARAMETER;
goto end;
}
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
Status = mountdev_query_stable_guid(Vcb, Irp);
goto end;
case IOCTL_DISK_IS_WRITABLE:
Status = is_writable(Vcb);
goto end;
default:
TRACE("unhandled control code %lx\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
break;
}
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
goto end2;
end:
Irp->IoStatus.Status = Status;
if (Status != STATUS_PENDING)
IoCompleteRequest(Irp, IO_NO_INCREMENT);
end2:
TRACE("returning %08lx\n", Status);
if (top_level)
IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem();
return Status;
}

1216
external/btrfs/src/dirctrl.c vendored Normal file

File diff suppressed because it is too large Load Diff

2309
external/btrfs/src/extent-tree.c vendored Normal file

File diff suppressed because it is too large Load Diff

511
external/btrfs/src/fastio.c vendored Normal file
View File

@ -0,0 +1,511 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
FAST_IO_DISPATCH FastIoDispatch;
_Function_class_(FAST_IO_QUERY_BASIC_INFO)
static BOOLEAN __stdcall fast_query_basic_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_BASIC_INFORMATION fbi,
PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb;
ccb* ccb;
FsRtlEnterFileSystem();
TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fbi, IoStatus, DeviceObject);
if (!FileObject) {
FsRtlExitFileSystem();
return false;
}
fcb = FileObject->FsContext;
if (!fcb) {
FsRtlExitFileSystem();
return false;
}
ccb = FileObject->FsContext2;
if (!ccb) {
FsRtlExitFileSystem();
return false;
}
if (!(ccb->access & (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES))) {
FsRtlExitFileSystem();
return false;
}
if (fcb->ads) {
if (!ccb->fileref || !ccb->fileref->parent || !ccb->fileref->parent->fcb) {
FsRtlExitFileSystem();
return false;
}
fcb = ccb->fileref->parent->fcb;
}
if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
FsRtlExitFileSystem();
return false;
}
if (fcb == fcb->Vcb->dummy_fcb) {
LARGE_INTEGER time;
KeQuerySystemTime(&time);
fbi->CreationTime = fbi->LastAccessTime = fbi->LastWriteTime = fbi->ChangeTime = time;
} else {
fbi->CreationTime.QuadPart = unix_time_to_win(&fcb->inode_item.otime);
fbi->LastAccessTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_atime);
fbi->LastWriteTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_mtime);
fbi->ChangeTime.QuadPart = unix_time_to_win(&fcb->inode_item.st_ctime);
}
fbi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
ExReleaseResourceLite(fcb->Header.Resource);
FsRtlExitFileSystem();
return true;
}
_Function_class_(FAST_IO_QUERY_STANDARD_INFO)
static BOOLEAN __stdcall fast_query_standard_info(PFILE_OBJECT FileObject, BOOLEAN wait, PFILE_STANDARD_INFORMATION fsi,
PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb;
ccb* ccb;
bool ads;
ULONG adssize;
FsRtlEnterFileSystem();
TRACE("(%p, %u, %p, %p, %p)\n", FileObject, wait, fsi, IoStatus, DeviceObject);
if (!FileObject) {
FsRtlExitFileSystem();
return false;
}
fcb = FileObject->FsContext;
ccb = FileObject->FsContext2;
if (!fcb) {
FsRtlExitFileSystem();
return false;
}
if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
FsRtlExitFileSystem();
return false;
}
ads = fcb->ads;
if (ads) {
struct _fcb* fcb2;
if (!ccb || !ccb->fileref || !ccb->fileref->parent || !ccb->fileref->parent->fcb) {
ExReleaseResourceLite(fcb->Header.Resource);
FsRtlExitFileSystem();
return false;
}
adssize = fcb->adsdata.Length;
fcb2 = ccb->fileref->parent->fcb;
ExReleaseResourceLite(fcb->Header.Resource);
fcb = fcb2;
if (!ExAcquireResourceSharedLite(fcb->Header.Resource, wait)) {
FsRtlExitFileSystem();
return false;
}
fsi->AllocationSize.QuadPart = fsi->EndOfFile.QuadPart = adssize;
fsi->NumberOfLinks = fcb->inode_item.st_nlink;
fsi->Directory = false;
} else {
fsi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
fsi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
fsi->NumberOfLinks = fcb->inode_item.st_nlink;
fsi->Directory = S_ISDIR(fcb->inode_item.st_mode);
}
fsi->DeletePending = ccb->fileref ? ccb->fileref->delete_on_close : false;
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
ExReleaseResourceLite(fcb->Header.Resource);
FsRtlExitFileSystem();
return true;
}
_Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
static BOOLEAN __stdcall fast_io_check_if_possible(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait,
ULONG LockKey, BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus,
PDEVICE_OBJECT DeviceObject) {
fcb* fcb = FileObject->FsContext;
LARGE_INTEGER len2;
UNUSED(Wait);
UNUSED(IoStatus);
UNUSED(DeviceObject);
len2.QuadPart = Length;
if (CheckForReadOperation) {
if (FsRtlFastCheckLockForRead(&fcb->lock, FileOffset, &len2, LockKey, FileObject, PsGetCurrentProcess()))
return true;
} else {
if (!fcb->Vcb->readonly && !is_subvol_readonly(fcb->subvol, NULL) && FsRtlFastCheckLockForWrite(&fcb->lock, FileOffset, &len2, LockKey, FileObject, PsGetCurrentProcess()))
return true;
}
return false;
}
_Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
static BOOLEAN __stdcall fast_io_query_network_open_info(PFILE_OBJECT FileObject, BOOLEAN Wait, FILE_NETWORK_OPEN_INFORMATION* fnoi,
PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb;
ccb* ccb;
file_ref* fileref;
FsRtlEnterFileSystem();
TRACE("(%p, %u, %p, %p, %p)\n", FileObject, Wait, fnoi, IoStatus, DeviceObject);
RtlZeroMemory(fnoi, sizeof(FILE_NETWORK_OPEN_INFORMATION));
fcb = FileObject->FsContext;
if (!fcb || fcb == fcb->Vcb->volume_fcb) {
FsRtlExitFileSystem();
return false;
}
ccb = FileObject->FsContext2;
if (!ccb) {
FsRtlExitFileSystem();
return false;
}
fileref = ccb->fileref;
if (fcb == fcb->Vcb->dummy_fcb) {
LARGE_INTEGER time;
KeQuerySystemTime(&time);
fnoi->CreationTime = fnoi->LastAccessTime = fnoi->LastWriteTime = fnoi->ChangeTime = time;
} else {
INODE_ITEM* ii;
if (fcb->ads) {
if (!fileref || !fileref->parent) {
ERR("no fileref for stream\n");
FsRtlExitFileSystem();
return false;
}
ii = &fileref->parent->fcb->inode_item;
} else
ii = &fcb->inode_item;
fnoi->CreationTime.QuadPart = unix_time_to_win(&ii->otime);
fnoi->LastAccessTime.QuadPart = unix_time_to_win(&ii->st_atime);
fnoi->LastWriteTime.QuadPart = unix_time_to_win(&ii->st_mtime);
fnoi->ChangeTime.QuadPart = unix_time_to_win(&ii->st_ctime);
}
if (fcb->ads) {
fnoi->AllocationSize.QuadPart = fnoi->EndOfFile.QuadPart = fcb->adsdata.Length;
fnoi->FileAttributes = fileref->parent->fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fileref->parent->fcb->atts;
} else {
fnoi->AllocationSize.QuadPart = fcb_alloc_size(fcb);
fnoi->EndOfFile.QuadPart = S_ISDIR(fcb->inode_item.st_mode) ? 0 : fcb->inode_item.st_size;
fnoi->FileAttributes = fcb->atts == 0 ? FILE_ATTRIBUTE_NORMAL : fcb->atts;
}
FsRtlExitFileSystem();
return true;
}
_Function_class_(FAST_IO_ACQUIRE_FOR_MOD_WRITE)
static NTSTATUS __stdcall fast_io_acquire_for_mod_write(PFILE_OBJECT FileObject, PLARGE_INTEGER EndingOffset,
struct _ERESOURCE **ResourceToRelease, PDEVICE_OBJECT DeviceObject) {
fcb* fcb;
TRACE("(%p, %I64x, %p, %p)\n", FileObject, EndingOffset ? EndingOffset->QuadPart : 0, ResourceToRelease, DeviceObject);
UNUSED(EndingOffset);
UNUSED(DeviceObject);
fcb = FileObject->FsContext;
if (!fcb)
return STATUS_INVALID_PARAMETER;
// Make sure we don't get interrupted by the flush thread, which can cause a deadlock
if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, false))
return STATUS_CANT_WAIT;
if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, false)) {
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
TRACE("returning STATUS_CANT_WAIT\n");
return STATUS_CANT_WAIT;
}
// Ideally this would be PagingIoResource, but that doesn't play well with copy-on-write,
// as we can't guarantee that we won't need to do any reallocations.
*ResourceToRelease = fcb->Header.Resource;
TRACE("returning STATUS_SUCCESS\n");
return STATUS_SUCCESS;
}
_Function_class_(FAST_IO_RELEASE_FOR_MOD_WRITE)
static NTSTATUS __stdcall fast_io_release_for_mod_write(PFILE_OBJECT FileObject, struct _ERESOURCE *ResourceToRelease,
PDEVICE_OBJECT DeviceObject) {
fcb* fcb;
TRACE("(%p, %p, %p)\n", FileObject, ResourceToRelease, DeviceObject);
UNUSED(DeviceObject);
fcb = FileObject->FsContext;
ExReleaseResourceLite(ResourceToRelease);
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
return STATUS_SUCCESS;
}
_Function_class_(FAST_IO_ACQUIRE_FOR_CCFLUSH)
static NTSTATUS __stdcall fast_io_acquire_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
UNUSED(FileObject);
UNUSED(DeviceObject);
IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return STATUS_SUCCESS;
}
_Function_class_(FAST_IO_RELEASE_FOR_CCFLUSH)
static NTSTATUS __stdcall fast_io_release_for_ccflush(PFILE_OBJECT FileObject, PDEVICE_OBJECT DeviceObject) {
UNUSED(FileObject);
UNUSED(DeviceObject);
if (IoGetTopLevelIrp() == (PIRP)FSRTL_CACHE_TOP_LEVEL_IRP)
IoSetTopLevelIrp(NULL);
return STATUS_SUCCESS;
}
_Function_class_(FAST_IO_WRITE)
static BOOLEAN __stdcall fast_io_write(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb = FileObject->FsContext;
bool ret;
FsRtlEnterFileSystem();
if (!ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, Wait)) {
FsRtlExitFileSystem();
return false;
}
if (!ExAcquireResourceExclusiveLite(fcb->Header.Resource, Wait)) {
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
FsRtlExitFileSystem();
return false;
}
ret = FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
if (ret)
fcb->inode_item.st_size = fcb->Header.FileSize.QuadPart;
ExReleaseResourceLite(fcb->Header.Resource);
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
FsRtlExitFileSystem();
return ret;
}
_Function_class_(FAST_IO_LOCK)
static BOOLEAN __stdcall fast_io_lock(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PLARGE_INTEGER Length, PEPROCESS ProcessId,
ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, PIO_STATUS_BLOCK IoStatus,
PDEVICE_OBJECT DeviceObject) {
BOOLEAN ret;
fcb* fcb = FileObject->FsContext;
TRACE("(%p, %I64x, %I64x, %p, %lx, %u, %u, %p, %p)\n", FileObject, FileOffset ? FileOffset->QuadPart : 0, Length ? Length->QuadPart : 0,
ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, DeviceObject);
if (fcb->type != BTRFS_TYPE_FILE) {
WARN("can only lock files\n");
IoStatus->Status = STATUS_INVALID_PARAMETER;
IoStatus->Information = 0;
return true;
}
FsRtlEnterFileSystem();
ExAcquireResourceSharedLite(fcb->Header.Resource, true);
ret = FsRtlFastLock(&fcb->lock, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately,
ExclusiveLock, IoStatus, NULL, false);
if (ret)
fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
ExReleaseResourceLite(fcb->Header.Resource);
FsRtlExitFileSystem();
return ret;
}
_Function_class_(FAST_IO_UNLOCK_SINGLE)
static BOOLEAN __stdcall fast_io_unlock_single(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PLARGE_INTEGER Length, PEPROCESS ProcessId,
ULONG Key, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb = FileObject->FsContext;
TRACE("(%p, %I64x, %I64x, %p, %lx, %p, %p)\n", FileObject, FileOffset ? FileOffset->QuadPart : 0, Length ? Length->QuadPart : 0,
ProcessId, Key, IoStatus, DeviceObject);
IoStatus->Information = 0;
if (fcb->type != BTRFS_TYPE_FILE) {
WARN("can only lock files\n");
IoStatus->Status = STATUS_INVALID_PARAMETER;
return true;
}
FsRtlEnterFileSystem();
IoStatus->Status = FsRtlFastUnlockSingle(&fcb->lock, FileObject, FileOffset, Length, ProcessId, Key, NULL, false);
fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
FsRtlExitFileSystem();
return true;
}
_Function_class_(FAST_IO_UNLOCK_ALL)
static BOOLEAN __stdcall fast_io_unlock_all(PFILE_OBJECT FileObject, PEPROCESS ProcessId, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb = FileObject->FsContext;
TRACE("(%p, %p, %p, %p)\n", FileObject, ProcessId, IoStatus, DeviceObject);
IoStatus->Information = 0;
if (fcb->type != BTRFS_TYPE_FILE) {
WARN("can only lock files\n");
IoStatus->Status = STATUS_INVALID_PARAMETER;
return true;
}
FsRtlEnterFileSystem();
ExAcquireResourceSharedLite(fcb->Header.Resource, true);
IoStatus->Status = FsRtlFastUnlockAll(&fcb->lock, FileObject, ProcessId, NULL);
fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
ExReleaseResourceLite(fcb->Header.Resource);
FsRtlExitFileSystem();
return true;
}
_Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY)
static BOOLEAN __stdcall fast_io_unlock_all_by_key(PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key,
PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) {
fcb* fcb = FileObject->FsContext;
TRACE("(%p, %p, %lx, %p, %p)\n", FileObject, ProcessId, Key, IoStatus, DeviceObject);
IoStatus->Information = 0;
if (fcb->type != BTRFS_TYPE_FILE) {
WARN("can only lock files\n");
IoStatus->Status = STATUS_INVALID_PARAMETER;
return true;
}
FsRtlEnterFileSystem();
ExAcquireResourceSharedLite(fcb->Header.Resource, true);
IoStatus->Status = FsRtlFastUnlockAllByKey(&fcb->lock, FileObject, ProcessId, Key, NULL);
fcb->Header.IsFastIoPossible = fast_io_possible(fcb);
ExReleaseResourceLite(fcb->Header.Resource);
FsRtlExitFileSystem();
return true;
}
void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) {
RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch));
FastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
FastIoDispatch.FastIoCheckIfPossible = fast_io_check_if_possible;
FastIoDispatch.FastIoRead = FsRtlCopyRead;
FastIoDispatch.FastIoWrite = fast_io_write;
FastIoDispatch.FastIoQueryBasicInfo = fast_query_basic_info;
FastIoDispatch.FastIoQueryStandardInfo = fast_query_standard_info;
FastIoDispatch.FastIoLock = fast_io_lock;
FastIoDispatch.FastIoUnlockSingle = fast_io_unlock_single;
FastIoDispatch.FastIoUnlockAll = fast_io_unlock_all;
FastIoDispatch.FastIoUnlockAllByKey = fast_io_unlock_all_by_key;
FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info;
FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write;
FastIoDispatch.MdlRead = FsRtlMdlReadDev;
FastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
FastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
FastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
FastIoDispatch.ReleaseForModWrite = fast_io_release_for_mod_write;
FastIoDispatch.AcquireForCcFlush = fast_io_acquire_for_ccflush;
FastIoDispatch.ReleaseForCcFlush = fast_io_release_for_ccflush;
*fiod = &FastIoDispatch;
}

5916
external/btrfs/src/fileinfo.c vendored Normal file

File diff suppressed because it is too large Load Diff

7829
external/btrfs/src/flushthread.c vendored Normal file

File diff suppressed because it is too large Load Diff

2056
external/btrfs/src/free-space.c vendored Normal file

File diff suppressed because it is too large Load Diff

5546
external/btrfs/src/fsctl.c vendored Normal file

File diff suppressed because it is too large Load Diff

126
external/btrfs/src/fsrtl.c vendored Normal file
View File

@ -0,0 +1,126 @@
/*
* PROJECT: ReactOS Kernel - Vista+ APIs
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* FILE: lib/drivers/ntoskrnl_vista/fsrtl.c
* PURPOSE: FsRtl functions of Vista+
* PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
*/
#include <ntifs.h>
#include <ntdef.h>
FORCEINLINE
BOOLEAN
IsNullGuid(IN PGUID Guid)
{
if (Guid->Data1 == 0 && Guid->Data2 == 0 && Guid->Data3 == 0 &&
((ULONG *)Guid->Data4)[0] == 0 && ((ULONG *)Guid->Data4)[1] == 0)
{
return TRUE;
}
return FALSE;
}
FORCEINLINE
BOOLEAN
IsEven(IN USHORT Digit)
{
return ((Digit & 1) != 1);
}
NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer)
{
USHORT DataLength;
ULONG ReparseTag;
PREPARSE_GUID_DATA_BUFFER GuidBuffer;
/* Validate data size range */
if (BufferLength < REPARSE_DATA_BUFFER_HEADER_SIZE || BufferLength > MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
{
return STATUS_IO_REPARSE_DATA_INVALID;
}
GuidBuffer = (PREPARSE_GUID_DATA_BUFFER)ReparseBuffer;
DataLength = ReparseBuffer->ReparseDataLength;
ReparseTag = ReparseBuffer->ReparseTag;
/* Validate size consistency */
if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE != BufferLength && DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE != BufferLength)
{
return STATUS_IO_REPARSE_DATA_INVALID;
}
/* REPARSE_DATA_BUFFER is reserved for MS tags */
if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE == BufferLength && !IsReparseTagMicrosoft(ReparseTag))
{
return STATUS_IO_REPARSE_DATA_INVALID;
}
/* If that a GUID data buffer, its GUID cannot be null, and it cannot contain a MS tag */
if (DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE == BufferLength && ((!IsReparseTagMicrosoft(ReparseTag)
&& IsNullGuid(&GuidBuffer->ReparseGuid)) || (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT || ReparseTag == IO_REPARSE_TAG_SYMLINK)))
{
return STATUS_IO_REPARSE_DATA_INVALID;
}
/* Check the data for MS non reserved tags */
if (!(ReparseTag & 0xFFF0000) && ReparseTag != IO_REPARSE_TAG_RESERVED_ZERO && ReparseTag != IO_REPARSE_TAG_RESERVED_ONE)
{
/* If that's a mount point, validate the MountPointReparseBuffer branch */
if (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
{
/* We need information */
if (DataLength >= REPARSE_DATA_BUFFER_HEADER_SIZE)
{
/* Substitue must be the first in row */
if (!ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset)
{
/* Substitude must be null-terminated */
if (ReparseBuffer->MountPointReparseBuffer.PrintNameOffset == ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL))
{
/* There must just be the Offset/Length fields + buffer + 2 null chars */
if (DataLength == ReparseBuffer->MountPointReparseBuffer.PrintNameLength + ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.SubstituteNameOffset)) + 2 * sizeof(UNICODE_NULL))
{
return STATUS_SUCCESS;
}
}
}
}
}
else
{
#define FIELDS_SIZE (FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))
/* If that's not a symlink, accept the MS tag as it */
if (ReparseTag != IO_REPARSE_TAG_SYMLINK)
{
return STATUS_SUCCESS;
}
/* We need information */
if (DataLength >= FIELDS_SIZE)
{
/* Validate lengths */
if (ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength && ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength)
{
/* Validate unicode strings */
if (IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength) &&
IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset))
{
if ((DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset + ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE)
&& (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE))
{
return STATUS_SUCCESS;
}
}
}
}
#undef FIELDS_SIZE
}
return STATUS_IO_REPARSE_DATA_INVALID;
}
return STATUS_IO_REPARSE_TAG_INVALID;
}

141
external/btrfs/src/galois.c vendored Normal file
View File

@ -0,0 +1,141 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
static const uint8_t glog[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01};
static const uint8_t gilog[] = {0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf};
// divides the bytes in data by 2^div
void galois_divpower(uint8_t* data, uint8_t div, uint32_t len) {
while (len > 0) {
if (data[0] != 0) {
if (gilog[data[0]] <= div)
data[0] = glog[(gilog[data[0]] + (255 - div)) % 255];
else
data[0] = glog[(gilog[data[0]] - div) % 255];
}
data++;
len--;
}
}
uint8_t gpow2(uint8_t e) {
return glog[e%255];
}
uint8_t gmul(uint8_t a, uint8_t b) {
if (a == 0 || b == 0)
return 0;
else
return glog[(gilog[a] + gilog[b]) % 255];
}
uint8_t gdiv(uint8_t a, uint8_t b) {
if (b == 0) {
return 0xff; // shouldn't happen
} else if (a == 0) {
return 0;
} else {
if (gilog[a] >= gilog[b])
return glog[(gilog[a] - gilog[b]) % 255];
else
return glog[255-((gilog[b] - gilog[a]) % 255)];
}
}
// The code from the following functions is derived from the paper
// "The mathematics of RAID-6", by H. Peter Anvin.
// https://www.kernel.org/pub/linux/kernel/people/hpa/raid6.pdf
#if defined(_AMD64_) || defined(_ARM64_)
__inline static uint64_t galois_double_mask64(uint64_t v) {
v &= 0x8080808080808080;
return (v << 1) - (v >> 7);
}
#else
__inline static uint32_t galois_double_mask32(uint32_t v) {
v &= 0x80808080;
return (v << 1) - (v >> 7);
}
#endif
void galois_double(uint8_t* data, uint32_t len) {
// FIXME - SIMD?
#if defined(_AMD64_) || defined(_ARM64_)
while (len > sizeof(uint64_t)) {
uint64_t v = *((uint64_t*)data), vv;
vv = (v << 1) & 0xfefefefefefefefe;
vv ^= galois_double_mask64(v) & 0x1d1d1d1d1d1d1d1d;
*((uint64_t*)data) = vv;
data += sizeof(uint64_t);
len -= sizeof(uint64_t);
}
#else
while (len > sizeof(uint32_t)) {
uint32_t v = *((uint32_t*)data), vv;
vv = (v << 1) & 0xfefefefe;
vv ^= galois_double_mask32(v) & 0x1d1d1d1d;
*((uint32_t*)data) = vv;
data += sizeof(uint32_t);
len -= sizeof(uint32_t);
}
#endif
while (len > 0) {
data[0] = (data[0] << 1) ^ ((data[0] & 0x80) ? 0x1d : 0);
data++;
len--;
}
}

20
external/btrfs/src/mkbtrfs/Makefile vendored Normal file
View File

@ -0,0 +1,20 @@
OBJS = mkbtrfs.o
INCLUDES = -I/usr/i686-w64-mingw32/usr/include/ddk
CFLAGS = -Wall $(INCLUDES) -fvtable-verify=none
LIBS = -lntdll
CC = i686-w64-mingw32-gcc
all: mkbtrfs.exe
ubtrfs.o: ubtrfs.c
$(CC) $(CFLAGS) -c -o $@ $<
mkbtrfs.exe: $(OBJS)
$(CC) -o $@ $(OBJS) $(LIBS)
clean:
rm -f *.o mkbtrfs.exe

342
external/btrfs/src/mkbtrfs/mkbtrfs.c vendored Normal file
View File

@ -0,0 +1,342 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include <windef.h>
#include <winbase.h>
#include <winternl.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stringapiset.h>
#include "resource.h"
#include "../btrfs.h"
#define UBTRFS_DLL L"ubtrfs.dll"
// These are undocumented, and what comes from format.exe
typedef struct {
void* table;
void* unk1;
WCHAR* string;
} DSTRING;
typedef struct {
void* table;
} STREAM_MESSAGE;
#define FORMAT_FLAG_QUICK_FORMAT 0x00000001
#define FORMAT_FLAG_UNKNOWN1 0x00000002
#define FORMAT_FLAG_DISMOUNT_FIRST 0x00000004
#define FORMAT_FLAG_UNKNOWN2 0x00000040
#define FORMAT_FLAG_LARGE_RECORDS 0x00000100
#define FORMAT_FLAG_INTEGRITY_DISABLE 0x00000100
typedef struct {
uint16_t unk1;
uint16_t unk2;
uint32_t flags;
DSTRING* label;
} options;
typedef BOOL (__stdcall* pFormatEx)(DSTRING* root, STREAM_MESSAGE* message, options* opts, uint32_t unk1);
typedef void (__stdcall* pSetSizes)(ULONG sector, ULONG node);
typedef void (__stdcall* pSetIncompatFlags)(uint64_t incompat_flags);
typedef void (__stdcall* pSetCsumType)(uint16_t csum_type);
static void print_string(FILE* f, int resid, ...) {
WCHAR s[1024], t[1024];
va_list ap;
if (!LoadStringW(GetModuleHandle(NULL), resid, s, sizeof(s) / sizeof(WCHAR))) {
fprintf(stderr, "LoadString failed (error %lu)\n", GetLastError());
return;
}
va_start(ap, resid);
vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap);
fwprintf(f, L"%s\n", t);
va_end(ap);
}
int main(int argc, char** argv) {
HMODULE ubtrfs;
bool baddrive = false, success;
char *ds = NULL, *labels = NULL;
WCHAR dsw[10], labelw[255], dsw2[255];
UNICODE_STRING drive, label;
pFormatEx FormatEx;
options opts;
DSTRING labelds, rootds;
ULONG sector_size = 0, node_size = 0;
int i;
bool invalid_args = false;
uint64_t incompat_flags = BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF | BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA;
uint16_t csum_type = CSUM_TYPE_CRC32C;
pSetIncompatFlags SetIncompatFlags;
pSetCsumType SetCsumType;
if (argc >= 2) {
for (i = 1; i < argc; i++) {
if (argv[i][0] == '/' && argv[i][1] != 0) {
char cmd[255], *colon;
colon = strstr(argv[i], ":");
if (colon) {
memcpy(cmd, argv[i] + 1, colon - argv[i] - 1);
cmd[colon - argv[i] - 1] = 0;
} else
strcpy(cmd, argv[i] + 1);
if (!_stricmp(cmd, "sectorsize")) {
if (!colon || colon[1] == 0) {
print_string(stdout, IDS_NO_SECTOR_SIZE);
invalid_args = true;
break;
} else
sector_size = atoi(&colon[1]);
} else if (!_stricmp(cmd, "nodesize")) {
if (!colon || colon[1] == 0) {
print_string(stdout, IDS_NO_NODE_SIZE);
invalid_args = true;
break;
} else
node_size = atoi(&colon[1]);
} else if (!_stricmp(cmd, "csum")) {
char* v;
if (!colon || colon[1] == 0) {
print_string(stdout, IDS_NO_CSUM);
invalid_args = true;
break;
}
v = &colon[1];
if (!_stricmp(v, "crc32c"))
csum_type = CSUM_TYPE_CRC32C;
else if (!_stricmp(v, "xxhash"))
csum_type = CSUM_TYPE_XXHASH;
else if (!_stricmp(v, "sha256"))
csum_type = CSUM_TYPE_SHA256;
else if (!_stricmp(v, "blake2"))
csum_type = CSUM_TYPE_BLAKE2;
else {
print_string(stdout, IDS_INVALID_CSUM_TYPE);
invalid_args = true;
break;
}
} else if (!_stricmp(cmd, "mixed"))
incompat_flags |= BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS;
else if (!_stricmp(cmd, "notmixed"))
incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS;
else if (!_stricmp(cmd, "extiref"))
incompat_flags |= BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF;
else if (!_stricmp(cmd, "notextiref"))
incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF;
else if (!_stricmp(cmd, "skinnymetadata"))
incompat_flags |= BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA;
else if (!_stricmp(cmd, "notskinnymetadata"))
incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA;
else if (!_stricmp(cmd, "noholes"))
incompat_flags |= BTRFS_INCOMPAT_FLAGS_NO_HOLES;
else if (!_stricmp(cmd, "notnoholes"))
incompat_flags &= ~BTRFS_INCOMPAT_FLAGS_NO_HOLES;
else {
print_string(stdout, IDS_UNKNOWN_ARG);
invalid_args = true;
break;
}
} else {
if (!ds)
ds = argv[i];
else if (!labels)
labels = argv[i];
else {
print_string(stdout, IDS_TOO_MANY_ARGS);
invalid_args = true;
break;
}
}
}
} else
invalid_args = true;
if (invalid_args) {
char* c = argv[0] + strlen(argv[0]) - 1;
char* fn = NULL;
WCHAR fnw[MAX_PATH], *s;
int ret;
while (c > argv[0]) {
if (*c == '/' || *c == '\\') {
fn = c + 1;
break;
}
c--;
}
if (!fn)
fn = argv[0];
if (!MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, fn, -1, fnw, sizeof(fnw) / sizeof(WCHAR))) {
print_string(stderr, IDS_MULTIBYTE_FAILED, GetLastError());
return 1;
}
print_string(stdout, IDS_USAGE, fnw);
ret = LoadStringW(GetModuleHandle(NULL), IDS_USAGE2, (WCHAR*)&s, 0);
if (!ret) {
fprintf(stderr, "LoadString failed (error %lu)\n", GetLastError());
return 0;
}
fwprintf(stdout, L"%.*s\n", ret, s);
return 0;
}
if (ds[0] != '\\') {
if ((ds[0] >= 'A' && ds[0] <= 'Z') || (ds[0] >= 'a' && ds[0] <= 'z')) {
if (ds[1] == 0 || (ds[1] == ':' && ds[2] == 0) || (ds[1] == ':' && ds[2] == '\\' && ds[3] == 0)) {
dsw[0] = '\\';
dsw[1] = '?';
dsw[2] = '?';
dsw[3] = '\\';
dsw[4] = ds[0];
dsw[5] = ':';
dsw[6] = 0;
drive.Buffer = dsw;
drive.Length = drive.MaximumLength = (USHORT)(wcslen(drive.Buffer) * sizeof(WCHAR));
} else
baddrive = true;
} else
baddrive = true;
} else {
if (!MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, ds, -1, dsw2, sizeof(dsw2) / sizeof(WCHAR))) {
print_string(stderr, IDS_MULTIBYTE_FAILED, GetLastError());
return 1;
}
drive.Buffer = dsw2;
drive.Length = drive.MaximumLength = (USHORT)(wcslen(drive.Buffer) * sizeof(WCHAR));
}
if (baddrive) {
if (!MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, ds, -1, dsw2, sizeof(dsw2) / sizeof(WCHAR))) {
print_string(stderr, IDS_MULTIBYTE_FAILED, GetLastError());
return 1;
}
print_string(stderr, IDS_CANT_RECOGNIZE_DRIVE, dsw2);
return 1;
}
if (labels) {
if (!MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, labels, -1, labelw, sizeof(labelw) / sizeof(WCHAR))) {
print_string(stderr, IDS_MULTIBYTE_FAILED, GetLastError());
return 1;
}
label.Buffer = labelw;
label.Length = label.MaximumLength = (USHORT)(wcslen(labelw) * sizeof(WCHAR));
} else {
label.Buffer = NULL;
label.Length = label.MaximumLength = 0;
}
ubtrfs = LoadLibraryW(UBTRFS_DLL);
if (!ubtrfs) {
#if defined(__i386) || defined(_M_IX86)
ubtrfs = LoadLibraryW(L"Debug\\x86\\ubtrfs.dll");
#elif defined(__x86_64__) || defined(_M_X64)
ubtrfs = LoadLibraryW(L"Debug\\x64\\ubtrfs.dll");
#endif
}
if (!ubtrfs) {
print_string(stderr, IDS_CANT_LOAD_DLL, UBTRFS_DLL);
return 1;
}
if (node_size != 0 || sector_size != 0) {
pSetSizes SetSizes;
SetSizes = (pSetSizes)GetProcAddress(ubtrfs, "SetSizes");
if (!SetSizes) {
print_string(stderr, IDS_CANT_FIND_SETSIZES, UBTRFS_DLL);
return 1;
}
SetSizes(node_size, sector_size);
}
SetIncompatFlags = (pSetIncompatFlags)GetProcAddress(ubtrfs, "SetIncompatFlags");
if (!SetIncompatFlags) {
print_string(stderr, IDS_CANT_FIND_SETINCOMPATFLAGS, UBTRFS_DLL);
return 1;
}
SetIncompatFlags(incompat_flags);
SetCsumType = (pSetCsumType)GetProcAddress(ubtrfs, "SetCsumType");
if (!SetCsumType) {
print_string(stderr, IDS_CANT_FIND_SETCSUMTYPE, UBTRFS_DLL);
return 1;
}
SetCsumType(csum_type);
FormatEx = (pFormatEx)GetProcAddress(ubtrfs, "FormatEx");
if (!FormatEx) {
print_string(stderr, IDS_CANT_FIND_FORMATEX, UBTRFS_DLL);
return 1;
}
memset(&opts, 0, sizeof(options));
if (label.Length > 0) {
labelds.string = label.Buffer;
opts.label = &labelds;
}
rootds.string = drive.Buffer;
success = FormatEx(&rootds, NULL, &opts, 0);
if (!success) {
print_string(stderr, IDS_FORMATEX_ERROR);
return 1;
}
print_string(stdout, IDS_SUCCESS);
return 0;
}

131
external/btrfs/src/mkbtrfs/mkbtrfs.rc vendored Normal file
View File

@ -0,0 +1,131 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,0,0
PRODUCTVERSION 1,7,0,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x0L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileDescription", "Btrfs formatting utility"
VALUE "FileVersion", "1.7"
VALUE "InternalName", "mkbtrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20"
VALUE "OriginalFilename", "mkbtrfs.exe"
VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "1.7"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_USAGE "Usage: %s device [label]\n"
IDS_MULTIBYTE_FAILED "MultiByteToWideChar failed (error %lu)"
IDS_CANT_RECOGNIZE_DRIVE "Could not recognize drive %s"
IDS_CANT_LOAD_DLL "Unable to load %s"
IDS_CANT_FIND_FORMATEX "Could not load function FormatEx in %s"
IDS_FORMATEX_ERROR "FormatEx failed"
IDS_SUCCESS "Completed successfully."
IDS_CANT_FIND_SETSIZES "Could not load function SetSizes in %s"
IDS_TOO_MANY_ARGS "Too many arguments."
IDS_UNKNOWN_ARG "Unknown argument."
IDS_NO_SECTOR_SIZE "No sector size specified."
END
STRINGTABLE
BEGIN
IDS_NO_NODE_SIZE "No node size specified."
IDS_CANT_FIND_SETINCOMPATFLAGS
"Could not load function SetIncompatFlags in %s"
IDS_USAGE2 "The device parameter can either be a drive letter, e.g. D:, or a device path,\nsuch as \\Device\\Harddisk0\\Partition2.\n\nTo format the whole of the first hard disk without using partitions, you would\nneed to use the parameter \\Device\\Harddisk0\\Partition0.\n\nSupported flags:\n\n/sectorsize:num Sets the sector size. This must be a\n multiple of the size that the disk itself\n reports. The default is 4096, which should\n be used unless you have a good reason.\n\n/nodesize:num Sets the node size, i.e. the size of the\n metadata trees. The default is 16384. This\n needs to either be the same as sector size,\n or a power of two multiple.\n \n/csum:id Sets the checksum algorithm to use. Valid\n values are crc32c, xxhash, sha256, and\n blake2.\n\n/mixed Enables or disable mixed block groups,\n/notmixed which store data and and metadata in the\n same chunks. The default is disabled. This\n is only useful for very small filesystems.\n\n/extiref Enables or disables extended inode refs,\n/notextiref which increase the number of hardlinks\n allowed. The default is enabled.\n\n/skinnymetadata Enables or disable skinny metadata, which\n/notskinnymetadata allows more efficient storage of metadata\n refs. The default is enabled.\n\n/noholes Enables or disables whether sparse extents\n/notnoholes should be stored implicitly, which can save\n a little space. The default is disabled."
IDS_CANT_FIND_SETCSUMTYPE "Could not load function SetCsumType in %s"
IDS_NO_CSUM "No csum value given. Valid values are crc32c, xxhash, sha256, and blake2."
IDS_INVALID_CSUM_TYPE "Invalid csum value. Valid values are crc32c, xxhash, sha256, and blake2."
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

32
external/btrfs/src/mkbtrfs/resource.h vendored Normal file
View File

@ -0,0 +1,32 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by mkbtrfs.rc
//
#define IDS_USAGE 101
#define IDS_MULTIBYTE_FAILED 102
#define IDS_CANT_RECOGNIZE_DRIVE 103
#define IDS_CANT_LOAD_DLL 104
#define IDS_CANT_FIND_FORMATEX 105
#define IDS_FORMATEX_ERROR 106
#define IDS_SUCCESS 107
#define IDS_CANT_FIND_SETSIZES 108
#define IDS_TOO_MANY_ARGS 109
#define IDS_UNKNOWN_ARG 110
#define IDS_NO_SECTOR_SIZE 111
#define IDS_NO_NODE_SIZE 112
#define IDS_CANT_FIND_SETINCOMPATFLAGS 113
#define IDS_USAGE2 114
#define IDS_CANT_FIND_SETCSUMTYPE 115
#define IDS_NO_CSUM 116
#define IDS_INVALID_CSUM_TYPE 117
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

693
external/btrfs/src/pnp.c vendored Normal file
View File

@ -0,0 +1,693 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "btrfs_drv.h"
struct pnp_context;
typedef struct {
struct pnp_context* context;
PIRP Irp;
IO_STATUS_BLOCK iosb;
NTSTATUS Status;
device* dev;
} pnp_stripe;
typedef struct {
KEVENT Event;
NTSTATUS Status;
LONG left;
pnp_stripe* stripes;
} pnp_context;
extern ERESOURCE pdo_list_lock;
extern LIST_ENTRY pdo_list;
_Function_class_(IO_COMPLETION_ROUTINE)
static NTSTATUS __stdcall pnp_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID conptr) {
pnp_stripe* stripe = conptr;
pnp_context* context = (pnp_context*)stripe->context;
UNUSED(DeviceObject);
stripe->Status = Irp->IoStatus.Status;
InterlockedDecrement(&context->left);
if (context->left == 0)
KeSetEvent(&context->Event, 0, false);
return STATUS_MORE_PROCESSING_REQUIRED;
}
static NTSTATUS send_disks_pnp_message(device_extension* Vcb, UCHAR minor) {
pnp_context context;
ULONG num_devices, i;
NTSTATUS Status;
LIST_ENTRY* le;
RtlZeroMemory(&context, sizeof(pnp_context));
KeInitializeEvent(&context.Event, NotificationEvent, false);
num_devices = (ULONG)min(0xffffffff, Vcb->superblock.num_devices);
context.stripes = ExAllocatePoolWithTag(NonPagedPool, sizeof(pnp_stripe) * num_devices, ALLOC_TAG);
if (!context.stripes) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(context.stripes, sizeof(pnp_stripe) * num_devices);
i = 0;
le = Vcb->devices.Flink;
while (le != &Vcb->devices) {
PIO_STACK_LOCATION IrpSp;
device* dev = CONTAINING_RECORD(le, device, list_entry);
if (dev->devobj) {
context.stripes[i].context = (struct pnp_context*)&context;
context.stripes[i].Irp = IoAllocateIrp(dev->devobj->StackSize, false);
if (!context.stripes[i].Irp) {
uint64_t j;
ERR("IoAllocateIrp failed\n");
for (j = 0; j < i; j++) {
if (context.stripes[j].dev->devobj) {
IoFreeIrp(context.stripes[j].Irp);
}
}
ExFreePool(context.stripes);
return STATUS_INSUFFICIENT_RESOURCES;
}
IrpSp = IoGetNextIrpStackLocation(context.stripes[i].Irp);
IrpSp->MajorFunction = IRP_MJ_PNP;
IrpSp->MinorFunction = minor;
IrpSp->FileObject = dev->fileobj;
context.stripes[i].Irp->UserIosb = &context.stripes[i].iosb;
IoSetCompletionRoutine(context.stripes[i].Irp, pnp_completion, &context.stripes[i], true, true, true);
context.stripes[i].Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
context.stripes[i].dev = dev;
context.left++;
}
le = le->Flink;
}
if (context.left == 0) {
Status = STATUS_SUCCESS;
goto end;
}
for (i = 0; i < num_devices; i++) {
if (context.stripes[i].Irp) {
IoCallDriver(context.stripes[i].dev->devobj, context.stripes[i].Irp);
}
}
KeWaitForSingleObject(&context.Event, Executive, KernelMode, false, NULL);
Status = STATUS_SUCCESS;
for (i = 0; i < num_devices; i++) {
if (context.stripes[i].Irp) {
if (context.stripes[i].Status != STATUS_SUCCESS)
Status = context.stripes[i].Status;
}
}
end:
for (i = 0; i < num_devices; i++) {
if (context.stripes[i].Irp) {
IoFreeIrp(context.stripes[i].Irp);
}
}
ExFreePool(context.stripes);
return Status;
}
static NTSTATUS pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject) {
device_extension* Vcb = DeviceObject->DeviceExtension;
NTSTATUS Status;
ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
ExAcquireResourceExclusiveLite(&Vcb->fileref_lock, true);
if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
Status = STATUS_ACCESS_DENIED;
goto end;
}
Status = send_disks_pnp_message(Vcb, IRP_MN_CANCEL_REMOVE_DEVICE);
if (!NT_SUCCESS(Status)) {
WARN("send_disks_pnp_message returned %08lx\n", Status);
goto end;
}
end:
ExReleaseResourceLite(&Vcb->fileref_lock);
ExReleaseResourceLite(&Vcb->tree_lock);
return STATUS_SUCCESS;
}
NTSTATUS pnp_query_remove_device(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
device_extension* Vcb = DeviceObject->DeviceExtension;
NTSTATUS Status;
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
if (Vcb->root_fileref && Vcb->root_fileref->fcb && (Vcb->root_fileref->open_count > 0 || has_open_children(Vcb->root_fileref))) {
ExReleaseResourceLite(&Vcb->tree_lock);
return STATUS_ACCESS_DENIED;
}
Status = send_disks_pnp_message(Vcb, IRP_MN_QUERY_REMOVE_DEVICE);
if (!NT_SUCCESS(Status)) {
WARN("send_disks_pnp_message returned %08lx\n", Status);
ExReleaseResourceLite(&Vcb->tree_lock);
return Status;
}
Vcb->removing = true;
if (Vcb->need_write && !Vcb->readonly) {
Status = do_write(Vcb, Irp);
free_trees(Vcb);
if (!NT_SUCCESS(Status)) {
ERR("do_write returned %08lx\n", Status);
ExReleaseResourceLite(&Vcb->tree_lock);
return Status;
}
}
ExReleaseResourceLite(&Vcb->tree_lock);
if (Vcb->open_files == 0)
uninit(Vcb);
return STATUS_SUCCESS;
}
static NTSTATUS pnp_remove_device(PDEVICE_OBJECT DeviceObject) {
device_extension* Vcb = DeviceObject->DeviceExtension;
NTSTATUS Status;
ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
Status = send_disks_pnp_message(Vcb, IRP_MN_REMOVE_DEVICE);
if (!NT_SUCCESS(Status))
WARN("send_disks_pnp_message returned %08lx\n", Status);
ExReleaseResourceLite(&Vcb->tree_lock);
if (DeviceObject->Vpb->Flags & VPB_MOUNTED) {
Status = FsRtlNotifyVolumeEvent(Vcb->root_file, FSRTL_VOLUME_DISMOUNT);
if (!NT_SUCCESS(Status)) {
WARN("FsRtlNotifyVolumeEvent returned %08lx\n", Status);
}
if (Vcb->vde)
Vcb->vde->mounted_device = NULL;
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
Vcb->removing = true;
ExReleaseResourceLite(&Vcb->tree_lock);
if (Vcb->open_files == 0)
uninit(Vcb);
}
return STATUS_SUCCESS;
}
NTSTATUS pnp_surprise_removal(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
device_extension* Vcb = DeviceObject->DeviceExtension;
TRACE("(%p, %p)\n", DeviceObject, Irp);
if (DeviceObject->Vpb->Flags & VPB_MOUNTED) {
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
if (Vcb->vde)
Vcb->vde->mounted_device = NULL;
Vcb->removing = true;
ExReleaseResourceLite(&Vcb->tree_lock);
if (Vcb->open_files == 0)
uninit(Vcb);
}
return STATUS_SUCCESS;
}
static NTSTATUS bus_query_capabilities(PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_CAPABILITIES dc = IrpSp->Parameters.DeviceCapabilities.Capabilities;
dc->UniqueID = true;
dc->SilentInstall = true;
return STATUS_SUCCESS;
}
static NTSTATUS bus_query_device_relations(PIRP Irp) {
NTSTATUS Status;
ULONG num_children;
LIST_ENTRY* le;
ULONG drsize, i;
DEVICE_RELATIONS* dr;
ExAcquireResourceSharedLite(&pdo_list_lock, true);
num_children = 0;
le = pdo_list.Flink;
while (le != &pdo_list) {
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
if (!pdode->dont_report)
num_children++;
le = le->Flink;
}
drsize = offsetof(DEVICE_RELATIONS, Objects[0]) + (num_children * sizeof(PDEVICE_OBJECT));
dr = ExAllocatePoolWithTag(PagedPool, drsize, ALLOC_TAG);
if (!dr) {
ERR("out of memory\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
dr->Count = num_children;
i = 0;
le = pdo_list.Flink;
while (le != &pdo_list) {
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
if (!pdode->dont_report) {
ObReferenceObject(pdode->pdo);
dr->Objects[i] = pdode->pdo;
i++;
}
le = le->Flink;
}
Irp->IoStatus.Information = (ULONG_PTR)dr;
Status = STATUS_SUCCESS;
end:
ExReleaseResourceLite(&pdo_list_lock);
return Status;
}
static NTSTATUS bus_query_hardware_ids(PIRP Irp) {
WCHAR* out;
static const WCHAR ids[] = L"ROOT\\btrfs\0";
out = ExAllocatePoolWithTag(PagedPool, sizeof(ids), ALLOC_TAG);
if (!out) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(out, ids, sizeof(ids));
Irp->IoStatus.Information = (ULONG_PTR)out;
return STATUS_SUCCESS;
}
static NTSTATUS bus_pnp(bus_device_extension* bde, PIRP Irp) {
NTSTATUS Status = Irp->IoStatus.Status;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
bool handled = false;
switch (IrpSp->MinorFunction) {
case IRP_MN_QUERY_CAPABILITIES:
Status = bus_query_capabilities(Irp);
handled = true;
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations || no_pnp)
break;
Status = bus_query_device_relations(Irp);
handled = true;
break;
case IRP_MN_QUERY_ID:
if (IrpSp->Parameters.QueryId.IdType != BusQueryHardwareIDs)
break;
Status = bus_query_hardware_ids(Irp);
handled = true;
break;
}
if (!NT_SUCCESS(Status) && handled) {
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Irp->IoStatus.Status = Status;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(bde->attached_device, Irp);
}
static NTSTATUS pdo_query_device_id(pdo_device_extension* pdode, PIRP Irp) {
WCHAR name[100], *noff, *out;
int i;
static const WCHAR pref[] = L"Btrfs\\";
RtlCopyMemory(name, pref, sizeof(pref) - sizeof(WCHAR));
noff = &name[(sizeof(pref) / sizeof(WCHAR)) - 1];
for (i = 0; i < 16; i++) {
*noff = hex_digit(pdode->uuid.uuid[i] >> 4); noff++;
*noff = hex_digit(pdode->uuid.uuid[i] & 0xf); noff++;
if (i == 3 || i == 5 || i == 7 || i == 9) {
*noff = '-';
noff++;
}
}
*noff = 0;
out = ExAllocatePoolWithTag(PagedPool, (wcslen(name) + 1) * sizeof(WCHAR), ALLOC_TAG);
if (!out) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(out, name, (wcslen(name) + 1) * sizeof(WCHAR));
Irp->IoStatus.Information = (ULONG_PTR)out;
return STATUS_SUCCESS;
}
static NTSTATUS pdo_query_hardware_ids(PIRP Irp) {
WCHAR* out;
static const WCHAR ids[] = L"BtrfsVolume\0";
out = ExAllocatePoolWithTag(PagedPool, sizeof(ids), ALLOC_TAG);
if (!out) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(out, ids, sizeof(ids));
Irp->IoStatus.Information = (ULONG_PTR)out;
return STATUS_SUCCESS;
}
static NTSTATUS pdo_query_id(pdo_device_extension* pdode, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->Parameters.QueryId.IdType) {
case BusQueryDeviceID:
TRACE("BusQueryDeviceID\n");
return pdo_query_device_id(pdode, Irp);
case BusQueryHardwareIDs:
TRACE("BusQueryHardwareIDs\n");
return pdo_query_hardware_ids(Irp);
default:
break;
}
return Irp->IoStatus.Status;
}
typedef struct {
IO_STATUS_BLOCK iosb;
KEVENT Event;
NTSTATUS Status;
} device_usage_context;
_Function_class_(IO_COMPLETION_ROUTINE)
static NTSTATUS __stdcall device_usage_completion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID conptr) {
device_usage_context* context = conptr;
UNUSED(DeviceObject);
context->Status = Irp->IoStatus.Status;
KeSetEvent(&context->Event, 0, false);
return STATUS_MORE_PROCESSING_REQUIRED;
}
static NTSTATUS pdo_device_usage_notification(pdo_device_extension* pdode, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
LIST_ENTRY* le;
TRACE("(%p, %p)\n", pdode, Irp);
ExAcquireResourceSharedLite(&pdode->child_lock, true);
le = pdode->children.Flink;
while (le != &pdode->children) {
volume_child* vc = CONTAINING_RECORD(le, volume_child, list_entry);
if (vc->devobj) {
PIRP Irp2;
PIO_STACK_LOCATION IrpSp2;
device_usage_context context;
Irp2 = IoAllocateIrp(vc->devobj->StackSize, false);
if (!Irp2) {
ERR("out of memory\n");
ExReleaseResourceLite(&pdode->child_lock);
return STATUS_INSUFFICIENT_RESOURCES;
}
IrpSp2 = IoGetNextIrpStackLocation(Irp2);
IrpSp2->MajorFunction = IRP_MJ_PNP;
IrpSp2->MinorFunction = IRP_MN_DEVICE_USAGE_NOTIFICATION;
IrpSp2->Parameters.UsageNotification = IrpSp->Parameters.UsageNotification;
IrpSp2->FileObject = vc->fileobj;
context.iosb.Status = STATUS_SUCCESS;
Irp2->UserIosb = &context.iosb;
KeInitializeEvent(&context.Event, NotificationEvent, false);
Irp2->UserEvent = &context.Event;
IoSetCompletionRoutine(Irp2, device_usage_completion, &context, true, true, true);
context.Status = IoCallDriver(vc->devobj, Irp2);
if (context.Status == STATUS_PENDING)
KeWaitForSingleObject(&context.Event, Executive, KernelMode, false, NULL);
if (!NT_SUCCESS(context.Status)) {
ERR("IoCallDriver returned %08lx\n", context.Status);
ExReleaseResourceLite(&pdode->child_lock);
return context.Status;
}
}
le = le->Flink;
}
ExReleaseResourceLite(&pdode->child_lock);
return STATUS_SUCCESS;
}
static NTSTATUS pdo_query_device_relations(PDEVICE_OBJECT pdo, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_RELATIONS device_relations;
if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
return Irp->IoStatus.Status;
device_relations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), ALLOC_TAG);
if (!device_relations) {
ERR("out of memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
device_relations->Count = 1;
device_relations->Objects[0] = pdo;
ObReferenceObject(pdo);
Irp->IoStatus.Information = (ULONG_PTR)device_relations;
return STATUS_SUCCESS;
}
static NTSTATUS pdo_pnp(PDEVICE_OBJECT pdo, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
pdo_device_extension* pdode = pdo->DeviceExtension;
switch (IrpSp->MinorFunction) {
case IRP_MN_QUERY_ID:
return pdo_query_id(pdode, Irp);
case IRP_MN_START_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_REMOVE_DEVICE:
return STATUS_SUCCESS;
case IRP_MN_QUERY_REMOVE_DEVICE:
return STATUS_UNSUCCESSFUL;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
return pdo_device_usage_notification(pdode, Irp);
case IRP_MN_QUERY_DEVICE_RELATIONS:
return pdo_query_device_relations(pdo, Irp);
}
return Irp->IoStatus.Status;
}
static NTSTATUS pnp_device_usage_notification(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
device_extension* Vcb = DeviceObject->DeviceExtension;
if (IrpSp->Parameters.UsageNotification.InPath) {
switch (IrpSp->Parameters.UsageNotification.Type) {
case DeviceUsageTypePaging:
case DeviceUsageTypeHibernation:
case DeviceUsageTypeDumpFile:
IoAdjustPagingPathCount(&Vcb->page_file_count, IrpSp->Parameters.UsageNotification.InPath);
break;
default:
break;
}
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(Vcb->Vpb->RealDevice, Irp);
}
_Dispatch_type_(IRP_MJ_PNP)
_Function_class_(DRIVER_DISPATCH)
NTSTATUS __stdcall drv_pnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
device_extension* Vcb = DeviceObject->DeviceExtension;
NTSTATUS Status;
bool top_level;
FsRtlEnterFileSystem();
top_level = is_top_level(Irp);
if (Vcb && Vcb->type == VCB_TYPE_BUS) {
Status = bus_pnp(DeviceObject->DeviceExtension, Irp);
goto exit;
} else if (Vcb && Vcb->type == VCB_TYPE_VOLUME) {
volume_device_extension* vde = DeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(vde->attached_device, Irp);
goto exit;
} else if (Vcb && Vcb->type == VCB_TYPE_PDO) {
Status = pdo_pnp(DeviceObject, Irp);
goto end;
} else if (!Vcb || Vcb->type != VCB_TYPE_FS) {
Status = STATUS_INVALID_PARAMETER;
goto end;
}
Status = STATUS_NOT_IMPLEMENTED;
switch (IrpSp->MinorFunction) {
case IRP_MN_CANCEL_REMOVE_DEVICE:
Status = pnp_cancel_remove_device(DeviceObject);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
Status = pnp_query_remove_device(DeviceObject, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
Status = pnp_remove_device(DeviceObject);
break;
case IRP_MN_SURPRISE_REMOVAL:
Status = pnp_surprise_removal(DeviceObject, Irp);
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
Status = pnp_device_usage_notification(DeviceObject, Irp);
goto exit;
default:
TRACE("passing minor function 0x%x on\n", IrpSp->MinorFunction);
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(Vcb->Vpb->RealDevice, Irp);
goto exit;
}
end:
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
exit:
TRACE("returning %08lx\n", Status);
if (top_level)
IoSetTopLevelIrp(NULL);
FsRtlExitFileSystem();
return Status;
}

3621
external/btrfs/src/read.c vendored Normal file

File diff suppressed because it is too large Load Diff

1037
external/btrfs/src/registry.c vendored Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More