[ext2fs] initial ext2fs support

This commit is contained in:
Pete Batard 2019-04-12 21:32:40 +01:00
parent f4d70345af
commit cda716c1ff
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
87 changed files with 29093 additions and 130 deletions

View File

@ -155,7 +155,6 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -175,7 +174,6 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -194,7 +192,6 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MinimalRebuild>true</MinimalRebuild>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

328
.vs/ext2fs.vcxproj Normal file
View File

@ -0,0 +1,328 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\ext2fs\alloc.c" />
<ClCompile Include="..\src\ext2fs\alloc_sb.c" />
<ClCompile Include="..\src\ext2fs\alloc_stats.c" />
<ClCompile Include="..\src\ext2fs\alloc_tables.c" />
<ClCompile Include="..\src\ext2fs\badblocks.c" />
<ClCompile Include="..\src\ext2fs\bb_inode.c" />
<ClCompile Include="..\src\ext2fs\bitmaps.c" />
<ClCompile Include="..\src\ext2fs\bitops.c" />
<ClCompile Include="..\src\ext2fs\blkmap64_ba.c" />
<ClCompile Include="..\src\ext2fs\blkmap64_rb.c" />
<ClCompile Include="..\src\ext2fs\blknum.c" />
<ClCompile Include="..\src\ext2fs\block.c" />
<ClCompile Include="..\src\ext2fs\bmap.c" />
<ClCompile Include="..\src\ext2fs\closefs.c" />
<ClCompile Include="..\src\ext2fs\crc16.c" />
<ClCompile Include="..\src\ext2fs\crc32c.c" />
<ClCompile Include="..\src\ext2fs\csum.c" />
<ClCompile Include="..\src\ext2fs\dirblock.c" />
<ClCompile Include="..\src\ext2fs\dir_iterate.c" />
<ClCompile Include="..\src\ext2fs\extent.c" />
<ClCompile Include="..\src\ext2fs\ext_attr.c" />
<ClCompile Include="..\src\ext2fs\fileio.c" />
<ClCompile Include="..\src\ext2fs\freefs.c" />
<ClCompile Include="..\src\ext2fs\gen_bitmap.c" />
<ClCompile Include="..\src\ext2fs\gen_bitmap64.c" />
<ClCompile Include="..\src\ext2fs\get_num_dirs.c" />
<ClCompile Include="..\src\ext2fs\ind_block.c" />
<ClCompile Include="..\src\ext2fs\initialize.c" />
<ClCompile Include="..\src\ext2fs\inline.c" />
<ClCompile Include="..\src\ext2fs\inline_data.c" />
<ClCompile Include="..\src\ext2fs\inode.c" />
<ClCompile Include="..\src\ext2fs\io_manager.c" />
<ClCompile Include="..\src\ext2fs\i_block.c" />
<ClCompile Include="..\src\ext2fs\link.c" />
<ClCompile Include="..\src\ext2fs\lookup.c" />
<ClCompile Include="..\src\ext2fs\missing.c" />
<ClCompile Include="..\src\ext2fs\mkdir.c" />
<ClCompile Include="..\src\ext2fs\mmp.c" />
<ClCompile Include="..\src\ext2fs\newdir.c" />
<ClCompile Include="..\src\ext2fs\nt_io.c" />
<ClCompile Include="..\src\ext2fs\punch.c" />
<ClCompile Include="..\src\ext2fs\rbtree.c" />
<ClCompile Include="..\src\ext2fs\read_bb.c" />
<ClCompile Include="..\src\ext2fs\rw_bitmaps.c" />
<ClCompile Include="..\src\ext2fs\symlink.c" />
<ClCompile Include="..\src\ext2fs\valid_blk.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\ext2fs\bitops.h" />
<ClInclude Include="..\src\ext2fs\bmap64.h" />
<ClInclude Include="..\src\ext2fs\com_err.h" />
<ClInclude Include="..\src\ext2fs\config.h" />
<ClInclude Include="..\src\ext2fs\crc16.h" />
<ClInclude Include="..\src\ext2fs\crc32c_defs.h" />
<ClInclude Include="..\src\ext2fs\e2image.h" />
<ClInclude Include="..\src\ext2fs\ext2fs.h" />
<ClInclude Include="..\src\ext2fs\ext2fsP.h" />
<ClInclude Include="..\src\ext2fs\ext2_err.h" />
<ClInclude Include="..\src\ext2fs\ext2_ext_attr.h" />
<ClInclude Include="..\src\ext2fs\ext2_fs.h" />
<ClInclude Include="..\src\ext2fs\ext2_io.h" />
<ClInclude Include="..\src\ext2fs\ext2_types.h" />
<ClInclude Include="..\src\ext2fs\ext3_extents.h" />
<ClInclude Include="..\src\ext2fs\ext4_acl.h" />
<ClInclude Include="..\src\ext2fs\rbtree.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>ext2fs</ProjectName>
<ProjectGuid>{B01F5886-2B39-4B66-B65C-6427135B6A02}</ProjectGuid>
<RootNamespace>ext2fs</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(SolutionDir)arm\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(SolutionDir)arm\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(SolutionDir)arm\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(SolutionDir)arm\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(SolutionDir)arm64\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(SolutionDir)arm64\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(SolutionDir)arm64\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(SolutionDir)arm64\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)x86\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)x86\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)x86\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)x86\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)x64\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)x64\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)x64\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)x64\$(Configuration)\$(ProjectName)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<DisableSpecificWarnings>4018;4146;4244;4267</DisableSpecificWarnings>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

204
.vs/ext2fs.vcxproj.filters Normal file
View File

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{396df203-84ec-49b8-ae11-074c50a020f0}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{0147b833-dc8f-4666-be99-77dfae5e6679}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\ext2fs\initialize.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\nt_io.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\alloc_sb.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\blknum.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\freefs.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\bitmaps.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\missing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\closefs.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\gen_bitmap.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\gen_bitmap64.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\inode.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\io_manager.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\csum.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\bitops.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\get_num_dirs.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\blkmap64_ba.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\blkmap64_rb.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\rbtree.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\crc16.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\crc32c.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\rw_bitmaps.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\mmp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\dir_iterate.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\inline.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\block.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\extent.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\alloc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\alloc_stats.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\dirblock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\inline_data.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\fileio.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\ext_attr.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\i_block.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\punch.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\ind_block.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\bmap.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\read_bb.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\badblocks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\symlink.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\valid_blk.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\lookup.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\link.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\alloc_tables.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\mkdir.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\newdir.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\ext2fs\bb_inode.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\ext2fs\ext2_fs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext2fs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext3_extents.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext2_io.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext2_ext_attr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\com_err.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\bitops.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext2_err.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext2_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext2fsP.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\rbtree.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\crc16.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\crc32c_defs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\bmap64.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\ext4_acl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\ext2fs\e2image.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -119,7 +119,6 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>HAVE_STRING_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -135,7 +134,6 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<ClCompile>
<PreprocessorDefinitions>HAVE_STRING_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -149,7 +147,6 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<PreprocessorDefinitions>HAVE_STRING_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

View File

@ -124,7 +124,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -149,7 +149,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -175,7 +175,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -201,7 +201,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
@ -230,7 +230,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -255,7 +255,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -282,7 +282,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -312,7 +312,7 @@
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;COBJMACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\src;..\src\msvc-missing;..\src\ms-sys\inc;..\src\syslinux\libinstaller;..\src\syslinux\libfat;..\src\syslinux\win;..\src\libcdio;..\src\getopt;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>false</ExceptionHandling>
@ -421,6 +421,9 @@
<ProjectReference Include=".\syslinux-win.vcxproj">
<Project>{7d2e9784-ddf7-4988-a887-cf099bc3b340}</Project>
</ProjectReference>
<ProjectReference Include="ext2fs.vcxproj">
<Project>{b01f5886-2b39-4b66-b65c-6427135b6a02}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

3
configure vendored
View File

@ -3907,6 +3907,8 @@ ac_config_files="$ac_config_files src/Makefile"
ac_config_files="$ac_config_files src/bled/Makefile"
ac_config_files="$ac_config_files src/ext2fs/Makefile"
ac_config_files="$ac_config_files src/libcdio/iso9660/Makefile"
ac_config_files="$ac_config_files src/libcdio/udf/Makefile"
@ -4651,6 +4653,7 @@ do
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
"src/bled/Makefile") CONFIG_FILES="$CONFIG_FILES src/bled/Makefile" ;;
"src/ext2fs/Makefile") CONFIG_FILES="$CONFIG_FILES src/ext2fs/Makefile" ;;
"src/libcdio/iso9660/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/iso9660/Makefile" ;;
"src/libcdio/udf/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/udf/Makefile" ;;
"src/libcdio/driver/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/driver/Makefile" ;;

View File

@ -72,6 +72,7 @@ AC_SUBST([SUFFIX])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([src/bled/Makefile])
AC_CONFIG_FILES([src/ext2fs/Makefile])
AC_CONFIG_FILES([src/libcdio/iso9660/Makefile])
AC_CONFIG_FILES([src/libcdio/udf/Makefile])
AC_CONFIG_FILES([src/libcdio/driver/Makefile])

102
rufus.sln
View File

@ -22,178 +22,196 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", ".vs\getopt.vcxpro
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bled", ".vs\bled.vcxproj", "{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext2fs", ".vs\ext2fs.vcxproj", "{B01F5886-2B39-4B66-B65C-6427135B6A02}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|arm = Debug|arm
Debug|arm64 = Debug|arm64
Debug|x86 = Debug|x86
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|arm = Release|arm
Release|arm64 = Release|arm64
Release|x86 = Release|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|arm.ActiveCfg = Debug|ARM
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|arm.Build.0 = Debug|ARM
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|arm64.ActiveCfg = Debug|ARM64
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|arm64.Build.0 = Debug|ARM64
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|x86.ActiveCfg = Debug|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|x86.Build.0 = Debug|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|x64.ActiveCfg = Debug|x64
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|x64.Build.0 = Debug|x64
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|x86.ActiveCfg = Debug|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Debug|x86.Build.0 = Debug|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Release|arm.ActiveCfg = Release|ARM
{731858A7-0303-4988-877B-9C0DD6471864}.Release|arm.Build.0 = Release|ARM
{731858A7-0303-4988-877B-9C0DD6471864}.Release|arm64.ActiveCfg = Release|ARM64
{731858A7-0303-4988-877B-9C0DD6471864}.Release|arm64.Build.0 = Release|ARM64
{731858A7-0303-4988-877B-9C0DD6471864}.Release|x86.ActiveCfg = Release|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Release|x86.Build.0 = Release|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Release|x64.ActiveCfg = Release|x64
{731858A7-0303-4988-877B-9C0DD6471864}.Release|x64.Build.0 = Release|x64
{731858A7-0303-4988-877B-9C0DD6471864}.Release|x86.ActiveCfg = Release|Win32
{731858A7-0303-4988-877B-9C0DD6471864}.Release|x86.Build.0 = Release|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|arm.ActiveCfg = Debug|ARM
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|arm.Build.0 = Debug|ARM
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|arm64.ActiveCfg = Debug|ARM64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|arm64.Build.0 = Debug|ARM64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x86.ActiveCfg = Debug|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x86.Build.0 = Debug|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x64.ActiveCfg = Debug|x64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x64.Build.0 = Debug|x64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x86.ActiveCfg = Debug|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Debug|x86.Build.0 = Debug|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|arm.ActiveCfg = Release|ARM
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|arm.Build.0 = Release|ARM
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|arm64.ActiveCfg = Release|ARM64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|arm64.Build.0 = Release|ARM64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x86.ActiveCfg = Release|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x86.Build.0 = Release|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x64.ActiveCfg = Release|x64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x64.Build.0 = Release|x64
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x86.ActiveCfg = Release|Win32
{2B1D078D-8EB4-4398-9CA4-23457265A7F6}.Release|x86.Build.0 = Release|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|arm.ActiveCfg = Debug|ARM
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|arm.Build.0 = Debug|ARM
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|arm64.ActiveCfg = Debug|ARM64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|arm64.Build.0 = Debug|ARM64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x86.ActiveCfg = Debug|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x86.Build.0 = Debug|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x64.ActiveCfg = Debug|x64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x64.Build.0 = Debug|x64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x86.ActiveCfg = Debug|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Debug|x86.Build.0 = Debug|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|arm.ActiveCfg = Release|ARM
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|arm.Build.0 = Release|ARM
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|arm64.ActiveCfg = Release|ARM64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|arm64.Build.0 = Release|ARM64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x86.ActiveCfg = Release|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x86.Build.0 = Release|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x64.ActiveCfg = Release|x64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x64.Build.0 = Release|x64
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x86.ActiveCfg = Release|Win32
{8390DCE0-859D-4F57-AD9C-AAEAC4D77EEF}.Release|x86.Build.0 = Release|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|arm.ActiveCfg = Debug|ARM
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|arm.Build.0 = Debug|ARM
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|arm64.ActiveCfg = Debug|ARM64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|arm64.Build.0 = Debug|ARM64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x86.ActiveCfg = Debug|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x86.Build.0 = Debug|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x64.ActiveCfg = Debug|x64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x64.Build.0 = Debug|x64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x86.ActiveCfg = Debug|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Debug|x86.Build.0 = Debug|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|arm.ActiveCfg = Release|ARM
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|arm.Build.0 = Release|ARM
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|arm64.ActiveCfg = Release|ARM64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|arm64.Build.0 = Release|ARM64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x86.ActiveCfg = Release|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x86.Build.0 = Release|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x64.ActiveCfg = Release|x64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x64.Build.0 = Release|x64
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x86.ActiveCfg = Release|Win32
{266502AC-CD74-4581-B707-938A7D05AD7A}.Release|x86.Build.0 = Release|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|arm.ActiveCfg = Debug|ARM
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|arm.Build.0 = Debug|ARM
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|arm64.ActiveCfg = Debug|ARM64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|arm64.Build.0 = Debug|ARM64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|x86.ActiveCfg = Debug|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|x86.Build.0 = Debug|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|x64.ActiveCfg = Debug|x64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|x64.Build.0 = Debug|x64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|x86.ActiveCfg = Debug|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Debug|x86.Build.0 = Debug|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|arm.ActiveCfg = Release|ARM
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|arm.Build.0 = Release|ARM
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|arm64.ActiveCfg = Release|ARM64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|arm64.Build.0 = Release|ARM64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|x86.ActiveCfg = Release|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|x86.Build.0 = Release|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|x64.ActiveCfg = Release|x64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|x64.Build.0 = Release|x64
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|x86.ActiveCfg = Release|Win32
{7D2E9784-DDF7-4988-A887-CF099BC3B340}.Release|x86.Build.0 = Release|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|arm.ActiveCfg = Debug|ARM
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|arm.Build.0 = Debug|ARM
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|arm64.ActiveCfg = Debug|ARM64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|arm64.Build.0 = Debug|ARM64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|x86.ActiveCfg = Debug|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|x86.Build.0 = Debug|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|x64.ActiveCfg = Debug|x64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|x64.Build.0 = Debug|x64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|x86.ActiveCfg = Debug|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Debug|x86.Build.0 = Debug|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|arm.ActiveCfg = Release|ARM
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|arm.Build.0 = Release|ARM
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|arm64.ActiveCfg = Release|ARM64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|arm64.Build.0 = Release|ARM64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|x86.ActiveCfg = Release|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|x86.Build.0 = Release|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|x64.ActiveCfg = Release|x64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|x64.Build.0 = Release|x64
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|x86.ActiveCfg = Release|Win32
{D4E80F35-2604-40AC-B436-97B052ECB572}.Release|x86.Build.0 = Release|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|arm.ActiveCfg = Debug|ARM
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|arm.Build.0 = Debug|ARM
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|arm64.ActiveCfg = Debug|ARM64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|arm64.Build.0 = Debug|ARM64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|x86.ActiveCfg = Debug|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|x86.Build.0 = Debug|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|x64.ActiveCfg = Debug|x64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|x64.Build.0 = Debug|x64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|x86.ActiveCfg = Debug|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Debug|x86.Build.0 = Debug|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|arm.ActiveCfg = Release|ARM
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|arm.Build.0 = Release|ARM
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|arm64.ActiveCfg = Release|ARM64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|arm64.Build.0 = Release|ARM64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|x86.ActiveCfg = Release|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|x86.Build.0 = Release|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|x64.ActiveCfg = Release|x64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|x64.Build.0 = Release|x64
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|x86.ActiveCfg = Release|Win32
{0CEC40A6-A195-4BE5-A88B-0AB00EB142EC}.Release|x86.Build.0 = Release|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|arm.ActiveCfg = Debug|ARM
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|arm.Build.0 = Debug|ARM
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|arm64.ActiveCfg = Debug|ARM64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|arm64.Build.0 = Debug|ARM64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|x86.ActiveCfg = Debug|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|x86.Build.0 = Debug|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|x64.ActiveCfg = Debug|x64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|x64.Build.0 = Debug|x64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|x86.ActiveCfg = Debug|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Debug|x86.Build.0 = Debug|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|arm.ActiveCfg = Release|ARM
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|arm.Build.0 = Release|ARM
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|arm64.ActiveCfg = Release|ARM64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|arm64.Build.0 = Release|ARM64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|x86.ActiveCfg = Release|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|x86.Build.0 = Release|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|x64.ActiveCfg = Release|x64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|x64.Build.0 = Release|x64
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|x86.ActiveCfg = Release|Win32
{FA1B1093-BA86-410A-B7A0-7A54C605F812}.Release|x86.Build.0 = Release|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|arm.ActiveCfg = Debug|ARM
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|arm.Build.0 = Debug|ARM
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|arm64.ActiveCfg = Debug|ARM64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|arm64.Build.0 = Debug|ARM64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x86.ActiveCfg = Debug|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x86.Build.0 = Debug|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.ActiveCfg = Debug|x64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x64.Build.0 = Debug|x64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x86.ActiveCfg = Debug|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Debug|x86.Build.0 = Debug|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|arm.ActiveCfg = Release|ARM
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|arm.Build.0 = Release|ARM
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|arm64.ActiveCfg = Release|ARM64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|arm64.Build.0 = Release|ARM64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x86.ActiveCfg = Release|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x86.Build.0 = Release|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x86.ActiveCfg = Release|Win32
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x86.Build.0 = Release|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|arm.ActiveCfg = Debug|ARM
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|arm.Build.0 = Debug|ARM
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|arm64.ActiveCfg = Debug|ARM64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|arm64.Build.0 = Debug|ARM64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|x86.ActiveCfg = Debug|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|x86.Build.0 = Debug|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|x64.ActiveCfg = Debug|x64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|x64.Build.0 = Debug|x64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|x86.ActiveCfg = Debug|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|x86.Build.0 = Debug|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|arm.ActiveCfg = Release|ARM
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|arm.Build.0 = Release|ARM
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|arm64.ActiveCfg = Release|ARM64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|arm64.Build.0 = Release|ARM64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|x86.ActiveCfg = Release|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|x86.Build.0 = Release|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|x64.ActiveCfg = Release|x64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|x64.Build.0 = Release|x64
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|x86.ActiveCfg = Release|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|x86.Build.0 = Release|Win32
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|arm.ActiveCfg = Debug|ARM
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|arm.Build.0 = Debug|ARM
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|arm64.ActiveCfg = Debug|ARM64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|arm64.Build.0 = Debug|ARM64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|x64.ActiveCfg = Debug|x64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|x64.Build.0 = Debug|x64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|x86.ActiveCfg = Debug|Win32
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Debug|x86.Build.0 = Debug|Win32
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|arm.ActiveCfg = Release|ARM
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|arm.Build.0 = Release|ARM
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|arm64.ActiveCfg = Release|ARM64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|arm64.Build.0 = Release|ARM64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|x64.ActiveCfg = Release|x64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|x64.Build.0 = Release|x64
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|x86.ActiveCfg = Release|Win32
{B01F5886-2B39-4B66-B65C-6427135B6A02}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,4 +1,4 @@
SUBDIRS = bled ms-sys syslinux/libfat syslinux/libinstaller syslinux/win libcdio/iso9660 libcdio/udf libcdio/driver ../res/loc
SUBDIRS = bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller syslinux/win libcdio/iso9660 libcdio/udf libcdio/driver ../res/loc
noinst_PROGRAMS = rufus
@ -12,7 +12,7 @@ AM_V_WINDRES = $(AM_V_WINDRES_$(V))
rufus_SOURCES = badblocks.c checksum.c dev.c dos.c dos_locale.c drive.c format.c icon.c iso.c localization.c \
net.c parser.c pki.c process.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c ui.c vhd.c
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS)
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) -Wno-shadow
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \
rufus_LDADD = rufus_rc.o bled/libbled.a ext2fs/libext2fs.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \
libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lwintrust -lcomdlg32 -lcomctl32 -luuid -lpsapi

View File

@ -99,10 +99,11 @@ am_rufus_OBJECTS = rufus-badblocks.$(OBJEXT) rufus-checksum.$(OBJEXT) \
rufus-syslinux.$(OBJEXT) rufus-ui.$(OBJEXT) \
rufus-vhd.$(OBJEXT)
rufus_OBJECTS = $(am_rufus_OBJECTS)
rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ms-sys/libmssys.a \
syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
syslinux/win/libwin.a libcdio/iso9660/libiso9660.a \
libcdio/udf/libudf.a libcdio/driver/libdriver.a
rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ext2fs/libext2fs.a \
ms-sys/libmssys.a syslinux/libfat/libfat.a \
syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \
libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a \
libcdio/driver/libdriver.a
rufus_LINK = $(CCLD) $(rufus_CFLAGS) $(CFLAGS) $(rufus_LDFLAGS) \
$(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
@ -266,7 +267,7 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = bled ms-sys syslinux/libfat syslinux/libinstaller syslinux/win libcdio/iso9660 libcdio/udf libcdio/driver ../res/loc
SUBDIRS = bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller syslinux/win libcdio/iso9660 libcdio/udf libcdio/driver ../res/loc
AM_V_WINDRES_0 = @echo " RC $@";$(WINDRES)
AM_V_WINDRES_1 = $(WINDRES)
AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY))
@ -274,9 +275,9 @@ AM_V_WINDRES = $(AM_V_WINDRES_$(V))
rufus_SOURCES = badblocks.c checksum.c dev.c dos.c dos_locale.c drive.c format.c icon.c iso.c localization.c \
net.c parser.c pki.c process.c rufus.c smart.c stdfn.c stdio.c stdlg.c syslinux.c ui.c vhd.c
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS)
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./syslinux/win -I./libcdio $(AM_CFLAGS) -Wno-shadow
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \
rufus_LDADD = rufus_rc.o bled/libbled.a ext2fs/libext2fs.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a syslinux/win/libwin.a \
libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lwintrust -lcomdlg32 -lcomctl32 -luuid -lpsapi
all: all-recursive

View File

@ -1,36 +1,19 @@
/*
* badblocks.c - Bad blocks checker
* badblocks.c - Bad blocks checker
*
* Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o
* Copyright 1999 by David Beattie
* Copyright 2011-2018 by Pete Batard
* Copyright 1992-1994 Remy Card <card@masi.ibp.fr>
* Copyright 1995-1999 Theodore Ts'o
* Copyright 1999 David Beattie
* Copyright 2011-2019 Pete Batard <pete@akeo.ie>
*
* This file is based on the minix file system programs fsck and mkfs
* written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* This file may be redistributed under the terms of the GNU Public License.
* %End-Header%
*/
/*
* History:
* 93/05/26 - Creation from e2fsck
* 94/02/27 - Made a separate bad blocks checker
* 99/06/30...99/07/26 - Added non-destructive write-testing,
* configurable blocks-at-once parameter,
* loading of badblocks list to avoid testing
* blocks known to be bad, multiple passes to
* make sure that no new blocks are added to the
* list. (Work done by David Beattie)
* 11/12/04 - Windows/Rufus integration (Pete Batard)
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@ -84,16 +67,16 @@ static errcode_t make_u64_list(int size, int num, uint64_t *list, bb_u64_list *r
bb->magic = BB_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10;
bb->num = num;
bb->list = malloc(sizeof(blk_t) * bb->size);
bb->list = malloc(sizeof(blk64_t) * bb->size);
if (bb->list == NULL) {
free(bb);
bb = NULL;
return BB_ET_NO_MEMORY;
}
if (list)
memcpy(bb->list, list, bb->size * sizeof(blk_t));
memcpy(bb->list, list, bb->size * sizeof(blk64_t));
else
memset(bb->list, 0, bb->size * sizeof(blk_t));
memset(bb->list, 0, bb->size * sizeof(blk64_t));
*ret = bb;
return 0;
}
@ -155,7 +138,7 @@ static errcode_t bb_u64_list_add(bb_u64_list bb, uint64_t blk)
return 0;
}
static errcode_t bb_badblocks_list_add(bb_badblocks_list bb, blk_t blk)
static errcode_t bb_badblocks_list_add(bb_badblocks_list bb, blk64_t blk)
{
return bb_u64_list_add((bb_u64_list) bb, blk);
}
@ -164,7 +147,7 @@ static errcode_t bb_badblocks_list_add(bb_badblocks_list bb, blk_t blk)
* This procedure finds a particular block is on a badblocks
* list.
*/
static int bb_u64_list_find(bb_u64_list bb, uint64_t blk)
static int bb_u64_list_find(bb_u64_list bb, blk64_t blk)
{
int low, high, mid;
@ -199,7 +182,7 @@ static int bb_u64_list_find(bb_u64_list bb, uint64_t blk)
* This procedure tests to see if a particular block is on a badblocks
* list.
*/
static int bb_u64_list_test(bb_u64_list bb, uint64_t blk)
static int bb_u64_list_test(bb_u64_list bb, blk64_t blk)
{
if (bb_u64_list_find(bb, blk) < 0)
return 0;
@ -207,12 +190,12 @@ static int bb_u64_list_test(bb_u64_list bb, uint64_t blk)
return 1;
}
static int bb_badblocks_list_test(bb_badblocks_list bb, blk_t blk)
static int bb_badblocks_list_test(bb_badblocks_list bb, blk64_t blk)
{
return bb_u64_list_test((bb_u64_list) bb, blk);
}
static int bb_u64_list_iterate(bb_u64_iterate iter, uint64_t *blk)
static int bb_u64_list_iterate(bb_u64_iterate iter, blk64_t *blk)
{
bb_u64_list bb;
@ -232,7 +215,7 @@ static int bb_u64_list_iterate(bb_u64_iterate iter, uint64_t *blk)
return 0;
}
static int bb_badblocks_list_iterate(bb_badblocks_iterate iter, blk_t *blk)
static int bb_badblocks_list_iterate(bb_badblocks_iterate iter, blk64_t *blk)
{
return bb_u64_list_iterate((bb_u64_iterate) iter, blk);
}
@ -247,13 +230,13 @@ static int cur_pattern, nr_pattern;
static int cur_op;
/* Abort test if more than this number of bad blocks has been encountered */
static unsigned int max_bb = BB_BAD_BLOCKS_THRESHOLD;
static blk_t currently_testing = 0;
static blk_t num_blocks = 0;
static blk64_t currently_testing = 0;
static blk64_t num_blocks = 0;
static uint32_t num_read_errors = 0;
static uint32_t num_write_errors = 0;
static uint32_t num_corruption_errors = 0;
static bb_badblocks_list bb_list = NULL;
static blk_t next_bad = 0;
static blk64_t next_bad = 0;
static bb_badblocks_iterate bb_iter = NULL;
static __inline void *allocate_buffer(size_t size) {
@ -268,7 +251,7 @@ static __inline void free_buffer(void* p) {
* This routine reports a new bad block. If the bad block has already
* been seen before, then it returns 0; otherwise it returns 1.
*/
static int bb_output (blk_t bad, enum error_types error_type)
static int bb_output (blk64_t bad, enum error_types error_type)
{
errcode_t error_code;
@ -381,8 +364,8 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
* Perform a read of a sequence of blocks; return the number of blocks
* successfully sequentially read.
*/
static int64_t do_read (HANDLE hDrive, unsigned char * buffer, uint64_t tryout, uint64_t block_size,
blk_t current_block)
static int64_t do_read (HANDLE hDrive, unsigned char * buffer, uint64_t tryout,
uint64_t block_size, blk64_t current_block)
{
int64_t got;
@ -403,8 +386,8 @@ static int64_t do_read (HANDLE hDrive, unsigned char * buffer, uint64_t tryout,
* Perform a write of a sequence of blocks; return the number of blocks
* successfully sequentially written.
*/
static int64_t do_write(HANDLE hDrive, unsigned char * buffer, uint64_t tryout, uint64_t block_size,
blk_t current_block)
static int64_t do_write(HANDLE hDrive, unsigned char * buffer, uint64_t tryout,
uint64_t block_size, blk64_t current_block)
{
int64_t got;
@ -421,15 +404,15 @@ static int64_t do_write(HANDLE hDrive, unsigned char * buffer, uint64_t tryout,
return got;
}
static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size, blk_t first_block,
size_t blocks_at_once, int pattern_type, int nb_passes)
static unsigned int test_rw(HANDLE hDrive, blk64_t last_block, size_t block_size, blk64_t first_block,
size_t blocks_at_once, int pattern_type, int nb_passes)
{
const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] =
{ BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC };
unsigned char *buffer = NULL, *read_buffer;
int i, pat_idx;
unsigned int bb_count = 0;
blk_t got, tryout, recover_block = ~0, *blk_id;
blk64_t got, tryout, recover_block = ~0, *blk_id;
size_t id_offset = 0;
if ((pattern_type < 0) || (pattern_type >= BADLOCKS_PATTERN_TYPES)) {
@ -463,7 +446,7 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
goto out;
if (detect_fakes && (pat_idx == 0)) {
srand((unsigned int)GetTickCount64());
id_offset = rand() * (block_size - sizeof(blk_t)) / RAND_MAX;
id_offset = rand() * (block_size - sizeof(blk64_t)) / RAND_MAX;
uprintf("%sUsing offset %d for fake device check\n", bb_prefix, id_offset);
}
// coverity[dont_call]
@ -492,8 +475,8 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
/* Add the block number at a fixed (random) offset during each pass to
allow for the detection of 'fake' media (eg. 2GB USB masquerading as 16GB) */
for (i=0; i<(int)blocks_at_once; i++) {
blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size);
*blk_id = (blk_t)(currently_testing + i);
blk_id = (blk64_t*)(intptr_t)(buffer + id_offset+ i*block_size);
*blk_id = (blk64_t)(currently_testing + i);
}
}
got = do_write(hDrive, buffer, tryout, block_size, currently_testing);
@ -538,8 +521,8 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
tryout = last_block - currently_testing;
if (detect_fakes && (pat_idx == 0)) {
for (i=0; i<(int)blocks_at_once; i++) {
blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size);
*blk_id = (blk_t)(currently_testing + i);
blk_id = (blk64_t*)(intptr_t)(buffer + id_offset+ i*block_size);
*blk_id = (blk64_t)(currently_testing + i);
}
}
got = do_read(hDrive, read_buffer, tryout, block_size,
@ -575,10 +558,10 @@ out:
}
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int nb_passes,
int flash_type, badblocks_report *report, FILE* fd)
int flash_type, badblocks_report *report, FILE* fd)
{
errcode_t error_code;
blk_t last_block = disk_size / BADBLOCK_BLOCK_SIZE;
blk64_t last_block = disk_size / BADBLOCK_BLOCK_SIZE;
if (report == NULL) return FALSE;
num_read_errors = 0;

View File

@ -21,8 +21,7 @@
#include <windows.h>
#include <stdint.h>
typedef uint64_t blk_t;
typedef DWORD errcode_t;
#include "ext2fs/ext2fs.h"
typedef struct bb_struct_u64_list *bb_badblocks_list;
typedef struct bb_struct_u64_iterate *bb_badblocks_iterate;

View File

@ -228,6 +228,22 @@ out:
return (success)?safe_strdup(physical_name):NULL;
}
/*
* Return an NT path to access the physical drive, or NULL on error.
* The string is allocated and must be freed (to ensure concurrent access)
*/
char* GetNtPhysicalName(DWORD DriveIndex)
{
BOOL success = FALSE;
char physical_name[32];
CheckDriveIndex(DriveIndex);
static_sprintf(physical_name, "\\??\\PHYSICALDRIVE%lu", DriveIndex);
success = TRUE;
out:
return (success) ? safe_strdup(physical_name) : NULL;
}
/*
* Return a handle to the physical drive identified by DriveIndex
*/

View File

@ -258,6 +258,7 @@ extern RUFUS_DRIVE_INFO SelectedDrive;
BOOL SetAutoMount(BOOL enable);
BOOL GetAutoMount(BOOL* enabled);
char* GetPhysicalName(DWORD DriveIndex);
char* GetNtPhysicalName(DWORD DriveIndex);
BOOL DeletePartitions(DWORD DriveIndex);
HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent);

2
src/ext2fs/.editorconfig Normal file
View File

@ -0,0 +1,2 @@
[*]
tab_width = 8

9
src/ext2fs/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
noinst_LIBRARIES = libext2fs.a
libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c bitmaps.c \
bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c crc32c.c csum.c \
dirblock.c dir_iterate.c extent.c ext_attr.c extent.c fileio.c freefs.c gen_bitmap.c gen_bitmap64.c \
get_num_dirs.c i_block.c ind_block.c initialize.c inline.c inline_data.c inode.c io_manager.c link.c \
lookup.c missing.c mkdir.c mmp.c newdir.c nt_io.c punch.c rbtree.c read_bb.c rw_bitmaps.c symlink.c valid_blk.c
libext2fs_a_CFLAGS = $(AM_CFLAGS) -DEXT2_FLAT_INCLUDES -DHAVE_CONFIG_H -I. -I.. -Wno-undef -Wno-strict-aliasing -Wno-shadow

779
src/ext2fs/Makefile.in Normal file
View File

@ -0,0 +1,779 @@
# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
subdir = src/ext2fs
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LIBRARIES = $(noinst_LIBRARIES)
ARFLAGS = cru
AM_V_AR = $(am__v_AR_@AM_V@)
am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
am__v_AR_0 = @echo " AR " $@;
am__v_AR_1 =
libext2fs_a_AR = $(AR) $(ARFLAGS)
libext2fs_a_LIBADD =
am_libext2fs_a_OBJECTS = libext2fs_a-alloc.$(OBJEXT) \
libext2fs_a-alloc_sb.$(OBJEXT) \
libext2fs_a-alloc_stats.$(OBJEXT) \
libext2fs_a-alloc_tables.$(OBJEXT) \
libext2fs_a-badblocks.$(OBJEXT) libext2fs_a-bb_inode.$(OBJEXT) \
libext2fs_a-bitmaps.$(OBJEXT) libext2fs_a-bitops.$(OBJEXT) \
libext2fs_a-blkmap64_ba.$(OBJEXT) \
libext2fs_a-blkmap64_rb.$(OBJEXT) libext2fs_a-blknum.$(OBJEXT) \
libext2fs_a-block.$(OBJEXT) libext2fs_a-bmap.$(OBJEXT) \
libext2fs_a-closefs.$(OBJEXT) libext2fs_a-crc16.$(OBJEXT) \
libext2fs_a-crc32c.$(OBJEXT) libext2fs_a-csum.$(OBJEXT) \
libext2fs_a-dirblock.$(OBJEXT) \
libext2fs_a-dir_iterate.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
libext2fs_a-ext_attr.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
libext2fs_a-fileio.$(OBJEXT) libext2fs_a-freefs.$(OBJEXT) \
libext2fs_a-gen_bitmap.$(OBJEXT) \
libext2fs_a-gen_bitmap64.$(OBJEXT) \
libext2fs_a-get_num_dirs.$(OBJEXT) \
libext2fs_a-i_block.$(OBJEXT) libext2fs_a-ind_block.$(OBJEXT) \
libext2fs_a-initialize.$(OBJEXT) libext2fs_a-inline.$(OBJEXT) \
libext2fs_a-inline_data.$(OBJEXT) libext2fs_a-inode.$(OBJEXT) \
libext2fs_a-io_manager.$(OBJEXT) libext2fs_a-link.$(OBJEXT) \
libext2fs_a-lookup.$(OBJEXT) libext2fs_a-missing.$(OBJEXT) \
libext2fs_a-mkdir.$(OBJEXT) libext2fs_a-mmp.$(OBJEXT) \
libext2fs_a-newdir.$(OBJEXT) libext2fs_a-nt_io.$(OBJEXT) \
libext2fs_a-punch.$(OBJEXT) libext2fs_a-rbtree.$(OBJEXT) \
libext2fs_a-read_bb.$(OBJEXT) libext2fs_a-rw_bitmaps.$(OBJEXT) \
libext2fs_a-symlink.$(OBJEXT) libext2fs_a-valid_blk.$(OBJEXT)
libext2fs_a_OBJECTS = $(am_libext2fs_a_OBJECTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp =
am__depfiles_maybe =
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libext2fs_a_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AM_LDFLAGS = @AM_LDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EXEEXT = @EXEEXT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
RM = @RM@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SUFFIX = @SUFFIX@
VERSION = @VERSION@
VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@
WINDRES = @WINDRES@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__leading_dot = @am__leading_dot@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build_alias = @build_alias@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host_alias = @host_alias@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
noinst_LIBRARIES = libext2fs.a
libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c bitmaps.c \
bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c crc32c.c csum.c \
dirblock.c dir_iterate.c extent.c ext_attr.c extent.c fileio.c freefs.c gen_bitmap.c gen_bitmap64.c \
get_num_dirs.c i_block.c ind_block.c initialize.c inline.c inline_data.c inode.c io_manager.c link.c \
lookup.c missing.c mkdir.c mmp.c newdir.c nt_io.c punch.c rbtree.c read_bb.c rw_bitmaps.c symlink.c valid_blk.c
libext2fs_a_CFLAGS = $(AM_CFLAGS) -DEXT2_FLAT_INCLUDES -DHAVE_CONFIG_H -I. -I.. -Wno-undef -Wno-strict-aliasing -Wno-shadow
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps src/ext2fs/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign --ignore-deps src/ext2fs/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libext2fs.a: $(libext2fs_a_OBJECTS) $(libext2fs_a_DEPENDENCIES) $(EXTRA_libext2fs_a_DEPENDENCIES)
$(AM_V_at)-rm -f libext2fs.a
$(AM_V_AR)$(libext2fs_a_AR) libext2fs.a $(libext2fs_a_OBJECTS) $(libext2fs_a_LIBADD)
$(AM_V_at)$(RANLIB) libext2fs.a
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
.c.o:
$(AM_V_CC)$(COMPILE) -c -o $@ $<
.c.obj:
$(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
libext2fs_a-alloc.o: alloc.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc.o `test -f 'alloc.c' || echo '$(srcdir)/'`alloc.c
libext2fs_a-alloc.obj: alloc.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc.obj `if test -f 'alloc.c'; then $(CYGPATH_W) 'alloc.c'; else $(CYGPATH_W) '$(srcdir)/alloc.c'; fi`
libext2fs_a-alloc_sb.o: alloc_sb.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc_sb.o `test -f 'alloc_sb.c' || echo '$(srcdir)/'`alloc_sb.c
libext2fs_a-alloc_sb.obj: alloc_sb.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc_sb.obj `if test -f 'alloc_sb.c'; then $(CYGPATH_W) 'alloc_sb.c'; else $(CYGPATH_W) '$(srcdir)/alloc_sb.c'; fi`
libext2fs_a-alloc_stats.o: alloc_stats.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc_stats.o `test -f 'alloc_stats.c' || echo '$(srcdir)/'`alloc_stats.c
libext2fs_a-alloc_stats.obj: alloc_stats.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc_stats.obj `if test -f 'alloc_stats.c'; then $(CYGPATH_W) 'alloc_stats.c'; else $(CYGPATH_W) '$(srcdir)/alloc_stats.c'; fi`
libext2fs_a-alloc_tables.o: alloc_tables.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc_tables.o `test -f 'alloc_tables.c' || echo '$(srcdir)/'`alloc_tables.c
libext2fs_a-alloc_tables.obj: alloc_tables.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-alloc_tables.obj `if test -f 'alloc_tables.c'; then $(CYGPATH_W) 'alloc_tables.c'; else $(CYGPATH_W) '$(srcdir)/alloc_tables.c'; fi`
libext2fs_a-badblocks.o: badblocks.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-badblocks.o `test -f 'badblocks.c' || echo '$(srcdir)/'`badblocks.c
libext2fs_a-badblocks.obj: badblocks.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-badblocks.obj `if test -f 'badblocks.c'; then $(CYGPATH_W) 'badblocks.c'; else $(CYGPATH_W) '$(srcdir)/badblocks.c'; fi`
libext2fs_a-bb_inode.o: bb_inode.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bb_inode.o `test -f 'bb_inode.c' || echo '$(srcdir)/'`bb_inode.c
libext2fs_a-bb_inode.obj: bb_inode.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bb_inode.obj `if test -f 'bb_inode.c'; then $(CYGPATH_W) 'bb_inode.c'; else $(CYGPATH_W) '$(srcdir)/bb_inode.c'; fi`
libext2fs_a-bitmaps.o: bitmaps.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bitmaps.o `test -f 'bitmaps.c' || echo '$(srcdir)/'`bitmaps.c
libext2fs_a-bitmaps.obj: bitmaps.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bitmaps.obj `if test -f 'bitmaps.c'; then $(CYGPATH_W) 'bitmaps.c'; else $(CYGPATH_W) '$(srcdir)/bitmaps.c'; fi`
libext2fs_a-bitops.o: bitops.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bitops.o `test -f 'bitops.c' || echo '$(srcdir)/'`bitops.c
libext2fs_a-bitops.obj: bitops.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bitops.obj `if test -f 'bitops.c'; then $(CYGPATH_W) 'bitops.c'; else $(CYGPATH_W) '$(srcdir)/bitops.c'; fi`
libext2fs_a-blkmap64_ba.o: blkmap64_ba.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-blkmap64_ba.o `test -f 'blkmap64_ba.c' || echo '$(srcdir)/'`blkmap64_ba.c
libext2fs_a-blkmap64_ba.obj: blkmap64_ba.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-blkmap64_ba.obj `if test -f 'blkmap64_ba.c'; then $(CYGPATH_W) 'blkmap64_ba.c'; else $(CYGPATH_W) '$(srcdir)/blkmap64_ba.c'; fi`
libext2fs_a-blkmap64_rb.o: blkmap64_rb.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-blkmap64_rb.o `test -f 'blkmap64_rb.c' || echo '$(srcdir)/'`blkmap64_rb.c
libext2fs_a-blkmap64_rb.obj: blkmap64_rb.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-blkmap64_rb.obj `if test -f 'blkmap64_rb.c'; then $(CYGPATH_W) 'blkmap64_rb.c'; else $(CYGPATH_W) '$(srcdir)/blkmap64_rb.c'; fi`
libext2fs_a-blknum.o: blknum.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-blknum.o `test -f 'blknum.c' || echo '$(srcdir)/'`blknum.c
libext2fs_a-blknum.obj: blknum.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-blknum.obj `if test -f 'blknum.c'; then $(CYGPATH_W) 'blknum.c'; else $(CYGPATH_W) '$(srcdir)/blknum.c'; fi`
libext2fs_a-block.o: block.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-block.o `test -f 'block.c' || echo '$(srcdir)/'`block.c
libext2fs_a-block.obj: block.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-block.obj `if test -f 'block.c'; then $(CYGPATH_W) 'block.c'; else $(CYGPATH_W) '$(srcdir)/block.c'; fi`
libext2fs_a-bmap.o: bmap.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bmap.o `test -f 'bmap.c' || echo '$(srcdir)/'`bmap.c
libext2fs_a-bmap.obj: bmap.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-bmap.obj `if test -f 'bmap.c'; then $(CYGPATH_W) 'bmap.c'; else $(CYGPATH_W) '$(srcdir)/bmap.c'; fi`
libext2fs_a-closefs.o: closefs.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-closefs.o `test -f 'closefs.c' || echo '$(srcdir)/'`closefs.c
libext2fs_a-closefs.obj: closefs.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-closefs.obj `if test -f 'closefs.c'; then $(CYGPATH_W) 'closefs.c'; else $(CYGPATH_W) '$(srcdir)/closefs.c'; fi`
libext2fs_a-crc16.o: crc16.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-crc16.o `test -f 'crc16.c' || echo '$(srcdir)/'`crc16.c
libext2fs_a-crc16.obj: crc16.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-crc16.obj `if test -f 'crc16.c'; then $(CYGPATH_W) 'crc16.c'; else $(CYGPATH_W) '$(srcdir)/crc16.c'; fi`
libext2fs_a-crc32c.o: crc32c.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-crc32c.o `test -f 'crc32c.c' || echo '$(srcdir)/'`crc32c.c
libext2fs_a-crc32c.obj: crc32c.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-crc32c.obj `if test -f 'crc32c.c'; then $(CYGPATH_W) 'crc32c.c'; else $(CYGPATH_W) '$(srcdir)/crc32c.c'; fi`
libext2fs_a-csum.o: csum.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-csum.o `test -f 'csum.c' || echo '$(srcdir)/'`csum.c
libext2fs_a-csum.obj: csum.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-csum.obj `if test -f 'csum.c'; then $(CYGPATH_W) 'csum.c'; else $(CYGPATH_W) '$(srcdir)/csum.c'; fi`
libext2fs_a-dirblock.o: dirblock.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dirblock.o `test -f 'dirblock.c' || echo '$(srcdir)/'`dirblock.c
libext2fs_a-dirblock.obj: dirblock.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dirblock.obj `if test -f 'dirblock.c'; then $(CYGPATH_W) 'dirblock.c'; else $(CYGPATH_W) '$(srcdir)/dirblock.c'; fi`
libext2fs_a-dir_iterate.o: dir_iterate.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dir_iterate.o `test -f 'dir_iterate.c' || echo '$(srcdir)/'`dir_iterate.c
libext2fs_a-dir_iterate.obj: dir_iterate.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dir_iterate.obj `if test -f 'dir_iterate.c'; then $(CYGPATH_W) 'dir_iterate.c'; else $(CYGPATH_W) '$(srcdir)/dir_iterate.c'; fi`
libext2fs_a-extent.o: extent.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-extent.o `test -f 'extent.c' || echo '$(srcdir)/'`extent.c
libext2fs_a-extent.obj: extent.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-extent.obj `if test -f 'extent.c'; then $(CYGPATH_W) 'extent.c'; else $(CYGPATH_W) '$(srcdir)/extent.c'; fi`
libext2fs_a-ext_attr.o: ext_attr.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-ext_attr.o `test -f 'ext_attr.c' || echo '$(srcdir)/'`ext_attr.c
libext2fs_a-ext_attr.obj: ext_attr.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-ext_attr.obj `if test -f 'ext_attr.c'; then $(CYGPATH_W) 'ext_attr.c'; else $(CYGPATH_W) '$(srcdir)/ext_attr.c'; fi`
libext2fs_a-fileio.o: fileio.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-fileio.o `test -f 'fileio.c' || echo '$(srcdir)/'`fileio.c
libext2fs_a-fileio.obj: fileio.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-fileio.obj `if test -f 'fileio.c'; then $(CYGPATH_W) 'fileio.c'; else $(CYGPATH_W) '$(srcdir)/fileio.c'; fi`
libext2fs_a-freefs.o: freefs.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-freefs.o `test -f 'freefs.c' || echo '$(srcdir)/'`freefs.c
libext2fs_a-freefs.obj: freefs.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-freefs.obj `if test -f 'freefs.c'; then $(CYGPATH_W) 'freefs.c'; else $(CYGPATH_W) '$(srcdir)/freefs.c'; fi`
libext2fs_a-gen_bitmap.o: gen_bitmap.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-gen_bitmap.o `test -f 'gen_bitmap.c' || echo '$(srcdir)/'`gen_bitmap.c
libext2fs_a-gen_bitmap.obj: gen_bitmap.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-gen_bitmap.obj `if test -f 'gen_bitmap.c'; then $(CYGPATH_W) 'gen_bitmap.c'; else $(CYGPATH_W) '$(srcdir)/gen_bitmap.c'; fi`
libext2fs_a-gen_bitmap64.o: gen_bitmap64.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-gen_bitmap64.o `test -f 'gen_bitmap64.c' || echo '$(srcdir)/'`gen_bitmap64.c
libext2fs_a-gen_bitmap64.obj: gen_bitmap64.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-gen_bitmap64.obj `if test -f 'gen_bitmap64.c'; then $(CYGPATH_W) 'gen_bitmap64.c'; else $(CYGPATH_W) '$(srcdir)/gen_bitmap64.c'; fi`
libext2fs_a-get_num_dirs.o: get_num_dirs.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-get_num_dirs.o `test -f 'get_num_dirs.c' || echo '$(srcdir)/'`get_num_dirs.c
libext2fs_a-get_num_dirs.obj: get_num_dirs.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-get_num_dirs.obj `if test -f 'get_num_dirs.c'; then $(CYGPATH_W) 'get_num_dirs.c'; else $(CYGPATH_W) '$(srcdir)/get_num_dirs.c'; fi`
libext2fs_a-i_block.o: i_block.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-i_block.o `test -f 'i_block.c' || echo '$(srcdir)/'`i_block.c
libext2fs_a-i_block.obj: i_block.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-i_block.obj `if test -f 'i_block.c'; then $(CYGPATH_W) 'i_block.c'; else $(CYGPATH_W) '$(srcdir)/i_block.c'; fi`
libext2fs_a-ind_block.o: ind_block.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-ind_block.o `test -f 'ind_block.c' || echo '$(srcdir)/'`ind_block.c
libext2fs_a-ind_block.obj: ind_block.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-ind_block.obj `if test -f 'ind_block.c'; then $(CYGPATH_W) 'ind_block.c'; else $(CYGPATH_W) '$(srcdir)/ind_block.c'; fi`
libext2fs_a-initialize.o: initialize.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-initialize.o `test -f 'initialize.c' || echo '$(srcdir)/'`initialize.c
libext2fs_a-initialize.obj: initialize.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-initialize.obj `if test -f 'initialize.c'; then $(CYGPATH_W) 'initialize.c'; else $(CYGPATH_W) '$(srcdir)/initialize.c'; fi`
libext2fs_a-inline.o: inline.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-inline.o `test -f 'inline.c' || echo '$(srcdir)/'`inline.c
libext2fs_a-inline.obj: inline.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-inline.obj `if test -f 'inline.c'; then $(CYGPATH_W) 'inline.c'; else $(CYGPATH_W) '$(srcdir)/inline.c'; fi`
libext2fs_a-inline_data.o: inline_data.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-inline_data.o `test -f 'inline_data.c' || echo '$(srcdir)/'`inline_data.c
libext2fs_a-inline_data.obj: inline_data.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-inline_data.obj `if test -f 'inline_data.c'; then $(CYGPATH_W) 'inline_data.c'; else $(CYGPATH_W) '$(srcdir)/inline_data.c'; fi`
libext2fs_a-inode.o: inode.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-inode.o `test -f 'inode.c' || echo '$(srcdir)/'`inode.c
libext2fs_a-inode.obj: inode.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-inode.obj `if test -f 'inode.c'; then $(CYGPATH_W) 'inode.c'; else $(CYGPATH_W) '$(srcdir)/inode.c'; fi`
libext2fs_a-io_manager.o: io_manager.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-io_manager.o `test -f 'io_manager.c' || echo '$(srcdir)/'`io_manager.c
libext2fs_a-io_manager.obj: io_manager.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-io_manager.obj `if test -f 'io_manager.c'; then $(CYGPATH_W) 'io_manager.c'; else $(CYGPATH_W) '$(srcdir)/io_manager.c'; fi`
libext2fs_a-link.o: link.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-link.o `test -f 'link.c' || echo '$(srcdir)/'`link.c
libext2fs_a-link.obj: link.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-link.obj `if test -f 'link.c'; then $(CYGPATH_W) 'link.c'; else $(CYGPATH_W) '$(srcdir)/link.c'; fi`
libext2fs_a-lookup.o: lookup.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-lookup.o `test -f 'lookup.c' || echo '$(srcdir)/'`lookup.c
libext2fs_a-lookup.obj: lookup.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-lookup.obj `if test -f 'lookup.c'; then $(CYGPATH_W) 'lookup.c'; else $(CYGPATH_W) '$(srcdir)/lookup.c'; fi`
libext2fs_a-missing.o: missing.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-missing.o `test -f 'missing.c' || echo '$(srcdir)/'`missing.c
libext2fs_a-missing.obj: missing.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-missing.obj `if test -f 'missing.c'; then $(CYGPATH_W) 'missing.c'; else $(CYGPATH_W) '$(srcdir)/missing.c'; fi`
libext2fs_a-mkdir.o: mkdir.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-mkdir.o `test -f 'mkdir.c' || echo '$(srcdir)/'`mkdir.c
libext2fs_a-mkdir.obj: mkdir.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-mkdir.obj `if test -f 'mkdir.c'; then $(CYGPATH_W) 'mkdir.c'; else $(CYGPATH_W) '$(srcdir)/mkdir.c'; fi`
libext2fs_a-mmp.o: mmp.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-mmp.o `test -f 'mmp.c' || echo '$(srcdir)/'`mmp.c
libext2fs_a-mmp.obj: mmp.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-mmp.obj `if test -f 'mmp.c'; then $(CYGPATH_W) 'mmp.c'; else $(CYGPATH_W) '$(srcdir)/mmp.c'; fi`
libext2fs_a-newdir.o: newdir.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-newdir.o `test -f 'newdir.c' || echo '$(srcdir)/'`newdir.c
libext2fs_a-newdir.obj: newdir.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-newdir.obj `if test -f 'newdir.c'; then $(CYGPATH_W) 'newdir.c'; else $(CYGPATH_W) '$(srcdir)/newdir.c'; fi`
libext2fs_a-nt_io.o: nt_io.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-nt_io.o `test -f 'nt_io.c' || echo '$(srcdir)/'`nt_io.c
libext2fs_a-nt_io.obj: nt_io.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-nt_io.obj `if test -f 'nt_io.c'; then $(CYGPATH_W) 'nt_io.c'; else $(CYGPATH_W) '$(srcdir)/nt_io.c'; fi`
libext2fs_a-punch.o: punch.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-punch.o `test -f 'punch.c' || echo '$(srcdir)/'`punch.c
libext2fs_a-punch.obj: punch.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-punch.obj `if test -f 'punch.c'; then $(CYGPATH_W) 'punch.c'; else $(CYGPATH_W) '$(srcdir)/punch.c'; fi`
libext2fs_a-rbtree.o: rbtree.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-rbtree.o `test -f 'rbtree.c' || echo '$(srcdir)/'`rbtree.c
libext2fs_a-rbtree.obj: rbtree.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-rbtree.obj `if test -f 'rbtree.c'; then $(CYGPATH_W) 'rbtree.c'; else $(CYGPATH_W) '$(srcdir)/rbtree.c'; fi`
libext2fs_a-read_bb.o: read_bb.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-read_bb.o `test -f 'read_bb.c' || echo '$(srcdir)/'`read_bb.c
libext2fs_a-read_bb.obj: read_bb.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-read_bb.obj `if test -f 'read_bb.c'; then $(CYGPATH_W) 'read_bb.c'; else $(CYGPATH_W) '$(srcdir)/read_bb.c'; fi`
libext2fs_a-rw_bitmaps.o: rw_bitmaps.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-rw_bitmaps.o `test -f 'rw_bitmaps.c' || echo '$(srcdir)/'`rw_bitmaps.c
libext2fs_a-rw_bitmaps.obj: rw_bitmaps.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-rw_bitmaps.obj `if test -f 'rw_bitmaps.c'; then $(CYGPATH_W) 'rw_bitmaps.c'; else $(CYGPATH_W) '$(srcdir)/rw_bitmaps.c'; fi`
libext2fs_a-symlink.o: symlink.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-symlink.o `test -f 'symlink.c' || echo '$(srcdir)/'`symlink.c
libext2fs_a-symlink.obj: symlink.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-symlink.obj `if test -f 'symlink.c'; then $(CYGPATH_W) 'symlink.c'; else $(CYGPATH_W) '$(srcdir)/symlink.c'; fi`
libext2fs_a-valid_blk.o: valid_blk.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-valid_blk.o `test -f 'valid_blk.c' || echo '$(srcdir)/'`valid_blk.c
libext2fs_a-valid_blk.obj: valid_blk.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-valid_blk.obj `if test -f 'valid_blk.c'; then $(CYGPATH_W) 'valid_blk.c'; else $(CYGPATH_W) '$(srcdir)/valid_blk.c'; fi`
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-tags dvi dvi-am \
html html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

556
src/ext2fs/alloc.c Normal file
View File

@ -0,0 +1,556 @@
/*
* alloc.c --- allocate new inodes, blocks for ext2fs
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <string.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
#undef DEBUG
#ifdef DEBUG
# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0)
#else
# define dbg_printf(f, ...)
#endif
/*
* Clear the uninit block bitmap flag if necessary
*/
void ext2fs_clear_block_uninit(ext2_filsys fs, dgrp_t group)
{
if (group >= fs->group_desc_count ||
!ext2fs_has_group_desc_csum(fs) ||
!(ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
return;
/* uninit block bitmaps are now initialized in read_bitmaps() */
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
}
/*
* Check for uninit inode bitmaps and deal with them appropriately
*/
static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
dgrp_t group)
{
ext2_ino_t i, ino;
if (group >= fs->group_desc_count ||
!ext2fs_has_group_desc_csum(fs) ||
!(ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
return;
ino = (group * fs->super->s_inodes_per_group) + 1;
for (i=0; i < fs->super->s_inodes_per_group; i++, ino++)
ext2fs_fast_unmark_inode_bitmap2(map, ino);
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
/* Mimics what the kernel does */
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_super_dirty(fs);
}
/*
* Right now, just search forward from the parent directory's block
* group to find the next free inode.
*
* Should have a special policy for directories.
*/
errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir,
int mode EXT2FS_ATTR((unused)),
ext2fs_inode_bitmap map, ext2_ino_t *ret)
{
ext2_ino_t start_inode = 0;
ext2_ino_t i, ino_in_group, upto, first_zero;
errcode_t retval;
dgrp_t group;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!map)
map = fs->inode_map;
if (!map)
return EXT2_ET_NO_INODE_BITMAP;
if (dir > 0) {
group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
start_inode = (group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
}
if (start_inode < EXT2_FIRST_INODE(fs->super))
start_inode = EXT2_FIRST_INODE(fs->super);
if (start_inode > fs->super->s_inodes_count)
return EXT2_ET_INODE_ALLOC_FAIL;
i = start_inode;
do {
ino_in_group = (i - 1) % EXT2_INODES_PER_GROUP(fs->super);
group = (i - 1) / EXT2_INODES_PER_GROUP(fs->super);
check_inode_uninit(fs, map, group);
upto = i + (EXT2_INODES_PER_GROUP(fs->super) - ino_in_group);
if (i < start_inode && upto >= start_inode)
upto = start_inode - 1;
if (upto > fs->super->s_inodes_count)
upto = fs->super->s_inodes_count;
retval = ext2fs_find_first_zero_inode_bitmap2(map, i, upto,
&first_zero);
if (retval == 0) {
i = first_zero;
break;
}
if (retval != ENOENT)
return EXT2_ET_INODE_ALLOC_FAIL;
i = upto + 1;
if (i > fs->super->s_inodes_count)
i = EXT2_FIRST_INODE(fs->super);
} while (i != start_inode);
if (ext2fs_test_inode_bitmap2(map, i))
return EXT2_ET_INODE_ALLOC_FAIL;
*ret = i;
return 0;
}
/*
* Stupid algorithm --- we now just search forward starting from the
* goal. Should put in a smarter one someday....
*/
errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal,
ext2fs_block_bitmap map, blk64_t *ret,
struct blk_alloc_ctx *ctx)
{
errcode_t retval;
blk64_t b = 0;
errcode_t (*gab)(ext2_filsys fs, blk64_t goal, blk64_t *ret);
errcode_t (*gab2)(ext2_filsys, blk64_t, blk64_t *,
struct blk_alloc_ctx *);
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!map) {
/*
* In case there are clients out there whose get_alloc_block
* handlers call ext2fs_new_block2 with a NULL block map,
* temporarily swap out the function pointer so that we don't
* end up in an infinite loop.
*/
if (fs->get_alloc_block2) {
gab2 = fs->get_alloc_block2;
fs->get_alloc_block2 = NULL;
retval = gab2(fs, goal, &b, ctx);
fs->get_alloc_block2 = gab2;
goto allocated;
} else if (fs->get_alloc_block) {
gab = fs->get_alloc_block;
fs->get_alloc_block = NULL;
retval = gab(fs, goal, &b);
fs->get_alloc_block = gab;
goto allocated;
}
}
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!goal || (goal >= ext2fs_blocks_count(fs->super)))
goal = fs->super->s_first_data_block;
goal &= ~EXT2FS_CLUSTER_MASK(fs);
retval = ext2fs_find_first_zero_block_bitmap2(map,
goal, ext2fs_blocks_count(fs->super) - 1, &b);
if ((retval == ENOENT) && (goal != fs->super->s_first_data_block))
retval = ext2fs_find_first_zero_block_bitmap2(map,
fs->super->s_first_data_block, goal - 1, &b);
allocated:
if (retval == ENOENT)
return EXT2_ET_BLOCK_ALLOC_FAIL;
if (retval)
return retval;
ext2fs_clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b));
*ret = b;
return 0;
}
errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
ext2fs_block_bitmap map, blk64_t *ret)
{
return ext2fs_new_block3(fs, goal, map, ret, NULL);
}
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
ext2fs_block_bitmap map, blk_t *ret)
{
errcode_t retval;
blk64_t val;
retval = ext2fs_new_block2(fs, goal, map, &val);
if (!retval)
*ret = (blk_t) val;
return retval;
}
/*
* This function zeros out the allocated block, and updates all of the
* appropriate filesystem records.
*/
errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal, char *block_buf,
blk64_t *ret, struct blk_alloc_ctx *ctx)
{
errcode_t retval;
blk64_t block;
if (fs->get_alloc_block2) {
retval = (fs->get_alloc_block2)(fs, goal, &block, ctx);
if (retval)
goto fail;
} else if (fs->get_alloc_block) {
retval = (fs->get_alloc_block)(fs, goal, &block);
if (retval)
goto fail;
} else {
if (!fs->block_map) {
retval = ext2fs_read_block_bitmap(fs);
if (retval)
goto fail;
}
retval = ext2fs_new_block3(fs, goal, 0, &block, ctx);
if (retval)
goto fail;
}
if (block_buf) {
memset(block_buf, 0, fs->blocksize);
retval = io_channel_write_blk64(fs->io, block, 1, block_buf);
} else
retval = ext2fs_zero_blocks2(fs, block, 1, NULL, NULL);
if (retval)
goto fail;
ext2fs_block_alloc_stats2(fs, block, +1);
*ret = block;
fail:
return retval;
}
errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
char *block_buf, blk64_t *ret)
{
return ext2fs_alloc_block3(fs, goal, block_buf, ret, NULL);
}
errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
char *block_buf, blk_t *ret)
{
errcode_t retval;
blk64_t ret64, goal64 = goal;
retval = ext2fs_alloc_block3(fs, goal64, block_buf, &ret64, NULL);
if (!retval)
*ret = (blk_t)ret64;
return retval;
}
errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, blk64_t finish,
int num, ext2fs_block_bitmap map, blk64_t *ret)
{
blk64_t b = start;
int c_ratio;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!b)
b = fs->super->s_first_data_block;
if (!finish)
finish = start;
if (!num)
num = 1;
c_ratio = 1 << ext2fs_get_bitmap_granularity(map);
b &= ~(c_ratio - 1);
finish &= ~(c_ratio -1);
do {
if (b + num - 1 >= ext2fs_blocks_count(fs->super)) {
if (finish > start)
return EXT2_ET_BLOCK_ALLOC_FAIL;
b = fs->super->s_first_data_block;
}
if (ext2fs_fast_test_block_bitmap_range2(map, b, num)) {
*ret = b;
return 0;
}
b += c_ratio;
} while (b != finish);
return EXT2_ET_BLOCK_ALLOC_FAIL;
}
errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
int num, ext2fs_block_bitmap map, blk_t *ret)
{
errcode_t retval;
blk64_t val;
retval = ext2fs_get_free_blocks2(fs, start, finish, num, map, &val);
if(!retval)
*ret = (blk_t) val;
return retval;
}
void ext2fs_set_alloc_block_callback(ext2_filsys fs,
errcode_t (*func)(ext2_filsys fs,
blk64_t goal,
blk64_t *ret),
errcode_t (**old)(ext2_filsys fs,
blk64_t goal,
blk64_t *ret))
{
if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
return;
if (old)
*old = fs->get_alloc_block;
fs->get_alloc_block = func;
}
blk64_t ext2fs_find_inode_goal(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, blk64_t lblk)
{
dgrp_t group;
__u8 log_flex;
struct ext2fs_extent extent;
ext2_extent_handle_t handle = NULL;
errcode_t err;
/* Make sure data stored in inode->i_block is neither fast symlink nor
* inline data.
*/
if (inode == NULL || ext2fs_is_fast_symlink(inode) ||
inode->i_flags & EXT4_INLINE_DATA_FL)
goto no_blocks;
if (inode->i_flags & EXT4_EXTENTS_FL) {
err = ext2fs_extent_open2(fs, ino, inode, &handle);
if (err)
goto no_blocks;
err = ext2fs_extent_goto2(handle, 0, lblk);
if (err)
goto no_blocks;
err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
if (err)
goto no_blocks;
ext2fs_extent_free(handle);
return extent.e_pblk + (lblk - extent.e_lblk);
}
/* block mapped file; see if block zero is mapped? */
if (inode->i_block[0])
return inode->i_block[0];
no_blocks:
ext2fs_extent_free(handle);
log_flex = fs->super->s_log_groups_per_flex;
group = ext2fs_group_of_ino(fs, ino);
if (log_flex)
group = group & ~((1 << (log_flex)) - 1);
return ext2fs_group_first_block2(fs, group);
}
/*
* Starting at _goal_, scan around the filesystem to find a run of free blocks
* that's at least _len_ blocks long. Possible flags:
* - EXT2_NEWRANGE_EXACT_GOAL: The range of blocks must start at _goal_.
* - EXT2_NEWRANGE_MIN_LENGTH: do not return a allocation shorter than _len_.
* - EXT2_NEWRANGE_ZERO_BLOCKS: Zero blocks pblk to pblk+plen before returning.
*
* The starting block is returned in _pblk_ and the length is returned via
* _plen_. The blocks are not marked in the bitmap; the caller must mark
* however much of the returned run they actually use, hopefully via
* ext2fs_block_alloc_stats_range().
*
* This function can return a range that is longer than what was requested.
*/
errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal,
blk64_t len, ext2fs_block_bitmap map, blk64_t *pblk,
blk64_t *plen)
{
errcode_t retval;
blk64_t start, end, b;
int looped = 0;
blk64_t max_blocks = ext2fs_blocks_count(fs->super);
errcode_t (*nrf)(ext2_filsys fs, int flags, blk64_t goal,
blk64_t len, blk64_t *pblk, blk64_t *plen);
dbg_printf("%s: flags=0x%x goal=%llu len=%llu\n", __func__, flags,
goal, len);
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (len == 0 || (flags & ~EXT2_NEWRANGE_ALL_FLAGS))
return EXT2_ET_INVALID_ARGUMENT;
if (!map && fs->new_range) {
/*
* In case there are clients out there whose new_range
* handlers call ext2fs_new_range with a NULL block map,
* temporarily swap out the function pointer so that we don't
* end up in an infinite loop.
*/
nrf = fs->new_range;
fs->new_range = NULL;
retval = nrf(fs, flags, goal, len, pblk, plen);
fs->new_range = nrf;
if (retval)
return retval;
start = *pblk;
end = *pblk + *plen;
goto allocated;
}
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!goal || goal >= ext2fs_blocks_count(fs->super))
goal = fs->super->s_first_data_block;
start = goal;
while (!looped || start <= goal) {
retval = ext2fs_find_first_zero_block_bitmap2(map, start,
max_blocks - 1,
&start);
if (retval == ENOENT) {
/*
* If there are no free blocks beyond the starting
* point, try scanning the whole filesystem, unless the
* user told us only to allocate from _goal_, or if
* we're already scanning the whole filesystem.
*/
if (flags & EXT2_NEWRANGE_FIXED_GOAL ||
start == fs->super->s_first_data_block)
goto fail;
start = fs->super->s_first_data_block;
continue;
} else if (retval)
goto errout;
if (flags & EXT2_NEWRANGE_FIXED_GOAL && start != goal)
goto fail;
b = min(start + len - 1, max_blocks - 1);
retval = ext2fs_find_first_set_block_bitmap2(map, start, b,
&end);
if (retval == ENOENT)
end = b + 1;
else if (retval)
goto errout;
if (!(flags & EXT2_NEWRANGE_MIN_LENGTH) ||
(end - start) >= len) {
/* Success! */
*pblk = start;
*plen = end - start;
dbg_printf("%s: new_range goal=%llu--%llu "
"blk=%llu--%llu %llu\n",
__func__, goal, goal + len - 1,
*pblk, *pblk + *plen - 1, *plen);
allocated:
for (b = start; b < end;
b += fs->super->s_blocks_per_group)
ext2fs_clear_block_uninit(fs,
ext2fs_group_of_blk2(fs, b));
return 0;
}
if (flags & EXT2_NEWRANGE_FIXED_GOAL)
goto fail;
start = end;
if (start >= max_blocks) {
if (looped)
goto fail;
looped = 1;
start = fs->super->s_first_data_block;
}
}
fail:
retval = EXT2_ET_BLOCK_ALLOC_FAIL;
errout:
return retval;
}
void ext2fs_set_new_range_callback(ext2_filsys fs,
errcode_t (*func)(ext2_filsys fs, int flags, blk64_t goal,
blk64_t len, blk64_t *pblk, blk64_t *plen),
errcode_t (**old)(ext2_filsys fs, int flags, blk64_t goal,
blk64_t len, blk64_t *pblk, blk64_t *plen))
{
if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
return;
if (old)
*old = fs->new_range;
fs->new_range = func;
}
errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal,
blk_t len, blk64_t *ret)
{
int newr_flags = EXT2_NEWRANGE_MIN_LENGTH;
errcode_t retval;
blk64_t plen;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (len == 0 || (flags & ~EXT2_ALLOCRANGE_ALL_FLAGS))
return EXT2_ET_INVALID_ARGUMENT;
if (flags & EXT2_ALLOCRANGE_FIXED_GOAL)
newr_flags |= EXT2_NEWRANGE_FIXED_GOAL;
retval = ext2fs_new_range(fs, newr_flags, goal, len, NULL, ret, &plen);
if (retval)
return retval;
if (plen < len)
return EXT2_ET_BLOCK_ALLOC_FAIL;
if (flags & EXT2_ALLOCRANGE_ZERO_BLOCKS) {
retval = ext2fs_zero_blocks2(fs, *ret, len, NULL, NULL);
if (retval)
return retval;
}
ext2fs_block_alloc_stats_range(fs, *ret, len, +1);
return retval;
}

81
src/ext2fs/alloc_sb.c Normal file
View File

@ -0,0 +1,81 @@
/*
* alloc_sb.c --- Allocate the superblock and block group descriptors for a
* newly initialized filesystem. Used by mke2fs when initializing a filesystem
*
* Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
/*
* This function reserves the superblock and block group descriptors
* for a given block group. It currently returns the number of free
* blocks assuming that inode table and allocation bitmaps will be in
* the group. This is not necessarily the case when the flex_bg
* feature is enabled, so callers should take care! It was only
* really intended for use by mke2fs, and even there it's not that
* useful. In the future, when we redo this function for 64-bit block
* numbers, we should probably return the number of blocks used by the
* super block and group descriptors instead.
*
* See also the comment for ext2fs_super_and_bgd_loc()
*/
int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
dgrp_t group,
ext2fs_block_bitmap bmap)
{
blk64_t super_blk, old_desc_blk, new_desc_blk;
blk_t used_blks;
int old_desc_blocks, num_blocks;
ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
&old_desc_blk, &new_desc_blk, &used_blks);
if (ext2fs_has_feature_meta_bg(fs->super))
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks =
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
if (super_blk || (group == 0))
ext2fs_mark_block_bitmap2(bmap, super_blk);
if ((group == 0) && (fs->blocksize == 1024) &&
EXT2FS_CLUSTER_RATIO(fs) > 1)
ext2fs_mark_block_bitmap2(bmap, 0);
if (old_desc_blk) {
num_blocks = old_desc_blocks;
if (old_desc_blk + num_blocks >= ext2fs_blocks_count(fs->super))
num_blocks = ext2fs_blocks_count(fs->super) -
old_desc_blk;
ext2fs_mark_block_bitmap_range2(bmap, old_desc_blk, num_blocks);
}
if (new_desc_blk)
ext2fs_mark_block_bitmap2(bmap, new_desc_blk);
num_blocks = ext2fs_group_blocks_count(fs, group);
num_blocks -= 2 + fs->inode_blocks_per_group + used_blks;
return num_blocks ;
}

164
src/ext2fs/alloc_stats.c Normal file
View File

@ -0,0 +1,164 @@
/*
* alloc_stats.c --- Update allocation statistics for ext2fs
*
* Copyright (C) 2001 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include "ext2_fs.h"
#include "ext2fs.h"
void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
int inuse, int isdir)
{
int group = ext2fs_group_of_ino(fs, ino);
if (ino > fs->super->s_inodes_count) {
#ifndef OMIT_COM_ERR
com_err("ext2fs_inode_alloc_stats2", 0,
"Illegal inode number: %lu", (unsigned long) ino);
#endif
return;
}
if (inuse > 0)
ext2fs_mark_inode_bitmap2(fs->inode_map, ino);
else
ext2fs_unmark_inode_bitmap2(fs->inode_map, ino);
ext2fs_bg_free_inodes_count_set(fs, group, ext2fs_bg_free_inodes_count(fs, group) - inuse);
if (isdir)
ext2fs_bg_used_dirs_count_set(fs, group, ext2fs_bg_used_dirs_count(fs, group) + inuse);
/* We don't strictly need to be clearing the uninit flag if inuse < 0
* (i.e. freeing inodes) but it also means something is bad. */
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
if (ext2fs_has_group_desc_csum(fs)) {
ext2_ino_t first_unused_inode = fs->super->s_inodes_per_group -
ext2fs_bg_itable_unused(fs, group) +
group * fs->super->s_inodes_per_group + 1;
if (ino >= first_unused_inode)
ext2fs_bg_itable_unused_set(fs, group, group * fs->super->s_inodes_per_group + fs->super->s_inodes_per_group - ino);
ext2fs_group_desc_csum_set(fs, group);
}
fs->super->s_free_inodes_count -= inuse;
ext2fs_mark_super_dirty(fs);
ext2fs_mark_ib_dirty(fs);
}
void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
{
ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
}
void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse)
{
int group = ext2fs_group_of_blk2(fs, blk);
if (blk >= ext2fs_blocks_count(fs->super)) {
#ifndef OMIT_COM_ERR
com_err("ext2fs_block_alloc_stats", 0,
"Illegal block number: %lu", (unsigned long) blk);
#endif
return;
}
if (inuse > 0)
ext2fs_mark_block_bitmap2(fs->block_map, blk);
else
ext2fs_unmark_block_bitmap2(fs->block_map, blk);
ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) - inuse);
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_free_blocks_count_add(fs->super,
-inuse * (blk64_t) EXT2FS_CLUSTER_RATIO(fs));
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
if (fs->block_alloc_stats)
(fs->block_alloc_stats)(fs, (blk64_t) blk, inuse);
}
void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
{
ext2fs_block_alloc_stats2(fs, blk, inuse);
}
void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
void (*func)(ext2_filsys fs,
blk64_t blk,
int inuse),
void (**old)(ext2_filsys fs,
blk64_t blk,
int inuse))
{
if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
return;
if (old)
*old = fs->block_alloc_stats;
fs->block_alloc_stats = func;
}
void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
blk_t num, int inuse)
{
#ifndef OMIT_COM_ERR
if (blk + num > ext2fs_blocks_count(fs->super)) {
com_err("ext2fs_block_alloc_stats_range", 0,
"Illegal block range: %llu (%u) ",
(unsigned long long) blk, num);
return;
}
#endif
if (inuse == 0)
return;
if (inuse > 0) {
ext2fs_mark_block_bitmap_range2(fs->block_map, blk, num);
inuse = 1;
} else {
ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, num);
inuse = -1;
}
while (num) {
int group = ext2fs_group_of_blk2(fs, blk);
blk64_t last_blk = ext2fs_group_last_block2(fs, group);
blk64_t n = num;
if (blk + num > last_blk)
n = last_blk - blk + 1;
ext2fs_bg_free_blocks_count_set(fs, group,
ext2fs_bg_free_blocks_count(fs, group) -
inuse*n/EXT2FS_CLUSTER_RATIO(fs));
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, group);
ext2fs_free_blocks_count_add(fs->super, -inuse * (blk64_t) n);
blk += n;
num -= n;
}
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
if (fs->block_alloc_stats_range)
(fs->block_alloc_stats_range)(fs, blk, num, inuse);
}
void ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs,
void (*func)(ext2_filsys fs, blk64_t blk,
blk_t num, int inuse),
void (**old)(ext2_filsys fs, blk64_t blk,
blk_t num, int inuse))
{
if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
return;
if (old)
*old = fs->block_alloc_stats_range;
fs->block_alloc_stats_range = func;
}

278
src/ext2fs/alloc_tables.c Normal file
View File

@ -0,0 +1,278 @@
/*
* alloc_tables.c --- Allocate tables for a newly initialized
* filesystem. Used by mke2fs when initializing a filesystem
*
* Copyright (C) 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
/*
* This routine searches for free blocks that can allocate a full
* group of bitmaps or inode tables for a flexbg group. Returns the
* block number with a correct offset were the bitmaps and inode
* tables can be allocated continuously and in order.
*/
static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk,
ext2fs_block_bitmap bmap, int rem_grp,
int elem_size)
{
int flexbg, flexbg_size, size;
blk64_t last_blk, first_free = 0;
dgrp_t last_grp;
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
flexbg = group / flexbg_size;
size = rem_grp * elem_size;
if (size > (int) (fs->super->s_blocks_per_group / 4))
size = (int) fs->super->s_blocks_per_group / 4;
/*
* Don't do a long search if the previous block search is still valid,
* but skip minor obstructions such as group descriptor backups.
*/
if (start_blk && start_blk < ext2fs_blocks_count(fs->super) &&
ext2fs_get_free_blocks2(fs, start_blk, start_blk + size, elem_size,
bmap, &first_free) == 0)
return first_free;
start_blk = ext2fs_group_first_block2(fs, flexbg_size * flexbg);
last_grp = group | (flexbg_size - 1);
if (last_grp > fs->group_desc_count-1)
last_grp = fs->group_desc_count-1;
last_blk = ext2fs_group_last_block2(fs, last_grp);
/* Find the first available block */
if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, size,
bmap, &first_free) == 0)
return first_free;
if (ext2fs_get_free_blocks2(fs, start_blk, last_blk, elem_size,
bmap, &first_free) == 0)
return first_free;
if (ext2fs_get_free_blocks2(fs, 0, last_blk, elem_size, bmap,
&first_free) == 0)
return first_free;
return first_free;
}
errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group,
ext2fs_block_bitmap bmap)
{
errcode_t retval;
blk64_t group_blk, start_blk, last_blk, new_blk;
dgrp_t last_grp = 0;
int rem_grps = 0, flexbg_size = 0, table_offset = 0;
group_blk = ext2fs_group_first_block2(fs, group);
last_blk = ext2fs_group_last_block2(fs, group);
if (!bmap)
bmap = fs->block_map;
if (ext2fs_has_feature_flex_bg(fs->super) &&
fs->super->s_log_groups_per_flex) {
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
last_grp = group | (flexbg_size - 1);
if (last_grp > fs->group_desc_count-1)
last_grp = fs->group_desc_count-1;
rem_grps = last_grp - group + 1;
}
/*
* Allocate the block and inode bitmaps, if necessary
*/
if (fs->stride && !flexbg_size) {
retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
1, bmap, &start_blk);
if (retval)
return retval;
start_blk += fs->inode_blocks_per_group;
start_blk += ((fs->stride * group) %
(last_blk - start_blk + 1));
if (start_blk >= last_blk)
start_blk = group_blk;
} else
start_blk = group_blk;
if (flexbg_size) {
blk64_t prev_block = 0;
table_offset = flexbg_size;
if (group % flexbg_size)
prev_block = ext2fs_block_bitmap_loc(fs, group - 1) + 1;
else if (last_grp == fs->group_desc_count-1) {
/*
* If we are allocating for the last flex_bg
* keep the metadata tables contiguous
*/
table_offset = last_grp & (flexbg_size - 1);
if (table_offset == 0)
table_offset = flexbg_size;
else
table_offset++;
}
/* FIXME: Take backup group descriptor blocks into account
* if the flexbg allocations will grow to overlap them... */
start_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, 1);
last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!ext2fs_block_bitmap_loc(fs, group)) {
retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap2(bmap, new_blk);
ext2fs_block_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
ext2fs_free_blocks_count_add(fs->super, -1);
ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, gr);
}
}
if (flexbg_size) {
blk64_t prev_block = 0;
if (group % flexbg_size)
prev_block = ext2fs_inode_bitmap_loc(fs, group - 1) + 1;
else
prev_block = ext2fs_block_bitmap_loc(fs, group) +
table_offset;
/* FIXME: Take backup group descriptor blocks into account
* if the flexbg allocations will grow to overlap them... */
start_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, 1);
last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!ext2fs_inode_bitmap_loc(fs, group)) {
retval = ext2fs_get_free_blocks2(fs, start_blk, last_blk,
1, bmap, &new_blk);
if (retval == EXT2_ET_BLOCK_ALLOC_FAIL)
retval = ext2fs_get_free_blocks2(fs, group_blk,
last_blk, 1, bmap, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap2(bmap, new_blk);
ext2fs_inode_bitmap_loc_set(fs, group, new_blk);
if (flexbg_size) {
dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk);
ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1);
ext2fs_free_blocks_count_add(fs->super, -1);
ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, gr);
}
}
/*
* Allocate the inode table
*/
if (flexbg_size) {
blk64_t prev_block = 0;
if (group % flexbg_size)
prev_block = ext2fs_inode_table_loc(fs, group - 1) +
fs->inode_blocks_per_group;
else
prev_block = ext2fs_inode_bitmap_loc(fs, group) +
table_offset;
/* FIXME: Take backup group descriptor blocks into account
* if the flexbg allocations will grow to overlap them... */
group_blk = flexbg_offset(fs, group, prev_block, bmap,
rem_grps, fs->inode_blocks_per_group);
last_blk = ext2fs_group_last_block2(fs, last_grp);
}
if (!ext2fs_inode_table_loc(fs, group)) {
retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
fs->inode_blocks_per_group,
bmap, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap_range2(bmap,
new_blk, fs->inode_blocks_per_group);
if (flexbg_size) {
blk64_t num, blk;
num = fs->inode_blocks_per_group;
blk = new_blk;
while (num) {
int gr = ext2fs_group_of_blk2(fs, blk);
last_blk = ext2fs_group_last_block2(fs, gr);
blk64_t n = num;
if (blk + num > last_blk)
n = last_blk - blk + 1;
ext2fs_bg_free_blocks_count_set(fs, gr,
ext2fs_bg_free_blocks_count(fs, gr) -
n/EXT2FS_CLUSTER_RATIO(fs));
ext2fs_bg_flags_clear(fs, gr,
EXT2_BG_BLOCK_UNINIT);
ext2fs_group_desc_csum_set(fs, gr);
ext2fs_free_blocks_count_add(fs->super, -n);
blk += n;
num -= n;
}
}
ext2fs_inode_table_loc_set(fs, group, new_blk);
}
ext2fs_group_desc_csum_set(fs, group);
return 0;
}
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
dgrp_t i;
struct ext2fs_numeric_progress_struct progress;
if (fs->progress_ops && fs->progress_ops->init)
(fs->progress_ops->init)(fs, &progress, NULL,
fs->group_desc_count);
for (i = 0; i < fs->group_desc_count; i++) {
if (fs->progress_ops && fs->progress_ops->update)
(fs->progress_ops->update)(fs, &progress, i);
retval = ext2fs_allocate_group_table(fs, i, fs->block_map);
if (retval)
return retval;
}
if (fs->progress_ops && fs->progress_ops->close)
(fs->progress_ops->close)(fs, &progress, NULL);
return 0;
}

328
src/ext2fs/badblocks.c Normal file
View File

@ -0,0 +1,328 @@
/*
* badblocks.c --- routines to manipulate the bad block structure
*
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
/*
* Helper function for making a badblocks list
*/
static errcode_t make_u32_list(int size, int num, __u32 *list,
ext2_u32_list *ret)
{
ext2_u32_list bb;
errcode_t retval;
retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb);
if (retval)
return retval;
memset(bb, 0, sizeof(struct ext2_struct_u32_list));
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10;
bb->num = num;
retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list);
if (retval) {
ext2fs_free_mem(&bb);
return retval;
}
if (list)
memcpy(bb->list, list, bb->size * sizeof(blk_t));
else
memset(bb->list, 0, bb->size * sizeof(blk_t));
*ret = bb;
return 0;
}
/*
* This procedure creates an empty u32 list.
*/
errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size)
{
return make_u32_list(size, 0, 0, ret);
}
/*
* This procedure creates an empty badblocks list.
*/
errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
{
return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret);
}
/*
* This procedure copies a badblocks list
*/
errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest)
{
errcode_t retval;
retval = make_u32_list(src->size, src->num, src->list, dest);
if (retval)
return retval;
(*dest)->badblocks_flags = src->badblocks_flags;
return 0;
}
errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
ext2_badblocks_list *dest)
{
return ext2fs_u32_copy((ext2_u32_list) src,
(ext2_u32_list *) dest);
}
/*
* This procedure frees a badblocks list.
*
* (note: moved to closefs.c)
*/
/*
* This procedure adds a block to a badblocks list.
*/
errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
{
errcode_t retval;
int i, j;
unsigned long old_size;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
if (bb->num >= bb->size) {
old_size = bb->size * sizeof(__u32);
bb->size += 100;
retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32),
&bb->list);
if (retval) {
bb->size -= 100;
return retval;
}
}
/*
* Add special case code for appending to the end of the list
*/
i = bb->num-1;
if ((bb->num != 0) && (bb->list[i] == blk))
return 0;
if ((bb->num == 0) || (bb->list[i] < blk)) {
bb->list[bb->num++] = blk;
return 0;
}
j = bb->num;
for (i=0; i < bb->num; i++) {
if (bb->list[i] == blk)
return 0;
if (bb->list[i] > blk) {
j = i;
break;
}
}
for (i=bb->num; i > j; i--)
bb->list[i] = bb->list[i-1];
bb->list[j] = blk;
bb->num++;
return 0;
}
errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
{
return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk);
}
/*
* This procedure finds a particular block is on a badblocks
* list.
*/
int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
{
int low, high, mid;
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return -1;
if (bb->num == 0)
return -1;
low = 0;
high = bb->num-1;
if (blk == bb->list[low])
return low;
if (blk == bb->list[high])
return high;
while (low < high) {
mid = ((unsigned)low + (unsigned)high)/2;
if (mid == low || mid == high)
break;
if (blk == bb->list[mid])
return mid;
if (blk < bb->list[mid])
high = mid;
else
low = mid;
}
return -1;
}
/*
* This procedure tests to see if a particular block is on a badblocks
* list.
*/
int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk)
{
if (ext2fs_u32_list_find(bb, blk) < 0)
return 0;
else
return 1;
}
int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
{
return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk);
}
/*
* Remove a block from the badblock list
*/
int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk)
{
int remloc, i;
if (bb->num == 0)
return -1;
remloc = ext2fs_u32_list_find(bb, blk);
if (remloc < 0)
return -1;
for (i = remloc ; i < bb->num-1; i++)
bb->list[i] = bb->list[i+1];
bb->num--;
return 0;
}
void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk)
{
ext2fs_u32_list_del(bb, blk);
}
errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb,
ext2_u32_iterate *ret)
{
ext2_u32_iterate iter;
errcode_t retval;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter);
if (retval)
return retval;
iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE;
iter->bb = bb;
iter->ptr = 0;
*ret = iter;
return 0;
}
errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
ext2_badblocks_iterate *ret)
{
return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb,
(ext2_u32_iterate *) ret);
}
int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
{
ext2_u32_list bb;
if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
return 0;
bb = iter->bb;
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return 0;
if (iter->ptr < bb->num) {
*blk = bb->list[iter->ptr++];
return 1;
}
*blk = 0;
return 0;
}
int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
{
return ext2fs_u32_list_iterate((ext2_u32_iterate) iter,
(__u32 *) blk);
}
void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter)
{
if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
return;
iter->bb = 0;
ext2fs_free_mem(&iter);
}
void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
{
ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter);
}
int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2)
{
EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST);
EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST);
if (bb1->num != bb2->num)
return 0;
if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0)
return 0;
return 1;
}
int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2)
{
return ext2fs_u32_list_equal((ext2_u32_list) bb1,
(ext2_u32_list) bb2);
}
int ext2fs_u32_list_count(ext2_u32_list bb)
{
return bb->num;
}

270
src/ext2fs/bb_inode.c Normal file
View File

@ -0,0 +1,270 @@
/*
* bb_inode.c --- routines to update the bad block inode.
*
* WARNING: This routine modifies a lot of state in the filesystem; if
* this routine returns an error, the bad block inode may be in an
* inconsistent state.
*
* Copyright (C) 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct set_badblock_record {
ext2_badblocks_iterate bb_iter;
int bad_block_count;
blk_t *ind_blocks;
int max_ind_blocks;
int ind_blocks_size;
int ind_blocks_ptr;
char *block_buf;
errcode_t err;
};
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block, int ref_offset,
void *priv_data);
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block, int ref_offset,
void *priv_data);
/*
* Given a bad blocks bitmap, update the bad blocks inode to reflect
* the map.
*/
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
{
errcode_t retval;
struct set_badblock_record rec;
struct ext2_inode inode;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!fs->block_map)
return EXT2_ET_NO_BLOCK_BITMAP;
memset(&rec, 0, sizeof(rec));
rec.max_ind_blocks = 10;
retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t),
&rec.ind_blocks);
if (retval)
return retval;
memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf);
if (retval)
goto cleanup;
memset(rec.block_buf, 0, fs->blocksize);
rec.err = 0;
/*
* First clear the old bad blocks (while saving the indirect blocks)
*/
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
clear_bad_block_proc, &rec);
if (retval)
goto cleanup;
if (rec.err) {
retval = rec.err;
goto cleanup;
}
/*
* Now set the bad blocks!
*
* First, mark the bad blocks as used. This prevents a bad
* block from being used as an indirect block for the bad
* block inode (!).
*/
if (bb_list) {
retval = ext2fs_badblocks_list_iterate_begin(bb_list,
&rec.bb_iter);
if (retval)
goto cleanup;
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
BLOCK_FLAG_APPEND, 0,
set_bad_block_proc, &rec);
ext2fs_badblocks_list_iterate_end(rec.bb_iter);
if (retval)
goto cleanup;
if (rec.err) {
retval = rec.err;
goto cleanup;
}
}
/*
* Update the bad block inode's mod time and block count
* field.
*/
retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
goto cleanup;
inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0);
if (!inode.i_ctime)
inode.i_ctime = fs->now ? fs->now : time(0);
ext2fs_iblk_set(fs, &inode, rec.bad_block_count);
retval = ext2fs_inode_size_set(fs, &inode,
rec.bad_block_count * fs->blocksize);
if (retval)
goto cleanup;
retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
goto cleanup;
cleanup:
ext2fs_free_mem(&rec.ind_blocks);
ext2fs_free_mem(&rec.block_buf);
return retval;
}
/*
* Helper function for update_bb_inode()
*
* Clear the bad blocks in the bad block inode, while saving the
* indirect blocks.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
priv_data;
errcode_t retval;
unsigned long old_size;
if (!*block_nr)
return 0;
/*
* If the block number is outrageous, clear it and ignore it.
*/
if (*block_nr >= ext2fs_blocks_count(fs->super) ||
*block_nr < fs->super->s_first_data_block) {
*block_nr = 0;
return BLOCK_CHANGED;
}
if (blockcnt < 0) {
if (rec->ind_blocks_size >= rec->max_ind_blocks) {
old_size = rec->max_ind_blocks * sizeof(blk_t);
rec->max_ind_blocks += 10;
retval = ext2fs_resize_mem(old_size,
rec->max_ind_blocks * sizeof(blk_t),
&rec->ind_blocks);
if (retval) {
rec->max_ind_blocks -= 10;
rec->err = retval;
return BLOCK_ABORT;
}
}
rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
}
/*
* Mark the block as unused, and update accounting information
*/
ext2fs_block_alloc_stats2(fs, *block_nr, -1);
*block_nr = 0;
return BLOCK_CHANGED;
}
/*
* Helper function for update_bb_inode()
*
* Set the block list in the bad block inode, using the supplied bitmap.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt,
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
priv_data;
errcode_t retval;
blk_t blk;
if (blockcnt >= 0) {
/*
* Get the next bad block.
*/
if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
return BLOCK_ABORT;
rec->bad_block_count++;
} else {
/*
* An indirect block; fetch a block from the
* previously used indirect block list. The block
* most be not marked as used; if so, get another one.
* If we run out of reserved indirect blocks, allocate
* a new one.
*/
retry:
if (rec->ind_blocks_ptr < rec->ind_blocks_size) {
blk = rec->ind_blocks[rec->ind_blocks_ptr++];
if (ext2fs_test_block_bitmap2(fs->block_map, blk))
goto retry;
} else {
retval = ext2fs_new_block(fs, 0, 0, &blk);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
}
}
retval = io_channel_write_blk64(fs->io, blk, 1, rec->block_buf);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
}
}
/*
* Update block counts
*/
ext2fs_block_alloc_stats2(fs, blk, +1);
*block_nr = blk;
return BLOCK_CHANGED;
}

308
src/ext2fs/bitmaps.c Normal file
View File

@ -0,0 +1,308 @@
/*
* bitmaps.c --- routines to read, write, and manipulate the inode and
* block bitmaps.
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
#include "bmap64.h"
void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
ext2fs_free_generic_bmap(bitmap);
}
void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
{
ext2fs_free_generic_bmap(bitmap);
}
errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest)
{
return (ext2fs_copy_generic_bmap(src, dest));
}
void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
{
ext2fs_set_generic_bmap_padding(map);
}
errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_inode_bitmap *ret)
{
__u64 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
start = 1;
end = fs->super->s_inodes_count;
real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
/* Are we permitted to use new-style bitmaps? */
if (fs->flags & EXT2_FLAG_64BITS)
return (ext2fs_alloc_generic_bmap(fs,
EXT2_ET_MAGIC_INODE_BITMAP64,
fs->default_bitmap_type,
start, end, real_end, descr, ret));
/* Otherwise, check to see if the file system is small enough
* to use old-style 32-bit bitmaps */
if ((end > ~0U) || (real_end > ~0U))
return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, fs,
start, end, real_end,
descr, 0,
(ext2fs_generic_bitmap *) ret));
}
errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret)
{
__u64 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
start = EXT2FS_B2C(fs, fs->super->s_first_data_block);
end = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1);
real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super)
* (__u64) fs->group_desc_count)-1 + start;
if (fs->flags & EXT2_FLAG_64BITS)
return (ext2fs_alloc_generic_bmap(fs,
EXT2_ET_MAGIC_BLOCK_BITMAP64,
fs->default_bitmap_type,
start, end, real_end, descr, ret));
if ((end > ~0U) || (real_end > ~0U))
return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs,
start, end, real_end,
descr, 0,
(ext2fs_generic_bitmap *) ret));
}
/*
* ext2fs_allocate_block_bitmap() really allocates a per-cluster
* bitmap for backwards compatibility. This function allocates a
* block bitmap which is truly per-block, even if clusters/bigalloc
* are enabled. mke2fs and e2fsck need this for tracking the
* allocation of the file system metadata blocks.
*/
errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs,
const char *descr,
ext2fs_block_bitmap *ret)
{
__u64 start, end, real_end;
ext2fs_generic_bitmap bmap;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs->write_bitmaps = ext2fs_write_bitmaps;
if (!fs->cluster_ratio_bits)
return ext2fs_allocate_block_bitmap(fs, descr, ret);
if ((fs->flags & EXT2_FLAG_64BITS) == 0)
return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
start = fs->super->s_first_data_block;
end = ext2fs_blocks_count(fs->super)-1;
real_end = ((__u64) EXT2_BLOCKS_PER_GROUP(fs->super)
* (__u64) fs->group_desc_count)-1 + start;
retval = ext2fs_alloc_generic_bmap(fs, EXT2_ET_MAGIC_BLOCK_BITMAP64,
fs->default_bitmap_type, start,
end, real_end, descr, &bmap);
if (retval)
return retval;
bmap->cluster_bits = 0;
*ret = bmap;
return 0;
}
int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap)
{
ext2fs_generic_bitmap bmap = bitmap;
if (!EXT2FS_IS_64_BITMAP(bmap))
return 0;
return bmap->cluster_bits;
}
errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
ext2_ino_t end, ext2_ino_t *oend)
{
__u64 tmp_oend;
int retval;
retval = ext2fs_fudge_generic_bmap_end((ext2fs_generic_bitmap) bitmap,
EXT2_ET_FUDGE_INODE_BITMAP_END,
end, &tmp_oend);
if (oend)
*oend = tmp_oend;
return retval;
}
errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
blk_t end, blk_t *oend)
{
return (ext2fs_fudge_generic_bitmap_end(bitmap,
EXT2_ET_MAGIC_BLOCK_BITMAP,
EXT2_ET_FUDGE_BLOCK_BITMAP_END,
end, oend));
}
errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap,
blk64_t end, blk64_t *oend)
{
return (ext2fs_fudge_generic_bmap_end(bitmap,
EXT2_ET_FUDGE_BLOCK_BITMAP_END,
end, oend));
}
void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
{
ext2fs_clear_generic_bmap(bitmap);
}
void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
{
ext2fs_clear_generic_bmap(bitmap);
}
errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
ext2fs_inode_bitmap bmap)
{
return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP,
new_end, new_real_end, bmap));
}
errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end, __u64 new_real_end,
ext2fs_inode_bitmap bmap)
{
return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end));
}
errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
ext2fs_block_bitmap bmap)
{
return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP,
new_end, new_real_end, bmap));
}
errcode_t ext2fs_resize_block_bitmap2(__u64 new_end, __u64 new_real_end,
ext2fs_block_bitmap bmap)
{
return (ext2fs_resize_generic_bmap(bmap, new_end, new_real_end));
}
errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
ext2fs_block_bitmap bm2)
{
return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_BLOCK_BITMAP,
bm1, bm2));
}
errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
ext2fs_inode_bitmap bm2)
{
return (ext2fs_compare_generic_bmap(EXT2_ET_NEQ_INODE_BITMAP,
bm1, bm2));
}
errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
ext2_ino_t start, unsigned int num,
void *in)
{
return (ext2fs_set_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_INODE_BITMAP,
start, num, in));
}
errcode_t ext2fs_set_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
__u64 start, size_t num,
void *in)
{
return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
}
errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
ext2_ino_t start, unsigned int num,
void *out)
{
return (ext2fs_get_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_INODE_BITMAP,
start, num, out));
}
errcode_t ext2fs_get_inode_bitmap_range2(ext2fs_inode_bitmap bmap,
__u64 start, size_t num,
void *out)
{
return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
}
errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
blk_t start, unsigned int num,
void *in)
{
return (ext2fs_set_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_BLOCK_BITMAP,
start, num, in));
}
errcode_t ext2fs_set_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t start, size_t num,
void *in)
{
return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
}
errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
blk_t start, unsigned int num,
void *out)
{
return (ext2fs_get_generic_bitmap_range(bmap,
EXT2_ET_MAGIC_BLOCK_BITMAP,
start, num, out));
}
errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t start, size_t num,
void *out)
{
return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
}

158
src/ext2fs/bitops.c Normal file
View File

@ -0,0 +1,158 @@
/*
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
* routines.
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#ifndef _EXT2_HAVE_ASM_BITOPS_
/*
* For the benefit of those who are trying to port Linux to another
* architecture, here are some C-language equivalents. You should
* recode these in the native assembly language, if at all possible.
*
* C language equivalents written by Theodore Ts'o, 9/26/92.
* Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian
* systems, as well as non-32 bit systems.
*/
int ext2fs_set_bit(unsigned int nr,void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR |= mask;
return retval;
}
int ext2fs_clear_bit(unsigned int nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR &= ~mask;
return retval;
}
int ext2fs_test_bit(unsigned int nr, const void * addr)
{
int mask;
const unsigned char *ADDR = (const unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
return (mask & *ADDR);
}
#endif /* !_EXT2_HAVE_ASM_BITOPS_ */
void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
const char *description)
{
#ifndef OMIT_COM_ERR
if (description)
com_err(0, errcode, "#%lu for %s", arg, description);
else
com_err(0, errcode, "#%lu", arg);
#endif
}
/*
* C-only 64 bit ops.
*/
int ext2fs_set_bit64(__u64 nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR |= mask;
return retval;
}
int ext2fs_clear_bit64(__u64 nr, void * addr)
{
int mask, retval;
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
retval = mask & *ADDR;
*ADDR &= ~mask;
return retval;
}
int ext2fs_test_bit64(__u64 nr, const void * addr)
{
int mask;
const unsigned char *ADDR = (const unsigned char *) addr;
ADDR += nr >> 3;
mask = 1 << (nr & 0x07);
return (mask & *ADDR);
}
static unsigned int popcount8(unsigned int w)
{
unsigned int res = w - ((w >> 1) & 0x55);
res = (res & 0x33) + ((res >> 2) & 0x33);
return (res + (res >> 4)) & 0x0F;
}
static unsigned int popcount32(unsigned int w)
{
unsigned int res = w - ((w >> 1) & 0x55555555);
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
res = (res + (res >> 4)) & 0x0F0F0F0F;
res = res + (res >> 8);
return (res + (res >> 16)) & 0x000000FF;
}
unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes)
{
const unsigned char *cp = addr;
const __u32 *p;
unsigned int res = 0;
while (((((uintptr_t) cp) & 3) != 0) && (nbytes > 0)) {
res += popcount8(*cp++);
nbytes--;
}
p = (const __u32 *) cp;
while (nbytes > 4) {
res += popcount32(*p++);
nbytes -= 4;
}
cp = (const unsigned char *) p;
while (nbytes > 0) {
res += popcount8(*cp++);
nbytes--;
}
return res;
}

703
src/ext2fs/bitops.h Normal file
View File

@ -0,0 +1,703 @@
/*
* bitops.h --- Bitmap frobbing code. The byte swapping routines are
* also included here.
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifdef WORDS_BIGENDIAN
#define ext2fs_cpu_to_le64(x) ((__force __le64)ext2fs_swab64((__u64)(x)))
#define ext2fs_le64_to_cpu(x) ext2fs_swab64((__force __u64)(__le64)(x))
#define ext2fs_cpu_to_le32(x) ((__force __le32)ext2fs_swab32((__u32)(x)))
#define ext2fs_le32_to_cpu(x) ext2fs_swab32((__force __u32)(__le32)(x))
#define ext2fs_cpu_to_le16(x) ((__force __le16)ext2fs_swab16((__u16)(x)))
#define ext2fs_le16_to_cpu(x) ext2fs_swab16((__force __u16)(__le16)(x))
#define ext2fs_cpu_to_be64(x) ((__force __be64)(__u64)(x))
#define ext2fs_be64_to_cpu(x) ((__force __u64)(__be64)(x))
#define ext2fs_cpu_to_be32(x) ((__force __be32)(__u32)(x))
#define ext2fs_be32_to_cpu(x) ((__force __u32)(__be32)(x))
#define ext2fs_cpu_to_be16(x) ((__force __be16)(__u16)(x))
#define ext2fs_be16_to_cpu(x) ((__force __u16)(__be16)(x))
#else
#define ext2fs_cpu_to_le64(x) ((__force __le64)(__u64)(x))
#define ext2fs_le64_to_cpu(x) ((__force __u64)(__le64)(x))
#define ext2fs_cpu_to_le32(x) ((__force __le32)(__u32)(x))
#define ext2fs_le32_to_cpu(x) ((__force __u32)(__le32)(x))
#define ext2fs_cpu_to_le16(x) ((__force __le16)(__u16)(x))
#define ext2fs_le16_to_cpu(x) ((__force __u16)(__le16)(x))
#define ext2fs_cpu_to_be64(x) ((__force __be64)ext2fs_swab64((__u64)(x)))
#define ext2fs_be64_to_cpu(x) ext2fs_swab64((__force __u64)(__be64)(x))
#define ext2fs_cpu_to_be32(x) ((__force __be32)ext2fs_swab32((__u32)(x)))
#define ext2fs_be32_to_cpu(x) ext2fs_swab32((__force __u32)(__be32)(x))
#define ext2fs_cpu_to_be16(x) ((__force __be16)ext2fs_swab16((__u16)(x)))
#define ext2fs_be16_to_cpu(x) ext2fs_swab16((__force __u16)(__be16)(x))
#endif
/*
* EXT2FS bitmap manipulation routines.
*/
/* Support for sending warning messages from the inline subroutines */
extern const char *ext2fs_block_string;
extern const char *ext2fs_inode_string;
extern const char *ext2fs_mark_string;
extern const char *ext2fs_unmark_string;
extern const char *ext2fs_test_string;
extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
const char *description);
extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
int code, unsigned long arg);
#ifdef NO_INLINE_FUNCS
extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
extern void ext2fs_fast_set_bit64(__u64 nr,void * addr);
extern void ext2fs_fast_clear_bit64(__u64 nr, void * addr);
extern __u16 ext2fs_swab16(__u16 val);
extern __u32 ext2fs_swab32(__u32 val);
extern __u64 ext2fs_swab64(__u64 val);
extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block);
extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
#endif
/* These functions routines moved to gen_bitmap.c */
extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode, int num);
extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno);
extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
/* 64-bit versions */
#ifdef NO_INLINE_FUNCS
extern int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block);
extern void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode);
extern errcode_t ext2fs_find_first_zero_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t start,
blk64_t end,
blk64_t *out);
extern errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t start,
ext2_ino_t end,
ext2_ino_t *out);
extern errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t start,
blk64_t end,
blk64_t *out);
extern errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t start,
ext2_ino_t end,
ext2_ino_t *out);
extern blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap);
extern blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap);
extern ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap);
extern int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num);
extern void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num);
extern void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num);
#endif
/* These routines moved to gen_bitmap64.c */
extern void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap);
extern errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
ext2fs_generic_bitmap bm1,
ext2fs_generic_bitmap bm2);
extern void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap);
extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
blk64_t bitno);
extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
blk64_t bitno);
extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
blk64_t bitno);
extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap);
extern __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap);
extern int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block, unsigned int num);
extern errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end,
__u64 *out);
extern errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end,
__u64 *out);
/*
* The inline routines themselves...
*
* If NO_INLINE_FUNCS is defined, then we won't try to do inline
* functions at all; they will be included as normal functions in
* inline.c
*/
#ifdef NO_INLINE_FUNCS
#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \
defined(__i586__)))
/* This prevents bitops.c from trying to include the C */
/* function version of these functions */
#define _EXT2_HAVE_ASM_BITOPS_
#endif
#endif /* NO_INLINE_FUNCS */
#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
#ifdef INCLUDE_INLINE_FUNCS
#if (__STDC_VERSION__ >= 199901L)
#define _INLINE_ extern inline
#else
#define _INLINE_ inline
#endif
#else /* !INCLUDE_INLINE FUNCS */
#if (__STDC_VERSION__ >= 199901L)
#define _INLINE_ inline
#else /* not C99 */
#ifdef __GNUC__
#define _INLINE_ extern __inline__
#else /* For Watcom C */
#define _INLINE_ extern inline
#endif /* __GNUC__ */
#endif /* __STDC_VERSION__ >= 199901L */
#endif /* INCLUDE_INLINE_FUNCS */
/*
* Fast bit set/clear functions that doesn't need to return the
* previous bit value.
*/
_INLINE_ void ext2fs_fast_set_bit(unsigned int nr,void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR |= (unsigned char) (1 << (nr & 0x07));
}
_INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR &= (unsigned char) ~(1 << (nr & 0x07));
}
_INLINE_ void ext2fs_fast_set_bit64(__u64 nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR |= (unsigned char) (1 << (nr & 0x07));
}
_INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr)
{
unsigned char *ADDR = (unsigned char *) addr;
ADDR += nr >> 3;
*ADDR &= (unsigned char) ~(1 << (nr & 0x07));
}
#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
(defined(__i386__) || defined(__i486__) || defined(__i586__)))
#define _EXT2_HAVE_ASM_BITOPS_
#define _EXT2_HAVE_ASM_SWAB_
/*
* These are done by inline assembly for speed reasons.....
*
* All bitoperations return 0 if the bit was cleared before the
* operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
* is the LSB of (addr+1).
*/
/*
* Some hacks to defeat gcc over-optimizations..
*/
struct __dummy_h { unsigned long a[100]; };
#define EXT2FS_ADDR (*(struct __dummy_h *) addr)
#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)
_INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr)
{
int oldbit;
addr = (void *) (((unsigned char *) addr) + (nr >> 3));
__asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"+m" (EXT2FS_ADDR)
:"r" (nr & 7));
return oldbit;
}
_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr)
{
int oldbit;
addr = (void *) (((unsigned char *) addr) + (nr >> 3));
__asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"+m" (EXT2FS_ADDR)
:"r" (nr & 7));
return oldbit;
}
_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr)
{
int oldbit;
addr = (const void *) (((const unsigned char *) addr) + (nr >> 3));
__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (EXT2FS_CONST_ADDR),"r" (nr & 7));
return oldbit;
}
_INLINE_ __u32 ext2fs_swab32(__u32 val)
{
#ifdef EXT2FS_REQUIRE_486
__asm__("bswap %0" : "=r" (val) : "0" (val));
#else
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (val)
: "0" (val));
#endif
return val;
}
_INLINE_ __u16 ext2fs_swab16(__u16 val)
{
__asm__("xchgb %b0,%h0" /* swap bytes */ \
: "=q" (val) \
: "0" (val)); \
return val;
}
#undef EXT2FS_ADDR
#endif /* i386 */
#if !defined(_EXT2_HAVE_ASM_SWAB_)
_INLINE_ __u16 ext2fs_swab16(__u16 val)
{
return (val >> 8) | (__u16) (val << 8);
}
_INLINE_ __u32 ext2fs_swab32(__u32 val)
{
return ((val>>24) | ((val>>8)&0xFF00) |
((val<<8)&0xFF0000) | (val<<24));
}
#endif /* !_EXT2_HAVE_ASM_SWAB */
_INLINE_ __u64 ext2fs_swab64(__u64 val)
{
return (ext2fs_swab32((__u32) (val >> 32)) |
(((__u64)ext2fs_swab32(val & 0xFFFFFFFFUL)) << 32));
}
_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
blk_t block)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
{
return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
return ext2fs_test_block_bitmap_range(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
ext2fs_mark_block_bitmap_range(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
ext2fs_unmark_block_bitmap_range(bitmap, block, num);
}
/* 64-bit versions */
_INLINE_ int ext2fs_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ int ext2fs_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ int ext2fs_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, block);
}
_INLINE_ int ext2fs_fast_test_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t block)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
block);
}
_INLINE_ void ext2fs_fast_mark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_mark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ void ext2fs_fast_unmark_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap) bitmap, inode);
}
_INLINE_ int ext2fs_fast_test_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode)
{
return ext2fs_test_generic_bmap((ext2fs_generic_bitmap) bitmap,
inode);
}
_INLINE_ errcode_t ext2fs_find_first_zero_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t start,
blk64_t end,
blk64_t *out)
{
__u64 o;
errcode_t rv;
rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap,
start, end, &o);
if (!rv)
*out = o;
return rv;
}
_INLINE_ errcode_t ext2fs_find_first_zero_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t start,
ext2_ino_t end,
ext2_ino_t *out)
{
__u64 o;
errcode_t rv;
rv = ext2fs_find_first_zero_generic_bmap((ext2fs_generic_bitmap) bitmap,
start, end, &o);
if (!rv)
*out = (ext2_ino_t) o;
return rv;
}
_INLINE_ errcode_t ext2fs_find_first_set_block_bitmap2(ext2fs_block_bitmap bitmap,
blk64_t start,
blk64_t end,
blk64_t *out)
{
__u64 o;
errcode_t rv;
rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap,
start, end, &o);
if (!rv)
*out = o;
return rv;
}
_INLINE_ errcode_t ext2fs_find_first_set_inode_bitmap2(ext2fs_inode_bitmap bitmap,
ext2_ino_t start,
ext2_ino_t end,
ext2_ino_t *out)
{
__u64 o;
errcode_t rv;
rv = ext2fs_find_first_set_generic_bmap((ext2fs_generic_bitmap) bitmap,
start, end, &o);
if (!rv)
*out = (ext2_ino_t) o;
return rv;
}
_INLINE_ blk64_t ext2fs_get_block_bitmap_start2(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start2(ext2fs_inode_bitmap bitmap)
{
return (ext2_ino_t) ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ blk64_t ext2fs_get_block_bitmap_end2(ext2fs_block_bitmap bitmap)
{
return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end2(ext2fs_inode_bitmap bitmap)
{
return (ext2_ino_t) ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap) bitmap);
}
_INLINE_ int ext2fs_fast_test_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num)
{
return ext2fs_test_block_bitmap_range2(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num)
{
ext2fs_mark_block_bitmap_range2(bitmap, block, num);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap,
blk64_t block,
unsigned int num)
{
ext2fs_unmark_block_bitmap_range2(bitmap, block, num);
}
#undef _INLINE_
#endif
#ifndef _EXT2_HAVE_ASM_BITOPS_
extern int ext2fs_set_bit(unsigned int nr,void * addr);
extern int ext2fs_clear_bit(unsigned int nr, void * addr);
extern int ext2fs_test_bit(unsigned int nr, const void * addr);
#endif
extern int ext2fs_set_bit64(__u64 nr,void * addr);
extern int ext2fs_clear_bit64(__u64 nr, void * addr);
extern int ext2fs_test_bit64(__u64 nr, const void * addr);
extern unsigned int ext2fs_bitcount(const void *addr, unsigned int nbytes);

492
src/ext2fs/blkmap64_ba.c Normal file
View File

@ -0,0 +1,492 @@
/*
* blkmap64_ba.c --- Simple bitarray implementation for bitmaps
*
* Copyright (C) 2008 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
#include "bmap64.h"
/*
* Private data for bit array implementation of bitmap ops.
* Currently, this is just a pointer to our big flat hunk of memory,
* exactly equivalent to the old-skool char * bitmap member.
*/
struct ext2fs_ba_private_struct {
char *bitarray;
};
typedef struct ext2fs_ba_private_struct *ext2fs_ba_private;
static errcode_t ba_alloc_private_data (ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp;
errcode_t retval;
size_t size;
/*
* Since we only have the one pointer, we could just shove our
* private data in the void *private field itself, but then
* we'd have to do a fair bit of rewriting if we ever added a
* field. I'm agnostic.
*/
retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp);
if (retval)
return retval;
size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
retval = ext2fs_get_mem(size, &bp->bitarray);
if (retval) {
ext2fs_free_mem(&bp);
bp = 0;
return retval;
}
bitmap->private = (void *) bp;
return 0;
}
static errcode_t ba_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp;
errcode_t retval;
size_t size;
retval = ba_alloc_private_data (bitmap);
if (retval)
return retval;
bp = (ext2fs_ba_private) bitmap->private;
size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
memset(bp->bitarray, 0, size);
return 0;
}
static void ba_free_bmap(ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
if (!bp)
return;
if (bp->bitarray) {
ext2fs_free_mem (&bp->bitarray);
bp->bitarray = 0;
}
ext2fs_free_mem (&bp);
bp = 0;
}
static errcode_t ba_copy_bmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap dest)
{
ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private;
ext2fs_ba_private dest_bp;
errcode_t retval;
size_t size;
retval = ba_alloc_private_data (dest);
if (retval)
return retval;
dest_bp = (ext2fs_ba_private) dest->private;
size = (size_t) (((src->real_end - src->start) / 8) + 1);
memcpy (dest_bp->bitarray, src_bp->bitarray, size);
return 0;
}
static errcode_t ba_resize_bmap(ext2fs_generic_bitmap bmap,
__u64 new_end, __u64 new_real_end)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private;
errcode_t retval;
size_t size, new_size;
__u64 bitno;
/*
* If we're expanding the bitmap, make sure all of the new
* parts of the bitmap are zero.
*/
if (new_end > bmap->end) {
bitno = bmap->real_end;
if (bitno > new_end)
bitno = new_end;
for (; bitno > bmap->end; bitno--)
ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray);
}
if (new_real_end == bmap->real_end) {
bmap->end = new_end;
return 0;
}
size = ((bmap->real_end - bmap->start) / 8) + 1;
new_size = ((new_real_end - bmap->start) / 8) + 1;
if (size != new_size) {
retval = ext2fs_resize_mem(size, new_size, &bp->bitarray);
if (retval)
return retval;
}
if (new_size > size)
memset(bp->bitarray + size, 0, new_size - size);
bmap->end = new_end;
bmap->real_end = new_real_end;
return 0;
}
static int ba_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray);
}
static int ba_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray);
}
static int ba_test_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray);
}
static void ba_mark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
unsigned int i;
for (i = 0; i < num; i++)
ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray);
}
static void ba_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
blk64_t bitno = (blk64_t) arg;
unsigned int i;
for (i = 0; i < num; i++)
ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray);
}
static int ba_test_clear_bmap_extent(ext2fs_generic_bitmap bitmap,
__u64 start, unsigned int len)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
__u64 start_byte, len_byte = len >> 3;
unsigned int start_bit, len_bit = len % 8;
unsigned int first_bit = 0;
unsigned int last_bit = 0;
int mark_count = 0;
int mark_bit = 0;
int i;
const char *ADDR;
ADDR = bp->bitarray;
start -= bitmap->start;
start_byte = start >> 3;
start_bit = start % 8;
if (start_bit != 0) {
/*
* The compared start block number or start inode number
* is not the first bit in a byte.
*/
mark_count = 8 - start_bit;
if (len < 8 - start_bit) {
mark_count = (int)len;
mark_bit = len + start_bit - 1;
} else
mark_bit = 7;
for (i = mark_count; i > 0; i--, mark_bit--)
first_bit |= 1 << mark_bit;
/*
* Compare blocks or inodes in the first byte.
* If there is any marked bit, this function returns 0.
*/
if (first_bit & ADDR[start_byte])
return 0;
else if (len <= 8 - start_bit)
return 1;
start_byte++;
len_bit = (len - mark_count) % 8;
len_byte = (len - mark_count) >> 3;
}
/*
* The compared start block number or start inode number is
* the first bit in a byte.
*/
if (len_bit != 0) {
/*
* The compared end block number or end inode number is
* not the last bit in a byte.
*/
for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
last_bit |= 1 << mark_bit;
/*
* Compare blocks or inodes in the last byte.
* If there is any marked bit, this function returns 0.
*/
if (last_bit & ADDR[start_byte + len_byte])
return 0;
else if (len_byte == 0)
return 1;
}
/* Check whether all bytes are 0 */
return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
}
static errcode_t ba_set_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *in)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3);
return 0;
}
static errcode_t ba_get_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *out)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3);
return 0;
}
static void ba_clear_bmap(ext2fs_generic_bitmap bitmap)
{
ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
memset(bp->bitarray, 0,
(size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
}
#ifdef ENABLE_BMAP_STATS
static void ba_print_stats(ext2fs_generic_bitmap bitmap)
{
fprintf(stderr, "%16llu Bytes used by bitarray\n",
((bitmap->real_end - bitmap->start) >> 3) + 1 +
sizeof(struct ext2fs_ba_private_struct));
}
#else
static void ba_print_stats(ext2fs_generic_bitmap bitmap EXT2FS_ATTR((unused)))
{
}
#endif
/* Find the first zero bit between start and end, inclusive. */
static errcode_t ba_find_first_zero(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
unsigned long bitpos = start - bitmap->start;
unsigned long count = end - start + 1;
int byte_found = 0; /* whether a != 0xff byte has been found */
const unsigned char *pos;
unsigned long max_loop_count, i;
/* scan bits until we hit a byte boundary */
while ((bitpos & 0x7) != 0 && count > 0) {
if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
*out = bitpos + bitmap->start;
return 0;
}
bitpos++;
count--;
}
if (!count)
return ENOENT;
pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
/* scan bytes until 8-byte (64-bit) aligned */
while (count >= 8 && (((uintptr_t)pos) & 0x07)) {
if (*pos != 0xff) {
byte_found = 1;
break;
}
pos++;
count -= 8;
bitpos += 8;
}
if (!byte_found) {
max_loop_count = count >> 6; /* 8-byte blocks */
i = max_loop_count;
while (i) {
if (*((const __u64 *)pos) != ((__u64)-1))
break;
pos += 8;
i--;
}
count -= 64 * (max_loop_count - i);
bitpos += 64 * (max_loop_count - i);
max_loop_count = count >> 3;
i = max_loop_count;
while (i) {
if (*pos != 0xff) {
byte_found = 1;
break;
}
pos++;
i--;
}
count -= 8 * (max_loop_count - i);
bitpos += 8 * (max_loop_count - i);
}
/* Here either count < 8 or byte_found == 1. */
while (count-- > 0) {
if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
*out = bitpos + bitmap->start;
return 0;
}
bitpos++;
}
return ENOENT;
}
/* Find the first one bit between start and end, inclusive. */
static errcode_t ba_find_first_set(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
unsigned long bitpos = start - bitmap->start;
unsigned long count = end - start + 1;
int byte_found = 0; /* whether a != 0xff byte has been found */
const unsigned char *pos;
unsigned long max_loop_count, i;
/* scan bits until we hit a byte boundary */
while ((bitpos & 0x7) != 0 && count > 0) {
if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
*out = bitpos + bitmap->start;
return 0;
}
bitpos++;
count--;
}
if (!count)
return ENOENT;
pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
/* scan bytes until 8-byte (64-bit) aligned */
while (count >= 8 && (((uintptr_t)pos) & 0x07)) {
if (*pos != 0) {
byte_found = 1;
break;
}
pos++;
count -= 8;
bitpos += 8;
}
if (!byte_found) {
max_loop_count = count >> 6; /* 8-byte blocks */
i = max_loop_count;
while (i) {
if (*((const __u64 *)pos) != 0)
break;
pos += 8;
i--;
}
count -= 64 * (max_loop_count - i);
bitpos += 64 * (max_loop_count - i);
max_loop_count = count >> 3;
i = max_loop_count;
while (i) {
if (*pos != 0) {
byte_found = 1;
break;
}
pos++;
i--;
}
count -= 8 * (max_loop_count - i);
bitpos += 8 * (max_loop_count - i);
}
/* Here either count < 8 or byte_found == 1. */
while (count-- > 0) {
if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
*out = bitpos + bitmap->start;
return 0;
}
bitpos++;
}
return ENOENT;
}
struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
.type = EXT2FS_BMAP64_BITARRAY,
.new_bmap = ba_new_bmap,
.free_bmap = ba_free_bmap,
.copy_bmap = ba_copy_bmap,
.resize_bmap = ba_resize_bmap,
.mark_bmap = ba_mark_bmap,
.unmark_bmap = ba_unmark_bmap,
.test_bmap = ba_test_bmap,
.test_clear_bmap_extent = ba_test_clear_bmap_extent,
.mark_bmap_extent = ba_mark_bmap_extent,
.unmark_bmap_extent = ba_unmark_bmap_extent,
.set_bmap_range = ba_set_bmap_range,
.get_bmap_range = ba_get_bmap_range,
.clear_bmap = ba_clear_bmap,
.print_stats = ba_print_stats,
.find_first_zero = ba_find_first_zero,
.find_first_set = ba_find_first_set
};

980
src/ext2fs/blkmap64_rb.c Normal file
View File

@ -0,0 +1,980 @@
/*
* blkmap64_rb.c --- Simple rb-tree implementation for bitmaps
*
* (C)2010 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_LINUX_TYPES_H
#include <linux/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
#include "bmap64.h"
#include "rbtree.h"
#include <limits.h>
struct bmap_rb_extent {
struct rb_node node;
__u64 start;
__u64 count;
};
struct ext2fs_rb_private {
struct rb_root root;
struct bmap_rb_extent *wcursor;
struct bmap_rb_extent *rcursor;
struct bmap_rb_extent *rcursor_next;
#ifdef ENABLE_BMAP_STATS_OPS
__u64 mark_hit;
__u64 test_hit;
#endif
};
inline static struct bmap_rb_extent *node_to_extent(struct rb_node *node)
{
/*
* This depends on the fact the struct rb_node is at the
* beginning of the bmap_rb_extent structure. We use this
* instead of the ext2fs_rb_entry macro because it causes gcc
* -Wall to generate a huge amount of noise.
*/
return (struct bmap_rb_extent *) node;
}
static int rb_insert_extent(__u64 start, __u64 count,
struct ext2fs_rb_private *);
static void rb_get_new_extent(struct bmap_rb_extent **, __u64, __u64);
/* #define DEBUG_RB */
#ifdef DEBUG_RB
static void print_tree(struct rb_root *root)
{
struct rb_node *node = NULL;
struct bmap_rb_extent *ext;
printf("\t\t\t=================================\n");
node = ext2fs_rb_first(root);
for (node = ext2fs_rb_first(root); node != NULL;
node = ext2fs_rb_next(node)) {
ext = node_to_extent(node);
printf("\t\t\t--> (%llu -> %llu)\n",
ext->start, ext->start + ext->count);
}
printf("\t\t\t=================================\n");
}
static void check_tree(struct rb_root *root, const char *msg)
{
struct rb_node *node;
struct bmap_rb_extent *ext, *old = NULL;
for (node = ext2fs_rb_first(root); node;
node = ext2fs_rb_next(node)) {
ext = node_to_extent(node);
if (ext->count == 0) {
printf("Tree Error: count is zero\n");
printf("extent: %llu -> %llu (%llu)\n", ext->start,
ext->start + ext->count, ext->count);
goto err_out;
}
if (ext->start + ext->count < ext->start) {
printf("Tree Error: start or count is crazy\n");
printf("extent: %llu -> %llu (%llu)\n", ext->start,
ext->start + ext->count, ext->count);
goto err_out;
}
if (old) {
if (old->start > ext->start) {
printf("Tree Error: start is crazy\n");
printf("extent: %llu -> %llu (%llu)\n",
old->start, old->start + old->count,
old->count);
printf("extent next: %llu -> %llu (%llu)\n",
ext->start, ext->start + ext->count,
ext->count);
goto err_out;
}
if ((old->start + old->count) >= ext->start) {
printf("Tree Error: extent is crazy\n");
printf("extent: %llu -> %llu (%llu)\n",
old->start, old->start + old->count,
old->count);
printf("extent next: %llu -> %llu (%llu)\n",
ext->start, ext->start + ext->count,
ext->count);
goto err_out;
}
}
old = ext;
}
return;
err_out:
printf("%s\n", msg);
print_tree(root);
exit(1);
}
#else
#define check_tree(root, msg) do {} while (0)
#define print_tree(root) do {} while (0)
#endif
static void rb_get_new_extent(struct bmap_rb_extent **ext, __u64 start,
__u64 count)
{
struct bmap_rb_extent *new_ext;
int retval;
retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent),
&new_ext);
if (retval)
abort();
new_ext->start = start;
new_ext->count = count;
*ext = new_ext;
}
inline
static void rb_free_extent(struct ext2fs_rb_private *bp,
struct bmap_rb_extent *ext)
{
if (bp->wcursor == ext)
bp->wcursor = NULL;
if (bp->rcursor == ext)
bp->rcursor = NULL;
if (bp->rcursor_next == ext)
bp->rcursor_next = NULL;
ext2fs_free_mem(&ext);
}
static errcode_t rb_alloc_private_data (ext2fs_generic_bitmap bitmap)
{
struct ext2fs_rb_private *bp;
errcode_t retval;
retval = ext2fs_get_mem(sizeof (struct ext2fs_rb_private), &bp);
if (retval)
return retval;
bp->root = RB_ROOT;
bp->rcursor = NULL;
bp->rcursor_next = NULL;
bp->wcursor = NULL;
#ifdef ENABLE_BMAP_STATS_OPS
bp->test_hit = 0;
bp->mark_hit = 0;
#endif
bitmap->private = (void *) bp;
return 0;
}
static errcode_t rb_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
ext2fs_generic_bitmap bitmap)
{
errcode_t retval;
retval = rb_alloc_private_data (bitmap);
if (retval)
return retval;
return 0;
}
static void rb_free_tree(struct rb_root *root)
{
struct bmap_rb_extent *ext;
struct rb_node *node, *next;
for (node = ext2fs_rb_first(root); node; node = next) {
next = ext2fs_rb_next(node);
ext = node_to_extent(node);
ext2fs_rb_erase(node, root);
ext2fs_free_mem(&ext);
}
}
static void rb_free_bmap(ext2fs_generic_bitmap bitmap)
{
struct ext2fs_rb_private *bp;
bp = (struct ext2fs_rb_private *) bitmap->private;
rb_free_tree(&bp->root);
ext2fs_free_mem(&bp);
bp = 0;
}
static errcode_t rb_copy_bmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap dest)
{
struct ext2fs_rb_private *src_bp, *dest_bp;
struct bmap_rb_extent *src_ext, *dest_ext;
struct rb_node *dest_node, *src_node, *dest_last, **n;
errcode_t retval = 0;
retval = rb_alloc_private_data (dest);
if (retval)
return retval;
src_bp = (struct ext2fs_rb_private *) src->private;
dest_bp = (struct ext2fs_rb_private *) dest->private;
src_bp->rcursor = NULL;
dest_bp->rcursor = NULL;
src_node = ext2fs_rb_first(&src_bp->root);
while (src_node) {
src_ext = node_to_extent(src_node);
retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent),
&dest_ext);
if (retval)
break;
memcpy(dest_ext, src_ext, sizeof(struct bmap_rb_extent));
dest_node = &dest_ext->node;
n = &dest_bp->root.rb_node;
dest_last = NULL;
if (*n) {
dest_last = ext2fs_rb_last(&dest_bp->root);
n = &(dest_last)->rb_right;
}
ext2fs_rb_link_node(dest_node, dest_last, n);
ext2fs_rb_insert_color(dest_node, &dest_bp->root);
src_node = ext2fs_rb_next(src_node);
}
return retval;
}
static void rb_truncate(__u64 new_max, struct rb_root *root)
{
struct bmap_rb_extent *ext;
struct rb_node *node;
node = ext2fs_rb_last(root);
while (node) {
ext = node_to_extent(node);
if ((ext->start + ext->count - 1) <= new_max)
break;
else if (ext->start > new_max) {
ext2fs_rb_erase(node, root);
ext2fs_free_mem(&ext);
node = ext2fs_rb_last(root);
continue;
} else
ext->count = new_max - ext->start + 1;
}
}
static errcode_t rb_resize_bmap(ext2fs_generic_bitmap bmap,
__u64 new_end, __u64 new_real_end)
{
struct ext2fs_rb_private *bp;
bp = (struct ext2fs_rb_private *) bmap->private;
bp->rcursor = NULL;
bp->wcursor = NULL;
rb_truncate(((new_end < bmap->end) ? new_end : bmap->end) - bmap->start,
&bp->root);
bmap->end = new_end;
bmap->real_end = new_real_end;
if (bmap->end < bmap->real_end)
rb_insert_extent(bmap->end + 1 - bmap->start,
bmap->real_end - bmap->end, bp);
return 0;
}
inline static int
rb_test_bit(struct ext2fs_rb_private *bp, __u64 bit)
{
struct bmap_rb_extent *rcursor, *next_ext = NULL;
struct rb_node *parent = NULL, *next;
struct rb_node **n = &bp->root.rb_node;
struct bmap_rb_extent *ext;
rcursor = bp->rcursor;
if (!rcursor)
goto search_tree;
if (bit >= rcursor->start && bit < rcursor->start + rcursor->count) {
#ifdef ENABLE_BMAP_STATS_OPS
bp->test_hit++;
#endif
return 1;
}
next_ext = bp->rcursor_next;
if (!next_ext) {
next = ext2fs_rb_next(&rcursor->node);
if (next)
next_ext = node_to_extent(next);
bp->rcursor_next = next_ext;
}
if (next_ext) {
if ((bit >= rcursor->start + rcursor->count) &&
(bit < next_ext->start)) {
#ifdef BMAP_STATS_OPS
bp->test_hit++;
#endif
return 0;
}
}
bp->rcursor = NULL;
bp->rcursor_next = NULL;
rcursor = bp->wcursor;
if (!rcursor)
goto search_tree;
if (bit >= rcursor->start && bit < rcursor->start + rcursor->count)
return 1;
search_tree:
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (bit < ext->start)
n = &(*n)->rb_left;
else if (bit >= (ext->start + ext->count))
n = &(*n)->rb_right;
else {
bp->rcursor = ext;
bp->rcursor_next = NULL;
return 1;
}
}
return 0;
}
static int rb_insert_extent(__u64 start, __u64 count,
struct ext2fs_rb_private *bp)
{
struct rb_root *root = &bp->root;
struct rb_node *parent = NULL, **n = &root->rb_node;
struct rb_node *new_node, *node, *next;
struct bmap_rb_extent *new_ext;
struct bmap_rb_extent *ext;
int retval = 0;
bp->rcursor_next = NULL;
ext = bp->wcursor;
if (ext) {
if (start >= ext->start &&
start <= (ext->start + ext->count)) {
#ifdef ENABLE_BMAP_STATS_OPS
bp->mark_hit++;
#endif
goto got_extent;
}
}
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (start < ext->start) {
n = &(*n)->rb_left;
} else if (start > (ext->start + ext->count)) {
n = &(*n)->rb_right;
} else {
got_extent:
if ((start + count) <= (ext->start + ext->count))
return 1;
if ((ext->start + ext->count) == start)
retval = 0;
else
retval = 1;
count += (start - ext->start);
start = ext->start;
new_ext = ext;
new_node = &ext->node;
goto skip_insert;
}
}
rb_get_new_extent(&new_ext, start, count);
new_node = &new_ext->node;
ext2fs_rb_link_node(new_node, parent, n);
ext2fs_rb_insert_color(new_node, root);
bp->wcursor = new_ext;
node = ext2fs_rb_prev(new_node);
if (node) {
ext = node_to_extent(node);
if ((ext->start + ext->count) == start) {
start = ext->start;
count += ext->count;
ext2fs_rb_erase(node, root);
rb_free_extent(bp, ext);
}
}
skip_insert:
/* See if we can merge extent to the right */
for (node = ext2fs_rb_next(new_node); node != NULL; node = next) {
next = ext2fs_rb_next(node);
ext = node_to_extent(node);
if ((ext->start + ext->count) <= start)
continue;
/* No more merging */
if ((start + count) < ext->start)
break;
/* ext is embedded in new_ext interval */
if ((start + count) >= (ext->start + ext->count)) {
ext2fs_rb_erase(node, root);
rb_free_extent(bp, ext);
continue;
} else {
/* merge ext with new_ext */
count += ((ext->start + ext->count) -
(start + count));
ext2fs_rb_erase(node, root);
rb_free_extent(bp, ext);
break;
}
}
new_ext->start = start;
new_ext->count = count;
return retval;
}
static int rb_remove_extent(__u64 start, __u64 count,
struct ext2fs_rb_private *bp)
{
struct rb_root *root = &bp->root;
struct rb_node *parent = NULL, **n = &root->rb_node;
struct rb_node *node;
struct bmap_rb_extent *ext;
__u64 new_start, new_count;
int retval = 0;
if (ext2fs_rb_empty_root(root))
return 0;
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (start < ext->start) {
n = &(*n)->rb_left;
continue;
} else if (start >= (ext->start + ext->count)) {
n = &(*n)->rb_right;
continue;
}
if ((start > ext->start) &&
(start + count) < (ext->start + ext->count)) {
/* We have to split extent into two */
new_start = start + count;
new_count = (ext->start + ext->count) - new_start;
ext->count = start - ext->start;
rb_insert_extent(new_start, new_count, bp);
return 1;
}
if ((start + count) >= (ext->start + ext->count)) {
ext->count = start - ext->start;
retval = 1;
}
if (0 == ext->count) {
parent = ext2fs_rb_next(&ext->node);
ext2fs_rb_erase(&ext->node, root);
rb_free_extent(bp, ext);
break;
}
if (start == ext->start) {
ext->start += count;
ext->count -= count;
return 1;
}
}
/* See if we should delete or truncate extent on the right */
for (; parent != NULL; parent = node) {
node = ext2fs_rb_next(parent);
ext = node_to_extent(parent);
if ((ext->start + ext->count) <= start)
continue;
/* No more extents to be removed/truncated */
if ((start + count) < ext->start)
break;
/* The entire extent is within the region to be removed */
if ((start + count) >= (ext->start + ext->count)) {
ext2fs_rb_erase(parent, root);
rb_free_extent(bp, ext);
retval = 1;
continue;
} else {
/* modify the last extent in region to be removed */
ext->count -= ((start + count) - ext->start);
ext->start = start + count;
retval = 1;
break;
}
}
return retval;
}
static int rb_mark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
struct ext2fs_rb_private *bp;
int retval;
bp = (struct ext2fs_rb_private *) bitmap->private;
arg -= bitmap->start;
retval = rb_insert_extent(arg, 1, bp);
check_tree(&bp->root, __func__);
return retval;
}
static int rb_unmark_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
struct ext2fs_rb_private *bp;
int retval;
bp = (struct ext2fs_rb_private *) bitmap->private;
arg -= bitmap->start;
retval = rb_remove_extent(arg, 1, bp);
check_tree(&bp->root, __func__);
return retval;
}
inline
static int rb_test_bmap(ext2fs_generic_bitmap bitmap, __u64 arg)
{
struct ext2fs_rb_private *bp;
bp = (struct ext2fs_rb_private *) bitmap->private;
arg -= bitmap->start;
return rb_test_bit(bp, arg);
}
static void rb_mark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num)
{
struct ext2fs_rb_private *bp;
bp = (struct ext2fs_rb_private *) bitmap->private;
arg -= bitmap->start;
rb_insert_extent(arg, num, bp);
check_tree(&bp->root, __func__);
}
static void rb_unmark_bmap_extent(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num)
{
struct ext2fs_rb_private *bp;
bp = (struct ext2fs_rb_private *) bitmap->private;
arg -= bitmap->start;
rb_remove_extent(arg, num, bp);
check_tree(&bp->root, __func__);
}
static int rb_test_clear_bmap_extent(ext2fs_generic_bitmap bitmap,
__u64 start, unsigned int len)
{
struct rb_node *parent = NULL, **n;
struct rb_node *node, *next;
struct ext2fs_rb_private *bp;
struct bmap_rb_extent *ext;
int retval = 1;
bp = (struct ext2fs_rb_private *) bitmap->private;
n = &bp->root.rb_node;
start -= bitmap->start;
if (len == 0 || ext2fs_rb_empty_root(&bp->root))
return 1;
/*
* If we find nothing, we should examine whole extent, but
* when we find match, the extent is not clean, thus be return
* false.
*/
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (start < ext->start) {
n = &(*n)->rb_left;
} else if (start >= (ext->start + ext->count)) {
n = &(*n)->rb_right;
} else {
/*
* We found extent int the tree -> extent is not
* clean
*/
return 0;
}
}
node = parent;
while (node) {
next = ext2fs_rb_next(node);
ext = node_to_extent(node);
node = next;
if ((ext->start + ext->count) <= start)
continue;
/* No more merging */
if ((start + len) <= ext->start)
break;
retval = 0;
break;
}
return retval;
}
static errcode_t rb_set_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *in)
{
struct ext2fs_rb_private *bp;
unsigned char *cp = in;
size_t i;
int first_set = -1;
bp = (struct ext2fs_rb_private *) bitmap->private;
for (i = 0; i < num; i++) {
if ((i & 7) == 0) {
unsigned char c = cp[i/8];
if (c == 0xFF) {
if (first_set == -1)
first_set = i;
i += 7;
continue;
}
if ((c == 0x00) && (first_set == -1)) {
i += 7;
continue;
}
}
if (ext2fs_test_bit(i, in)) {
if (first_set == -1)
first_set = i;
continue;
}
if (first_set == -1)
continue;
rb_insert_extent(start + first_set - bitmap->start,
i - first_set, bp);
check_tree(&bp->root, __func__);
first_set = -1;
}
if (first_set != -1) {
rb_insert_extent(start + first_set - bitmap->start,
num - first_set, bp);
check_tree(&bp->root, __func__);
}
return 0;
}
static errcode_t rb_get_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *out)
{
struct rb_node *parent = NULL, *next, **n;
struct ext2fs_rb_private *bp;
struct bmap_rb_extent *ext;
__u64 count, pos;
bp = (struct ext2fs_rb_private *) bitmap->private;
n = &bp->root.rb_node;
start -= bitmap->start;
if (ext2fs_rb_empty_root(&bp->root))
return 0;
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (start < ext->start) {
n = &(*n)->rb_left;
} else if (start >= (ext->start + ext->count)) {
n = &(*n)->rb_right;
} else
break;
}
memset(out, 0, (num + 7) >> 3);
for (; parent != NULL; parent = next) {
next = ext2fs_rb_next(parent);
ext = node_to_extent(parent);
pos = ext->start;
count = ext->count;
if (pos >= start + num)
break;
if (pos < start) {
if (pos + count < start)
continue;
count -= start - pos;
pos = start;
}
if (pos + count > start + num)
count = start + num - pos;
while (count > 0) {
if ((count >= 8) &&
((pos - start) % 8) == 0) {
int nbytes = count >> 3;
int offset = (pos - start) >> 3;
memset(((char *) out) + offset, 0xFF, nbytes);
pos += nbytes << 3;
count -= nbytes << 3;
continue;
}
ext2fs_fast_set_bit64((pos - start), out);
pos++;
count--;
}
}
return 0;
}
static void rb_clear_bmap(ext2fs_generic_bitmap bitmap)
{
struct ext2fs_rb_private *bp;
bp = (struct ext2fs_rb_private *) bitmap->private;
rb_free_tree(&bp->root);
bp->rcursor = NULL;
bp->rcursor_next = NULL;
bp->wcursor = NULL;
check_tree(&bp->root, __func__);
}
static errcode_t rb_find_first_zero(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
struct rb_node *parent = NULL, **n;
struct ext2fs_rb_private *bp;
struct bmap_rb_extent *ext;
bp = (struct ext2fs_rb_private *) bitmap->private;
n = &bp->root.rb_node;
start -= bitmap->start;
end -= bitmap->start;
if (start > end)
return EINVAL;
if (ext2fs_rb_empty_root(&bp->root))
return ENOENT;
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (start < ext->start) {
n = &(*n)->rb_left;
} else if (start >= (ext->start + ext->count)) {
n = &(*n)->rb_right;
} else if (ext->start + ext->count <= end) {
*out = ext->start + ext->count + bitmap->start;
return 0;
} else
return ENOENT;
}
*out = start + bitmap->start;
return 0;
}
static errcode_t rb_find_first_set(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
struct rb_node *parent = NULL, **n;
struct rb_node *node;
struct ext2fs_rb_private *bp;
struct bmap_rb_extent *ext;
bp = (struct ext2fs_rb_private *) bitmap->private;
n = &bp->root.rb_node;
start -= bitmap->start;
end -= bitmap->start;
if (start > end)
return EINVAL;
if (ext2fs_rb_empty_root(&bp->root))
return ENOENT;
while (*n) {
parent = *n;
ext = node_to_extent(parent);
if (start < ext->start) {
n = &(*n)->rb_left;
} else if (start >= (ext->start + ext->count)) {
n = &(*n)->rb_right;
} else {
/* The start bit is set */
*out = start + bitmap->start;
return 0;
}
}
node = parent;
ext = node_to_extent(node);
if (ext->start < start) {
node = ext2fs_rb_next(node);
if (node == NULL)
return ENOENT;
ext = node_to_extent(node);
}
if (ext->start <= end) {
*out = ext->start + bitmap->start;
return 0;
}
return ENOENT;
}
#ifdef ENABLE_BMAP_STATS
static void rb_print_stats(ext2fs_generic_bitmap bitmap)
{
struct ext2fs_rb_private *bp;
struct rb_node *node = NULL;
struct bmap_rb_extent *ext;
__u64 count = 0;
__u64 max_size = 0;
__u64 min_size = ULONG_MAX;
__u64 size = 0, avg_size = 0;
double eff;
#ifdef ENABLE_BMAP_STATS_OPS
__u64 mark_all, test_all;
double m_hit = 0.0, t_hit = 0.0;
#endif
bp = (struct ext2fs_rb_private *) bitmap->private;
for (node = ext2fs_rb_first(&bp->root); node != NULL;
node = ext2fs_rb_next(node)) {
ext = node_to_extent(node);
count++;
if (ext->count > max_size)
max_size = ext->count;
if (ext->count < min_size)
min_size = ext->count;
size += ext->count;
}
if (count)
avg_size = size / count;
if (min_size == ULONG_MAX)
min_size = 0;
eff = (double)((count * sizeof(struct bmap_rb_extent)) << 3) /
(bitmap->real_end - bitmap->start);
#ifdef ENABLE_BMAP_STATS_OPS
mark_all = bitmap->stats.mark_count + bitmap->stats.mark_ext_count;
test_all = bitmap->stats.test_count + bitmap->stats.test_ext_count;
if (mark_all)
m_hit = ((double)bp->mark_hit / mark_all) * 100;
if (test_all)
t_hit = ((double)bp->test_hit / test_all) * 100;
fprintf(stderr, "%16llu cache hits on test (%.2f%%)\n"
"%16llu cache hits on mark (%.2f%%)\n",
bp->test_hit, t_hit, bp->mark_hit, m_hit);
#endif
fprintf(stderr, "%16llu extents (%llu bytes)\n",
count, ((count * sizeof(struct bmap_rb_extent)) +
sizeof(struct ext2fs_rb_private)));
fprintf(stderr, "%16llu bits minimum size\n",
min_size);
fprintf(stderr, "%16llu bits maximum size\n"
"%16llu bits average size\n",
max_size, avg_size);
fprintf(stderr, "%16llu bits set in bitmap (out of %llu)\n", size,
bitmap->real_end - bitmap->start);
fprintf(stderr,
"%16.4lf memory / bitmap bit memory ratio (bitarray = 1)\n",
eff);
}
#else
static void rb_print_stats(ext2fs_generic_bitmap bitmap EXT2FS_ATTR((unused)))
{
}
#endif
struct ext2_bitmap_ops ext2fs_blkmap64_rbtree = {
.type = EXT2FS_BMAP64_RBTREE,
.new_bmap = rb_new_bmap,
.free_bmap = rb_free_bmap,
.copy_bmap = rb_copy_bmap,
.resize_bmap = rb_resize_bmap,
.mark_bmap = rb_mark_bmap,
.unmark_bmap = rb_unmark_bmap,
.test_bmap = rb_test_bmap,
.test_clear_bmap_extent = rb_test_clear_bmap_extent,
.mark_bmap_extent = rb_mark_bmap_extent,
.unmark_bmap_extent = rb_unmark_bmap_extent,
.set_bmap_range = rb_set_bmap_range,
.get_bmap_range = rb_get_bmap_range,
.clear_bmap = rb_clear_bmap,
.print_stats = rb_print_stats,
.find_first_zero = rb_find_first_zero,
.find_first_set = rb_find_first_set,
};

543
src/ext2fs/blknum.c Normal file
View File

@ -0,0 +1,543 @@
/*
* blknum.c --- Functions to handle blk64_t and high/low 64-bit block
* number.
*
* Copyright IBM Corporation, 2007
* Author Jose R. Santos <jrs@us.ibm.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "config.h"
#include "ext2fs.h"
/*
* Return the group # of a block
*/
dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk)
{
return (blk - fs->super->s_first_data_block) /
fs->super->s_blocks_per_group;
}
/*
* Return the first block (inclusive) in a group
*/
blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group)
{
return fs->super->s_first_data_block +
EXT2_GROUPS_TO_BLOCKS(fs->super, group);
}
/*
* Return the last block (inclusive) in a group
*/
blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group)
{
return (group == fs->group_desc_count - 1 ?
ext2fs_blocks_count(fs->super) - 1 :
ext2fs_group_first_block2(fs, group) +
(fs->super->s_blocks_per_group - 1));
}
/*
* Return the number of blocks in a group
*/
int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group)
{
int num_blocks;
if (group == fs->group_desc_count - 1) {
num_blocks = (ext2fs_blocks_count(fs->super) -
fs->super->s_first_data_block) %
fs->super->s_blocks_per_group;
if (!num_blocks)
num_blocks = fs->super->s_blocks_per_group;
} else
num_blocks = fs->super->s_blocks_per_group;
return num_blocks;
}
/*
* Return the inode data block count
*/
blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
struct ext2_inode *inode)
{
return (inode->i_blocks |
(ext2fs_has_feature_huge_file(fs->super) ?
(__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
(inode->i_file_acl ? EXT2_CLUSTER_SIZE(fs->super) >> 9 : 0);
}
/*
* Return the inode i_blocks count
*/
blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
struct ext2_inode *inode)
{
return (inode->i_blocks |
(ext2fs_has_feature_huge_file(fs->super) ?
(__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
}
/*
* Return the fs block count
*/
blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
{
return super->s_blocks_count |
(ext2fs_has_feature_64bit(super) ?
(__u64) super->s_blocks_count_hi << 32 : 0);
}
/*
* Set the fs block count
*/
void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_blocks_count = blk;
if (ext2fs_has_feature_64bit(super))
super->s_blocks_count_hi = (__u64) blk >> 32;
}
/*
* Add to the current fs block count
*/
void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
{
blk64_t tmp;
tmp = ext2fs_blocks_count(super) + blk;
ext2fs_blocks_count_set(super, tmp);
}
/*
* Return the fs reserved block count
*/
blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
{
return super->s_r_blocks_count |
(ext2fs_has_feature_64bit(super) ?
(__u64) super->s_r_blocks_count_hi << 32 : 0);
}
/*
* Set the fs reserved block count
*/
void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_r_blocks_count = blk;
if (ext2fs_has_feature_64bit(super))
super->s_r_blocks_count_hi = (__u64) blk >> 32;
}
/*
* Add to the current reserved fs block count
*/
void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
{
blk64_t tmp;
tmp = ext2fs_r_blocks_count(super) + blk;
ext2fs_r_blocks_count_set(super, tmp);
}
/*
* Return the fs free block count
*/
blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
{
return super->s_free_blocks_count |
(ext2fs_has_feature_64bit(super) ?
(__u64) super->s_free_blocks_hi << 32 : 0);
}
/*
* Set the fs free block count
*/
void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
{
super->s_free_blocks_count = blk;
if (ext2fs_has_feature_64bit(super))
super->s_free_blocks_hi = (__u64) blk >> 32;
}
/*
* Add to the current free fs block count
*/
void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
{
blk64_t tmp;
tmp = ext2fs_free_blocks_count(super) + blk;
ext2fs_free_blocks_count_set(super, tmp);
}
/*
* Get a pointer to a block group descriptor. We need the explicit
* pointer to the group desc for code that swaps block group
* descriptors before writing them out, as it wants to make a copy and
* do the swap there.
*/
struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
struct opaque_ext2_group_desc *gdp,
dgrp_t group)
{
int desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
return (struct ext2_group_desc *)((char *)gdp + group * desc_size);
}
/* Do the same but as an ext4 group desc for internal use here */
static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs,
struct opaque_ext2_group_desc *gdp,
dgrp_t group)
{
return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group);
}
/*
* Return the block bitmap checksum of a group
*/
__u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
__u32 csum;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
csum = gdp->bg_block_bitmap_csum_lo;
if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
csum |= ((__u32)gdp->bg_block_bitmap_csum_hi << 16);
return csum;
}
/*
* Return the block bitmap block of a group
*/
blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_block_bitmap |
(ext2fs_has_feature_64bit(fs->super) ?
(__u64)gdp->bg_block_bitmap_hi << 32 : 0);
}
/*
* Set the block bitmap block of a group
*/
void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_block_bitmap = blk;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
}
/*
* Return the inode bitmap checksum of a group
*/
__u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
__u32 csum;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
csum = gdp->bg_inode_bitmap_csum_lo;
if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
csum |= ((__u32)gdp->bg_inode_bitmap_csum_hi << 16);
return csum;
}
/*
* Return the inode bitmap block of a group
*/
blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_inode_bitmap |
(ext2fs_has_feature_64bit(fs->super) ?
(__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
}
/*
* Set the inode bitmap block of a group
*/
void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_inode_bitmap = blk;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
}
/*
* Return the inode table block of a group
*/
blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_inode_table |
(ext2fs_has_feature_64bit(fs->super) ?
(__u64) gdp->bg_inode_table_hi << 32 : 0);
}
/*
* Set the inode table block of a group
*/
void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_inode_table = blk;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_inode_table_hi = (__u64) blk >> 32;
}
/*
* Return the free blocks count of a group
*/
__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_free_blocks_count |
(ext2fs_has_feature_64bit(fs->super) ?
(__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
}
/*
* Set the free blocks count of a group
*/
void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_free_blocks_count = n;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
}
/*
* Return the free inodes count of a group
*/
__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_free_inodes_count |
(ext2fs_has_feature_64bit(fs->super) ?
(__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
}
/*
* Set the free inodes count of a group
*/
void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_free_inodes_count = n;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
}
/*
* Return the used dirs count of a group
*/
__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_used_dirs_count |
(ext2fs_has_feature_64bit(fs->super) ?
(__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
}
/*
* Set the used dirs count of a group
*/
void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_used_dirs_count = n;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
}
/*
* Return the unused inodes count of a group
*/
__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_itable_unused |
(ext2fs_has_feature_64bit(fs->super) ?
(__u32) gdp->bg_itable_unused_hi << 16 : 0);
}
/*
* Set the unused inodes count of a group
*/
void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_itable_unused = n;
if (ext2fs_has_feature_64bit(fs->super))
gdp->bg_itable_unused_hi = (__u32) n >> 16;
}
/*
* Get the flags for this block group
*/
__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_flags;
}
/*
* Zero out the flags for this block group
*/
void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_flags = 0;
return;
}
/*
* Get the value of a particular flag for this block group
*/
int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_flags & bg_flag;
}
/*
* Set a flag or set of flags for this block group
*/
void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_flags |= bg_flags;
return;
}
/*
* Clear a flag or set of flags for this block group
*/
void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_flags &= ~bg_flags;
return;
}
/*
* Get the checksum for this block group
*/
__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
return gdp->bg_checksum;
}
/*
* Set the checksum for this block group to a previously calculated value
*/
void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum)
{
struct ext4_group_desc *gdp;
gdp = ext4fs_group_desc(fs, fs->group_desc, group);
gdp->bg_checksum = checksum;
return;
}
/*
* Get the acl block of a file
*/
blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
{
blk64_t blk = inode->i_file_acl;
if (fs && ext2fs_has_feature_64bit(fs->super))
blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
return blk;
}
/*
* Set the acl block of a file
*/
void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
blk64_t blk)
{
inode->i_file_acl = blk;
if (fs && ext2fs_has_feature_64bit(fs->super))
inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
}
/*
* Set the size of the inode
*/
errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode,
ext2_off64_t size)
{
/* Only regular files get to be larger than 4GB */
if (!LINUX_S_ISREG(inode->i_mode) && (size >> 32))
return EXT2_ET_FILE_TOO_BIG;
/* If we're writing a large file, set the large_file flag */
if (LINUX_S_ISREG(inode->i_mode) &&
ext2fs_needs_large_file_feature(size) &&
(!ext2fs_has_feature_large_file(fs->super) ||
fs->super->s_rev_level == EXT2_GOOD_OLD_REV)) {
ext2fs_set_feature_large_file(fs->super);
ext2fs_update_dynamic_rev(fs);
ext2fs_mark_super_dirty(fs);
}
inode->i_size = size & 0xffffffff;
inode->i_size_high = (size >> 32);
return 0;
}

659
src/ext2fs/block.c Normal file
View File

@ -0,0 +1,659 @@
/*
* block.c --- iterate over all blocks in an inode
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct block_context {
ext2_filsys fs;
int (*func)(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t bcount,
blk64_t ref_blk,
int ref_offset,
void *priv_data);
e2_blkcnt_t bcount;
int bsize;
int flags;
errcode_t errcode;
char *ind_buf;
char *dind_buf;
char *tind_buf;
void *priv_data;
};
#define check_for_ro_violation_return(ctx, ret) \
do { \
if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
((ret) & BLOCK_CHANGED)) { \
(ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
ret |= BLOCK_ABORT | BLOCK_ERROR; \
return ret; \
} \
} while (0)
#define check_for_ro_violation_goto(ctx, ret, label) \
do { \
if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \
((ret) & BLOCK_CHANGED)) { \
(ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \
ret |= BLOCK_ABORT | BLOCK_ERROR; \
goto label; \
} \
} while (0)
static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
blk_t *block_nr;
blk64_t blk64;
limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY)) {
blk64 = *ind_block;
ret = (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->priv_data);
*ind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
if (!*ind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit;
return ret;
}
if (*ind_block >= ext2fs_blocks_count(ctx->fs->super) ||
*ind_block < ctx->fs->super->s_first_data_block) {
ctx->errcode = EXT2_ET_BAD_IND_BLOCK;
ret |= BLOCK_ERROR;
return ret;
}
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block,
ctx->ind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
block_nr = (blk_t *) ctx->ind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
blk64 = *block_nr;
flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount,
*ind_block, offset,
ctx->priv_data);
*block_nr = blk64;
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
if (*block_nr == 0)
goto skip_sparse;
blk64 = *block_nr;
flags = (*ctx->func)(ctx->fs, &blk64, ctx->bcount,
*ind_block, offset,
ctx->priv_data);
*block_nr = blk64;
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
skip_sparse:
offset += sizeof(blk_t);
}
}
check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block,
ctx->ind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT)) {
blk64 = *ind_block;
ret |= (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->priv_data);
*ind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
return ret;
}
static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
blk_t *block_nr;
blk64_t blk64;
limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
BLOCK_FLAG_DATA_ONLY))) {
blk64 = *dind_block;
ret = (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->priv_data);
*dind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
if (!*dind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += limit*limit;
return ret;
}
if (*dind_block >= ext2fs_blocks_count(ctx->fs->super) ||
*dind_block < ctx->fs->super->s_first_data_block) {
ctx->errcode = EXT2_ET_BAD_DIND_BLOCK;
ret |= BLOCK_ERROR;
return ret;
}
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block,
ctx->dind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
block_nr = (blk_t *) ctx->dind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
flags = block_iterate_ind(block_nr,
*dind_block, offset,
ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
if (*block_nr == 0) {
ctx->bcount += limit;
continue;
}
flags = block_iterate_ind(block_nr,
*dind_block, offset,
ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
}
check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block,
ctx->dind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT)) {
blk64 = *dind_block;
ret |= (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->priv_data);
*dind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
return ret;
}
static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit, offset;
blk_t *block_nr;
blk64_t blk64;
limit = ctx->fs->blocksize >> 2;
if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE |
BLOCK_FLAG_DATA_ONLY))) {
blk64 = *tind_block;
ret = (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->priv_data);
*tind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
if (!*tind_block || (ret & BLOCK_ABORT)) {
ctx->bcount += ((unsigned long long) limit)*limit*limit;
return ret;
}
if (*tind_block >= ext2fs_blocks_count(ctx->fs->super) ||
*tind_block < ctx->fs->super->s_first_data_block) {
ctx->errcode = EXT2_ET_BAD_TIND_BLOCK;
ret |= BLOCK_ERROR;
return ret;
}
ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block,
ctx->tind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
block_nr = (blk_t *) ctx->tind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
flags = block_iterate_dind(block_nr,
*tind_block,
offset, ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
if (*block_nr == 0) {
ctx->bcount += limit*limit;
continue;
}
flags = block_iterate_dind(block_nr,
*tind_block,
offset, ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
}
check_for_ro_violation_return(ctx, changed);
if (changed & BLOCK_CHANGED) {
ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block,
ctx->tind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT)) {
blk64 = *tind_block;
ret |= (*ctx->func)(ctx->fs, &blk64,
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->priv_data);
*tind_block = blk64;
}
check_for_ro_violation_return(ctx, ret);
return ret;
}
errcode_t ext2fs_block_iterate3(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t blockcnt,
blk64_t ref_blk,
int ref_offset,
void *priv_data),
void *priv_data)
{
int i;
int r, ret = 0;
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
int limit;
blk64_t blk64;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
ctx.errcode = ext2fs_read_inode(fs, ino, &inode);
if (ctx.errcode)
return ctx.errcode;
/*
* An inode with inline data has no blocks over which to
* iterate, so return an error code indicating this fact.
*/
if (inode.i_flags & EXT4_INLINE_DATA_FL)
return EXT2_ET_INLINE_DATA_CANT_ITERATE;
/*
* Check to see if we need to limit large files
*/
if (flags & BLOCK_FLAG_NO_LARGE) {
if (!LINUX_S_ISDIR(inode.i_mode) &&
(inode.i_size_high != 0))
return EXT2_ET_FILE_TOO_BIG;
}
limit = fs->blocksize >> 2;
ctx.fs = fs;
ctx.func = func;
ctx.priv_data = priv_data;
ctx.flags = flags;
ctx.bcount = 0;
if (block_buf) {
ctx.ind_buf = block_buf;
} else {
retval = ext2fs_get_array(3, fs->blocksize, &ctx.ind_buf);
if (retval)
return retval;
}
ctx.dind_buf = ctx.ind_buf + fs->blocksize;
ctx.tind_buf = ctx.dind_buf + fs->blocksize;
/*
* Iterate over the HURD translator block (if present)
*/
if ((fs->super->s_creator_os == EXT2_OS_HURD) &&
!(flags & BLOCK_FLAG_DATA_ONLY)) {
if (inode.osd1.hurd1.h_i_translator) {
blk64 = inode.osd1.hurd1.h_i_translator;
ret |= (*ctx.func)(fs, &blk64,
BLOCK_COUNT_TRANSLATOR,
0, 0, priv_data);
inode.osd1.hurd1.h_i_translator = (blk_t) blk64;
if (ret & BLOCK_ABORT)
goto abort_exit;
check_for_ro_violation_goto(&ctx, ret, abort_exit);
}
}
if (inode.i_flags & EXT4_EXTENTS_FL) {
ext2_extent_handle_t handle;
struct ext2fs_extent extent, next;
e2_blkcnt_t blockcnt = 0;
blk64_t blk, new_blk;
int op = EXT2_EXTENT_ROOT;
int uninit;
unsigned int j;
ctx.errcode = ext2fs_extent_open2(fs, ino, &inode, &handle);
if (ctx.errcode)
goto abort_exit;
while (1) {
if (op == EXT2_EXTENT_CURRENT)
ctx.errcode = 0;
else
ctx.errcode = ext2fs_extent_get(handle, op,
&extent);
if (ctx.errcode) {
if (ctx.errcode != EXT2_ET_EXTENT_NO_NEXT)
break;
ctx.errcode = 0;
if (!(flags & BLOCK_FLAG_APPEND))
break;
next_block_set:
blk = 0;
r = (*ctx.func)(fs, &blk, blockcnt,
0, 0, priv_data);
ret |= r;
check_for_ro_violation_goto(&ctx, ret,
extent_done);
if (r & BLOCK_CHANGED) {
ctx.errcode =
ext2fs_extent_set_bmap(handle,
(blk64_t) blockcnt++,
(blk64_t) blk, 0);
if (ctx.errcode || (ret & BLOCK_ABORT))
break;
if (blk)
goto next_block_set;
}
break;
}
op = EXT2_EXTENT_NEXT;
blk = extent.e_pblk;
if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) {
if (ctx.flags & BLOCK_FLAG_DATA_ONLY)
continue;
if ((!(extent.e_flags &
EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
!(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE)) ||
((extent.e_flags &
EXT2_EXTENT_FLAGS_SECOND_VISIT) &&
(ctx.flags & BLOCK_FLAG_DEPTH_TRAVERSE))) {
ret |= (*ctx.func)(fs, &blk,
-1, 0, 0, priv_data);
if (ret & BLOCK_CHANGED) {
extent.e_pblk = blk;
ctx.errcode =
ext2fs_extent_replace(handle, 0, &extent);
if (ctx.errcode)
break;
}
if (ret & BLOCK_ABORT)
break;
}
continue;
}
uninit = 0;
if (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
uninit = EXT2_EXTENT_SET_BMAP_UNINIT;
/*
* Get the next extent before we start messing
* with the current extent
*/
retval = ext2fs_extent_get(handle, op, &next);
#if 0
printf("lblk %llu pblk %llu len %d blockcnt %llu\n",
extent.e_lblk, extent.e_pblk,
extent.e_len, blockcnt);
#endif
if (extent.e_lblk + extent.e_len <= (blk64_t) blockcnt)
continue;
if (extent.e_lblk > (blk64_t) blockcnt)
blockcnt = extent.e_lblk;
j = blockcnt - extent.e_lblk;
blk += j;
for (blockcnt = extent.e_lblk, j = 0;
j < extent.e_len;
blk++, blockcnt++, j++) {
new_blk = blk;
r = (*ctx.func)(fs, &new_blk, blockcnt,
0, 0, priv_data);
ret |= r;
check_for_ro_violation_goto(&ctx, ret,
extent_done);
if (r & BLOCK_CHANGED) {
ctx.errcode =
ext2fs_extent_set_bmap(handle,
(blk64_t) blockcnt,
new_blk, uninit);
if (ctx.errcode)
goto extent_done;
}
if (ret & BLOCK_ABORT)
goto extent_done;
}
if (retval == 0) {
extent = next;
op = EXT2_EXTENT_CURRENT;
}
}
extent_done:
ext2fs_extent_free(handle);
ret |= BLOCK_ERROR; /* ctx.errcode is always valid here */
goto errout;
}
/*
* Iterate over normal data blocks
*/
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
if (inode.i_block[i] || (flags & BLOCK_FLAG_APPEND)) {
blk64 = inode.i_block[i];
ret |= (*ctx.func)(fs, &blk64, ctx.bcount, 0, i,
priv_data);
inode.i_block[i] = (blk_t) blk64;
if (ret & BLOCK_ABORT)
goto abort_exit;
}
}
check_for_ro_violation_goto(&ctx, ret, abort_exit);
if (inode.i_block[EXT2_IND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_ind(&inode.i_block[EXT2_IND_BLOCK],
0, EXT2_IND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit;
if (inode.i_block[EXT2_DIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_dind(&inode.i_block[EXT2_DIND_BLOCK],
0, EXT2_DIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
} else
ctx.bcount += limit * limit;
if (inode.i_block[EXT2_TIND_BLOCK] || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_tind(&inode.i_block[EXT2_TIND_BLOCK],
0, EXT2_TIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort_exit;
}
abort_exit:
if (ret & BLOCK_CHANGED) {
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval) {
ret |= BLOCK_ERROR;
ctx.errcode = retval;
}
}
errout:
if (!block_buf)
ext2fs_free_mem(&ctx.ind_buf);
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
}
/*
* Emulate the old ext2fs_block_iterate function!
*/
struct xlate64 {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
e2_blkcnt_t blockcnt,
blk_t ref_blk,
int ref_offset,
void *priv_data);
void *real_private;
};
static int xlate64_func(ext2_filsys fs, blk64_t *blocknr,
e2_blkcnt_t blockcnt, blk64_t ref_blk,
int ref_offset, void *priv_data)
{
struct xlate64 *xl = (struct xlate64 *) priv_data;
int ret;
blk_t block32 = *blocknr;
ret = (*xl->func)(fs, &block32, blockcnt, (blk_t) ref_blk, ref_offset,
xl->real_private);
*blocknr = block32;
return ret;
}
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
e2_blkcnt_t blockcnt,
blk_t ref_blk,
int ref_offset,
void *priv_data),
void *priv_data)
{
struct xlate64 xl;
xl.real_private = priv_data;
xl.func = func;
return ext2fs_block_iterate3(fs, ino, flags, block_buf,
xlate64_func, &xl);
}
struct xlate {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int bcount,
void *priv_data);
void *real_private;
};
#ifdef __TURBOC__
#pragma argsused
#endif
static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct xlate *xl = (struct xlate *) priv_data;
return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private);
}
errcode_t ext2fs_block_iterate(ext2_filsys fs,
ext2_ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *priv_data),
void *priv_data)
{
struct xlate xl;
xl.real_private = priv_data;
xl.func = func;
return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags,
block_buf, xlate_func, &xl);
}

497
src/ext2fs/bmap.c Normal file
View File

@ -0,0 +1,497 @@
/*
* bmap.c --- logical to physical block mapping
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS)
#define _BMAP_INLINE_ __inline__
#else
#define _BMAP_INLINE_
#endif
extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
char *block_buf, int bmap_flags,
blk_t block, blk_t *phys_blk);
#define inode_bmap(inode, nr) ((inode)->i_block[(nr)])
static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags,
blk_t ind, char *block_buf,
int *blocks_alloc,
blk_t nr, blk_t *ret_blk)
{
errcode_t retval;
blk_t b;
if (!ind) {
if (flags & BMAP_SET)
return EXT2_ET_SET_BMAP_NO_IND;
*ret_blk = 0;
return 0;
}
retval = io_channel_read_blk(fs->io, ind, 1, block_buf);
if (retval)
return retval;
if (flags & BMAP_SET) {
b = *ret_blk;
#ifdef WORDS_BIGENDIAN
b = ext2fs_swab32(b);
#endif
((blk_t *) block_buf)[nr] = b;
return io_channel_write_blk(fs->io, ind, 1, block_buf);
}
b = ((blk_t *) block_buf)[nr];
#ifdef WORDS_BIGENDIAN
b = ext2fs_swab32(b);
#endif
if (!b && (flags & BMAP_ALLOC)) {
b = nr ? ext2fs_le32_to_cpu(((blk_t *)block_buf)[nr - 1]) : ind;
retval = ext2fs_alloc_block(fs, b,
block_buf + fs->blocksize, &b);
if (retval)
return retval;
#ifdef WORDS_BIGENDIAN
((blk_t *) block_buf)[nr] = ext2fs_swab32(b);
#else
((blk_t *) block_buf)[nr] = b;
#endif
retval = io_channel_write_blk(fs->io, ind, 1, block_buf);
if (retval)
return retval;
(*blocks_alloc)++;
}
*ret_blk = b;
return 0;
}
static _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags,
blk_t dind, char *block_buf,
int *blocks_alloc,
blk_t nr, blk_t *ret_blk)
{
blk_t b = 0;
errcode_t retval;
blk_t addr_per_block;
addr_per_block = (blk_t) fs->blocksize >> 2;
retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf,
blocks_alloc, nr / addr_per_block, &b);
if (retval)
return retval;
retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
nr % addr_per_block, ret_blk);
return retval;
}
static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags,
blk_t tind, char *block_buf,
int *blocks_alloc,
blk_t nr, blk_t *ret_blk)
{
blk_t b = 0;
errcode_t retval;
blk_t addr_per_block;
addr_per_block = (blk_t) fs->blocksize >> 2;
retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf,
blocks_alloc, nr / addr_per_block, &b);
if (retval)
return retval;
retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc,
nr % addr_per_block, ret_blk);
return retval;
}
static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
ext2_extent_handle_t handle,
char *block_buf, int bmap_flags, blk64_t block,
int *ret_flags, int *blocks_alloc,
blk64_t *phys_blk);
static errcode_t implied_cluster_alloc(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
ext2_extent_handle_t handle,
blk64_t lblk, blk64_t *phys_blk)
{
blk64_t base_block, pblock = 0;
int i;
if (!ext2fs_has_feature_bigalloc(fs->super))
return 0;
base_block = lblk & ~EXT2FS_CLUSTER_MASK(fs);
/*
* Except for the logical block (lblk) that was passed in, search all
* blocks in this logical cluster for a mapping to a physical cluster.
* If any such map exists, calculate the physical block that maps to
* the logical block and return that.
*
* The old code wouldn't even look if (block % cluster_ratio) == 0;
* this is incorrect if we're allocating blocks in reverse order.
*/
for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) {
if (base_block + i == lblk)
continue;
extent_bmap(fs, ino, inode, handle, 0, 0,
base_block + i, 0, 0, &pblock);
if (pblock)
break;
}
if (pblock == 0)
return 0;
*phys_blk = pblock - i + (lblk - base_block);
return 0;
}
/* Try to map a logical block to an already-allocated physical cluster. */
errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, blk64_t lblk,
blk64_t *pblk)
{
ext2_extent_handle_t handle;
errcode_t retval;
/* Need bigalloc and extents to be enabled */
*pblk = 0;
if (!ext2fs_has_feature_bigalloc(fs->super) ||
!(inode->i_flags & EXT4_EXTENTS_FL))
return 0;
retval = ext2fs_extent_open2(fs, ino, inode, &handle);
if (retval)
goto out;
retval = implied_cluster_alloc(fs, ino, inode, handle, lblk, pblk);
if (retval)
goto out2;
out2:
ext2fs_extent_free(handle);
out:
return retval;
}
static errcode_t extent_bmap(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
ext2_extent_handle_t handle,
char *block_buf, int bmap_flags, blk64_t block,
int *ret_flags, int *blocks_alloc,
blk64_t *phys_blk)
{
struct blk_alloc_ctx alloc_ctx;
struct ext2fs_extent extent;
unsigned int offset;
errcode_t retval = 0;
blk64_t blk64 = 0;
int alloc = 0;
int set_flags;
set_flags = bmap_flags & BMAP_UNINIT ? EXT2_EXTENT_SET_BMAP_UNINIT : 0;
if (bmap_flags & BMAP_SET) {
retval = ext2fs_extent_set_bmap(handle, block,
*phys_blk, set_flags);
return retval;
}
retval = ext2fs_extent_goto(handle, block);
if (retval) {
/* If the extent is not found, return phys_blk = 0 */
if (retval == EXT2_ET_EXTENT_NOT_FOUND)
goto got_block;
return retval;
}
retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
if (retval)
return retval;
offset = block - extent.e_lblk;
if (block >= extent.e_lblk && (offset <= extent.e_len)) {
*phys_blk = extent.e_pblk + offset;
if (ret_flags && extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)
*ret_flags |= BMAP_RET_UNINIT;
}
got_block:
if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
implied_cluster_alloc(fs, ino, inode, handle, block, &blk64);
if (blk64)
goto set_extent;
retval = extent_bmap(fs, ino, inode, handle, block_buf,
0, block-1, 0, blocks_alloc, &blk64);
if (retval)
blk64 = ext2fs_find_inode_goal(fs, ino, inode, block);
alloc_ctx.ino = ino;
alloc_ctx.inode = inode;
alloc_ctx.lblk = extent.e_lblk;
alloc_ctx.flags = BLOCK_ALLOC_DATA;
retval = ext2fs_alloc_block3(fs, blk64, block_buf, &blk64,
&alloc_ctx);
if (retval)
return retval;
blk64 &= ~EXT2FS_CLUSTER_MASK(fs);
blk64 += EXT2FS_CLUSTER_MASK(fs) & block;
alloc++;
set_extent:
retval = ext2fs_extent_set_bmap(handle, block,
blk64, set_flags);
if (retval) {
ext2fs_block_alloc_stats2(fs, blk64, -1);
return retval;
}
/* Update inode after setting extent */
retval = ext2fs_read_inode(fs, ino, inode);
if (retval)
return retval;
*blocks_alloc += alloc;
*phys_blk = blk64;
}
return 0;
}
int ext2fs_file_block_offset_too_big(ext2_filsys fs,
struct ext2_inode *inode,
blk64_t offset)
{
blk64_t addr_per_block, max_map_block;
/* Kernel seems to cut us off at 4294967294 blocks */
if (offset >= (1ULL << 32) - 1)
return 1;
if (inode->i_flags & EXT4_EXTENTS_FL)
return 0;
addr_per_block = fs->blocksize >> 2;
max_map_block = addr_per_block;
max_map_block += addr_per_block * addr_per_block;
max_map_block += addr_per_block * addr_per_block * addr_per_block;
max_map_block += 12;
return offset >= max_map_block;
}
errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf, int bmap_flags, blk64_t block,
int *ret_flags, blk64_t *phys_blk)
{
struct ext2_inode inode_buf;
ext2_extent_handle_t handle = 0;
blk_t addr_per_block;
blk_t b, blk32;
blk64_t b64;
char *buf = 0;
errcode_t retval = 0;
int blocks_alloc = 0, inode_dirty = 0;
struct blk_alloc_ctx alloc_ctx = {
.ino = ino,
.inode = inode,
.lblk = 0,
.flags = BLOCK_ALLOC_DATA,
};
if (!(bmap_flags & BMAP_SET))
*phys_blk = 0;
if (ret_flags)
*ret_flags = 0;
/* Read inode structure if necessary */
if (!inode) {
retval = ext2fs_read_inode(fs, ino, &inode_buf);
if (retval)
return retval;
inode = &inode_buf;
}
addr_per_block = (blk_t) fs->blocksize >> 2;
if (ext2fs_file_block_offset_too_big(fs, inode, block))
return EXT2_ET_FILE_TOO_BIG;
/*
* If an inode has inline data, that means that it doesn't have
* any blocks and we shouldn't map any blocks for it.
*/
if (inode->i_flags & EXT4_INLINE_DATA_FL)
return EXT2_ET_INLINE_DATA_NO_BLOCK;
if (!block_buf) {
retval = ext2fs_get_array(2, fs->blocksize, &buf);
if (retval)
return retval;
block_buf = buf;
}
if (inode->i_flags & EXT4_EXTENTS_FL) {
retval = ext2fs_extent_open2(fs, ino, inode, &handle);
if (retval)
goto done;
retval = extent_bmap(fs, ino, inode, handle, block_buf,
bmap_flags, block, ret_flags,
&blocks_alloc, phys_blk);
goto done;
}
if (block < EXT2_NDIR_BLOCKS) {
if (bmap_flags & BMAP_SET) {
b = *phys_blk;
inode_bmap(inode, block) = b;
inode_dirty++;
goto done;
}
*phys_blk = inode_bmap(inode, block);
b = block ? inode_bmap(inode, block - 1) :
ext2fs_find_inode_goal(fs, ino, inode, block);
if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
b64 = b;
retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
&alloc_ctx);
b = b64;
if (retval)
goto done;
inode_bmap(inode, block) = b;
blocks_alloc++;
*phys_blk = b;
}
goto done;
}
/* Indirect block */
block -= EXT2_NDIR_BLOCKS;
blk32 = *phys_blk;
if (block < addr_per_block) {
b = inode_bmap(inode, EXT2_IND_BLOCK);
if (!b) {
if (!(bmap_flags & BMAP_ALLOC)) {
if (bmap_flags & BMAP_SET)
retval = EXT2_ET_SET_BMAP_NO_IND;
goto done;
}
b = inode_bmap(inode, EXT2_IND_BLOCK-1);
b64 = b;
retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
&alloc_ctx);
b = b64;
if (retval)
goto done;
inode_bmap(inode, EXT2_IND_BLOCK) = b;
blocks_alloc++;
}
retval = block_ind_bmap(fs, bmap_flags, b, block_buf,
&blocks_alloc, block, &blk32);
if (retval == 0)
*phys_blk = blk32;
goto done;
}
/* Doubly indirect block */
block -= addr_per_block;
if (block < addr_per_block * addr_per_block) {
b = inode_bmap(inode, EXT2_DIND_BLOCK);
if (!b) {
if (!(bmap_flags & BMAP_ALLOC)) {
if (bmap_flags & BMAP_SET)
retval = EXT2_ET_SET_BMAP_NO_IND;
goto done;
}
b = inode_bmap(inode, EXT2_IND_BLOCK);
b64 = b;
retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
&alloc_ctx);
b = b64;
if (retval)
goto done;
inode_bmap(inode, EXT2_DIND_BLOCK) = b;
blocks_alloc++;
}
retval = block_dind_bmap(fs, bmap_flags, b, block_buf,
&blocks_alloc, block, &blk32);
if (retval == 0)
*phys_blk = blk32;
goto done;
}
/* Triply indirect block */
block -= addr_per_block * addr_per_block;
b = inode_bmap(inode, EXT2_TIND_BLOCK);
if (!b) {
if (!(bmap_flags & BMAP_ALLOC)) {
if (bmap_flags & BMAP_SET)
retval = EXT2_ET_SET_BMAP_NO_IND;
goto done;
}
b = inode_bmap(inode, EXT2_DIND_BLOCK);
b64 = b;
retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
&alloc_ctx);
b = b64;
if (retval)
goto done;
inode_bmap(inode, EXT2_TIND_BLOCK) = b;
blocks_alloc++;
}
retval = block_tind_bmap(fs, bmap_flags, b, block_buf,
&blocks_alloc, block, &blk32);
if (retval == 0)
*phys_blk = blk32;
done:
if (*phys_blk && retval == 0 && (bmap_flags & BMAP_ZERO))
retval = ext2fs_zero_blocks2(fs, *phys_blk, 1, NULL, NULL);
if (buf)
ext2fs_free_mem(&buf);
if (handle)
ext2fs_extent_free(handle);
if ((retval == 0) && (blocks_alloc || inode_dirty)) {
ext2fs_iblk_add_blocks(fs, inode, blocks_alloc);
retval = ext2fs_write_inode(fs, ino, inode);
}
return retval;
}
errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
char *block_buf, int bmap_flags, blk_t block,
blk_t *phys_blk)
{
errcode_t ret;
blk64_t ret_blk = *phys_blk;
ret = ext2fs_bmap2(fs, ino, inode, block_buf, bmap_flags, block,
0, &ret_blk);
if (ret)
return ret;
if (ret_blk >= ((long long) 1 << 32))
return EOVERFLOW;
*phys_blk = ret_blk;
return 0;
}

104
src/ext2fs/bmap64.h Normal file
View File

@ -0,0 +1,104 @@
/*
* bmap64.h --- 64-bit bitmap structure
*
* Copyright (C) 2007, 2008 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
struct ext2_bmap_statistics {
int type;
struct timeval created;
#ifdef ENABLE_BMAP_STATS_OPS
unsigned long copy_count;
unsigned long resize_count;
unsigned long mark_count;
unsigned long unmark_count;
unsigned long test_count;
unsigned long mark_ext_count;
unsigned long unmark_ext_count;
unsigned long test_ext_count;
unsigned long set_range_count;
unsigned long get_range_count;
unsigned long clear_count;
blk64_t last_marked;
blk64_t last_tested;
blk64_t mark_back;
blk64_t test_back;
unsigned long mark_seq;
unsigned long test_seq;
#endif /* ENABLE_BMAP_STATS_OPS */
};
struct ext2fs_struct_generic_bitmap {
errcode_t magic;
ext2_filsys fs;
struct ext2_bitmap_ops *bitmap_ops;
int flags;
__u64 start, end;
__u64 real_end;
int cluster_bits;
char *description;
void *private;
errcode_t base_error_code;
#ifdef ENABLE_BMAP_STATS
struct ext2_bmap_statistics stats;
#endif
};
#define EXT2FS_IS_32_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))
#define EXT2FS_IS_64_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
struct ext2_bitmap_ops {
int type;
/* Generic bmap operators */
errcode_t (*new_bmap)(ext2_filsys fs, ext2fs_generic_bitmap bmap);
void (*free_bmap)(ext2fs_generic_bitmap bitmap);
errcode_t (*copy_bmap)(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap dest);
errcode_t (*resize_bmap)(ext2fs_generic_bitmap bitmap,
__u64 new_end,
__u64 new_real_end);
/* bit set/test operators */
int (*mark_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
int (*unmark_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
int (*test_bmap)(ext2fs_generic_bitmap bitmap, __u64 arg);
void (*mark_bmap_extent)(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num);
void (*unmark_bmap_extent)(ext2fs_generic_bitmap bitmap, __u64 arg,
unsigned int num);
int (*test_clear_bmap_extent)(ext2fs_generic_bitmap bitmap,
__u64 arg, unsigned int num);
errcode_t (*set_bmap_range)(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *in);
errcode_t (*get_bmap_range)(ext2fs_generic_bitmap bitmap,
__u64 start, size_t num, void *out);
void (*clear_bmap)(ext2fs_generic_bitmap bitmap);
void (*print_stats)(ext2fs_generic_bitmap);
/* Find the first zero bit between start and end, inclusive.
* May be NULL, in which case a generic function is used. */
errcode_t (*find_first_zero)(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out);
/* Find the first set bit between start and end, inclusive.
* May be NULL, in which case a generic function is used. */
errcode_t (*find_first_set)(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out);
};
extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray;
extern struct ext2_bitmap_ops ext2fs_blkmap64_rbtree;

512
src/ext2fs/closefs.c Normal file
View File

@ -0,0 +1,512 @@
/*
* closefs.c --- close an ext2 filesystem
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <string.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
static int test_root(unsigned int a, unsigned int b)
{
while (1) {
if (a < b)
return 0;
if (a == b)
return 1;
if (a % b)
return 0;
a = a / b;
}
}
int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group)
{
if (group == 0)
return 1;
if (ext2fs_has_feature_sparse_super2(fs->super)) {
if (group == fs->super->s_backup_bgs[0] ||
group == fs->super->s_backup_bgs[1])
return 1;
return 0;
}
if ((group <= 1) || !ext2fs_has_feature_sparse_super(fs->super))
return 1;
if (!(group & 1))
return 0;
if (test_root(group, 3) || (test_root(group, 5)) ||
test_root(group, 7))
return 1;
return 0;
}
/*
* ext2fs_super_and_bgd_loc2()
* @fs: ext2 fs pointer
* @group given block group
* @ret_super_blk: if !NULL, returns super block location
* @ret_old_desc_blk: if !NULL, returns location of the old block
* group descriptor
* @ret_new_desc_blk: if !NULL, returns location of meta_bg block
* group descriptor
* @ret_used_blks: if !NULL, returns number of blocks used by
* super block and group_descriptors.
*
* Returns errcode_t of 0
*/
errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
dgrp_t group,
blk64_t *ret_super_blk,
blk64_t *ret_old_desc_blk,
blk64_t *ret_new_desc_blk,
blk_t *ret_used_blks)
{
blk64_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0;
unsigned int meta_bg, meta_bg_size;
blk_t numblocks = 0;
blk64_t old_desc_blocks;
int has_super;
group_block = ext2fs_group_first_block2(fs, group);
if (group_block == 0 && fs->blocksize == 1024)
group_block = 1; /* Deal with 1024 blocksize && bigalloc */
if (ext2fs_has_feature_meta_bg(fs->super))
old_desc_blocks = fs->super->s_first_meta_bg;
else
old_desc_blocks =
fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
has_super = ext2fs_bg_has_super(fs, group);
if (has_super) {
super_blk = group_block;
numblocks++;
}
meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
meta_bg = group / meta_bg_size;
if (!ext2fs_has_feature_meta_bg(fs->super) ||
(meta_bg < fs->super->s_first_meta_bg)) {
if (has_super) {
old_desc_blk = group_block + 1;
numblocks += old_desc_blocks;
}
} else {
if (((group % meta_bg_size) == 0) ||
((group % meta_bg_size) == 1) ||
((group % meta_bg_size) == (meta_bg_size-1))) {
if (has_super)
has_super = 1;
new_desc_blk = group_block + has_super;
numblocks++;
}
}
if (ret_super_blk)
*ret_super_blk = super_blk;
if (ret_old_desc_blk)
*ret_old_desc_blk = old_desc_blk;
if (ret_new_desc_blk)
*ret_new_desc_blk = new_desc_blk;
if (ret_used_blks)
*ret_used_blks = numblocks;
return 0;
}
/*
* This function returns the location of the superblock, block group
* descriptors for a given block group. It currently returns the
* number of free blocks assuming that inode table and allocation
* bitmaps will be in the group. This is not necessarily the case
* when the flex_bg feature is enabled, so callers should take care!
* It was only really intended for use by mke2fs, and even there it's
* not that useful.
*
* The ext2fs_super_and_bgd_loc2() function is 64-bit block number
* capable and returns the number of blocks used by super block and
* group descriptors.
*/
int ext2fs_super_and_bgd_loc(ext2_filsys fs,
dgrp_t group,
blk_t *ret_super_blk,
blk_t *ret_old_desc_blk,
blk_t *ret_new_desc_blk,
int *ret_meta_bg)
{
blk64_t ret_super_blk2;
blk64_t ret_old_desc_blk2;
blk64_t ret_new_desc_blk2;
blk_t ret_used_blks;
blk_t numblocks;
unsigned int meta_bg_size;
ext2fs_super_and_bgd_loc2(fs, group, &ret_super_blk2,
&ret_old_desc_blk2,
&ret_new_desc_blk2,
&ret_used_blks);
numblocks = ext2fs_group_blocks_count(fs, group);
if (ret_super_blk)
*ret_super_blk = (blk_t)ret_super_blk2;
if (ret_old_desc_blk)
*ret_old_desc_blk = (blk_t)ret_old_desc_blk2;
if (ret_new_desc_blk)
*ret_new_desc_blk = (blk_t)ret_new_desc_blk2;
if (ret_meta_bg) {
meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
*ret_meta_bg = group / meta_bg_size;
}
numblocks -= 2 + fs->inode_blocks_per_group + ret_used_blks;
return numblocks;
}
/*
* This function forces out the primary superblock. We need to only
* write out those fields which we have changed, since if the
* filesystem is mounted, it may have changed some of the other
* fields.
*
* It takes as input a superblock which has already been byte swapped
* (if necessary).
*
*/
static errcode_t write_primary_superblock(ext2_filsys fs,
struct ext2_super_block *super)
{
__u16 *old_super, *new_super;
int check_idx, write_idx, size;
errcode_t retval;
if (!fs->io->manager->write_byte || !fs->orig_super) {
fallback:
io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
retval = io_channel_write_blk64(fs->io, 1, -SUPERBLOCK_SIZE,
super);
io_channel_set_blksize(fs->io, fs->blocksize);
return retval;
}
old_super = (__u16 *) fs->orig_super;
new_super = (__u16 *) super;
for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) {
if (old_super[check_idx] == new_super[check_idx])
continue;
write_idx = check_idx;
for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++)
if (old_super[check_idx] == new_super[check_idx])
break;
size = 2 * (check_idx - write_idx);
#if 0
printf("Writing %d bytes starting at %d\n",
size, write_idx*2);
#endif
retval = io_channel_write_byte(fs->io,
SUPERBLOCK_OFFSET + (2 * write_idx), size,
new_super + write_idx);
if (retval == EXT2_ET_UNIMPLEMENTED)
goto fallback;
if (retval)
return retval;
}
memcpy(fs->orig_super, super, SUPERBLOCK_SIZE);
return 0;
}
/*
* Updates the revision to EXT2_DYNAMIC_REV
*/
void ext2fs_update_dynamic_rev(ext2_filsys fs)
{
struct ext2_super_block *sb = fs->super;
if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
return;
sb->s_rev_level = EXT2_DYNAMIC_REV;
sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
/* s_uuid is handled by e2fsck already */
/* other fields should be left alone */
}
static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group,
blk64_t group_block,
struct ext2_super_block *super_shadow)
{
errcode_t retval;
dgrp_t sgrp = group;
if (sgrp > ((1 << 16) - 1))
sgrp = (1 << 16) - 1;
super_shadow->s_block_group_nr = ext2fs_cpu_to_le16(sgrp);
retval = ext2fs_superblock_csum_set(fs, super_shadow);
if (retval)
return retval;
return io_channel_write_blk64(fs->io, group_block, -SUPERBLOCK_SIZE,
super_shadow);
}
errcode_t ext2fs_flush(ext2_filsys fs)
{
return ext2fs_flush2(fs, 0);
}
errcode_t ext2fs_flush2(ext2_filsys fs, int flags)
{
dgrp_t i;
errcode_t retval;
unsigned long fs_state;
__u32 feature_incompat;
struct ext2_super_block *super_shadow = 0;
struct opaque_ext2_group_desc *group_shadow = 0;
#ifdef WORDS_BIGENDIAN
struct ext2_group_desc *gdp;
dgrp_t j;
#endif
char *group_ptr;
blk64_t old_desc_blocks;
struct ext2fs_numeric_progress_struct progress;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
fs_state = fs->super->s_state;
feature_incompat = fs->super->s_feature_incompat;
fs->super->s_wtime = fs->now ? fs->now : time(NULL);
fs->super->s_block_group_nr = 0;
/*
* If the write_bitmaps() function is present, call it to
* flush the bitmaps. This is done this way so that a simple
* program that doesn't mess with the bitmaps doesn't need to
* drag in the bitmaps.c code.
*
* Bitmap checksums live in the group descriptor, so the
* bitmaps need to be written before the descriptors.
*/
if (fs->write_bitmaps) {
retval = fs->write_bitmaps(fs);
if (retval)
goto errout;
}
/*
* Set the state of the FS to be non-valid. (The state has
* already been backed up earlier, and will be restored after
* we write out the backup superblocks.)
*/
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_clear_feature_journal_needs_recovery(fs->super);
/* Byte swap the superblock and the group descriptors if necessary */
#ifdef WORDS_BIGENDIAN
retval = EXT2_ET_NO_MEMORY;
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
if (retval)
goto errout;
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&group_shadow);
if (retval)
goto errout;
memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block));
memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize *
fs->desc_blocks);
ext2fs_swap_super(super_shadow);
for (j = 0; j < fs->group_desc_count; j++) {
gdp = ext2fs_group_desc(fs, group_shadow, j);
ext2fs_swap_group_desc2(fs, gdp);
}
#else
super_shadow = fs->super;
group_shadow = fs->group_desc;
#endif
/*
* If this is an external journal device, don't write out the
* block group descriptors or any of the backup superblocks
*/
if (ext2fs_has_feature_journal_dev(fs->super))
goto write_primary_superblock_only;
/*
* Write out the master group descriptors, and the backup
* superblocks and group descriptors.
*/
group_ptr = (char *) group_shadow;
if (ext2fs_has_feature_meta_bg(fs->super)) {
old_desc_blocks = fs->super->s_first_meta_bg;
if (old_desc_blocks > fs->desc_blocks)
old_desc_blocks = fs->desc_blocks;
} else
old_desc_blocks = fs->desc_blocks;
if (fs->progress_ops && fs->progress_ops->init)
(fs->progress_ops->init)(fs, &progress, NULL,
fs->group_desc_count);
for (i = 0; i < fs->group_desc_count; i++) {
blk64_t super_blk, old_desc_blk, new_desc_blk;
if (fs->progress_ops && fs->progress_ops->update)
(fs->progress_ops->update)(fs, &progress, i);
ext2fs_super_and_bgd_loc2(fs, i, &super_blk, &old_desc_blk,
&new_desc_blk, 0);
if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) {
retval = write_backup_super(fs, i, super_blk,
super_shadow);
if (retval)
goto errout;
}
if (fs->flags & EXT2_FLAG_SUPER_ONLY)
continue;
if ((old_desc_blk) &&
(!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) {
retval = io_channel_write_blk64(fs->io,
old_desc_blk, old_desc_blocks, group_ptr);
if (retval)
goto errout;
}
if (new_desc_blk) {
int meta_bg = i / EXT2_DESC_PER_BLOCK(fs->super);
retval = io_channel_write_blk64(fs->io, new_desc_blk,
1, group_ptr + (meta_bg*fs->blocksize));
if (retval)
goto errout;
}
}
if (fs->progress_ops && fs->progress_ops->close)
(fs->progress_ops->close)(fs, &progress, NULL);
write_primary_superblock_only:
/*
* Write out master superblock. This has to be done
* separately, since it is located at a fixed location
* (SUPERBLOCK_OFFSET). We flush all other pending changes
* out to disk first, just to avoid a race condition with an
* insy-tinsy window....
*/
fs->super->s_block_group_nr = 0;
fs->super->s_state = fs_state;
fs->super->s_feature_incompat = feature_incompat;
#ifdef WORDS_BIGENDIAN
*super_shadow = *fs->super;
ext2fs_swap_super(super_shadow);
#endif
retval = ext2fs_superblock_csum_set(fs, super_shadow);
if (retval)
return retval;
if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) {
retval = io_channel_flush(fs->io);
if (retval)
goto errout;
}
retval = write_primary_superblock(fs, super_shadow);
if (retval)
goto errout;
fs->flags &= ~EXT2_FLAG_DIRTY;
if (!(flags & EXT2_FLAG_FLUSH_NO_SYNC)) {
retval = io_channel_flush(fs->io);
if (retval)
goto errout;
}
errout:
fs->super->s_state = fs_state;
#ifdef WORDS_BIGENDIAN
if (super_shadow)
ext2fs_free_mem(&super_shadow);
if (group_shadow)
ext2fs_free_mem(&group_shadow);
#endif
return retval;
}
errcode_t ext2fs_close_free(ext2_filsys *fs_ptr)
{
errcode_t ret;
ext2_filsys fs = *fs_ptr;
ret = ext2fs_close2(fs, 0);
if (ret)
ext2fs_free(fs);
*fs_ptr = NULL;
return ret;
}
errcode_t ext2fs_close(ext2_filsys fs)
{
return ext2fs_close2(fs, 0);
}
errcode_t ext2fs_close2(ext2_filsys fs, int flags)
{
errcode_t retval;
int meta_blks;
io_stats stats = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (fs->write_bitmaps) {
retval = fs->write_bitmaps(fs);
if (retval)
return retval;
}
if (fs->super->s_kbytes_written &&
fs->io->manager->get_stats)
fs->io->manager->get_stats(fs->io, &stats);
if (stats && stats->bytes_written && (fs->flags & EXT2_FLAG_RW)) {
fs->super->s_kbytes_written += stats->bytes_written >> 10;
meta_blks = fs->desc_blocks + 1;
if (!(fs->flags & EXT2_FLAG_SUPER_ONLY))
fs->super->s_kbytes_written += meta_blks /
(fs->blocksize / 1024);
if ((fs->flags & EXT2_FLAG_DIRTY) == 0)
fs->flags |= EXT2_FLAG_SUPER_ONLY | EXT2_FLAG_DIRTY;
}
if (fs->flags & EXT2_FLAG_DIRTY) {
retval = ext2fs_flush2(fs, flags);
if (retval)
return retval;
}
retval = ext2fs_mmp_stop(fs);
if (retval)
return retval;
ext2fs_free(fs);
return 0;
}

66
src/ext2fs/com_err.h Normal file
View File

@ -0,0 +1,66 @@
/*
* Header file for common error description library.
*
* Copyright 1988, Student Information Processing Board of the
* Massachusetts Institute of Technology.
*
* For copyright and distribution info, see the documentation supplied
* with this package.
*/
#if !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)
#ifdef __GNUC__
#define COM_ERR_ATTR(x) __attribute__(x)
#else
#define COM_ERR_ATTR(x)
#endif
#include <stddef.h>
#include <stdarg.h>
#include "rufus.h"
typedef long errcode_t;
struct error_table {
char const * const * msgs;
long base;
int n_msgs;
};
struct et_list;
#define VA_ARGS(...) , ##__VA_ARGS__
#define com_err(src, err, fmt, ...) uprintf("%s: [%d] " # fmt, src?src:"ext2fs", err VA_ARGS(__VA_ARGS__))
extern char const *error_message (long);
extern void (*com_err_hook) (const char *, long, const char *, va_list);
extern void (*set_com_err_hook (void (*) (const char *, long,
const char *, va_list)))
(const char *, long, const char *, va_list);
extern void (*reset_com_err_hook (void)) (const char *, long,
const char *, va_list);
extern int init_error_table(const char * const *msgs, long base, int count);
extern char *(*set_com_err_gettext (char *(*) (const char *)))
(const char *);
extern errcode_t add_error_table(const struct error_table * et);
extern errcode_t remove_error_table(const struct error_table * et);
extern void add_to_error_table(struct et_list *new_table);
/* Provided for Heimdall compatibility */
extern const char *com_right(struct et_list *list, long code);
extern const char *com_right_r(struct et_list *list, long code, char *str, size_t len);
extern void initialize_error_table_r(struct et_list **list,
const char **messages,
int num_errors,
long base);
extern void free_error_table(struct et_list *et);
/* Provided for compatibility with other com_err libraries */
extern int et_list_lock(void);
extern int et_list_unlock(void);
#define __COM_ERR_H
#define __COM_ERR_H__
#endif /* !defined(__COM_ERR_H) && !defined(__COM_ERR_H__)*/

428
src/ext2fs/config.h Normal file
View File

@ -0,0 +1,428 @@
#ifdef _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#define ENABLE_NLS 0
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have the `asprintf' function. */
#define HAVE_ASPRINTF 1
/* Define to 1 if the compiler understands __builtin_expect. */
#define HAVE_BUILTIN_EXPECT 1
/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
don't. */
#define HAVE_DECL_FEOF_UNLOCKED 0
/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
you don't. */
#define HAVE_DECL_FGETS_UNLOCKED 0
/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
don't. */
#define HAVE_DECL_GETC_UNLOCKED 0
/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you
don't. */
#define HAVE_DECL__SNPRINTF 1
/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you
don't. */
#define HAVE_DECL__SNWPRINTF 1
/* Define to 1 if you have the `fwprintf' function. */
#define HAVE_FWPRINTF 1
/* Define to 1 if you have the `getcwd' function. */
#define HAVE_GETCWD 1
/* Define to 1 if you have the `getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define if you have the iconv() function and it works. */
#define HAVE_ICONV 1
/* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
#define HAVE_INTMAX_T 1
/* Define to 1 if the system has the type `intptr_t'. */
#define HAVE_INTPTR_T 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, and
declares uintmax_t. */
#define HAVE_INTTYPES_H_WITH_UINTMAX 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if the system has the type 'long long int'. */
#define HAVE_LONG_LONG_INT 1
/* Define to 1 if lseek64 declared in unistd.h */
#define HAVE_LSEEK64_PROTOTYPE 1
/* Define to 1 if you have the `mbrtowc' function. */
#define HAVE_MBRTOWC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mempcpy' function. */
#define HAVE_MEMPCPY 1
/* Define to 1 if you have the <pthread.h> header file. */
#define HAVE_PTHREAD_H 1
/* Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE. */
#define HAVE_PTHREAD_MUTEX_RECURSIVE 1
/* Define if the POSIX multithreading library has read/write locks. */
#define HAVE_PTHREAD_RWLOCK 1
/* Define to 1 if you have the `putenv' function. */
#define HAVE_PUTENV 1
/* Define to 1 if dirent has d_reclen */
#define HAVE_RECLEN_DIRENT 1
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define if <stdint.h> exists, doesn't clash with <sys/types.h>, and declares
uintmax_t. */
#define HAVE_STDINT_H_WITH_UINTMAX 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strnlen' function. */
#define HAVE_STRNLEN 1
/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the `tsearch' function. */
#define HAVE_TSEARCH 1
/* Define to 1 if ssize_t declared */
#define HAVE_TYPE_SSIZE_T 1
/* Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>. */
#define HAVE_UINTMAX_T 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if the system has the type 'unsigned long long int'. */
#define HAVE_UNSIGNED_LONG_LONG_INT 1
/* Define to 1 or 0, depending whether the compiler supports simple visibility
declarations. */
#define HAVE_VISIBILITY 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define if you have the 'wchar_t' type. */
#define HAVE_WCHAR_T 1
/* Define to 1 if you have the `wcrtomb' function. */
#define HAVE_WCRTOMB 1
/* Define to 1 if you have the `wcslen' function. */
#define HAVE_WCSLEN 1
/* Define to 1 if you have the `wcsnlen' function. */
#define HAVE_WCSNLEN 1
/* Define if you have the 'wint_t' type. */
#define HAVE_WINT_T 1
/* Define to 1 if O_NOATIME works. */
#define HAVE_WORKING_O_NOATIME 0
/* Define to 1 if O_NOFOLLOW works. */
#define HAVE_WORKING_O_NOFOLLOW 0
/* Define as const if the declaration of iconv() needs const. */
#define ICONV_CONST
/* Define if integer division by zero raises signal SIGFPE. */
#define INTDIV0_RAISES_SIGFPE 1
/* The size of `int', as computed by sizeof. */
#define SIZEOF_INT sizeof(int)
/* The size of `long', as computed by sizeof. */
#define SIZEOF_LONG sizeof(long)
/* The size of `long long', as computed by sizeof. */
#define SIZEOF_LONG_LONG sizeof(long long)
/* The size of `off_t', as computed by sizeof. */
#define SIZEOF_OFF_T 4
/* The size of `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
/* The size of `time_t', as computed by sizeof. */
#define SIZEOF_TIME_T 4
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* If the compiler supports a TLS storage class define it to that here */
#define TLS __thread
/* Define if the POSIX multithreading library can be used. */
#define USE_POSIX_THREADS 1
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Define to 1 to build uuidd */
#define USE_UUIDD 1
/* Define if the native Windows multithreading API can be used. */
/* #undef USE_WINDOWS_THREADS */
#define USE_WINDOWS_THREADS 1
/* version for gettext */
//#define VERSION "0.14.1"
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef _POSIX_SOURCE */
/* Please see the Gnulib manual for how to use these macros.
Suppress extern inline with HP-UX cc, as it appears to be broken; see
<http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>.
Suppress extern inline with Sun C in standards-conformance mode, as it
mishandles inline functions that call each other. E.g., for 'inline void f
(void) { } inline void g (void) { f (); }', c99 incorrectly complains
'reference to static identifier "f" in extern inline function'.
This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16.
Suppress extern inline (with or without __attribute__ ((__gnu_inline__)))
on configurations that mistakenly use 'static inline' to implement
functions or macros in standard C headers like <ctype.h>. For example,
if isdigit is mistakenly implemented via a static inline function,
a program containing an extern inline function that calls isdigit
may not work since the C standard prohibits extern inline functions
from calling static functions. This bug is known to occur on:
OS X 10.8 and earlier; see:
http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html
DragonFly; see
http://muscles.dragonflybsd.org/bulk/bleeding-edge-potential/latest-per-pkg/ah-tty-0.3.12.log
FreeBSD; see:
http://lists.gnu.org/archive/html/bug-gnulib/2014-07/msg00104.html
OS X 10.9 has a macro __header_inline indicating the bug is fixed for C and
for clang but remains for g++; see <http://trac.macports.org/ticket/41033>.
Assume DragonFly and FreeBSD will be similar. */
#if (((defined __APPLE__ && defined __MACH__) \
|| defined __DragonFly__ || defined __FreeBSD__) \
&& (defined __header_inline \
? (defined __cplusplus && defined __GNUC_STDC_INLINE__ \
&& ! defined __clang__) \
: ((! defined _DONT_USE_CTYPE_INLINE_ \
&& (defined __GNUC__ || defined __cplusplus)) \
|| (defined _FORTIFY_SOURCE && 0 < _FORTIFY_SOURCE \
&& defined __GNUC__ && ! defined __cplusplus))))
# define _GL_EXTERN_INLINE_STDHEADER_BUG
#endif
#if ((__GNUC__ \
? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \
: (199901L <= __STDC_VERSION__ \
&& !defined __HP_cc \
&& !defined __PGI \
&& !(defined __SUNPRO_C && __STDC__))) \
&& !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
# define _GL_INLINE inline
# define _GL_EXTERN_INLINE extern inline
# define _GL_EXTERN_INLINE_IN_USE
#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \
&& !defined _GL_EXTERN_INLINE_STDHEADER_BUG)
# if defined __GNUC_GNU_INLINE__ && __GNUC_GNU_INLINE__
/* __gnu_inline__ suppresses a GCC 4.2 diagnostic. */
# define _GL_INLINE extern inline __attribute__ ((__gnu_inline__))
# else
# define _GL_INLINE extern inline
# endif
# define _GL_EXTERN_INLINE extern
# define _GL_EXTERN_INLINE_IN_USE
#else
# define _GL_INLINE static _GL_UNUSED
# define _GL_EXTERN_INLINE static _GL_UNUSED
#endif
/* In GCC 4.6 (inclusive) to 5.1 (exclusive),
suppress bogus "no previous prototype for 'FOO'"
and "no previous declaration for 'FOO'" diagnostics,
when FOO is an inline function in the header; see
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113> and
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63877>. */
#if __GNUC__ == 4 && 6 <= __GNUC_MINOR__
# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__
# define _GL_INLINE_HEADER_CONST_PRAGMA
# else
# define _GL_INLINE_HEADER_CONST_PRAGMA \
_Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"")
# endif
# define _GL_INLINE_HEADER_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \
_Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \
_GL_INLINE_HEADER_CONST_PRAGMA
# define _GL_INLINE_HEADER_END \
_Pragma ("GCC diagnostic pop")
#else
# define _GL_INLINE_HEADER_BEGIN
# define _GL_INLINE_HEADER_END
#endif
/* Define as a marker that can be attached to declarations that might not
be used. This helps to reduce warnings, such as from
GCC -Wunused-parameter. */
#ifndef _GL_UNUSED
# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
# define _GL_UNUSED __attribute__ ((__unused__))
# else
# define _GL_UNUSED
# endif
#endif
/* The __pure__ attribute was added in gcc 2.96. */
#ifndef _GL_ATTRIBUTE_PURE
# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
# define _GL_ATTRIBUTE_PURE /* empty */
# endif
#endif
#ifdef _MSC_VER
#define __attribute__(x)
#endif
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define as the type of the result of subtracting two pointers, if the system
doesn't define it. */
/* #undef ptrdiff_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */
/* Define to unsigned long or unsigned long long if <stdint.h> and
<inttypes.h> don't define. */
/* #undef uintmax_t */
#define __libc_lock_t gl_lock_t
#define __libc_lock_define gl_lock_define
#define __libc_lock_define_initialized gl_lock_define_initialized
#define __libc_lock_init gl_lock_init
#define __libc_lock_lock gl_lock_lock
#define __libc_lock_unlock gl_lock_unlock
#define __libc_lock_recursive_t gl_recursive_lock_t
#define __libc_lock_define_recursive gl_recursive_lock_define
#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized
#define __libc_lock_init_recursive gl_recursive_lock_init
#define __libc_lock_lock_recursive gl_recursive_lock_lock
#define __libc_lock_unlock_recursive gl_recursive_lock_unlock
#define glthread_in_use libintl_thread_in_use
#define glthread_lock_init_func libintl_lock_init_func
#define glthread_lock_lock_func libintl_lock_lock_func
#define glthread_lock_unlock_func libintl_lock_unlock_func
#define glthread_lock_destroy_func libintl_lock_destroy_func
#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded
#define glthread_rwlock_init_func libintl_rwlock_init_func
#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded
#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func
#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded
#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func
#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded
#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func
#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded
#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func
#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded
#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func
#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded
#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func
#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded
#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func
#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded
#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func
#define glthread_once_func libintl_once_func
#define glthread_once_singlethreaded libintl_once_singlethreaded
#define glthread_once_multithreaded libintl_once_multithreaded

74
src/ext2fs/crc16.c Normal file
View File

@ -0,0 +1,74 @@
/*
* crc16.c
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#include "config.h"
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <ext2fs/ext2_types.h>
#include "crc16.h"
/** CRC table for the CRC-16. The poly is 0x8005 (x16 + x15 + x2 + 1) */
static __u16 const crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
/**
* Compute the CRC-16 for the data buffer
*
* @param crc previous CRC value
* @param buffer data pointer
* @param len number of bytes in the buffer
* @return the updated CRC value
*/
crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len)
{
const unsigned char *cp = buffer;
while (len--)
/*
* for an unknown reason, PPC treats __u16 as signed
* and keeps doing sign extension on the value.
* Instead, use only the low 16 bits of an unsigned
* int for holding the CRC value to avoid this.
*/
crc = (((crc >> 8) & 0xffU) ^
crc16_table[(crc ^ *cp++) & 0xffU]) & 0x0000ffffU;
return crc;
}

26
src/ext2fs/crc16.h Normal file
View File

@ -0,0 +1,26 @@
/*
* crc16.h - CRC-16 routine
*
* Implements the standard CRC-16:
* Width 16
* Poly 0x8005 (x16 + x15 + x2 + 1)
* Init 0
*
* Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#ifndef __CRC16_H
#define __CRC16_H
/* for an unknown reason, PPC treats __u16 as signed and keeps doing sign
* extension on the value. Instead, use only the low 16 bits of an
* unsigned int for holding the CRC value to avoid this.
*/
typedef unsigned int crc16_t;
extern crc16_t ext2fs_crc16(crc16_t crc, const void *buffer, unsigned int len);
#endif /* __CRC16_H */

934
src/ext2fs/crc32c.c Normal file
View File

@ -0,0 +1,934 @@
/*
* crc32c.c
*
* August 26, 2011 Darrick J. Wong <djwong at us.ibm.com>
* Reuse Bob Pearson's slice-by-8 implementation for e2fsprogs.
*
* July 20, 2011 Bob Pearson <rpearson at systemfabricworks.com>
* added slice by 8 algorithm to the existing conventional and
* slice by 4 algorithms.
*
* Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
* Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks!
* Code was from the public domain, copyright abandoned. Code was
* subsequently included in the kernel, thus was re-licensed under the
* GNU GPL v2.
*
* Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com>
* Same crc32 function was used in 5 other places in the kernel.
* I made one version, and deleted the others.
* There are various incantations of crc32(). Some use a seed of 0 or ~0.
* Some xor at the end with ~0. The generic crc32() function takes
* seed as an argument, and doesn't xor at the end. Then individual
* users can do whatever they need.
* drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0.
* fs/jffs2 uses seed 0, doesn't xor with ~0.
* fs/partitions/efi.c uses seed ~0, xor's with ~0.
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
#include "config.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef min
#define min(x, y) ((x) > (y) ? (y) : (x))
#endif
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
#define PTR_ALIGN(p, a) ((__typeof__(p))ALIGN((unsigned long)(p), (a)))
#include "crc32c_defs.h"
#include "ext2fs.h"
#ifdef WORDS_BIGENDIAN
#define __constant_cpu_to_le32(x) ___constant_swab32((x))
#define __constant_cpu_to_be32(x) (x)
#define __be32_to_cpu(x) (x)
#define __cpu_to_be32(x) (x)
#define __cpu_to_le32(x) (ext2fs_cpu_to_le32((x)))
#define __le32_to_cpu(x) (ext2fs_le32_to_cpu((x)))
#else
#define __constant_cpu_to_le32(x) (x)
#define __constant_cpu_to_be32(x) ___constant_swab32((x))
#define __be32_to_cpu(x) (ext2fs_be32_to_cpu((x)))
#define __cpu_to_be32(x) (ext2fs_cpu_to_be32((x)))
#define __cpu_to_le32(x) (x)
#define __le32_to_cpu(x) (x)
#endif
#if CRC_LE_BITS > 8
# define tole(x) __constant_cpu_to_le32(x)
#else
# define tole(x) (x)
#endif
#if CRC_BE_BITS > 8
# define tobe(x) __constant_cpu_to_be32(x)
#else
# define tobe(x) (x)
#endif
#include "crc32c_table.h"
#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8
/* implements slicing-by-4 or slicing-by-8 algorithm */
static inline uint32_t
crc32_body(uint32_t crc, unsigned char const *buf, size_t len,
const uint32_t (*tab)[256])
{
# ifndef WORDS_BIGENDIAN
# define DO_CRC(x) (crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8))
# define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \
t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255])
# define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \
t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255])
# else
# define DO_CRC(x) (crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8))
# define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \
t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255])
# define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \
t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255])
# endif
const uint32_t *b;
size_t rem_len;
const uint32_t *t0 = tab[0], *t1 = tab[1], *t2 = tab[2], *t3 = tab[3];
const uint32_t *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7];
uint32_t q;
/* Align it */
if (unlikely((uintptr_t)buf & 3 && len)) {
do {
DO_CRC(*buf++);
} while ((--len) && ((uintptr_t)buf)&3);
}
# if CRC_LE_BITS == 32
rem_len = len & 3;
len = len >> 2;
# else
rem_len = len & 7;
len = len >> 3;
# endif
b = (const uint32_t *)buf;
for (--b; len; --len) {
q = crc ^ *++b; /* use pre increment for speed */
# if CRC_LE_BITS == 32
crc = DO_CRC4;
# else
crc = DO_CRC8;
q = *++b;
crc ^= DO_CRC4;
# endif
}
len = rem_len;
/* And the last few bytes */
if (len) {
const uint8_t *p = (const uint8_t *)(b + 1) - 1;
do {
DO_CRC(*++p); /* use pre increment for speed */
} while (--len);
}
return crc;
#undef DO_CRC
#undef DO_CRC4
#undef DO_CRC8
}
#endif
/**
* crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
* @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for
* other uses, or the previous crc32 value if computing incrementally.
* @p: pointer to buffer over which CRC is run
* @len: length of buffer @p
*/
static inline uint32_t crc32_le_generic(uint32_t crc, unsigned char const *p,
size_t len, const uint32_t (*tab)[256],
uint32_t polynomial EXT2FS_ATTR((unused)))
{
#if CRC_LE_BITS == 1
int i;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
}
# elif CRC_LE_BITS == 2
while (len--) {
crc ^= *p++;
crc = (crc >> 2) ^ tab[0][crc & 3];
crc = (crc >> 2) ^ tab[0][crc & 3];
crc = (crc >> 2) ^ tab[0][crc & 3];
crc = (crc >> 2) ^ tab[0][crc & 3];
}
# elif CRC_LE_BITS == 4
while (len--) {
crc ^= *p++;
crc = (crc >> 4) ^ tab[0][crc & 15];
crc = (crc >> 4) ^ tab[0][crc & 15];
}
# elif CRC_LE_BITS == 8
/* aka Sarwate algorithm */
while (len--) {
crc ^= *p++;
crc = (crc >> 8) ^ tab[0][crc & 255];
}
# else
crc = __cpu_to_le32(crc);
crc = crc32_body(crc, p, len, tab);
crc = __le32_to_cpu(crc);
#endif
return crc;
}
uint32_t ext2fs_crc32c_le(uint32_t crc, unsigned char const *p, size_t len)
{
return crc32_le_generic(crc, p, len, crc32ctable_le, CRC32C_POLY_LE);
}
/**
* crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
* @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for
* other uses, or the previous crc32 value if computing incrementally.
* @p: pointer to buffer over which CRC is run
* @len: length of buffer @p
*/
static inline uint32_t crc32_be_generic(uint32_t crc, unsigned char const *p,
size_t len, const uint32_t (*tab)[256],
uint32_t polynomial EXT2FS_ATTR((unused)))
{
#if CRC_BE_BITS == 1
int i;
while (len--) {
crc ^= *p++ << 24;
for (i = 0; i < 8; i++)
crc =
(crc << 1) ^ ((crc & 0x80000000) ? polynomial :
0);
}
# elif CRC_BE_BITS == 2
while (len--) {
crc ^= *p++ << 24;
crc = (crc << 2) ^ tab[0][crc >> 30];
crc = (crc << 2) ^ tab[0][crc >> 30];
crc = (crc << 2) ^ tab[0][crc >> 30];
crc = (crc << 2) ^ tab[0][crc >> 30];
}
# elif CRC_BE_BITS == 4
while (len--) {
crc ^= *p++ << 24;
crc = (crc << 4) ^ tab[0][crc >> 28];
crc = (crc << 4) ^ tab[0][crc >> 28];
}
# elif CRC_BE_BITS == 8
while (len--) {
crc ^= *p++ << 24;
crc = (crc << 8) ^ tab[0][crc >> 24];
}
# else
crc = __cpu_to_be32(crc);
crc = crc32_body(crc, p, len, tab);
crc = __be32_to_cpu(crc);
# endif
return crc;
}
uint32_t ext2fs_crc32_be(uint32_t crc, unsigned char const *p, size_t len)
{
return crc32_be_generic(crc, p, len, crc32table_be, CRCPOLY_BE);
}
#ifdef UNITTEST
static uint8_t test_buf[] = {
0xd9, 0xd7, 0x6a, 0x13, 0x3a, 0xb1, 0x05, 0x48,
0xda, 0xad, 0x14, 0xbd, 0x03, 0x3a, 0x58, 0x5e,
0x6e, 0xd1, 0x56, 0xc9, 0x2e, 0xc4, 0xcb, 0x6b,
0xe8, 0x77, 0x52, 0x37, 0x4e, 0x0f, 0x55, 0xd2,
0x12, 0x65, 0x90, 0xc2, 0x41, 0x49, 0x81, 0x01,
0xf5, 0x01, 0xeb, 0x2d, 0x78, 0x74, 0x23, 0x5d,
0x84, 0x5c, 0x81, 0x92, 0x21, 0xe9, 0x8d, 0x1d,
0x89, 0xf2, 0x4a, 0xac, 0xdd, 0xf9, 0xaf, 0xee,
0x44, 0xe7, 0x6e, 0xed, 0xfb, 0xd8, 0x89, 0x0e,
0x96, 0x62, 0xcd, 0xa4, 0x4b, 0xa9, 0xe5, 0x45,
0xb1, 0x29, 0x9b, 0x0f, 0xfc, 0xbd, 0x83, 0xab,
0xa8, 0x54, 0x96, 0x44, 0x2c, 0x7f, 0xbb, 0xe7,
0x52, 0x29, 0x08, 0xee, 0x14, 0xc5, 0xc2, 0xec,
0x5a, 0xeb, 0x40, 0x40, 0xea, 0xd1, 0x3d, 0x15,
0x73, 0xaa, 0x8c, 0x73, 0xfc, 0xf2, 0x2b, 0x49,
0x0b, 0x13, 0x96, 0xd9, 0x8e, 0x4b, 0xbc, 0xe0,
0xf4, 0xd2, 0xe0, 0x2e, 0x7a, 0xf0, 0x5d, 0x1f,
0xd2, 0x92, 0x97, 0xe0, 0xaa, 0x59, 0xab, 0xc9,
0x5c, 0xa6, 0x51, 0x1a, 0xe3, 0xd6, 0x06, 0xb9,
0xae, 0xb8, 0x76, 0x36, 0x79, 0x37, 0x52, 0xf6,
0x34, 0xaf, 0x27, 0x19, 0xe1, 0xc0, 0x2b, 0xdd,
0x01, 0x15, 0xcd, 0xce, 0x44, 0xf6, 0x4c, 0x18,
0x92, 0x69, 0xbe, 0x8a, 0x76, 0x23, 0x52, 0x13,
0x3f, 0xf9, 0xe0, 0xf5, 0x06, 0x28, 0x7c, 0xc7,
0xf3, 0x42, 0x0f, 0xdd, 0x40, 0x33, 0xf7, 0x99,
0xe2, 0xad, 0x26, 0xd9, 0x53, 0x10, 0x72, 0x0c,
0x4e, 0x43, 0x4c, 0x61, 0xfe, 0xd9, 0xc1, 0x16,
0xa1, 0x93, 0xca, 0x3c, 0x75, 0x7f, 0x07, 0x7a,
0x65, 0xb3, 0x53, 0x2a, 0x52, 0x00, 0xa0, 0x62,
0xe0, 0xa3, 0x1f, 0xad, 0xd7, 0xbb, 0xc0, 0x83,
0x5d, 0x54, 0x87, 0x5f, 0xc8, 0x2f, 0xc8, 0xbf,
0x69, 0x04, 0x91, 0xc8, 0xa6, 0x1d, 0x4d, 0x46,
0x91, 0xfc, 0x26, 0xf4, 0x16, 0xd1, 0xa4, 0xbf,
0x5c, 0xa2, 0x6c, 0xdd, 0xb4, 0x40, 0xf2, 0x2e,
0xa2, 0xad, 0xf7, 0xf4, 0xa5, 0x8a, 0x3e, 0x23,
0x64, 0x08, 0xc8, 0xa1, 0xa0, 0xf0, 0x5d, 0x70,
0xd2, 0x77, 0xfd, 0xc8, 0x50, 0x83, 0x0f, 0xd6,
0x2b, 0xe4, 0x1f, 0x52, 0x34, 0x33, 0x68, 0xfd,
0x92, 0xbe, 0x9f, 0x97, 0x6b, 0x8d, 0x81, 0x91,
0x0f, 0xef, 0x65, 0xc8, 0x0d, 0x15, 0x01, 0x77,
0x58, 0xb2, 0xf4, 0x1b, 0x06, 0x7e, 0xf5, 0xca,
0x15, 0x2e, 0x38, 0xd8, 0x81, 0x1c, 0x1c, 0xa0,
0xb6, 0x13, 0x6a, 0x2b, 0x71, 0x34, 0x52, 0xd7,
0x1d, 0xbd, 0x37, 0x59, 0xbc, 0x86, 0x25, 0x2b,
0xa8, 0x93, 0xce, 0x1a, 0x03, 0x16, 0xfe, 0x01,
0x57, 0x99, 0x24, 0x25, 0x2c, 0xb3, 0xab, 0x1e,
0x2d, 0x65, 0x20, 0x89, 0x17, 0x02, 0x0e, 0x0a,
0xf5, 0x1e, 0xc7, 0xff, 0x1f, 0x61, 0xa9, 0x54,
0x18, 0xd4, 0xba, 0x50, 0x57, 0x02, 0xa1, 0xab,
0x22, 0x2e, 0x07, 0xea, 0xa9, 0xa3, 0x83, 0x4f,
0x27, 0xf5, 0xc5, 0xee, 0x3c, 0x3b, 0x10, 0xad,
0x32, 0x2b, 0x1c, 0x03, 0xcb, 0xaf, 0x98, 0x83,
0x54, 0xc3, 0x68, 0x63, 0xd4, 0xe0, 0x0e, 0x3c,
0x1a, 0x4e, 0xc0, 0x81, 0xd0, 0xe8, 0x6a, 0x62,
0x6b, 0x3e, 0x6f, 0xc4, 0xc6, 0x33, 0x4e, 0x26,
0x21, 0xf5, 0x04, 0xdf, 0xfa, 0xce, 0x45, 0xaf,
0xdc, 0x5e, 0x1b, 0xad, 0x93, 0xca, 0xf5, 0xcf,
0xd7, 0xee, 0x0c, 0x5c, 0x5e, 0xb4, 0xf0, 0x92,
0xd2, 0xf2, 0xf0, 0xa9, 0x1e, 0xab, 0x80, 0x68,
0x46, 0xef, 0xcc, 0x26, 0x0c, 0x5c, 0xdd, 0x4e,
0x83, 0xb8, 0xb9, 0x53, 0x6e, 0xf8, 0x93, 0x38,
0x67, 0xa4, 0x41, 0x87, 0x72, 0xe7, 0x7e, 0x86,
0xc9, 0x49, 0x00, 0x33, 0xb1, 0x38, 0x6c, 0x71,
0xd7, 0x1d, 0x8e, 0x61, 0x01, 0xb6, 0x57, 0xa9,
0xf1, 0xac, 0x15, 0xc2, 0x83, 0x77, 0xca, 0x64,
0xca, 0x7b, 0x6c, 0xa1, 0x10, 0x1b, 0x13, 0xd0,
0xd3, 0x9e, 0x9e, 0x10, 0x70, 0xc8, 0x1a, 0xbb,
0x3f, 0x19, 0x86, 0xab, 0x01, 0x0e, 0xea, 0x34,
0x22, 0xea, 0xe2, 0x15, 0xb7, 0xed, 0x21, 0x21,
0x75, 0xa5, 0xe7, 0x08, 0xa1, 0x38, 0xe0, 0x91,
0x05, 0x60, 0xea, 0xa7, 0x50, 0x27, 0x18, 0x07,
0x9d, 0xe0, 0x18, 0x2b, 0xd4, 0x07, 0x59, 0x00,
0xe6, 0x45, 0x18, 0x2a, 0x30, 0x6e, 0xf3, 0xb4,
0xd0, 0xef, 0xa6, 0x5b, 0x71, 0xa2, 0x5a, 0x3b,
0x89, 0x4c, 0xaf, 0x3f, 0xcb, 0x9f, 0x03, 0xfb,
0x43, 0x7c, 0x6b, 0xd3, 0x6a, 0xea, 0xce, 0x4a,
0x5f, 0x64, 0xb5, 0x62, 0xda, 0x5d, 0x27, 0xb7,
0xb8, 0x11, 0xca, 0x33, 0x30, 0xec, 0x70, 0xf0,
0x1b, 0x03, 0x50, 0xff, 0x5e, 0xa6, 0x08, 0xde,
0x37, 0x70, 0xc0, 0x81, 0x55, 0x60, 0x17, 0xa1,
0x85, 0xae, 0x26, 0x44, 0xe4, 0x67, 0x3c, 0x91,
0xfd, 0xc4, 0x3d, 0x97, 0x72, 0x23, 0xf3, 0x3c,
0x8f, 0xe0, 0xe2, 0xf2, 0x09, 0x96, 0x10, 0x67,
0xb5, 0xfe, 0xff, 0x3d, 0x4a, 0xc8, 0x62, 0x11,
0xa5, 0x98, 0xc1, 0x2d, 0x40, 0x82, 0x88, 0x8b,
0xe5, 0xb0, 0x75, 0xbf, 0x2f, 0xa8, 0x6a, 0x55,
0x49, 0x2e, 0x9c, 0x29, 0xd2, 0x7c, 0xbf, 0xf3,
0xaa, 0x3a, 0x16, 0x4a, 0xa4, 0x15, 0xf3, 0x48,
0xde, 0x38, 0x13, 0x44, 0x26, 0x02, 0xe6, 0xe9,
0xa8, 0x24, 0x89, 0xb5, 0x43, 0x95, 0xe4, 0x4c,
0xc3, 0xa0, 0xdf, 0xcc, 0x42, 0xf8, 0x8d, 0xb0,
0x3b, 0xea, 0x10, 0xb7, 0xe1, 0x40, 0x54, 0xb9,
0xa3, 0x2d, 0xfb, 0xb4, 0x91, 0xc0, 0x3e, 0x94,
0xf1, 0xa1, 0x3c, 0xbe, 0xef, 0xb8, 0x70, 0x55,
0x0a, 0x26, 0x93, 0xbf, 0xe6, 0x21, 0x92, 0x32,
0x3c, 0x39, 0x27, 0x6a, 0x23, 0x48, 0x02, 0x35,
0x3c, 0xd4, 0xcc, 0x04, 0xc0, 0x4e, 0xa7, 0x02,
0x63, 0x37, 0xc2, 0xb8, 0x56, 0x1d, 0x57, 0x57,
0x42, 0x04, 0x8d, 0xee, 0xcf, 0x8b, 0xc9, 0xc3,
0xba, 0x3b, 0x15, 0xd7, 0xaf, 0xbf, 0x9e, 0xcd,
0x44, 0xcf, 0xf0, 0x00, 0xb7, 0x3a, 0xfc, 0xa8,
0x12, 0xab, 0x3a, 0x62, 0x01, 0x21, 0x46, 0xe9,
0x1e, 0x48, 0x37, 0xfc, 0x13, 0x4d, 0xf6, 0x2a,
0x72, 0x40, 0x75, 0x38, 0x71, 0xf2, 0x17, 0x20,
0x2c, 0xdd, 0xc0, 0x49, 0xbc, 0x63, 0x33, 0xea,
0x06, 0x75, 0x41, 0xe7, 0x5c, 0x1f, 0xfb, 0xf9,
0x68, 0x83, 0xc2, 0x5a, 0x4a, 0x1e, 0x61, 0x08,
0x57, 0xf3, 0x00, 0xba, 0x77, 0x92, 0x63, 0xa5,
0xb7, 0xfe, 0x97, 0x22, 0xda, 0x5e, 0xd3, 0xaf,
0xbc, 0x89, 0x0d, 0x4c, 0x37, 0xa9, 0x27, 0x4a,
0x7f, 0xdb, 0x81, 0x39, 0x11, 0x86, 0x12, 0xf9,
0x10, 0x50, 0xe4, 0xdb, 0x72, 0xf9, 0xae, 0x10,
0x7c, 0xed, 0x50, 0x5c, 0x61, 0xeb, 0x42, 0x1e,
0xa4, 0xf4, 0xf0, 0xfa, 0x45, 0x4d, 0x95, 0x2b,
0xd4, 0x67, 0x4a, 0xe3, 0x8a, 0x15, 0x55, 0x92,
0x77, 0x64, 0x8c, 0x51, 0x38, 0xf9, 0x26, 0x3e,
0x68, 0xe2, 0xac, 0xbb, 0x64, 0x77, 0xe2, 0x82,
0xa4, 0x42, 0x41, 0x38, 0xa0, 0xf0, 0xc9, 0xd8,
0x6c, 0xe0, 0xef, 0x4c, 0xda, 0xb4, 0x92, 0xef,
0x1b, 0xe3, 0x9b, 0xc1, 0x44, 0x3c, 0xb9, 0xb7,
0x39, 0xac, 0x5c, 0x32, 0x39, 0xb4, 0x21, 0x85,
0x93, 0xbc, 0xf2, 0x51, 0x43, 0xb7, 0xae, 0x1e,
0x61, 0x9c, 0x38, 0x9c, 0xaa, 0xff, 0xde, 0xfc,
0xbf, 0x85, 0xef, 0x17, 0x34, 0x36, 0x71, 0x5f,
0x04, 0x16, 0xa6, 0x9e, 0xfd, 0x3a, 0x03, 0xd8,
0xbf, 0x71, 0x70, 0x20, 0x8f, 0x7c, 0xfb, 0xff,
0x61, 0xe0, 0xe2, 0x60, 0xa7, 0xb1, 0xc0, 0xe0,
0xd9, 0x3f, 0xdc, 0x8d, 0x4a, 0xa4, 0x52, 0x61,
0xaf, 0x9d, 0xdf, 0x8a, 0x0d, 0x41, 0xc0, 0x25,
0x68, 0x12, 0x7b, 0xd5, 0xc7, 0xdb, 0x68, 0x70,
0x2d, 0x7d, 0x95, 0x12, 0x03, 0x23, 0x0c, 0xe8,
0x14, 0x41, 0x11, 0x28, 0xec, 0x9d, 0xd3, 0x28,
0x77, 0x7a, 0x3c, 0x93, 0x8e, 0x5c, 0x7e, 0xb3,
0x42, 0x9a, 0x18, 0x25, 0x93, 0xc8, 0xea, 0x43,
0x1b, 0xbe, 0xd5, 0x27, 0xf1, 0xd4, 0xe0, 0x1e,
0xce, 0xc7, 0xc7, 0x2c, 0x25, 0x35, 0x58, 0xb8,
0x6c, 0xf3, 0xa2, 0xad, 0xe7, 0x58, 0x49, 0x47,
0xf7, 0xca, 0xde, 0x8b, 0x81, 0xb7, 0x75, 0xf4,
0x95, 0xa7, 0x5c, 0xc3, 0x2c, 0x0e, 0x1c, 0x52,
0x9a, 0xc3, 0x2a, 0x00, 0x21, 0xa7, 0x51, 0x6b,
0xf0, 0x05, 0x87, 0x8c, 0x42, 0x1b, 0xc3, 0x2e,
0xa3, 0x76, 0x22, 0xd5, 0x7f, 0x56, 0x10, 0xef,
0x98, 0x85, 0x65, 0x86, 0x71, 0x87, 0xd2, 0x8c,
0xc0, 0x47, 0x20, 0xe8, 0xb5, 0x1c, 0xe3, 0xdd,
0x3c, 0x5c, 0x03, 0xbb, 0x0e, 0x97, 0x3b, 0xe1,
0x56, 0x9a, 0xd5, 0x0a, 0x63, 0xd5, 0x33, 0xaf,
0x36, 0xca, 0xcf, 0x8f, 0x00, 0x28, 0xa3, 0x45,
0xb8, 0xcd, 0xde, 0x73, 0xd4, 0xfa, 0x2d, 0x6f,
0xdb, 0x93, 0xaa, 0xdd, 0x7f, 0xd2, 0x22, 0x9c,
0x96, 0x48, 0x1e, 0xa8, 0x63, 0xbe, 0xbc, 0x0d,
0x14, 0x3c, 0x2e, 0x11, 0x1f, 0xd2, 0xf4, 0x57,
0xb3, 0x47, 0xf8, 0xa6, 0x1b, 0xc3, 0xa7, 0x95,
0x2d, 0xd4, 0xca, 0xb8, 0x0d, 0xfb, 0x06, 0x85,
0xda, 0x63, 0xf0, 0x3e, 0x9d, 0x5e, 0xee, 0xce,
0xed, 0x74, 0x1d, 0x2c, 0x97, 0x3f, 0x71, 0x95,
0x12, 0x03, 0xc5, 0x92, 0x46, 0x84, 0x1b, 0x07,
0xe6, 0xb4, 0x1d, 0x3a, 0xf1, 0x89, 0x90, 0x50,
0x10, 0x29, 0x34, 0xc0, 0x90, 0xbe, 0x4a, 0xa9,
0x0d, 0xb0, 0x7b, 0xfb, 0x35, 0xee, 0x4e, 0x34,
0xec, 0x5a, 0x58, 0xbc, 0xb8, 0xda, 0x38, 0x88,
0x8c, 0x74, 0x1e, 0xc9, 0xab, 0x78, 0x2e, 0x2a,
0x17, 0x8a, 0x43, 0x3d, 0xa1, 0x2a, 0x41, 0xb5,
0xd6, 0xe8, 0x5b, 0xc5, 0x4a, 0x1c, 0x3c, 0x9f,
0x8d, 0x3a, 0x69, 0x88, 0xf8, 0x80, 0xd2, 0x11,
0xfc, 0x7e, 0x80, 0x8e, 0x7f, 0x85, 0x64, 0x9c,
0x46, 0x58, 0xc8, 0x48, 0x98, 0x4b, 0xf5, 0x73,
0x3f, 0x49, 0xce, 0x53, 0x2c, 0xd5, 0xfc, 0x33,
0xf1, 0x6f, 0xd8, 0xe9, 0x2e, 0x70, 0x2e, 0xdc,
0xe5, 0x43, 0x80, 0x38, 0xf2, 0x87, 0xed, 0x85,
0xe4, 0x3e, 0x45, 0x14, 0x20, 0xcf, 0xa0, 0x61,
0x4f, 0xe8, 0xd7, 0x5b, 0xb3, 0x0d, 0x0e, 0x4e,
0x4d, 0xce, 0xbe, 0xba, 0xaa, 0x90, 0x09, 0xcb,
0x4b, 0x5d, 0x08, 0xff, 0x52, 0xd5, 0x23, 0xbc,
0xad, 0x8d, 0xd3, 0x06, 0x4a, 0xa0, 0x51, 0x56,
0xa7, 0xd8, 0x33, 0xab, 0xbc, 0xd0, 0xdf, 0x92,
0x87, 0x20, 0x2d, 0x7b, 0x5e, 0xfa, 0x30, 0xa7,
0x06, 0x06, 0xe5, 0x4f, 0x2c, 0xb5, 0x61, 0xd7,
0x54, 0xd3, 0xdf, 0xd0, 0x0a, 0xb0, 0x06, 0xce,
0xf6, 0x86, 0xb7, 0x8e, 0xaa, 0x7b, 0x78, 0xd5,
0xb9, 0xeb, 0x07, 0xac, 0x5f, 0xc5, 0xd2, 0x8c,
0x40, 0xe0, 0x7f, 0x98, 0xd4, 0xe5, 0x4b, 0xca,
0xfb, 0x47, 0xef, 0xef, 0xb9, 0x4d, 0x6d, 0x8f,
0x82, 0x68, 0x74, 0x84, 0xe0, 0x0a, 0x93, 0x0f,
0xb2, 0x01, 0xa9, 0x9f, 0x68, 0x6a, 0xe8, 0xf7,
0xfb, 0x0b, 0xde, 0x17, 0xe0, 0x30, 0x38, 0x51,
0xbc, 0x07, 0xb8, 0x2c, 0x91, 0x0f, 0xc1, 0x0e,
0xa6, 0xf9, 0xf0, 0xd5, 0x48, 0x76, 0x8a, 0xde,
0x74, 0xe3, 0x30, 0x65, 0x56, 0xb3, 0x5c, 0xe2,
0x89, 0x8d, 0xda, 0x80, 0xad, 0x0f, 0x22, 0xfb,
0x24, 0x1d, 0x16, 0xdd, 0x34, 0x4b, 0x90, 0x58,
0x4e, 0x0c, 0x13, 0x28, 0xcf, 0x1d, 0xa4, 0xaa,
0xb7, 0xf3, 0xb1, 0x66, 0xad, 0x3b, 0xcf, 0x79,
0x12, 0x04, 0xd7, 0x79, 0xd9, 0x5f, 0xdf, 0x89,
0xb2, 0x5b, 0xa7, 0x9a, 0x26, 0x1e, 0x67, 0x46,
0x7c, 0x66, 0x95, 0x67, 0xe6, 0x45, 0x8b, 0x1f,
0x65, 0x79, 0x9f, 0x6d, 0x11, 0x81, 0x17, 0x0d,
0x11, 0xb0, 0x5c, 0xb4, 0xc7, 0x27, 0x87, 0xab,
0x5d, 0x0a, 0x18, 0xae, 0x4e, 0x06, 0xa3, 0x3d,
0xc7, 0xb0, 0x22, 0xba, 0x03, 0xa4, 0x0f, 0xe5,
0x1c, 0x72, 0x2a, 0x04, 0xce, 0x83, 0xe9, 0xf3,
0xd7, 0xc9, 0x67, 0x6c, 0x1e, 0x6b, 0x3c, 0x9b,
0x0b, 0x5e, 0x6a, 0xa6, 0x79, 0x0a, 0xf1, 0xbe,
0xd7, 0xb4, 0x6f, 0x45, 0x1e, 0xfb, 0x78, 0x97,
0xaf, 0x34, 0x76, 0x95, 0x52, 0xf7, 0x3d, 0x5d,
0x07, 0x28, 0x57, 0x9c, 0x4a, 0x0f, 0xcf, 0x0b,
0x1b, 0xc4, 0xc2, 0x72, 0xd7, 0x72, 0x38, 0x9b,
0xea, 0xeb, 0xee, 0xae, 0x34, 0xc8, 0x01, 0xd7,
0xa5, 0xe3, 0xce, 0x41, 0xad, 0x02, 0x60, 0x23,
0x18, 0x36, 0xba, 0x17, 0xfa, 0xcf, 0xe4, 0xda,
0xdc, 0xfc, 0x82, 0xdc, 0x7c, 0x11, 0xf4, 0xb8,
0x52, 0x5d, 0xf7, 0x2f, 0xc8, 0xfe, 0x4a, 0xe6,
0xb9, 0xaf, 0x4b, 0x17, 0x18, 0x91, 0xc2, 0xfe,
0xd7, 0x3a, 0x77, 0x0c, 0xa0, 0x43, 0x9c, 0x6f,
0x13, 0x06, 0xbe, 0x6e, 0xe0, 0x1a, 0x3c, 0xf3,
0xf5, 0xcc, 0x78, 0xfb, 0x5d, 0xd5, 0xda, 0xb7,
0x58, 0xea, 0x86, 0x42, 0x6b, 0x32, 0xff, 0xb2,
0xe2, 0xee, 0x03, 0x1f, 0xf4, 0xef, 0xdb, 0x53,
0x79, 0xd5, 0x4e, 0xaf, 0x60, 0x8e, 0x02, 0xc2,
0xcc, 0x39, 0x97, 0x7b, 0xfd, 0xa1, 0xf8, 0x7a,
0x26, 0xe8, 0x55, 0xd6, 0xa4, 0x8b, 0xa0, 0x1b,
0x2d, 0x63, 0xaa, 0x73, 0x71, 0x6e, 0xbf, 0x8b,
0x3b, 0xe3, 0x1b, 0x0d, 0xbb, 0x2e, 0x44, 0x09,
0x64, 0xac, 0xc7, 0x9e, 0xb5, 0xc6, 0x77, 0xb0,
0x79, 0xb3, 0xaa, 0xfc, 0x67, 0x57, 0x9a, 0x50,
0x81, 0x37, 0x14, 0x7c, 0xd7, 0xa0, 0xd4, 0x6a,
0x79, 0x84, 0x51, 0x0e, 0x95, 0x0a, 0x30, 0xa3,
0x60, 0x55, 0x48, 0x05, 0x16, 0xae, 0x43, 0x90,
0xdc, 0x8e, 0x09, 0xbe, 0x79, 0xf6, 0x90, 0x74,
0xf8, 0x20, 0x96, 0x4d, 0xa7, 0xf5, 0x1a, 0x2b,
0xc7, 0x15, 0x9d, 0x18, 0xf7, 0x94, 0x87, 0xf7,
0xf4, 0xfb, 0x0d, 0x61, 0xb6, 0xd7, 0xbe, 0x10,
0x8e, 0x47, 0x3c, 0x10, 0x44, 0x90, 0x52, 0x21,
0x83, 0xc0, 0xf5, 0x99, 0xaa, 0xbc, 0xf6, 0x55,
0xae, 0xf5, 0xb2, 0xa4, 0xcd, 0x4d, 0xb9, 0x38,
0x6c, 0xbc, 0x80, 0xc3, 0xad, 0xf4, 0x46, 0x31,
0x01, 0x58, 0x2d, 0x88, 0x57, 0xc3, 0x23, 0xd1,
0x64, 0xc9, 0xa3, 0x21, 0x6b, 0x8b, 0x8a, 0x23,
0x2c, 0x4f, 0xa9, 0xcd, 0x67, 0xfa, 0x77, 0xad,
0xa3, 0x16, 0xa2, 0xe5, 0x19, 0x14, 0x70, 0x41,
0x5b, 0xda, 0x14, 0xde, 0xe3, 0xe5, 0xc1, 0x15,
0xb4, 0x77, 0xa4, 0x9b, 0xb8, 0xb1, 0x28, 0x51,
0x30, 0xb4, 0xf1, 0xf3, 0xf8, 0x6d, 0xd0, 0xc3,
0x8c, 0x4c, 0x76, 0xb0, 0x9a, 0xdf, 0xc8, 0xbe,
0xf8, 0x4a, 0x61, 0x6e, 0x3e, 0xd6, 0x3c, 0xe8,
0xde, 0x56, 0xa0, 0x9c, 0x25, 0xbe, 0xce, 0x93,
0x1f, 0x88, 0xfb, 0x9a, 0x1a, 0xe2, 0xff, 0x88,
0xad, 0x10, 0xcb, 0x6c, 0xd6, 0xe7, 0x39, 0x0b,
0xe5, 0x1a, 0x06, 0x05, 0x64, 0x5b, 0x0a, 0xdf,
0x22, 0x58, 0xd7, 0xfb, 0x88, 0x12, 0xdd, 0xb7,
0x52, 0x3a, 0xc9, 0xbf, 0x49, 0xdf, 0x8c, 0x87,
0x9f, 0x84, 0xb5, 0x0a, 0xf6, 0x00, 0x52, 0xae,
0x67, 0x12, 0x1a, 0x8c, 0x71, 0x15, 0xf5, 0xa1,
0x13, 0x39, 0xf0, 0x91, 0x7e, 0x88, 0x7c, 0xb3,
0x95, 0x50, 0x02, 0xa6, 0x63, 0xb5, 0x64, 0xfb,
0x90, 0x87, 0x61, 0xe2, 0x27, 0xaf, 0x11, 0x0c,
0x73, 0x83, 0xef, 0xa9, 0x28, 0xfe, 0xc8, 0x85,
0x1a, 0x3a, 0xde, 0xf2, 0xe5, 0x25, 0x64, 0x6d,
0xaa, 0x41, 0x4c, 0x80, 0x2e, 0x84, 0xff, 0xc1,
0xc0, 0x54, 0x0c, 0x29, 0x1b, 0xa3, 0x07, 0x7c,
0x33, 0x4c, 0x10, 0xf6, 0x6f, 0x79, 0xdf, 0xd3,
0xf0, 0x24, 0x57, 0xf1, 0x60, 0xe1, 0xf0, 0xbd,
0xc4, 0x1f, 0xf4, 0x67, 0xd2, 0xd3, 0xcc, 0x6a,
0x07, 0x72, 0x44, 0x16, 0x85, 0x46, 0xd0, 0x73,
0x87, 0xa9, 0xc7, 0x2f, 0xd1, 0xf5, 0xec, 0xe3,
0x28, 0xa3, 0x93, 0x4f, 0xd7, 0x76, 0xc1, 0x3c,
0x0d, 0x13, 0x33, 0xcf, 0x5b, 0xbd, 0x6a, 0x52,
0x4e, 0xee, 0xc8, 0x5e, 0xa1, 0x58, 0x4a, 0x08,
0x81, 0xd9, 0x23, 0xcc, 0xfb, 0x1c, 0xb2, 0xd8,
0xa3, 0xe4, 0x53, 0xfe, 0xf4, 0x4b, 0x48, 0xc1,
0x20, 0xa4, 0x97, 0xf8, 0x38, 0xa3, 0x69, 0xc1,
0x11, 0xf0, 0xa1, 0x3b, 0xa9, 0x9a, 0x12, 0x61,
0xe8, 0x8d, 0x99, 0x44, 0x3f, 0x94, 0x72, 0x82,
0x19, 0x96, 0x62, 0xb0, 0xa6, 0x64, 0x05, 0x19,
0x8f, 0xd6, 0x5d, 0x05, 0xbf, 0x79, 0x9e, 0x9d,
0xe4, 0x93, 0x4c, 0xad, 0x61, 0x8c, 0x18, 0xda,
0xb6, 0x2e, 0xb3, 0xca, 0x14, 0x4d, 0x53, 0xa4,
0x97, 0x27, 0x10, 0x56, 0xa2, 0x67, 0x5a, 0x5a,
0x5e, 0x13, 0xc0, 0xdb, 0xa7, 0x9f, 0x45, 0x5b,
0xeb, 0x1a, 0x14, 0x0c, 0x8c, 0x38, 0x5e, 0x77,
0x9a, 0xec, 0x75, 0x68, 0x93, 0x65, 0x02, 0x9c,
0xfb, 0x62, 0x60, 0x49, 0xdd, 0xb2, 0x2a, 0x67,
0x86, 0xe3, 0x8a, 0x7d, 0x8c, 0x46, 0x78, 0x81,
0x60, 0x69, 0xf2, 0x3f, 0x74, 0x11, 0x35, 0xff,
0x77, 0xa3, 0x66, 0x20, 0xfc, 0x98, 0x4a, 0x35,
0x7a, 0x52, 0xe4, 0x90, 0x13, 0x80, 0xb9, 0xa6,
0x73, 0x7a, 0x7d, 0x66, 0x6e, 0x6b, 0xb6, 0x43,
0x10, 0xd5, 0x91, 0x2b, 0x66, 0xdd, 0x89, 0x87,
0xe3, 0x8c, 0x58, 0x53, 0x2f, 0x40, 0x74, 0x45,
0x1b, 0x77, 0x7a, 0xa4, 0x44, 0x19, 0x78, 0xba,
0x87, 0x10, 0x41, 0x31, 0x32, 0x5f, 0x87, 0x68,
0xde, 0x43, 0x4a, 0xef, 0x33, 0xb3, 0x11, 0x83,
0xa9, 0xc2, 0x6f, 0x8d, 0x34, 0xe2, 0x95, 0x84,
0x3a, 0x4f, 0x6f, 0x8c, 0x31, 0x1d, 0xb6, 0xf5,
0x95, 0x0d, 0x01, 0x11, 0x20, 0xdf, 0x72, 0xf3,
0x3f, 0x9a, 0x33, 0xaa, 0xb1, 0x06, 0x6a, 0x63,
0x47, 0x91, 0x01, 0xdf, 0xb3, 0x54, 0x36, 0xfd,
0x06, 0x2d, 0xb8, 0x08, 0xe3, 0xd3, 0x65, 0xac,
0x66, 0x03, 0xee, 0xa4, 0x63, 0xbd, 0xd4, 0xce,
0xbd, 0x79, 0xa7, 0x48, 0x38, 0xc5, 0x7d, 0xb5,
0x71, 0x9a, 0x3c, 0x11, 0x7c, 0x6c, 0xe2, 0x54,
0x02, 0x5d, 0x42, 0xab, 0x25, 0x93, 0x66, 0x01,
0x37, 0x78, 0x35, 0x4a, 0x8c, 0x19, 0x4d, 0x00,
0x75, 0x4f, 0xcc, 0xc0, 0x26, 0x82, 0xc1, 0x35,
0x8c, 0xc7, 0xc2, 0x59, 0x01, 0x3e, 0x98, 0x22,
0x88, 0x9c, 0x90, 0x75, 0x05, 0x33, 0x07, 0xb9,
0x39, 0x81, 0x38, 0x58, 0x10, 0x29, 0xcf, 0xc8,
0x98, 0xb2, 0x03, 0xd7, 0x5b, 0xb3, 0x18, 0xba,
0x34, 0x0c, 0x9f, 0xab, 0xd7, 0xed, 0x29, 0x82,
0x41, 0xe0, 0x20, 0x97, 0x57, 0x92, 0xb2, 0xb8,
0x10, 0x2d, 0x0b, 0xa2, 0xc5, 0x8f, 0x90, 0x6f,
0xed, 0x12, 0x56, 0x25, 0xbe, 0xfd, 0x75, 0xf7,
0xb6, 0xf8, 0x40, 0x67, 0x39, 0x11, 0xfa, 0x15,
0xae, 0x6a, 0x54, 0x5f, 0x32, 0x2b, 0xf8, 0x48,
0x55, 0xbe, 0x86, 0x2f, 0x69, 0x48, 0x5b, 0x5d,
0x4d, 0xb7, 0x35, 0xaa, 0xb6, 0x91, 0x88, 0x19,
0x96, 0x1c, 0x68, 0xf6, 0x85, 0x9e, 0xb3, 0xb2,
0xa3, 0x32, 0xd4, 0x52, 0x70, 0xb7, 0x62, 0xe3,
0x14, 0xb6, 0x78, 0x5f, 0x1b, 0x1d, 0x04, 0x9c,
0x26, 0x0c, 0x33, 0x94, 0xb1, 0x97, 0x08, 0xdb,
0x0b, 0x39, 0x29, 0xd4, 0xbc, 0x6d, 0xdf, 0x02,
0xc6, 0x99, 0xab, 0x99, 0x32, 0xe5, 0xce, 0x51,
0x4f, 0xae, 0xb8, 0x8b, 0xe0, 0xaf, 0x07, 0xc4,
0xf9, 0x41, 0x7c, 0x59, 0xa0, 0xac, 0x74, 0x4d,
0x7e, 0x43, 0x77, 0x9c, 0x06, 0x49, 0x79, 0x8a,
0x14, 0x73, 0x93, 0xa8, 0x5b, 0x1b, 0x34, 0x29,
0x78, 0x04, 0x2f, 0xd7, 0x1f, 0x13, 0x90, 0xe0,
0xdd, 0x3b, 0x42, 0x6b, 0x79, 0x6e, 0x52, 0xc7,
0x0f, 0x38, 0xda, 0x01, 0x2c, 0x8d, 0xe6, 0x94,
0x5d, 0x59, 0x27, 0x1d, 0x10, 0x4e, 0x11, 0x36,
0xfb, 0x53, 0x16, 0x05, 0x25, 0xf2, 0x64, 0xd8,
0xf9, 0xcd, 0x5c, 0xfe, 0xb4, 0x18, 0x44, 0x80,
0x10, 0xbc, 0x3d, 0xf3, 0x1d, 0x5a, 0xf0, 0xc1,
0xc3, 0x55, 0xff, 0x41, 0x3e, 0xe3, 0xef, 0x44,
0xb2, 0xc0, 0x01, 0x18, 0xa2, 0x49, 0x88, 0x78,
0x0d, 0x4c, 0xc8, 0x73, 0xcf, 0x30, 0x85, 0x3a,
0x88, 0x90, 0x01, 0xcf, 0x69, 0x53, 0xa3, 0x18,
0x3f, 0xd6, 0xe7, 0x94, 0x14, 0xa7, 0xae, 0xcd,
0x6f, 0x11, 0x72, 0xfe, 0x2b, 0xb0, 0x81, 0x53,
0xea, 0x67, 0xd6, 0xe4, 0xca, 0x42, 0xa0, 0xf9,
0xb1, 0xd4, 0xb5, 0x3b, 0xc9, 0xf0, 0x36, 0xc1,
0x1c, 0xf4, 0xb1, 0xf6, 0x84, 0xd0, 0x86, 0x6c,
0x76, 0x9a, 0x03, 0xc2, 0xb6, 0x2e, 0x9a, 0x46,
0xf5, 0x5f, 0x2c, 0x38, 0xac, 0xad, 0x6f, 0x2e,
0x7a, 0x18, 0x2d, 0x22, 0x95, 0x5e, 0x5e, 0xc9,
0x7a, 0x0a, 0x56, 0xe1, 0xc7, 0x15, 0xfd, 0xbf,
0xff, 0xf7, 0x7e, 0x85, 0x20, 0xa9, 0x8a, 0x9c,
0xa9, 0x7d, 0xe8, 0xed, 0xfc, 0x7f, 0xbb, 0xf0,
0x05, 0x3f, 0xce, 0x4f, 0x4c, 0xee, 0xa4, 0xa0,
0xcc, 0x9c, 0x62, 0x1e, 0xd6, 0xd0, 0x30, 0x37,
0xb8, 0x98, 0x56, 0x1d, 0xaa, 0xd6, 0x5e, 0x73,
0x12, 0xe4, 0x88, 0x82, 0x48, 0x64, 0x06, 0xd7,
0x2a, 0x31, 0x50, 0x7b, 0x10, 0x17, 0xb8, 0x4c,
0x5a, 0x8d, 0xf1, 0xfc, 0xf1, 0x33, 0x3b, 0x98,
0x42, 0x18, 0x5b, 0x35, 0x78, 0xca, 0x8e, 0x41,
0x52, 0xae, 0x6d, 0xe1, 0xa2, 0x9d, 0x5b, 0xbd,
0xf3, 0x5f, 0x49, 0xc1, 0x27, 0x06, 0xc1, 0xaf,
0xc0, 0xa3, 0x9d, 0xf3, 0x1c, 0x8e, 0x90, 0x8a,
0xb0, 0x69, 0xb0, 0xc5, 0x11, 0x0c, 0x91, 0x14,
0x1f, 0x5e, 0x10, 0xe1, 0x1d, 0x14, 0x30, 0x54,
0x1e, 0x17, 0x3d, 0x31, 0x7b, 0xbf, 0x2f, 0x9d,
0x6d, 0x63, 0x32, 0xf0, 0x9d, 0x9f, 0x95, 0x3d,
0x0b, 0xd2, 0x4d, 0x10, 0xe2, 0x3f, 0x67, 0x69,
0x43, 0x9a, 0x4a, 0x2c, 0x54, 0x71, 0xa8, 0xa0,
0x9e, 0x9f, 0x10, 0xaf, 0x1b, 0xce, 0x99, 0xe3,
0x25, 0x32, 0x10, 0x54, 0x80, 0xfe, 0xda, 0x57,
0xd0, 0xb2, 0x92, 0x7f, 0xbb, 0x5f, 0xe7, 0x4d,
0x1b, 0x3d, 0x46, 0x4d, 0xe4, 0x4c, 0xd6, 0xaf,
0x1a, 0x32, 0x12, 0x40, 0xb8, 0x84, 0x8e, 0xe4,
0x80, 0xce, 0x7e, 0xc1, 0x13, 0x8b, 0xb0, 0xb7,
0x6f, 0x24, 0xba, 0x85, 0x50, 0x83, 0xc3, 0xcf,
0x19, 0xb3, 0xf0, 0xc7, 0xee, 0x68, 0xbe, 0x9e,
0x6d, 0xb9, 0xfb, 0xd5, 0x29, 0xce, 0x82, 0xcd,
0x69, 0x16, 0x68, 0x6b, 0x6a, 0xf4, 0x02, 0x32,
0xce, 0x60, 0x37, 0x0c, 0xb9, 0x38, 0x92, 0x9c,
0x42, 0xa9, 0x0b, 0x53, 0x96, 0xfe, 0x39, 0xc1,
0x24, 0x65, 0x9b, 0xcd, 0xe7, 0x8d, 0x36, 0x07,
0x9f, 0x1d, 0x35, 0x8e, 0xdc, 0x4c, 0xb5, 0x68,
0xc5, 0xfd, 0x44, 0x19, 0xf2, 0x6c, 0x59, 0x1c,
0xb1, 0x0b, 0x35, 0x48, 0x86, 0x1a, 0x05, 0x22,
0x03, 0x0c, 0x0c, 0xa2, 0x92, 0x90, 0x35, 0xfb,
0x37, 0x94, 0xc7, 0x15, 0x84, 0xae, 0xe8, 0x05,
0xa0, 0xf7, 0x30, 0x11, 0x5c, 0xe4, 0x5d, 0x3e,
0x12, 0x54, 0x80, 0x54, 0x6b, 0x09, 0x8c, 0xce,
0x80, 0x5e, 0xa7, 0xc8, 0x6a, 0x0c, 0x56, 0xe1,
0x18, 0x7d, 0xc9, 0x39, 0xc1, 0xef, 0xe3, 0x25,
0xa0, 0x8b, 0x2f, 0x60, 0x3a, 0x43, 0x39, 0xa6,
0x28, 0x28, 0x7b, 0x4c, 0x77, 0xd4, 0x49, 0x61,
0x46, 0xe9, 0x1b, 0x45, 0xd6, 0xb1, 0x56, 0xe1,
0x7d, 0x34, 0xcd, 0x06, 0xb6, 0x67, 0x8d, 0x7d,
0x7a, 0xe2, 0xbe, 0x68, 0x35, 0xa6, 0x78, 0xe5,
0x47, 0x48, 0xb7, 0xc7, 0xde, 0xcd, 0xc9, 0x05,
0xb4, 0xe7, 0x50, 0x48, 0xe1, 0x4b, 0xfe, 0x76,
0x77, 0xc6, 0xf7, 0x5f, 0xcb, 0xc2, 0xa8, 0xd7,
0xd6, 0x8a, 0xe5, 0x49, 0xd9, 0xca, 0x45, 0xf4,
0xda, 0xcd, 0x33, 0xd1, 0x59, 0x2d, 0x9e, 0xc1,
0x5c, 0xe6, 0x01, 0x18, 0xb8, 0xf0, 0x5e, 0xb1,
0x69, 0x95, 0x2f, 0x02, 0x2a, 0xe7, 0x4a, 0xd7,
0xd1, 0xc3, 0xd5, 0x6f, 0x15, 0xc8, 0xdc, 0x29,
0xde, 0xb9, 0x3f, 0x8b, 0xa6, 0xbc, 0xdd, 0x25,
0x84, 0x35, 0x3c, 0x90, 0x2d, 0xc2, 0x1e, 0x98,
0x8a, 0x50, 0x09, 0x77, 0x42, 0xe9, 0x35, 0x8a,
0x7c, 0x97, 0xbf, 0xe8, 0xbf, 0x56, 0xd0, 0x8b,
0x65, 0xd3, 0xaf, 0x1e, 0x05, 0x94, 0xfa, 0xac,
0xa8, 0x2b, 0x28, 0xcb, 0x37, 0x3e, 0xe8, 0xbb,
0x66, 0x3a, 0xed, 0xb2, 0x48, 0x10, 0x0f, 0x3a,
0x5a, 0xc5, 0xdb, 0x26, 0x0e, 0xaa, 0x5e, 0x69,
0x15, 0xd6, 0x81, 0xae, 0xbd, 0xe6, 0x03, 0xf1,
0xf6, 0x37, 0xc8, 0xde, 0x70, 0x1f, 0x64, 0xb9,
0x5e, 0xbf, 0x2e, 0x4f, 0xb1, 0xea, 0xa0, 0x17,
0xe6, 0x7c, 0xf9, 0x2f, 0x1e, 0xd8, 0x58, 0xde,
0xa7, 0xf0, 0x46, 0x52, 0x95, 0xdf, 0xa4, 0x96,
0xd0, 0xc4, 0x97, 0x2b, 0x95, 0xcd, 0x5e, 0x40,
0x23, 0x5c, 0x10, 0xee, 0xba, 0x72, 0x9b, 0xcf,
0x0b, 0xe8, 0x18, 0x3a, 0x70, 0xd2, 0x5e, 0x07,
0x68, 0x93, 0xef, 0x4a, 0x5b, 0x8d, 0x72, 0x41,
0x4e, 0xea, 0x33, 0x6a, 0x0a, 0x5e, 0xfb, 0x02,
0x3f, 0xd4, 0xed, 0x5b, 0xe0, 0x42, 0x84, 0xd4,
0xaa, 0x85, 0xdc, 0x5b, 0x67, 0xee, 0x71, 0x67,
0xba, 0x8e, 0xd2, 0xbe, 0x61, 0xdf, 0x5a, 0x26,
0xb9, 0xf0, 0x77, 0x81, 0x53, 0x24, 0x16, 0xcb,
0x8c, 0xb8, 0x06, 0x6e, 0x68, 0xda, 0xc8, 0x2d,
0x17, 0x54, 0xdb, 0x46, 0xcb, 0xfd, 0x1f, 0x3d,
0x94, 0x81, 0x09, 0x4b, 0xfa, 0xb1, 0x46, 0xd9,
0x11, 0xa3, 0xb7, 0x31, 0x9c, 0xd2, 0x38, 0xd6,
0xba, 0x3d, 0xa3, 0x74, 0xd8, 0xf1, 0x24, 0xe8,
0x9c, 0xcb, 0x1d, 0xf9, 0x4a, 0xf7, 0xc8, 0x4b,
0xfe, 0x97, 0x7c, 0xa1, 0x02, 0xeb, 0x40, 0xc3,
0x89, 0x71, 0x01, 0xcd, 0x33, 0x2a, 0xc2, 0x82,
0xce, 0x62, 0x8d, 0x53, 0x7c, 0xdf, 0xce, 0xd7,
0xf5, 0xa8, 0x4f, 0xf2, 0xf2, 0x2e, 0xc1, 0xeb,
0x97, 0x99, 0x37, 0x3c, 0x53, 0xa6, 0xb4, 0x46,
0x05, 0x64, 0x92, 0x87, 0x08, 0x3c, 0x23, 0x4b,
0x9d, 0x67, 0x18, 0xf9, 0xe2, 0x0b, 0x1c, 0x39,
0xd3, 0x87, 0x70, 0xc0, 0xb9, 0x1e, 0x52, 0x0a,
0x0f, 0x48, 0xe2, 0xe7, 0x51, 0x72, 0x94, 0xf7,
0xa3, 0xdc, 0xe5, 0x66, 0x33, 0x39, 0x54, 0x06,
0x55, 0x93, 0x30, 0xf9, 0x5e, 0x76, 0x8f, 0xe0,
0x59, 0x4d, 0x0d, 0xa7, 0xf5, 0xbe, 0xdb, 0x20,
0xad, 0x0d, 0x76, 0x88, 0x5f, 0x9c, 0x7c, 0x75,
0x2f, 0x2a, 0x0b, 0x79, 0x6e, 0xd3, 0xe2, 0x66,
0xf5, 0x4a, 0x2d, 0x87, 0x87, 0x49, 0x84, 0x17,
0xa2, 0x62, 0x4c, 0xbb, 0xe4, 0x6e, 0x98, 0x10,
0xc9, 0xfb, 0x8a, 0x04, 0x68, 0x8d, 0x22, 0x66,
0xad, 0xea, 0x2a, 0xc9, 0x97, 0x2d, 0x3c, 0xbc,
0xd0, 0x77, 0x5f, 0xe6, 0xb8, 0x7f, 0xe6, 0xf6,
0x39, 0xbf, 0x56, 0x0e, 0x26, 0x6d, 0xc5, 0x3e,
0x53, 0x19, 0xd6, 0xb4, 0x57, 0x36, 0xa3, 0xc6,
0xd3, 0x3d, 0x66, 0x79, 0x30, 0x5c, 0x14, 0x0c,
0x0f, 0x3e, 0x96, 0xae, 0x90, 0x97, 0xab, 0x0d,
0x9f, 0xc3, 0xe7, 0x66, 0x3e, 0xe0, 0x31, 0x43,
0x4b, 0x01, 0xb3, 0x0e, 0x9e, 0x8c, 0x82, 0x4a,
0x8c, 0xc7, 0x79, 0x85, 0xdf, 0x75, 0x0d, 0xb4,
0x2b, 0x03, 0x14, 0xef, 0x72, 0x58, 0xfd, 0x64,
0xc8, 0xe3, 0x0d, 0x9a, 0x14, 0x6f, 0x76, 0xf9,
0x46, 0xd1, 0xd2, 0x81, 0xb3, 0x16, 0x6e, 0xc7,
0x76, 0x82, 0xce, 0xf4, 0xee, 0x33, 0x00, 0xe6,
0x77, 0xc4, 0xad, 0x4f, 0x06, 0xa7, 0x48, 0x80,
0x9e, 0x21, 0x66, 0xca, 0x75, 0x69, 0x57, 0xcb,
0xf0, 0x67, 0x6a, 0xaa, 0x8f, 0x88, 0x14, 0xbd,
0x65, 0x62, 0xe2, 0xad, 0xcc, 0x22, 0x88, 0x7b,
0x94, 0xbd, 0x0e, 0xcd, 0xb6, 0x69, 0xa2, 0xcb,
0x7d, 0x57, 0x5c, 0xb4, 0x92, 0x80, 0x13, 0x99,
0x84, 0xf3, 0x79, 0x0a, 0x2d, 0x70, 0xa4, 0xe0,
0xde, 0xc6, 0x32, 0xb0, 0x8a, 0x62, 0xb5, 0xcf,
0xfa, 0x5e, 0x5a, 0x92, 0x32, 0x7d, 0x34, 0x07,
0xb5, 0x52, 0x3a, 0xb5, 0x7d, 0x0f, 0xa1, 0xba,
0x56, 0xd0, 0x07, 0x76, 0x11, 0xf2, 0xc3, 0x33,
0x9d, 0xbd, 0x12, 0x35, 0x5e, 0xf7, 0x05, 0x88,
0x76, 0x94, 0xa6, 0xbf, 0xed, 0xb8, 0xa4, 0xa2,
0x0c, 0xbe, 0x0f, 0x6a, 0xaf, 0xf3, 0x1b, 0x33,
0x4a, 0xb7, 0x68, 0x3f, 0xbe, 0x95, 0x13, 0x97,
0x0f, 0x15, 0x17, 0x1b, 0x23, 0xaa, 0x08, 0x78,
0xa6, 0x5b, 0x08, 0xa2, 0x9d, 0x03, 0xa8, 0xa7,
0x39, 0xdc, 0xbc, 0x9a, 0x85, 0xf5, 0xe5, 0x55,
0x59, 0x3c, 0xef, 0xf9, 0x3f, 0x22, 0x8e, 0xf8,
0xd8, 0x3e, 0x02, 0x0b, 0xd8, 0x78, 0x4b, 0x15,
0x7f, 0xaa, 0x2c, 0xff, 0xbe, 0x77, 0x33, 0xc7,
0x6a, 0x12, 0xaa, 0xa4, 0xbe, 0xc0, 0x3b, 0xcb,
0x13, 0x9d, 0x9c, 0x5a, 0x9f, 0x8a, 0x57, 0x36,
0x4f, 0x02, 0x5a, 0xf8, 0x1d, 0x97, 0x77, 0x43,
0xc8, 0xa5, 0xb7, 0x9b, 0x10, 0x98, 0xfd, 0x58,
0xbf, 0x42, 0xf6, 0xbf, 0xff, 0x6c, 0x40, 0x18,
0x18, 0xdf, 0xac, 0x57, 0x71, 0xea, 0xcc, 0x8e,
0xfd, 0xfe, 0x10, 0xfb, 0xb9, 0xfe, 0xbc, 0x9a,
0x9c, 0x27, 0xe4, 0x10, 0x15, 0x94, 0x41, 0xa1,
0xcc, 0xf6, 0x25, 0x49, 0x4f, 0x96, 0xc1, 0x8c,
0x9e, 0x3e, 0x18, 0x29, 0x49, 0x92, 0xe7, 0xfe,
0x22, 0xff, 0xed, 0x02, 0x16, 0x90, 0xef, 0xac,
0xec, 0x95, 0x1d, 0x5b, 0x94, 0x9c, 0xf6, 0x7c,
0x1b, 0x5a, 0x9d, 0xb0, 0x9b, 0x05, 0x36, 0xbf,
0xef, 0xec, 0x63, 0x35, 0x40, 0x24, 0x45, 0x40,
0x30, 0x1a, 0x9b, 0x90, 0xc3, 0xc2, 0xf7, 0x37,
0xfb, 0x08, 0x8e, 0x48, 0x19, 0x48, 0xed, 0xa8,
0xa8, 0x04, 0x6f, 0xd0, 0x33, 0xe9, 0xb8, 0x8d,
0xe7, 0x1e, 0x5c, 0x47, 0x74, 0xc0, 0x66, 0x30,
0x4e, 0xa7, 0x86, 0x73, 0xf1, 0xe5, 0x78, 0xa6,
0xe0, 0xc1, 0xda, 0x13, 0x72, 0x07, 0x85, 0x34,
0x63, 0x95, 0x49, 0x30, 0x4b, 0x9d, 0x03, 0xf1,
0x7a, 0x6b, 0x91, 0xa2, 0x85, 0x41, 0xf9, 0x4a,
0xd6, 0xff, 0xff, 0x86, 0xf7, 0xf0, 0xce, 0xb9,
0x07, 0xf1, 0x88, 0x04, 0x33, 0xaa, 0xeb, 0x54,
0xb2, 0x1c, 0x8e, 0x2e, 0x7b, 0x04, 0xa8, 0xcc,
0x2c, 0x7a, 0xb3, 0xad, 0x1a, 0x89, 0x38, 0x89,
0xd7, 0x11, 0x3a, 0x8c, 0xcf, 0xe3, 0xc5, 0xba,
0xb0, 0xcc, 0xc4, 0xe3, 0x33, 0xf3, 0x18, 0xba,
0xec, 0x56, 0xd9, 0x1c, 0x40, 0x70, 0x0d, 0x4e,
0x97, 0x01, 0x23, 0xf3, 0x5a, 0xdc, 0xbf, 0x68,
0x93, 0xc2, 0x1d, 0x8a, 0x96, 0xb7, 0xac, 0x18,
0x6f, 0xf7, 0x84, 0x71, 0x0d, 0x3d, 0xf8, 0xba,
0xdf, 0xb6, 0x89, 0x1d, 0x78, 0x19, 0xf2, 0x59,
0xe9, 0x15, 0x55, 0x29, 0x73, 0x50, 0x59, 0x14,
0x02, 0x21, 0x16, 0x8f, 0x0f, 0xdf, 0xa5, 0xf0,
};
static struct crc_test {
uint32_t crc; /* random starting crc */
uint32_t start; /* random offset in buf */
uint32_t length; /* random length of test */
uint32_t crc32c_le; /* expected crc32c_le result */
uint32_t crc32_be; /* expected crc32_be result */
} test[] = {
{0xffffffff, 0x00000000, 0x00001000, 0x13934bef, 0xd8ddcdc3},
{0xfe7328ea, 0x00000763, 0x00000717, 0xed2c0d70, 0xc863aef8},
{0x4c40684e, 0x00000721, 0x0000011e, 0xd7f46ccc, 0x173a11c4},
{0x6b487f90, 0x00000264, 0x000007bc, 0x759e9939, 0xd6307c56},
{0x9f5810db, 0x00000afa, 0x00000255, 0x2685197f, 0x2e5c9201},
{0xb15c4755, 0x00000d5b, 0x000002a4, 0xd8fadcb5, 0xf682c4be},
{0x06518253, 0x00000ffb, 0x00000004, 0xabee2433, 0x3d8abdf9},
{0xd9e71c55, 0x00000a2a, 0x00000259, 0x96682af2, 0x47b4d26c},
{0x0c1ae843, 0x00000ce4, 0x0000031b, 0x7b637c43, 0x62b47e8b},
{0xec3cd517, 0x000002ff, 0x00000566, 0x5d719a77, 0xff5bc5b7},
{0x77828e95, 0x0000067f, 0x0000038f, 0x43ee5b6c, 0x1a0cfacd},
{0xec87b4e3, 0x00000d1c, 0x000002e3, 0x2ddd2eee, 0x275118a7},
{0x412158bb, 0x00000eee, 0x00000111, 0x67b38ba2, 0xa74ecff5},
{0x2e52de3e, 0x00000c4a, 0x000003b5, 0xbcc5d61d, 0xbd800707},
{0x6ddaae8b, 0x00000d99, 0x00000266, 0x8b535544, 0xecbde1a1},
{0x049b6cb1, 0x000009c5, 0x000000b0, 0xfc22cabc, 0xfb78eb9f},
{0x77d4b954, 0x0000028a, 0x000007fa, 0x71d00923, 0x8c116f85},
{0x5e192355, 0x00000ac1, 0x000001fa, 0xb966b81a, 0x5aa17bbe},
{0x7d80b71d, 0x00000213, 0x000001e0, 0x2bba371a, 0xb5906aa6},
{0x01f6f1e4, 0x000001d6, 0x00000395, 0xb7e8a647, 0x3ad112b1},
{0x1dfabb13, 0x00000e14, 0x000001eb, 0x53917fba, 0xbaee0339},
{0xb00a4449, 0x00000bf6, 0x00000409, 0xedecb577, 0x6f3a3979},
{0x7ecd3981, 0x0000083f, 0x0000016b, 0xefef62b9, 0xe3e52eed},
{0xf8f330d2, 0x000004be, 0x00000757, 0x9357c9f3, 0x0835bc1b},
{0x03c38af2, 0x00000d23, 0x000002dc, 0x360fa8c0, 0x2ca885e6},
{0x687bb79b, 0x00000f3d, 0x000000c2, 0x448d3be2, 0x79be2f78},
{0x6710f550, 0x000009e9, 0x00000603, 0xdbfd1998, 0x1d25f627},
{0x873171d1, 0x00000787, 0x000004d5, 0xab7f1b62, 0xa76a5656},
{0x373b1314, 0x00000f0f, 0x000000f0, 0x184098ab, 0xba273974},
{0x90fad9cd, 0x00000ead, 0x00000152, 0x23ce52ff, 0xb7bc958c},
{0x19676fe7, 0x0000007d, 0x0000070d, 0xf8a76f1e, 0xf882b644},
{0x89facd45, 0x000005f3, 0x00000473, 0x4331a006, 0xe9dc1396},
{0x6f173747, 0x00000fc3, 0x0000003c, 0xb012f08e, 0xc6b888ee},
{0x4b44a106, 0x0000075a, 0x0000008b, 0xf6f7ac38, 0x60cd2b74},
{0xb620ad06, 0x00000774, 0x0000017e, 0xd34558e6, 0x3a0a615b},
{0x976f21e9, 0x000008d7, 0x0000034a, 0xe533aa3a, 0xa99e60be},
{0x687628c0, 0x000006c5, 0x0000061b, 0x3a840b15, 0x9bfcaef2},
{0xe24ac108, 0x00000cd0, 0x0000032f, 0x51010ae8, 0x20958672},
{0x361c44a3, 0x00000304, 0x00000719, 0xfd7bd481, 0xd70ff2b2},
{0xd93ff95e, 0x00000db7, 0x0000008e, 0xcfbbc304, 0xad716acd},
{0xed752d12, 0x00000883, 0x00000091, 0x65a6c868, 0x95c71c7b},
{0xb4ff4b54, 0x000003d3, 0x000001c1, 0xf82597e7, 0x44b7f99b},
{0x111b520f, 0x00000708, 0x000000eb, 0xc3e109f3, 0x71bc01ee},
{0x62c806f2, 0x00000ba3, 0x0000045c, 0x874d3a72, 0xc539b753},
{0x40d97470, 0x000005e1, 0x0000058d, 0x87a9684f, 0xea6073a5},
{0x4312179c, 0x00000056, 0x0000070e, 0x809a00f5, 0x209aea3b},
{0x13d5f84c, 0x00000a2d, 0x00000104, 0xf3d27578, 0xe087a8b6},
{0x1f302cb2, 0x00000151, 0x00000014, 0x1e162693, 0x95e4b90e},
{0xe491db24, 0x00000600, 0x000006f6, 0x7ff09615, 0x77611523},
{0xf9a98069, 0x000002ba, 0x000002ad, 0x01af7387, 0xea925faa},
{0xe9c477ad, 0x0000015f, 0x00000778, 0x6facf9a0, 0x1130f736},
{0x353f32b2, 0x0000087c, 0x00000783, 0x6cc964ea, 0x32459994},
{0x78e1b24f, 0x00000650, 0x000006a8, 0xb3bb7c27, 0x5a632f78},
{0x61aa400e, 0x00000049, 0x00000254, 0xb8cd1681, 0xdf2652d5},
{0xb84b10b0, 0x00000f73, 0x0000008c, 0x406a6450, 0x3619d31b},
{0x9fa99c9c, 0x00000a7c, 0x000004d7, 0xfb3d21b4, 0xea31c743},
{0x3fc9ebe3, 0x00000cd9, 0x000000d6, 0x43803f9c, 0x1f76a809},
{0x529879cd, 0x000002f2, 0x00000595, 0x78b4c6a6, 0x63b9b93f},
{0x3a933019, 0x00000516, 0x00000266, 0xdcb45436, 0x8f99c98c},
{0x887b4977, 0x00000227, 0x0000038d, 0xc5f7c3d9, 0xaf5e3091},
{0x770745de, 0x000008c6, 0x00000739, 0xf69145e8, 0x53d0dce1},
{0x28be3b47, 0x00000c46, 0x0000032b, 0x764c028f, 0x106d0905},
{0x5013a050, 0x00000cf6, 0x00000309, 0xea8fe164, 0x62180b57},
{0x2ec4c9ba, 0x000006e8, 0x0000078d, 0xa35557a9, 0xf44430a4},
{0xa9f950c9, 0x00000d33, 0x000002cc, 0x41ea8618, 0x587b4eb3},
{0x5b520229, 0x000007b2, 0x00000484, 0x44569f1f, 0x92406c32},
{0xd8dcbbfc, 0x0000002f, 0x0000048c, 0xdb88ab8b, 0x13bfe70e},
{0x25529792, 0x00000d1d, 0x000002e2, 0x20cda404, 0x19d3b4e4},
{0x9f3f6d71, 0x00000238, 0x0000079a, 0x0720443e, 0x3c107021},
{0x64121215, 0x000007ff, 0x0000038f, 0x6aacff2c, 0xb82fdc3e},
{0xfb6cdde0, 0x00000ef8, 0x00000107, 0xbd43a0f1, 0xab0d3c1d},
{0x221c9d6f, 0x000007b6, 0x0000014f, 0xb67f834b, 0x1371ad05},
{0x030e1de4, 0x00000836, 0x000004b4, 0x0d67d26a, 0xe2e72df1},
{0xb56fa6cf, 0x00000c07, 0x000003f8, 0x60601ac1, 0x039de73e},
{0xb55c89f5, 0x0000098e, 0x000001d4, 0x2400efbe, 0xfe39a2bb},
{0x5e90b6d5, 0x0000070b, 0x000003ea, 0x3bb5d6ea, 0xf0f794a0},
{0x2a7045ae, 0x00000961, 0x00000633, 0xfca89e4b, 0xe66ce41c},
{0x8b374ea9, 0x000006ba, 0x00000780, 0xbce036ed, 0x4cb28ef7},
{0x8bd90bc9, 0x00000562, 0x00000369, 0xcb26a24b, 0x40236d1d},
{0x5b1b1762, 0x000000fd, 0x0000051a, 0x33cdda07, 0xc32e420a},
{0xa4153555, 0x0000058f, 0x000005c7, 0xbe50eeca, 0x83a67f35},
{0x0be1f931, 0x00000651, 0x00000672, 0x95a25753, 0x88f1aac1},
{0xb7e78618, 0x00000a7f, 0x000002bb, 0xe06bcc1c, 0x74274f66},
{0x4a9bc41b, 0x00000e51, 0x000001ae, 0x709e8d2c, 0x54eff534},
{0xfc359d13, 0x00000440, 0x000002f8, 0x0a58451f, 0x55e9363f},
{0x5aa48619, 0x000006d1, 0x00000284, 0x928ead83, 0x31041c06},
{0xa609afa8, 0x0000053e, 0x00000272, 0xb048c141, 0x4704efba},
{0x3f108afb, 0x00000949, 0x00000150, 0x9a6bb5bc, 0x4e4430c8},
{0x79bec2d3, 0x000008ed, 0x00000712, 0x32692d57, 0x11d52a7b},
{0x9429e067, 0x00000bc3, 0x0000043c, 0x5295ceff, 0x04640f4d},
{0xae58b96a, 0x0000082d, 0x000007d2, 0xc2a681ba, 0xf7ca4a2c},
{0x95df24be, 0x00000985, 0x000004c1, 0x3a287765, 0x2c4af003},
{0x5e94976f, 0x00000596, 0x000004ed, 0xff00c489, 0x5ae11687},
{0xf5e5f1de, 0x00000d31, 0x000002ce, 0x35f28e91, 0x30d47957},
{0xa2c219cf, 0x00000a3c, 0x00000374, 0x707d21eb, 0x2a14a255},
{0xf21b6ceb, 0x00000919, 0x00000135, 0x0847fb8b, 0xcb8d3b93},
{0xaa988728, 0x00000787, 0x00000771, 0x885aeaa4, 0x6531b509},
{0xaa5dfaac, 0x000003e5, 0x0000051b, 0x52c48ab7, 0xe43cc5e9},
{0x0a053968, 0x00000d2a, 0x000002d5, 0x7a90256d, 0x8004765c},
{0x1421dc20, 0x00000eef, 0x00000110, 0x97d6da24, 0x1378f6ff},
{0xb47c2166, 0x00000a6a, 0x00000209, 0xcfd6cc52, 0x676e14a5},
{0x77dd1955, 0x000000de, 0x00000266, 0xba74bcaa, 0xc71b429c},
{0x68a03cc2, 0x0000082f, 0x000007b0, 0x752bd5d8, 0x19ed14aa},
{0x0226b0a3, 0x00000a5f, 0x000005a0, 0x82de4970, 0xf654d3ed},
{0x637bf3b1, 0x00000d93, 0x0000026c, 0x5c7115cb, 0x3cccb57e},
{0x3b120edf, 0x00000c13, 0x000003ec, 0x80d7d20f, 0x92132798},
{0xe2456780, 0x000002eb, 0x00000641, 0xc0a5d289, 0x6160c87a},
{0x9b2e7125, 0x00000c0c, 0x000003f3, 0xcc15f57e, 0x6f00f637},
{0x153033ef, 0x00000787, 0x000006b6, 0x3cde443b, 0xb46caa6e},
{0x18458b3f, 0x0000066c, 0x00000561, 0x9a2bd8c6, 0xb6c29121},
{0x4ff9d4b9, 0x00000c8f, 0x0000033a, 0xd0ee6d6d, 0xc81cf380},
{0xdf84b5d9, 0x00000802, 0x0000029a, 0xdab0d74a, 0xb2464559},
{0x81ee15df, 0x000003ce, 0x00000725, 0x9942e2de, 0x4ccf571b},
{0x5c768e04, 0x00000afd, 0x00000160, 0x36110831, 0xae0b305a},
{0xe5e18094, 0x00000b4b, 0x000000a0, 0xffa3e4a7, 0x6c8a4f09},
{0xed7263b6, 0x00000d0d, 0x000002f2, 0xb0006a35, 0x7e04af8c},
{0x5bfde7d7, 0x000006fb, 0x00000554, 0xa4193b76, 0xb3a91d12},
{0x67f4a743, 0x00000b85, 0x0000047a, 0xf05c8d8f, 0xfb472fdf},
{0xf13bdf22, 0x00000ff7, 0x00000008, 0x816351eb, 0xf347f235},
{0x08ecc608, 0x00000d5d, 0x00000098, 0x90492772, 0x0b7f1521},
{0x296f52ba, 0x000004f9, 0x00000788, 0x5e5a4896, 0x1cc67088},
{0xbe4624c2, 0x00000427, 0x000004ef, 0xcd267b94, 0x550caefd},
{0x906f7c7c, 0x00000a05, 0x0000003f, 0x03fcfc33, 0x9ed82a02},
{0x8f7b323e, 0x00000458, 0x000004c7, 0xcd4969c8, 0x633c38a8},
{0x88d6593d, 0x00000597, 0x000005b5, 0xf199cd3b, 0x0491452f},
{0x978a7768, 0x00000268, 0x000001d3, 0xb28c95bd, 0x1a42fe61},
{0x857a621e, 0x000007a7, 0x000003a8, 0xf4bf84ab, 0xcd0694c6},
{0xb0e121ef, 0x000005be, 0x00000644, 0x28747c14, 0xf0510c72},
{0, 0, 0, 0, 0},
};
static int test_crc32c(void)
{
struct crc_test *t = test;
int failures = 0;
while (t->length) {
uint32_t be, le;
le = ext2fs_crc32c_le(t->crc, test_buf + t->start, t->length);
be = ext2fs_crc32_be(t->crc, test_buf + t->start, t->length);
if (le != t->crc32c_le) {
printf("Test %d LE fails, %x != %x\n",
(int) (t - test), le, t->crc32c_le);
failures++;
}
if (be != t->crc32_be) {
printf("Test %d BE fails, %x != %x\n",
(int) (t - test), be, t->crc32_be);
failures++;
}
t++;
}
return failures;
}
int main(int argc, char *argv[])
{
int ret;
ret = test_crc32c();
if (!ret)
printf("No failures.\n");
return ret;
}
#endif /* UNITTEST */

59
src/ext2fs/crc32c_defs.h Normal file
View File

@ -0,0 +1,59 @@
/*
* There are multiple 16-bit CRC polynomials in common use, but this is
* *the* standard CRC-32 polynomial, first popularized by Ethernet.
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
*/
#define CRCPOLY_LE 0xedb88320
#define CRCPOLY_BE 0x04c11db7
/*
* This is the CRC32c polynomial, as outlined by Castagnoli.
* x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
* x^8+x^6+x^0
*/
#define CRC32C_POLY_LE 0x82F63B78
#define CRC32C_POLY_BE 0x1EDC6F41
/* How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. */
/* For less performance-sensitive, use 4 */
#ifndef CRC_LE_BITS
# define CRC_LE_BITS 64
#endif
#ifndef CRC_BE_BITS
# define CRC_BE_BITS 64
#endif
/*
* Little-endian CRC computation. Used with serial bit streams sent
* lsbit-first. Be sure to use cpu_to_le32() to append the computed CRC.
*/
#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \
CRC_LE_BITS & CRC_LE_BITS-1
# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
#endif
/*
* Big-endian CRC computation. Used with serial bit streams sent
* msbit-first. Be sure to use cpu_to_be32() to append the computed CRC.
*/
#if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \
CRC_BE_BITS & CRC_BE_BITS-1
# error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}"
#endif
#define ___constant_swab32(x) \
((uint32_t)( \
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24)))
#if (__GNUC__ >= 3)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif

1044
src/ext2fs/crc32c_table.h Normal file

File diff suppressed because it is too large Load Diff

1015
src/ext2fs/csum.c Normal file

File diff suppressed because it is too large Load Diff

311
src/ext2fs/dir_iterate.c Normal file
View File

@ -0,0 +1,311 @@
/*
* dir_iterate.c --- ext2fs directory iteration operations
*
* Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
#define EXT4_MAX_REC_LEN ((1<<16)-1)
errcode_t ext2fs_get_rec_len(ext2_filsys fs,
struct ext2_dir_entry *dirent,
unsigned int *rec_len)
{
unsigned int len = dirent->rec_len;
if (fs->blocksize < 65536)
*rec_len = len;
else if (len == EXT4_MAX_REC_LEN || len == 0)
*rec_len = fs->blocksize;
else
*rec_len = (len & 65532) | ((len & 3) << 16);
return 0;
}
errcode_t ext2fs_set_rec_len(ext2_filsys fs,
unsigned int len,
struct ext2_dir_entry *dirent)
{
if ((len > fs->blocksize) || (fs->blocksize > (1 << 18)) || (len & 3))
return EINVAL;
if (len < 65536) {
dirent->rec_len = len;
return 0;
}
if (len == fs->blocksize) {
if (fs->blocksize == 65536)
dirent->rec_len = EXT4_MAX_REC_LEN;
else
dirent->rec_len = 0;
} else
dirent->rec_len = (len & 65532) | ((len >> 16) & 3);
return 0;
}
/*
* This function checks to see whether or not a potential deleted
* directory entry looks valid. What we do is check the deleted entry
* and each successive entry to make sure that they all look valid and
* that the last deleted entry ends at the beginning of the next
* undeleted entry. Returns 1 if the deleted entry looks valid, zero
* if not valid.
*/
static int ext2fs_validate_entry(ext2_filsys fs, char *buf,
unsigned int offset,
unsigned int final_offset)
{
struct ext2_dir_entry *dirent;
unsigned int rec_len;
#define DIRENT_MIN_LENGTH 12
while ((offset < final_offset) &&
(offset <= fs->blocksize - DIRENT_MIN_LENGTH)) {
dirent = (struct ext2_dir_entry *)(buf + offset);
if (ext2fs_get_rec_len(fs, dirent, &rec_len))
return 0;
offset += rec_len;
if ((rec_len < 8) ||
((rec_len % 4) != 0) ||
((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len))
return 0;
}
return (offset == final_offset);
}
errcode_t ext2fs_dir_iterate2(ext2_filsys fs,
ext2_ino_t dir,
int flags,
char *block_buf,
int (*func)(ext2_ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data),
void *priv_data)
{
struct dir_context ctx;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;
ctx.dir = dir;
ctx.flags = flags;
if (block_buf)
ctx.buf = block_buf;
else {
retval = ext2fs_get_mem(fs->blocksize, &ctx.buf);
if (retval)
return retval;
}
ctx.func = func;
ctx.priv_data = priv_data;
ctx.errcode = 0;
retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY, 0,
ext2fs_process_dir_block, &ctx);
if (!block_buf)
ext2fs_free_mem(&ctx.buf);
if (retval == EXT2_ET_INLINE_DATA_CANT_ITERATE) {
(void) ext2fs_inline_data_dir_iterate(fs, dir, &ctx);
retval = 0;
}
if (retval)
return retval;
return ctx.errcode;
}
struct xlate {
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data);
void *real_private;
};
static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)),
int entry EXT2FS_ATTR((unused)),
struct ext2_dir_entry *dirent, int offset,
int blocksize, char *buf, void *priv_data)
{
struct xlate *xl = (struct xlate *) priv_data;
return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private);
}
errcode_t ext2fs_dir_iterate(ext2_filsys fs,
ext2_ino_t dir,
int flags,
char *block_buf,
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data),
void *priv_data)
{
struct xlate xl;
xl.real_private = priv_data;
xl.func = func;
return ext2fs_dir_iterate2(fs, dir, flags, block_buf,
xlate_func, &xl);
}
/*
* Helper function which is private to this module. Used by
* ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
*/
int ext2fs_process_dir_block(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t blockcnt,
blk64_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct dir_context *ctx = (struct dir_context *) priv_data;
unsigned int offset = 0;
unsigned int next_real_entry = 0;
int ret = 0;
int changed = 0;
int do_abort = 0;
unsigned int rec_len, size, buflen;
int entry;
struct ext2_dir_entry *dirent;
int csum_size = 0;
int inline_data;
errcode_t retval = 0;
if (blockcnt < 0)
return 0;
entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
/* If a dir has inline data, we don't need to read block */
inline_data = !!(ctx->flags & DIRENT_FLAG_INCLUDE_INLINE_DATA);
if (!inline_data) {
ctx->errcode = ext2fs_read_dir_block4(fs, *blocknr, ctx->buf, 0,
ctx->dir);
if (ctx->errcode)
return BLOCK_ABORT;
/* If we handle a normal dir, we traverse the entire block */
buflen = fs->blocksize;
} else {
buflen = ctx->buflen;
}
if (ext2fs_has_feature_metadata_csum(fs->super))
csum_size = sizeof(struct ext2_dir_entry_tail);
while (offset < buflen - 8) {
dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
if (ext2fs_get_rec_len(fs, dirent, &rec_len))
return BLOCK_ABORT;
if (((offset + rec_len) > buflen) ||
(rec_len < 8) ||
((rec_len % 4) != 0) ||
((ext2fs_dirent_name_len(dirent)+8) > (int) rec_len)) {
ctx->errcode = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
if (!dirent->inode) {
/*
* We just need to check metadata_csum when this
* dir hasn't inline data. That means that 'buflen'
* should be blocksize.
*/
if (!inline_data &&
(offset == buflen - csum_size) &&
(dirent->rec_len == csum_size) &&
(dirent->name_len == EXT2_DIR_NAME_LEN_CSUM)) {
if (!(ctx->flags & DIRENT_FLAG_INCLUDE_CSUM))
goto next;
entry = DIRENT_CHECKSUM;
} else if (!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
goto next;
}
ret = (ctx->func)(ctx->dir,
(next_real_entry > offset) ?
DIRENT_DELETED_FILE : entry,
dirent, offset,
buflen, ctx->buf,
ctx->priv_data);
if (entry < DIRENT_OTHER_FILE)
entry++;
if (ret & DIRENT_CHANGED) {
if (ext2fs_get_rec_len(fs, dirent, &rec_len))
return BLOCK_ABORT;
changed++;
}
if (ret & DIRENT_ABORT) {
do_abort++;
break;
}
next:
if (next_real_entry == offset)
next_real_entry += rec_len;
if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
size = (ext2fs_dirent_name_len(dirent) + 11) & ~3;
if (rec_len != size) {
unsigned int final_offset;
final_offset = offset + rec_len;
offset += size;
while (offset < final_offset &&
!ext2fs_validate_entry(fs, ctx->buf,
offset,
final_offset))
offset += 4;
continue;
}
}
offset += rec_len;
}
if (changed) {
if (!inline_data) {
ctx->errcode = ext2fs_write_dir_block4(fs, *blocknr,
ctx->buf,
0, ctx->dir);
if (ctx->errcode)
return BLOCK_ABORT;
} else {
/*
* return BLOCK_INLINE_DATA_CHANGED to notify caller
* that inline data has been changed.
*/
retval = BLOCK_INLINE_DATA_CHANGED;
}
}
if (do_abort)
return retval | BLOCK_ABORT;
return retval;
}

113
src/ext2fs/dirblock.c Normal file
View File

@ -0,0 +1,113 @@
/*
* dirblock.c --- directory block routines.
*
* Copyright (C) 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "ext2_fs.h"
#include "ext2fs.h"
errcode_t ext2fs_read_dir_block4(ext2_filsys fs, blk64_t block,
void *buf, int flags EXT2FS_ATTR((unused)),
ext2_ino_t ino)
{
errcode_t retval;
int corrupt = 0;
retval = io_channel_read_blk64(fs->io, block, 1, buf);
if (retval)
return retval;
if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
!ext2fs_dir_block_csum_verify(fs, ino,
(struct ext2_dir_entry *)buf))
corrupt = 1;
#ifdef WORDS_BIGENDIAN
retval = ext2fs_dirent_swab_in(fs, buf, flags);
#endif
if (!retval && corrupt)
retval = EXT2_ET_DIR_CSUM_INVALID;
return retval;
}
errcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
void *buf, int flags EXT2FS_ATTR((unused)))
{
return ext2fs_read_dir_block4(fs, block, buf, flags, 0);
}
errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
void *buf, int flags EXT2FS_ATTR((unused)))
{
return ext2fs_read_dir_block3(fs, block, buf, flags);
}
errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
void *buf)
{
return ext2fs_read_dir_block3(fs, block, buf, 0);
}
errcode_t ext2fs_write_dir_block4(ext2_filsys fs, blk64_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)),
ext2_ino_t ino)
{
errcode_t retval;
char *buf = inbuf;
#ifdef WORDS_BIGENDIAN
retval = ext2fs_get_mem(fs->blocksize, &buf);
if (retval)
return retval;
memcpy(buf, inbuf, fs->blocksize);
retval = ext2fs_dirent_swab_out(fs, buf, flags);
if (retval)
return retval;
#endif
retval = ext2fs_dir_block_csum_set(fs, ino,
(struct ext2_dir_entry *)buf);
if (retval)
goto out;
retval = io_channel_write_blk64(fs->io, block, 1, buf);
out:
#ifdef WORDS_BIGENDIAN
ext2fs_free_mem(&buf);
#endif
return retval;
}
errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)))
{
return ext2fs_write_dir_block4(fs, block, inbuf, flags, 0);
}
errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
void *inbuf, int flags EXT2FS_ATTR((unused)))
{
return ext2fs_write_dir_block3(fs, block, inbuf, flags);
}
errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *inbuf)
{
return ext2fs_write_dir_block3(fs, block, inbuf, 0);
}

37
src/ext2fs/e2image.h Normal file
View File

@ -0,0 +1,37 @@
/*
* e2image.h --- header file describing the ext2 image format
*
* Copyright (C) 2000 Theodore Ts'o.
*
* Note: this uses the POSIX IO interfaces, unlike most of the other
* functions in this library. So sue me.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
struct ext2_image_hdr {
__u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */
char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */
char fs_hostname[64];/* Hostname of machine of image */
char fs_netaddr[32]; /* Network address */
__u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */
__u32 fs_device; /* Device number of image */
char fs_device_name[64]; /* Device name */
char fs_uuid[16]; /* UUID of filesystem */
__u32 fs_blocksize; /* Block size of the filesystem */
__u32 fs_reserved[8];
__u32 image_device; /* Device number of image file */
__u32 image_inode; /* Inode number of image file */
__u32 image_time; /* Time of image creation */
__u32 image_reserved[8];
__u32 offset_super; /* Byte offset of the sb and descriptors */
__u32 offset_inode; /* Byte offset of the inode table */
__u32 offset_inodemap; /* Byte offset of the inode bitmaps */
__u32 offset_blockmap; /* Byte offset of the inode bitmaps */
__u32 offset_reserved[8];
};

197
src/ext2fs/ext2_err.h Normal file
View File

@ -0,0 +1,197 @@
/*
* ext2_err.h:
* This file is automatically generated; please do not edit it.
*/
#include "com_err.h"
#define EXT2_ET_BASE (2133571328L)
#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L)
#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L)
#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L)
#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L)
#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L)
#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L)
#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L)
#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L)
#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L)
#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L)
#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L)
#define EXT2_ET_MAGIC_DBLIST (2133571340L)
#define EXT2_ET_MAGIC_ICOUNT (2133571341L)
#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L)
#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L)
#define EXT2_ET_MAGIC_E2IMAGE (2133571344L)
#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L)
#define EXT2_ET_MAGIC_EXTENT_HANDLE (2133571346L)
#define EXT2_ET_BAD_MAGIC (2133571347L)
#define EXT2_ET_REV_TOO_HIGH (2133571348L)
#define EXT2_ET_RO_FILSYS (2133571349L)
#define EXT2_ET_GDESC_READ (2133571350L)
#define EXT2_ET_GDESC_WRITE (2133571351L)
#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L)
#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L)
#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L)
#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L)
#define EXT2_ET_INODE_BITMAP_READ (2133571356L)
#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L)
#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L)
#define EXT2_ET_INODE_TABLE_WRITE (2133571359L)
#define EXT2_ET_INODE_TABLE_READ (2133571360L)
#define EXT2_ET_NEXT_INODE_READ (2133571361L)
#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L)
#define EXT2_ET_DIR_CORRUPTED (2133571363L)
#define EXT2_ET_SHORT_READ (2133571364L)
#define EXT2_ET_SHORT_WRITE (2133571365L)
#define EXT2_ET_DIR_NO_SPACE (2133571366L)
#define EXT2_ET_NO_INODE_BITMAP (2133571367L)
#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L)
#define EXT2_ET_BAD_INODE_NUM (2133571369L)
#define EXT2_ET_BAD_BLOCK_NUM (2133571370L)
#define EXT2_ET_EXPAND_DIR_ERR (2133571371L)
#define EXT2_ET_TOOSMALL (2133571372L)
#define EXT2_ET_BAD_BLOCK_MARK (2133571373L)
#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L)
#define EXT2_ET_BAD_BLOCK_TEST (2133571375L)
#define EXT2_ET_BAD_INODE_MARK (2133571376L)
#define EXT2_ET_BAD_INODE_UNMARK (2133571377L)
#define EXT2_ET_BAD_INODE_TEST (2133571378L)
#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L)
#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L)
#define EXT2_ET_BAD_IND_BLOCK (2133571381L)
#define EXT2_ET_BAD_DIND_BLOCK (2133571382L)
#define EXT2_ET_BAD_TIND_BLOCK (2133571383L)
#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L)
#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L)
#define EXT2_ET_BAD_DEVICE_NAME (2133571386L)
#define EXT2_ET_MISSING_INODE_TABLE (2133571387L)
#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L)
#define EXT2_ET_BAD_GENERIC_MARK (2133571389L)
#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L)
#define EXT2_ET_BAD_GENERIC_TEST (2133571391L)
#define EXT2_ET_SYMLINK_LOOP (2133571392L)
#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L)
#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L)
#define EXT2_ET_UNSUPP_FEATURE (2133571395L)
#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L)
#define EXT2_ET_LLSEEK_FAILED (2133571397L)
#define EXT2_ET_NO_MEMORY (2133571398L)
#define EXT2_ET_INVALID_ARGUMENT (2133571399L)
#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L)
#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L)
#define EXT2_ET_NO_DIRECTORY (2133571402L)
#define EXT2_ET_TOO_MANY_REFS (2133571403L)
#define EXT2_ET_FILE_NOT_FOUND (2133571404L)
#define EXT2_ET_FILE_RO (2133571405L)
#define EXT2_ET_DB_NOT_FOUND (2133571406L)
#define EXT2_ET_DIR_EXISTS (2133571407L)
#define EXT2_ET_UNIMPLEMENTED (2133571408L)
#define EXT2_ET_CANCEL_REQUESTED (2133571409L)
#define EXT2_ET_FILE_TOO_BIG (2133571410L)
#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L)
#define EXT2_ET_NO_JOURNAL_SB (2133571412L)
#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L)
#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L)
#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L)
#define EXT2_ET_NO_JOURNAL (2133571416L)
#define EXT2_ET_DIRHASH_UNSUPP (2133571417L)
#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L)
#define EXT2_ET_TOO_MANY_INODES (2133571419L)
#define EXT2_ET_NOT_IMAGE_FILE (2133571420L)
#define EXT2_ET_RES_GDT_BLOCKS (2133571421L)
#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L)
#define EXT2_ET_SET_BMAP_NO_IND (2133571423L)
#define EXT2_ET_TDB_SUCCESS (2133571424L)
#define EXT2_ET_TDB_ERR_CORRUPT (2133571425L)
#define EXT2_ET_TDB_ERR_IO (2133571426L)
#define EXT2_ET_TDB_ERR_LOCK (2133571427L)
#define EXT2_ET_TDB_ERR_OOM (2133571428L)
#define EXT2_ET_TDB_ERR_EXISTS (2133571429L)
#define EXT2_ET_TDB_ERR_NOLOCK (2133571430L)
#define EXT2_ET_TDB_ERR_EINVAL (2133571431L)
#define EXT2_ET_TDB_ERR_NOEXIST (2133571432L)
#define EXT2_ET_TDB_ERR_RDONLY (2133571433L)
#define EXT2_ET_DBLIST_EMPTY (2133571434L)
#define EXT2_ET_RO_BLOCK_ITERATE (2133571435L)
#define EXT2_ET_MAGIC_EXTENT_PATH (2133571436L)
#define EXT2_ET_MAGIC_GENERIC_BITMAP64 (2133571437L)
#define EXT2_ET_MAGIC_BLOCK_BITMAP64 (2133571438L)
#define EXT2_ET_MAGIC_INODE_BITMAP64 (2133571439L)
#define EXT2_ET_MAGIC_RESERVED_13 (2133571440L)
#define EXT2_ET_MAGIC_RESERVED_14 (2133571441L)
#define EXT2_ET_MAGIC_RESERVED_15 (2133571442L)
#define EXT2_ET_MAGIC_RESERVED_16 (2133571443L)
#define EXT2_ET_MAGIC_RESERVED_17 (2133571444L)
#define EXT2_ET_MAGIC_RESERVED_18 (2133571445L)
#define EXT2_ET_MAGIC_RESERVED_19 (2133571446L)
#define EXT2_ET_EXTENT_HEADER_BAD (2133571447L)
#define EXT2_ET_EXTENT_INDEX_BAD (2133571448L)
#define EXT2_ET_EXTENT_LEAF_BAD (2133571449L)
#define EXT2_ET_EXTENT_NO_SPACE (2133571450L)
#define EXT2_ET_INODE_NOT_EXTENT (2133571451L)
#define EXT2_ET_EXTENT_NO_NEXT (2133571452L)
#define EXT2_ET_EXTENT_NO_PREV (2133571453L)
#define EXT2_ET_EXTENT_NO_UP (2133571454L)
#define EXT2_ET_EXTENT_NO_DOWN (2133571455L)
#define EXT2_ET_NO_CURRENT_NODE (2133571456L)
#define EXT2_ET_OP_NOT_SUPPORTED (2133571457L)
#define EXT2_ET_CANT_INSERT_EXTENT (2133571458L)
#define EXT2_ET_CANT_SPLIT_EXTENT (2133571459L)
#define EXT2_ET_EXTENT_NOT_FOUND (2133571460L)
#define EXT2_ET_EXTENT_NOT_SUPPORTED (2133571461L)
#define EXT2_ET_EXTENT_INVALID_LENGTH (2133571462L)
#define EXT2_ET_IO_CHANNEL_NO_SUPPORT_64 (2133571463L)
#define EXT2_ET_NO_MTAB_FILE (2133571464L)
#define EXT2_ET_CANT_USE_LEGACY_BITMAPS (2133571465L)
#define EXT2_ET_MMP_MAGIC_INVALID (2133571466L)
#define EXT2_ET_MMP_FAILED (2133571467L)
#define EXT2_ET_MMP_FSCK_ON (2133571468L)
#define EXT2_ET_MMP_BAD_BLOCK (2133571469L)
#define EXT2_ET_MMP_UNKNOWN_SEQ (2133571470L)
#define EXT2_ET_MMP_CHANGE_ABORT (2133571471L)
#define EXT2_ET_MMP_OPEN_DIRECT (2133571472L)
#define EXT2_ET_BAD_DESC_SIZE (2133571473L)
#define EXT2_ET_INODE_CSUM_INVALID (2133571474L)
#define EXT2_ET_INODE_BITMAP_CSUM_INVALID (2133571475L)
#define EXT2_ET_EXTENT_CSUM_INVALID (2133571476L)
#define EXT2_ET_DIR_NO_SPACE_FOR_CSUM (2133571477L)
#define EXT2_ET_DIR_CSUM_INVALID (2133571478L)
#define EXT2_ET_EXT_ATTR_CSUM_INVALID (2133571479L)
#define EXT2_ET_SB_CSUM_INVALID (2133571480L)
#define EXT2_ET_UNKNOWN_CSUM (2133571481L)
#define EXT2_ET_MMP_CSUM_INVALID (2133571482L)
#define EXT2_ET_FILE_EXISTS (2133571483L)
#define EXT2_ET_BLOCK_BITMAP_CSUM_INVALID (2133571484L)
#define EXT2_ET_INLINE_DATA_CANT_ITERATE (2133571485L)
#define EXT2_ET_EA_BAD_NAME_LEN (2133571486L)
#define EXT2_ET_EA_BAD_VALUE_SIZE (2133571487L)
#define EXT2_ET_BAD_EA_HASH (2133571488L)
#define EXT2_ET_BAD_EA_HEADER (2133571489L)
#define EXT2_ET_EA_KEY_NOT_FOUND (2133571490L)
#define EXT2_ET_EA_NO_SPACE (2133571491L)
#define EXT2_ET_MISSING_EA_FEATURE (2133571492L)
#define EXT2_ET_NO_INLINE_DATA (2133571493L)
#define EXT2_ET_INLINE_DATA_NO_BLOCK (2133571494L)
#define EXT2_ET_INLINE_DATA_NO_SPACE (2133571495L)
#define EXT2_ET_MAGIC_EA_HANDLE (2133571496L)
#define EXT2_ET_INODE_IS_GARBAGE (2133571497L)
#define EXT2_ET_EA_BAD_VALUE_OFFSET (2133571498L)
#define EXT2_ET_JOURNAL_FLAGS_WRONG (2133571499L)
#define EXT2_ET_UNDO_FILE_CORRUPT (2133571500L)
#define EXT2_ET_UNDO_FILE_WRONG (2133571501L)
#define EXT2_ET_FILESYSTEM_CORRUPTED (2133571502L)
#define EXT2_ET_BAD_CRC (2133571503L)
#define EXT2_ET_CORRUPT_JOURNAL_SB (2133571504L)
#define EXT2_ET_INODE_CORRUPTED (2133571505L)
#define EXT2_ET_EA_INODE_CORRUPTED (2133571506L)
extern const struct error_table et_ext2_error_table;
extern void initialize_ext2_error_table(void);
/* For compatibility with Heimdal */
extern void initialize_ext2_error_table_r(struct et_list **list);
#define ERROR_TABLE_BASE_ext2 (2133571328L)
/* for compatibility with older versions... */
#define init_ext2_err_tbl initialize_ext2_error_table
#define ext2_err_base ERROR_TABLE_BASE_ext2

View File

@ -0,0 +1,73 @@
/*
File: linux/ext2_ext_attr.h
On-disk format of extended attributes for the ext2 filesystem.
(C) 2000 Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/
#ifndef _EXT2_EXT_ATTR_H
#define _EXT2_EXT_ATTR_H
/* Magic value in attribute blocks */
#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000
#define EXT2_EXT_ATTR_MAGIC 0xEA020000
/* Maximum number of references to one attribute block */
#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024
struct ext2_ext_attr_header {
__u32 h_magic; /* magic number for identification */
__u32 h_refcount; /* reference count */
__u32 h_blocks; /* number of disk blocks used */
__u32 h_hash; /* hash value of all attributes */
__u32 h_checksum; /* crc32c(uuid+id+xattrs) */
/* id = inum if refcount = 1, else blknum */
__u32 h_reserved[3]; /* zero right now */
};
struct ext2_ext_attr_entry {
__u8 e_name_len; /* length of name */
__u8 e_name_index; /* attribute name index */
__u16 e_value_offs; /* offset in disk block of value */
__u32 e_value_inum; /* inode in which the value is stored */
__u32 e_value_size; /* size of attribute value */
__u32 e_hash; /* hash value of name and value */
#if 0
char e_name[0]; /* attribute name */
#endif
};
#define EXT2_EXT_ATTR_PAD_BITS 2
#define EXT2_EXT_ATTR_PAD ((unsigned) 1<<EXT2_EXT_ATTR_PAD_BITS)
#define EXT2_EXT_ATTR_ROUND (EXT2_EXT_ATTR_PAD-1)
#define EXT2_EXT_ATTR_LEN(name_len) \
(((name_len) + EXT2_EXT_ATTR_ROUND + \
sizeof(struct ext2_ext_attr_entry)) & ~EXT2_EXT_ATTR_ROUND)
#define EXT2_EXT_ATTR_NEXT(entry) \
( (struct ext2_ext_attr_entry *)( \
(char *)(entry) + EXT2_EXT_ATTR_LEN((entry)->e_name_len)) )
#define EXT2_EXT_ATTR_SIZE(size) \
(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL)
#define EXT2_EXT_ATTR_NAME(entry) \
(((char *) (entry)) + sizeof(struct ext2_ext_attr_entry))
#define EXT2_XATTR_LEN(name_len) \
(((name_len) + EXT2_EXT_ATTR_ROUND + \
sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND)
#define EXT2_XATTR_SIZE(size) \
(((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND)
#ifdef __KERNEL__
# ifdef CONFIG_EXT2_FS_EXT_ATTR
extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int);
extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int);
extern void ext2_ext_attr_free_inode(struct inode *inode);
extern void ext2_ext_attr_put_super(struct super_block *sb);
extern int ext2_ext_attr_init(void);
extern void ext2_ext_attr_done(void);
# else
# define ext2_get_ext_attr NULL
# define ext2_set_ext_attr NULL
# endif
#endif /* __KERNEL__ */
#endif /* _EXT2_EXT_ATTR_H */

1110
src/ext2fs/ext2_fs.h Normal file

File diff suppressed because it is too large Load Diff

169
src/ext2fs/ext2_io.h Normal file
View File

@ -0,0 +1,169 @@
/*
* io.h --- the I/O manager abstraction
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _EXT2FS_EXT2_IO_H
#define _EXT2FS_EXT2_IO_H
#include "ext2_types.h"
/*
* ext2_loff_t is defined here since unix_io.c needs it.
*/
#if defined(__GNUC__) || defined(HAS_LONG_LONG)
typedef long long ext2_loff_t;
#else
typedef long ext2_loff_t;
#endif
/* llseek.c */
ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int);
typedef struct struct_io_manager *io_manager;
typedef struct struct_io_channel *io_channel;
typedef struct struct_io_stats *io_stats;
#define CHANNEL_FLAGS_WRITETHROUGH 0x01
#define CHANNEL_FLAGS_DISCARD_ZEROES 0x02
#define CHANNEL_FLAGS_BLOCK_DEVICE 0x04
#define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES)
struct struct_io_channel {
errcode_t magic;
io_manager manager;
char *name;
int block_size;
errcode_t (*read_error)(io_channel channel,
unsigned long block,
int count,
void *data,
size_t size,
int actual_bytes_read,
errcode_t error);
errcode_t (*write_error)(io_channel channel,
unsigned long block,
int count,
const void *data,
size_t size,
int actual_bytes_written,
errcode_t error);
int refcount;
int flags;
long reserved[14];
void *private_data;
void *app_data;
int align;
};
struct struct_io_stats {
int num_fields;
int reserved;
unsigned long long bytes_read;
unsigned long long bytes_written;
};
struct struct_io_manager {
errcode_t magic;
const char *name;
errcode_t (*open)(const char *name, int flags, io_channel *channel);
errcode_t (*close)(io_channel channel);
errcode_t (*set_blksize)(io_channel channel, int blksize);
errcode_t (*read_blk)(io_channel channel, unsigned long block,
int count, void *data);
errcode_t (*write_blk)(io_channel channel, unsigned long block,
int count, const void *data);
errcode_t (*flush)(io_channel channel);
errcode_t (*write_byte)(io_channel channel, unsigned long offset,
int count, const void *data);
errcode_t (*set_option)(io_channel channel, const char *option,
const char *arg);
errcode_t (*get_stats)(io_channel channel, io_stats *io_stats);
errcode_t (*read_blk64)(io_channel channel, unsigned long long block,
int count, void *data);
errcode_t (*write_blk64)(io_channel channel, unsigned long long block,
int count, const void *data);
errcode_t (*discard)(io_channel channel, unsigned long long block,
unsigned long long count);
errcode_t (*cache_readahead)(io_channel channel,
unsigned long long block,
unsigned long long count);
errcode_t (*zeroout)(io_channel channel, unsigned long long block,
unsigned long long count);
long reserved[14];
};
#define IO_FLAG_RW 0x0001
#define IO_FLAG_EXCLUSIVE 0x0002
#define IO_FLAG_DIRECT_IO 0x0004
#define IO_FLAG_FORCE_BOUNCE 0x0008
/*
* Convenience functions....
*/
#define io_channel_close(c) ((c)->manager->close((c)))
#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s))
#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d))
#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
#define io_channel_flush(c) ((c)->manager->flush((c)))
#define io_channel_bumpcount(c) ((c)->refcount++)
/* io_manager.c */
extern errcode_t io_channel_set_options(io_channel channel,
const char *options);
extern errcode_t io_channel_write_byte(io_channel channel,
unsigned long offset,
int count, const void *data);
extern errcode_t io_channel_read_blk64(io_channel channel,
unsigned long long block,
int count, void *data);
extern errcode_t io_channel_write_blk64(io_channel channel,
unsigned long long block,
int count, const void *data);
extern errcode_t io_channel_discard(io_channel channel,
unsigned long long block,
unsigned long long count);
extern errcode_t io_channel_zeroout(io_channel channel,
unsigned long long block,
unsigned long long count);
extern errcode_t io_channel_alloc_buf(io_channel channel,
int count, void *ptr);
extern errcode_t io_channel_cache_readahead(io_channel io,
unsigned long long block,
unsigned long long count);
/* unix_io.c */
extern io_manager unix_io_manager;
extern io_manager unixfd_io_manager;
/* sparse_io.c */
extern io_manager sparse_io_manager;
extern io_manager sparsefd_io_manager;
/* undo_io.c */
extern io_manager undo_io_manager;
extern errcode_t set_undo_io_backing_manager(io_manager manager);
extern errcode_t set_undo_io_backup_file(char *file_name);
/* test_io.c */
extern io_manager test_io_manager, test_io_backing_manager;
extern void (*test_io_cb_read_blk)
(unsigned long block, int count, errcode_t err);
extern void (*test_io_cb_write_blk)
(unsigned long block, int count, errcode_t err);
extern void (*test_io_cb_read_blk64)
(unsigned long long block, int count, errcode_t err);
extern void (*test_io_cb_write_blk64)
(unsigned long long block, int count, errcode_t err);
extern void (*test_io_cb_set_blksize)
(int blksize, errcode_t err);
#endif /* _EXT2FS_EXT2_IO_H */

197
src/ext2fs/ext2_types.h Normal file
View File

@ -0,0 +1,197 @@
/*
* If linux/types.h is already been included, assume it has defined
* everything we need. (cross fingers) Other header files may have
* also defined the types that we need.
*/
#if (!defined(_LINUX_TYPES_H) && !defined(_BLKID_TYPES_H) && \
!defined(_EXT2_TYPES_H))
#define _EXT2_TYPES_H
#ifndef HAVE___U8
#define HAVE___U8
#ifdef __U8_TYPEDEF
typedef __U8_TYPEDEF __u8;
#else
typedef unsigned char __u8;
#endif
#endif /* HAVE___U8 */
#ifndef HAVE___S8
#define HAVE___S8
#ifdef __S8_TYPEDEF
typedef __S8_TYPEDEF __s8;
#else
typedef signed char __s8;
#endif
#endif /* HAVE___S8 */
#ifndef HAVE___U16
#define HAVE___U16
#ifdef __U16_TYPEDEF
typedef __U16_TYPEDEF __u16;
#else
#if (4 == 2)
typedef unsigned int __u16;
#else
#if (2 == 2)
typedef unsigned short __u16;
#else
#undef HAVE___U16
?==error: undefined 16 bit type
#endif /* SIZEOF_SHORT == 2 */
#endif /* SIZEOF_INT == 2 */
#endif /* __U16_TYPEDEF */
#endif /* HAVE___U16 */
#ifndef HAVE___S16
#define HAVE___S16
#ifdef __S16_TYPEDEF
typedef __S16_TYPEDEF __s16;
#else
#if (4 == 2)
typedef int __s16;
#else
#if (2 == 2)
typedef short __s16;
#else
#undef HAVE___S16
?==error: undefined 16 bit type
#endif /* SIZEOF_SHORT == 2 */
#endif /* SIZEOF_INT == 2 */
#endif /* __S16_TYPEDEF */
#endif /* HAVE___S16 */
#ifndef HAVE___U32
#define HAVE___U32
#ifdef __U32_TYPEDEF
typedef __U32_TYPEDEF __u32;
#else
#if (4 == 4)
typedef unsigned int __u32;
#else
#if (4 == 4)
typedef unsigned long __u32;
#else
#if (2 == 4)
typedef unsigned short __u32;
#else
#undef HAVE___U32
?== error: undefined 32 bit type
#endif /* SIZEOF_SHORT == 4 */
#endif /* SIZEOF_LONG == 4 */
#endif /* SIZEOF_INT == 4 */
#endif /* __U32_TYPEDEF */
#endif /* HAVE___U32 */
#ifndef HAVE___S32
#define HAVE___S32
#ifdef __S32_TYPEDEF
typedef __S32_TYPEDEF __s32;
#else
#if (4 == 4)
typedef int __s32;
#else
#if (4 == 4)
typedef long __s32;
#else
#if (2 == 4)
typedef short __s32;
#else
#undef HAVE___S32
?== error: undefined 32 bit type
#endif /* SIZEOF_SHORT == 4 */
#endif /* SIZEOF_LONG == 4 */
#endif /* SIZEOF_INT == 4 */
#endif /* __S32_TYPEDEF */
#endif /* HAVE___S32 */
#ifndef HAVE___U64
#define HAVE___U64
#ifdef __U64_TYPEDEF
typedef __U64_TYPEDEF __u64;
#else
#if (4 == 8)
typedef unsigned int __u64;
#else
#if (8 == 8)
typedef unsigned long long __u64;
#else
#if (4 == 8)
typedef unsigned long __u64;
#else
#undef HAVE___U64
?== error: undefined 64 bit type
#endif /* SIZEOF_LONG_LONG == 8 */
#endif /* SIZEOF_LONG == 8 */
#endif /* SIZEOF_INT == 8 */
#endif /* __U64_TYPEDEF */
#endif /* HAVE___U64 */
#ifndef HAVE___S64
#define HAVE___S64
#ifdef __S64_TYPEDEF
typedef __S64_TYPEDEF __s64;
#else
#if (4 == 8)
typedef int __s64;
#else
#if (8 == 8)
#if defined(__GNUC__)
typedef __signed__ long long __s64;
#else
typedef signed long long __s64;
#endif /* __GNUC__ */
#else
#if (4 == 8)
typedef long __s64;
#else
#undef HAVE___S64
?== error: undefined 64 bit type
#endif /* SIZEOF_LONG_LONG == 8 */
#endif /* SIZEOF_LONG == 8 */
#endif /* SIZEOF_INT == 8 */
#endif /* __S64_TYPEDEF */
#endif /* HAVE___S64 */
#undef __S8_TYPEDEF
#undef __U8_TYPEDEF
#undef __S16_TYPEDEF
#undef __U16_TYPEDEF
#undef __S32_TYPEDEF
#undef __U32_TYPEDEF
#undef __S64_TYPEDEF
#undef __U64_TYPEDEF
#endif /* _*_TYPES_H */
#include <stdint.h>
/* endian checking stuff */
#ifndef EXT2_ENDIAN_H_
#define EXT2_ENDIAN_H_
#ifdef __CHECKER__
# ifndef __bitwise
# define __bitwise __attribute__((bitwise))
# endif
#define __force __attribute__((force))
#else
# ifndef __bitwise
# define __bitwise
# endif
#define __force
#endif
typedef __u16 __bitwise __le16;
typedef __u32 __bitwise __le32;
typedef __u64 __bitwise __le64;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __be32;
typedef __u64 __bitwise __be64;
#endif /* EXT2_ENDIAN_H_ */
/* These defines are needed for the public ext2fs.h header file */
#define HAVE_SYS_TYPES_H 1
#undef WORDS_BIGENDIAN

2036
src/ext2fs/ext2fs.h Normal file

File diff suppressed because it is too large Load Diff

191
src/ext2fs/ext2fsP.h Normal file
View File

@ -0,0 +1,191 @@
/*
* ext2fsP.h --- private header file for ext2 library
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#include "ext2fs.h"
#define EXT2FS_MAX_NESTED_LINKS 8
static inline int ext2fsP_is_disk_device(mode_t mode)
{
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
return S_ISBLK(mode) || S_ISCHR(mode);
#else
return S_ISBLK(mode);
#endif
}
/*
* Badblocks list
*/
struct ext2_struct_u32_list {
int magic;
int num;
int size;
__u32 *list;
int badblocks_flags;
};
struct ext2_struct_u32_iterate {
int magic;
ext2_u32_list bb;
int ptr;
};
/*
* Directory block iterator definition
*/
struct ext2_struct_dblist {
int magic;
ext2_filsys fs;
unsigned long long size;
unsigned long long count;
int sorted;
struct ext2_db_entry2 * list;
};
/*
* For directory iterators
*/
struct dir_context {
ext2_ino_t dir;
int flags;
char *buf;
unsigned int buflen;
int (*func)(ext2_ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data);
void *priv_data;
errcode_t errcode;
};
/*
* Inode cache structure
*/
struct ext2_inode_cache {
void * buffer;
blk64_t buffer_blk;
int cache_last;
unsigned int cache_size;
int refcount;
struct ext2_inode_cache_ent *cache;
};
struct ext2_inode_cache_ent {
ext2_ino_t ino;
struct ext2_inode *inode;
};
/* Function prototypes */
extern int ext2fs_process_dir_block(ext2_filsys fs,
blk64_t *blocknr,
e2_blkcnt_t blockcnt,
blk64_t ref_block,
int ref_offset,
void *priv_data);
extern errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino);
extern errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino);
extern int ext2fs_inline_data_dir_iterate(ext2_filsys fs,
ext2_ino_t ino,
void *priv_data);
/* Generic numeric progress meter */
struct ext2fs_numeric_progress_struct {
__u64 max;
int log_max;
int skip_progress;
};
/*
* progress callback functions
*/
struct ext2fs_progress_ops {
void (*init)(ext2_filsys fs,
struct ext2fs_numeric_progress_struct * progress,
const char *label, __u64 max);
void (*update)(ext2_filsys fs,
struct ext2fs_numeric_progress_struct * progress,
__u64 val);
void (*close)(ext2_filsys fs,
struct ext2fs_numeric_progress_struct * progress,
const char *message);
};
extern struct ext2fs_progress_ops ext2fs_numeric_progress_ops;
extern void ext2fs_numeric_progress_init(ext2_filsys fs,
struct ext2fs_numeric_progress_struct * progress,
const char *label, __u64 max);
extern void ext2fs_numeric_progress_update(ext2_filsys fs,
struct ext2fs_numeric_progress_struct * progress,
__u64 val);
extern void ext2fs_numeric_progress_close(ext2_filsys fs,
struct ext2fs_numeric_progress_struct * progress,
const char *message);
/*
* 64-bit bitmap support
*/
extern errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
int type, __u64 start, __u64 end,
__u64 real_end,
const char * description,
ext2fs_generic_bitmap *bmap);
extern void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap);
extern errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest);
extern errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
__u64 new_end,
__u64 new_real_end);
extern errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
errcode_t neq,
__u64 end, __u64 *oend);
extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 arg);
extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 arg);
extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 arg);
extern errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, unsigned int num,
void *in);
extern errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bitmap,
__u64 start, unsigned int num,
void *out);
extern void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap,const char *func);
extern int ext2fs_mem_is_zero(const char *mem, size_t len);
extern int ext2fs_file_block_offset_too_big(ext2_filsys fs,
struct ext2_inode *inode,
blk64_t offset);
/* atexit support */
typedef void (*ext2_exit_fn)(void *);
errcode_t ext2fs_add_exit_fn(ext2_exit_fn fn, void *data);
errcode_t ext2fs_remove_exit_fn(ext2_exit_fn fn, void *data);
#define EXT2FS_BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2*!!(cond)]))

127
src/ext2fs/ext3_extents.h Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2003,2004 Cluster File Systems, Inc, info@clusterfs.com
* Written by Alex Tomas <alex@clusterfs.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _LINUX_EXT3_EXTENTS
#define _LINUX_EXT3_EXTENTS
/*
* ext3_inode has i_block array (total 60 bytes)
* first 4 bytes are used to store:
* - tree depth (0 mean there is no tree yet. all extents in the inode)
* - number of alive extents in the inode
*/
/*
* This is extent tail on-disk structure.
* All other extent structures are 12 bytes long. It turns out that
* block_size % 12 >= 4 for at least all powers of 2 greater than 512, which
* covers all valid ext4 block sizes. Therefore, this tail structure can be
* crammed into the end of the block without having to rebalance the tree.
*/
struct ext3_extent_tail {
__le32 et_checksum; /* crc32c(uuid+inum+extent_block) */
};
/*
* this is extent on-disk structure
* it's used at the bottom of the tree
*/
struct ext3_extent {
__le32 ee_block; /* first logical block extent covers */
__le16 ee_len; /* number of blocks covered by extent */
__le16 ee_start_hi; /* high 16 bits of physical block */
__le32 ee_start; /* low 32 bigs of physical block */
};
/*
* this is index on-disk structure
* it's used at all the levels, but the bottom
*/
struct ext3_extent_idx {
__le32 ei_block; /* index covers logical blocks from 'block' */
__le32 ei_leaf; /* pointer to the physical block of the next *
* level. leaf or next index could bet here */
__le16 ei_leaf_hi; /* high 16 bits of physical block */
__le16 ei_unused;
};
/*
* each block (leaves and indexes), even inode-stored has header
*/
struct ext3_extent_header {
__le16 eh_magic; /* probably will support different formats */
__le16 eh_entries; /* number of valid entries */
__le16 eh_max; /* capacity of store in entries */
__le16 eh_depth; /* has tree real underlying blocks? */
__le32 eh_generation; /* generation of the tree */
};
#define EXT3_EXT_MAGIC 0xf30a
/*
* array of ext3_ext_path contains path to some extent
* creation/lookup routines use it for traversal/splitting/etc
* truncate uses it to simulate recursive walking
*/
struct ext3_ext_path {
__u32 p_block;
__u16 p_depth;
struct ext3_extent *p_ext;
struct ext3_extent_idx *p_idx;
struct ext3_extent_header *p_hdr;
struct buffer_head *p_bh;
};
/*
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
* initialized extent. This is 2^15 and not (2^16 - 1), since we use the
* MSB of ee_len field in the extent datastructure to signify if this
* particular extent is an initialized extent or an uninitialized (i.e.
* preallocated).
* EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
* uninitialized extent.
* If ee_len is <= 0x8000, it is an initialized extent. Otherwise, it is an
* uninitialized one. In other words, if MSB of ee_len is set, it is an
* uninitialized extent with only one special scenario when ee_len = 0x8000.
* In this case we can not have an uninitialized extent of zero length and
* thus we make it as a special case of initialized extent with 0x8000 length.
* This way we get better extent-to-group alignment for initialized extents.
* Hence, the maximum number of blocks we can have in an *initialized*
* extent is 2^15 (32768) and in an *uninitialized* extent is 2^15-1 (32767).
*/
#define EXT_INIT_MAX_LEN (1UL << 15)
#define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
#define EXT_MAX_EXTENT_LBLK (((__u64) 1 << 32) - 1)
#define EXT_MAX_EXTENT_PBLK (((__u64) 1 << 48) - 1)
#define EXT_FIRST_EXTENT(__hdr__) \
((struct ext3_extent *) (((char *) (__hdr__)) + \
sizeof(struct ext3_extent_header)))
#define EXT_FIRST_INDEX(__hdr__) \
((struct ext3_extent_idx *) (((char *) (__hdr__)) + \
sizeof(struct ext3_extent_header)))
#define EXT_HAS_FREE_INDEX(__path__) \
(ext2fs_le16_to_cpu((__path__)->p_hdr->eh_entries) < \
ext2fs_le16_to_cpu((__path__)->p_hdr->eh_max))
#define EXT_LAST_EXTENT(__hdr__) \
(EXT_FIRST_EXTENT((__hdr__)) + \
ext2fs_le16_to_cpu((__hdr__)->eh_entries) - 1)
#define EXT_LAST_INDEX(__hdr__) \
(EXT_FIRST_INDEX((__hdr__)) + \
ext2fs_le16_to_cpu((__hdr__)->eh_entries) - 1)
#define EXT_MAX_EXTENT(__hdr__) \
(EXT_FIRST_EXTENT((__hdr__)) + \
ext2fs_le16_to_cpu((__hdr__)->eh_max) - 1)
#define EXT_MAX_INDEX(__hdr__) \
(EXT_FIRST_INDEX((__hdr__)) + \
ext2fs_le16_to_cpu((__hdr__)->eh_max) - 1)
#endif /* _LINUX_EXT3_EXTENTS */

55
src/ext2fs/ext4_acl.h Normal file
View File

@ -0,0 +1,55 @@
/*
* Ext4's on-disk acl format. From linux/fs/ext4/acl.h
*/
#define EXT4_ACL_VERSION 0x0001
/* 23.2.5 acl_tag_t values */
#define ACL_UNDEFINED_TAG (0x00)
#define ACL_USER_OBJ (0x01)
#define ACL_USER (0x02)
#define ACL_GROUP_OBJ (0x04)
#define ACL_GROUP (0x08)
#define ACL_MASK (0x10)
#define ACL_OTHER (0x20)
/* 23.3.6 acl_type_t values */
#define ACL_TYPE_ACCESS (0x8000)
#define ACL_TYPE_DEFAULT (0x4000)
/* 23.2.7 ACL qualifier constants */
#define ACL_UNDEFINED_ID ((id_t)-1)
typedef struct {
__le16 e_tag;
__le16 e_perm;
__le32 e_id;
} ext4_acl_entry;
typedef struct {
__le16 e_tag;
__le16 e_perm;
} ext4_acl_entry_short;
typedef struct {
__le32 a_version;
} ext4_acl_header;
/* Supported ACL a_version fields */
#define POSIX_ACL_XATTR_VERSION 0x0002
typedef struct {
__le16 e_tag;
__le16 e_perm;
__le32 e_id;
} posix_acl_xattr_entry;
typedef struct {
__le32 a_version;
posix_acl_xattr_entry a_entries[0];
} posix_acl_xattr_header;

1716
src/ext2fs/ext_attr.c Normal file

File diff suppressed because it is too large Load Diff

1747
src/ext2fs/extent.c Normal file

File diff suppressed because it is too large Load Diff

615
src/ext2fs/fileio.c Normal file
View File

@ -0,0 +1,615 @@
/*
* fileio.c --- Simple file I/O routines
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
struct ext2_file {
errcode_t magic;
ext2_filsys fs;
ext2_ino_t ino;
struct ext2_inode inode;
int flags;
__u64 pos;
blk64_t blockno;
blk64_t physblock;
char *buf;
};
#define BMAP_BUFFER (file->buf + fs->blocksize)
errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
int flags, ext2_file_t *ret)
{
ext2_file_t file;
errcode_t retval;
/*
* Don't let caller create or open a file for writing if the
* filesystem is read-only.
*/
if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
if (retval)
return retval;
memset(file, 0, sizeof(struct ext2_file));
file->magic = EXT2_ET_MAGIC_EXT2_FILE;
file->fs = fs;
file->ino = ino;
file->flags = flags & EXT2_FILE_MASK;
if (inode) {
memcpy(&file->inode, inode, sizeof(struct ext2_inode));
} else {
retval = ext2fs_read_inode(fs, ino, &file->inode);
if (retval)
goto fail;
}
retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
if (retval)
goto fail;
*ret = file;
return 0;
fail:
if (file->buf)
ext2fs_free_mem(&file->buf);
ext2fs_free_mem(&file);
return retval;
}
errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
int flags, ext2_file_t *ret)
{
return ext2fs_file_open2(fs, ino, NULL, flags, ret);
}
/*
* This function returns the filesystem handle of a file from the structure
*/
ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return 0;
return file->fs;
}
/*
* This function returns the pointer to the inode of a file from the structure
*/
struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return NULL;
return &file->inode;
}
/* This function returns the inode number from the structure */
ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return 0;
return file->ino;
}
/*
* This function flushes the dirty block buffer out to disk if
* necessary.
*/
errcode_t ext2fs_file_flush(ext2_file_t file)
{
errcode_t retval;
ext2_filsys fs;
int ret_flags;
blk64_t dontcare;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
if (!(file->flags & EXT2_FILE_BUF_VALID) ||
!(file->flags & EXT2_FILE_BUF_DIRTY))
return 0;
/* Is this an uninit block? */
if (file->physblock && file->inode.i_flags & EXT4_EXTENTS_FL) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode, BMAP_BUFFER,
0, file->blockno, &ret_flags, &dontcare);
if (retval)
return retval;
if (ret_flags & BMAP_RET_UNINIT) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER, BMAP_SET,
file->blockno, 0,
&file->physblock);
if (retval)
return retval;
}
}
/*
* OK, the physical block hasn't been allocated yet.
* Allocate it.
*/
if (!file->physblock) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
file->blockno, 0, &file->physblock);
if (retval)
return retval;
}
retval = io_channel_write_blk64(fs->io, file->physblock, 1, file->buf);
if (retval)
return retval;
file->flags &= ~EXT2_FILE_BUF_DIRTY;
return retval;
}
/*
* This function synchronizes the file's block buffer and the current
* file position, possibly invalidating block buffer if necessary
*/
static errcode_t sync_buffer_position(ext2_file_t file)
{
blk64_t b;
errcode_t retval;
b = file->pos / file->fs->blocksize;
if (b != file->blockno) {
retval = ext2fs_file_flush(file);
if (retval)
return retval;
file->flags &= ~EXT2_FILE_BUF_VALID;
}
file->blockno = b;
return 0;
}
/*
* This function loads the file's block buffer with valid data from
* the disk as necessary.
*
* If dontfill is true, then skip initializing the buffer since we're
* going to be replacing its entire contents anyway. If set, then the
* function basically only sets file->physblock and EXT2_FILE_BUF_VALID
*/
#define DONTFILL 1
static errcode_t load_buffer(ext2_file_t file, int dontfill)
{
ext2_filsys fs = file->fs;
errcode_t retval;
int ret_flags;
if (!(file->flags & EXT2_FILE_BUF_VALID)) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER, 0, file->blockno, &ret_flags,
&file->physblock);
if (retval)
return retval;
if (!dontfill) {
if (file->physblock &&
!(ret_flags & BMAP_RET_UNINIT)) {
retval = io_channel_read_blk64(fs->io,
file->physblock,
1, file->buf);
if (retval)
return retval;
} else
memset(file->buf, 0, fs->blocksize);
}
file->flags |= EXT2_FILE_BUF_VALID;
}
return 0;
}
errcode_t ext2fs_file_close(ext2_file_t file)
{
errcode_t retval;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
retval = ext2fs_file_flush(file);
if (file->buf)
ext2fs_free_mem(&file->buf);
ext2fs_free_mem(&file);
return retval;
}
static errcode_t
ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
unsigned int wanted, unsigned int *got)
{
ext2_filsys fs;
errcode_t retval;
unsigned int count = 0;
size_t size;
fs = file->fs;
retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
file->buf, &size);
if (retval)
return retval;
if (file->pos >= size)
goto out;
count = size - file->pos;
if (count > wanted)
count = wanted;
memcpy(buf, file->buf + file->pos, count);
file->pos += count;
buf = (char *) buf + count;
out:
if (got)
*got = count;
return retval;
}
errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
unsigned int wanted, unsigned int *got)
{
ext2_filsys fs;
errcode_t retval = 0;
unsigned int start, c, count = 0;
__u64 left;
char *ptr = (char *) buf;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
/* If an inode has inline data, things get complicated. */
if (file->inode.i_flags & EXT4_INLINE_DATA_FL)
return ext2fs_file_read_inline_data(file, buf, wanted, got);
while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
retval = sync_buffer_position(file);
if (retval)
goto fail;
retval = load_buffer(file, 0);
if (retval)
goto fail;
start = file->pos % fs->blocksize;
c = fs->blocksize - start;
if (c > wanted)
c = wanted;
left = EXT2_I_SIZE(&file->inode) - file->pos ;
if (c > left)
c = left;
memcpy(ptr, file->buf+start, c);
file->pos += c;
ptr += c;
count += c;
wanted -= c;
}
fail:
if (got)
*got = count;
return retval;
}
static errcode_t
ext2fs_file_write_inline_data(ext2_file_t file, const void *buf,
unsigned int nbytes, unsigned int *written)
{
ext2_filsys fs;
errcode_t retval;
unsigned int count = 0;
size_t size;
fs = file->fs;
retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
file->buf, &size);
if (retval)
return retval;
if (file->pos < size) {
count = nbytes - file->pos;
memcpy(file->buf + file->pos, buf, count);
retval = ext2fs_inline_data_set(fs, file->ino, &file->inode,
file->buf, count);
if (retval == EXT2_ET_INLINE_DATA_NO_SPACE)
goto expand;
if (retval)
return retval;
file->pos += count;
/* Update inode size */
if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
errcode_t rc;
rc = ext2fs_file_set_size2(file, file->pos);
if (retval == 0)
retval = rc;
}
if (written)
*written = count;
return 0;
}
expand:
retval = ext2fs_inline_data_expand(fs, file->ino);
if (retval)
return retval;
/*
* reload inode and return no space error
*
* XXX: file->inode could be copied from the outside
* in ext2fs_file_open2(). We have no way to modify
* the outside inode.
*/
retval = ext2fs_read_inode(fs, file->ino, &file->inode);
if (retval)
return retval;
return EXT2_ET_INLINE_DATA_NO_SPACE;
}
errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
unsigned int nbytes, unsigned int *written)
{
ext2_filsys fs;
errcode_t retval = 0;
unsigned int start, c, count = 0;
const char *ptr = (const char *) buf;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
if (!(file->flags & EXT2_FILE_WRITE))
return EXT2_ET_FILE_RO;
/* If an inode has inline data, things get complicated. */
if (file->inode.i_flags & EXT4_INLINE_DATA_FL) {
retval = ext2fs_file_write_inline_data(file, buf, nbytes,
written);
if (retval != EXT2_ET_INLINE_DATA_NO_SPACE)
return retval;
/* fall through to read data from the block */
retval = 0;
}
while (nbytes > 0) {
retval = sync_buffer_position(file);
if (retval)
goto fail;
start = file->pos % fs->blocksize;
c = fs->blocksize - start;
if (c > nbytes)
c = nbytes;
/*
* We only need to do a read-modify-update cycle if
* we're doing a partial write.
*/
retval = load_buffer(file, (c == fs->blocksize));
if (retval)
goto fail;
/*
* OK, the physical block hasn't been allocated yet.
* Allocate it.
*/
if (!file->physblock) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER,
file->ino ? BMAP_ALLOC : 0,
file->blockno, 0,
&file->physblock);
if (retval)
goto fail;
}
file->flags |= EXT2_FILE_BUF_DIRTY;
memcpy(file->buf+start, ptr, c);
file->pos += c;
ptr += c;
count += c;
nbytes -= c;
}
fail:
/* Update inode size */
if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
errcode_t rc;
rc = ext2fs_file_set_size2(file, file->pos);
if (retval == 0)
retval = rc;
}
if (written)
*written = count;
return retval;
}
errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
int whence, __u64 *ret_pos)
{
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
if (whence == EXT2_SEEK_SET)
file->pos = offset;
else if (whence == EXT2_SEEK_CUR)
file->pos += offset;
else if (whence == EXT2_SEEK_END)
file->pos = EXT2_I_SIZE(&file->inode) + offset;
else
return EXT2_ET_INVALID_ARGUMENT;
if (ret_pos)
*ret_pos = file->pos;
return 0;
}
errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
int whence, ext2_off_t *ret_pos)
{
__u64 loffset, ret_loffset = 0;
errcode_t retval;
loffset = offset;
retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
if (ret_pos)
*ret_pos = (ext2_off_t) ret_loffset;
return retval;
}
/*
* This function returns the size of the file, according to the inode
*/
errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return EXT2_ET_MAGIC_EXT2_FILE;
*ret_size = EXT2_I_SIZE(&file->inode);
return 0;
}
/*
* This function returns the size of the file, according to the inode
*/
ext2_off_t ext2fs_file_get_size(ext2_file_t file)
{
__u64 size;
if (ext2fs_file_get_lsize(file, &size))
return 0;
if ((size >> 32) != 0)
return 0;
return size;
}
/* Zero the parts of the last block that are past EOF. */
static errcode_t ext2fs_file_zero_past_offset(ext2_file_t file,
ext2_off64_t offset)
{
ext2_filsys fs = file->fs;
char *b = NULL;
ext2_off64_t off = offset % fs->blocksize;
blk64_t blk;
int ret_flags;
errcode_t retval;
if (off == 0)
return 0;
retval = sync_buffer_position(file);
if (retval)
return retval;
/* Is there an initialized block at the end? */
retval = ext2fs_bmap2(fs, file->ino, NULL, NULL, 0,
offset / fs->blocksize, &ret_flags, &blk);
if (retval)
return retval;
if ((blk == 0) || (ret_flags & BMAP_RET_UNINIT))
return 0;
/* Zero to the end of the block */
retval = ext2fs_get_mem(fs->blocksize, &b);
if (retval)
return retval;
/* Read/zero/write block */
retval = io_channel_read_blk64(fs->io, blk, 1, b);
if (retval)
goto out;
memset(b + off, 0, fs->blocksize - off);
retval = io_channel_write_blk64(fs->io, blk, 1, b);
if (retval)
goto out;
out:
ext2fs_free_mem(&b);
return retval;
}
/*
* This function sets the size of the file, truncating it if necessary
*
*/
errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size)
{
ext2_off64_t old_size;
errcode_t retval;
blk64_t old_truncate, truncate_block;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
if (size && ext2fs_file_block_offset_too_big(file->fs, &file->inode,
(size - 1) / file->fs->blocksize))
return EXT2_ET_FILE_TOO_BIG;
truncate_block = ((size + file->fs->blocksize - 1) >>
EXT2_BLOCK_SIZE_BITS(file->fs->super));
old_size = EXT2_I_SIZE(&file->inode);
old_truncate = ((old_size + file->fs->blocksize - 1) >>
EXT2_BLOCK_SIZE_BITS(file->fs->super));
retval = ext2fs_inode_size_set(file->fs, &file->inode, size);
if (retval)
return retval;
if (file->ino) {
retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
if (retval)
return retval;
}
retval = ext2fs_file_zero_past_offset(file, size);
if (retval)
return retval;
if (truncate_block >= old_truncate)
return 0;
return ext2fs_punch(file->fs, file->ino, &file->inode, 0,
truncate_block, ~0ULL);
}
errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
{
return ext2fs_file_set_size2(file, size);
}

104
src/ext2fs/freefs.c Normal file
View File

@ -0,0 +1,104 @@
/*
* freefs.c --- free an ext2 filesystem
*
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
void ext2fs_free(ext2_filsys fs)
{
if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS))
return;
if (fs->image_io != fs->io) {
if (fs->image_io)
io_channel_close(fs->image_io);
}
if (fs->io) {
io_channel_close(fs->io);
}
if (fs->device_name)
ext2fs_free_mem(&fs->device_name);
if (fs->super)
ext2fs_free_mem(&fs->super);
if (fs->orig_super)
ext2fs_free_mem(&fs->orig_super);
if (fs->group_desc)
ext2fs_free_mem(&fs->group_desc);
if (fs->block_map)
ext2fs_free_block_bitmap(fs->block_map);
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
if (fs->image_header)
ext2fs_free_mem(&fs->image_header);
if (fs->badblocks)
ext2fs_badblocks_list_free(fs->badblocks);
fs->badblocks = 0;
if (fs->dblist)
ext2fs_free_dblist(fs->dblist);
if (fs->icache)
ext2fs_free_inode_cache(fs->icache);
if (fs->mmp_buf)
ext2fs_free_mem(&fs->mmp_buf);
if (fs->mmp_cmp)
ext2fs_free_mem(&fs->mmp_cmp);
fs->magic = 0;
ext2fs_zero_blocks2(NULL, 0, 0, NULL, NULL);
ext2fs_free_mem(&fs);
}
/*
* This procedure frees a badblocks list.
*/
void ext2fs_u32_list_free(ext2_u32_list bb)
{
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return;
if (bb->list)
ext2fs_free_mem(&bb->list);
bb->list = 0;
ext2fs_free_mem(&bb);
}
void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
{
ext2fs_u32_list_free((ext2_u32_list) bb);
}
/*
* Free a directory block list
*/
void ext2fs_free_dblist(ext2_dblist dblist)
{
if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
return;
if (dblist->list)
ext2fs_free_mem(&dblist->list);
dblist->list = 0;
if (dblist->fs && dblist->fs->dblist == dblist)
dblist->fs->dblist = 0;
dblist->magic = 0;
ext2fs_free_mem(&dblist);
}

607
src/ext2fs/gen_bitmap.c Normal file
View File

@ -0,0 +1,607 @@
/*
* gen_bitmap.c --- Generic (32-bit) bitmap routines
*
* Copyright (C) 2001 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
struct ext2fs_struct_generic_bitmap {
errcode_t magic;
ext2_filsys fs;
__u32 start, end;
__u32 real_end;
char * description;
char * bitmap;
errcode_t base_error_code;
__u32 reserved[7];
};
#define EXT2FS_IS_32_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP))
#define EXT2FS_IS_64_BITMAP(bmap) \
(((bmap)->magic == EXT2_ET_MAGIC_GENERIC_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
/*
* Used by previously inlined function, so we have to export this and
* not change the function signature
*/
void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
int code, unsigned long arg)
{
#ifndef OMIT_COM_ERR
if (bitmap->description)
com_err(0, bitmap->base_error_code+code,
"#%lu for %s", arg, bitmap->description);
else
com_err(0, bitmap->base_error_code + code, "#%lu", arg);
#endif
}
static errcode_t check_magic(ext2fs_generic_bitmap bitmap)
{
if (!bitmap || !((bitmap->magic == EXT2_ET_MAGIC_GENERIC_BITMAP) ||
(bitmap->magic == EXT2_ET_MAGIC_INODE_BITMAP) ||
(bitmap->magic == EXT2_ET_MAGIC_BLOCK_BITMAP)))
return EXT2_ET_MAGIC_GENERIC_BITMAP;
return 0;
}
errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
__u32 start, __u32 end, __u32 real_end,
const char *descr, char *init_map,
ext2fs_generic_bitmap *ret)
{
ext2fs_generic_bitmap bitmap;
errcode_t retval;
size_t size;
retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
&bitmap);
if (retval)
return retval;
bitmap->magic = magic;
bitmap->fs = fs;
bitmap->start = start;
bitmap->end = end;
bitmap->real_end = real_end;
switch (magic) {
case EXT2_ET_MAGIC_INODE_BITMAP:
bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
break;
case EXT2_ET_MAGIC_BLOCK_BITMAP:
bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
break;
default:
bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
}
if (descr) {
retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
if (retval) {
ext2fs_free_mem(&bitmap);
return retval;
}
strcpy(bitmap->description, descr);
} else
bitmap->description = 0;
size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
/* Round up to allow for the BT x86 instruction */
size = (size + 7) & ~3;
retval = ext2fs_get_mem(size, &bitmap->bitmap);
if (retval) {
ext2fs_free_mem(&bitmap->description);
ext2fs_free_mem(&bitmap);
return retval;
}
if (init_map)
memcpy(bitmap->bitmap, init_map, size);
else
memset(bitmap->bitmap, 0, size);
*ret = bitmap;
return 0;
}
errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
__u32 end,
__u32 real_end,
const char *descr,
ext2fs_generic_bitmap *ret)
{
return ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_GENERIC_BITMAP, 0,
start, end, real_end, descr, 0, ret);
}
errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest)
{
return (ext2fs_make_generic_bitmap(src->magic, src->fs,
src->start, src->end,
src->real_end,
src->description, src->bitmap,
dest));
}
void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
{
if (check_magic(bitmap))
return;
bitmap->magic = 0;
if (bitmap->description) {
ext2fs_free_mem(&bitmap->description);
bitmap->description = 0;
}
if (bitmap->bitmap) {
ext2fs_free_mem(&bitmap->bitmap);
bitmap->bitmap = 0;
}
ext2fs_free_mem(&bitmap);
}
int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno)
{
if (!EXT2FS_IS_32_BITMAP(bitmap)) {
if (EXT2FS_IS_64_BITMAP(bitmap)) {
ext2fs_warn_bitmap32(bitmap, __func__);
return ext2fs_test_generic_bmap(bitmap, bitno);
}
#ifndef OMIT_COM_ERR
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"test_bitmap(%lu)", (unsigned long) bitno);
#endif
return 0;
}
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
return 0;
}
return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
}
int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno)
{
if (!EXT2FS_IS_32_BITMAP(bitmap)) {
if (EXT2FS_IS_64_BITMAP(bitmap)) {
ext2fs_warn_bitmap32(bitmap, __func__);
return ext2fs_mark_generic_bmap(bitmap, bitno);
}
#ifndef OMIT_COM_ERR
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"mark_bitmap(%lu)", (unsigned long) bitno);
#endif
return 0;
}
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
return 0;
}
return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap);
}
int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno)
{
if (!EXT2FS_IS_32_BITMAP(bitmap)) {
if (EXT2FS_IS_64_BITMAP(bitmap)) {
ext2fs_warn_bitmap32(bitmap, __func__);
return ext2fs_unmark_generic_bmap(bitmap, bitno);
}
#ifndef OMIT_COM_ERR
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"mark_bitmap(%lu)", (unsigned long) bitno);
#endif
return 0;
}
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
return 0;
}
return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap);
}
__u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap)
{
if (!EXT2FS_IS_32_BITMAP(bitmap)) {
if (EXT2FS_IS_64_BITMAP(bitmap)) {
ext2fs_warn_bitmap32(bitmap, __func__);
return ext2fs_get_generic_bmap_start(bitmap);
}
#ifndef OMIT_COM_ERR
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"get_bitmap_start");
#endif
return 0;
}
return bitmap->start;
}
__u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap)
{
if (!EXT2FS_IS_32_BITMAP(bitmap)) {
if (EXT2FS_IS_64_BITMAP(bitmap)) {
ext2fs_warn_bitmap32(bitmap, __func__);
return ext2fs_get_generic_bmap_end(bitmap);
}
#ifndef OMIT_COM_ERR
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"get_bitmap_end");
#endif
return 0;
}
return bitmap->end;
}
void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap)
{
if (!EXT2FS_IS_32_BITMAP(bitmap)) {
if (EXT2FS_IS_64_BITMAP(bitmap)) {
ext2fs_warn_bitmap32(bitmap, __func__);
ext2fs_clear_generic_bmap(bitmap);
return;
}
#ifndef OMIT_COM_ERR
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"clear_generic_bitmap");
#endif
return;
}
memset(bitmap->bitmap, 0,
(size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
}
errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
errcode_t magic, errcode_t neq,
ext2_ino_t end, ext2_ino_t *oend)
{
EXT2_CHECK_MAGIC(bitmap, magic);
if (end > bitmap->real_end)
return neq;
if (oend)
*oend = bitmap->end;
bitmap->end = end;
return 0;
}
errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
__u32 new_end, __u32 new_real_end,
ext2fs_generic_bitmap bmap)
{
errcode_t retval;
size_t size, new_size;
__u32 bitno;
if (!bmap || (bmap->magic != magic))
return magic;
/*
* If we're expanding the bitmap, make sure all of the new
* parts of the bitmap are zero.
*/
if (new_end > bmap->end) {
bitno = bmap->real_end;
if (bitno > new_end)
bitno = new_end;
for (; bitno > bmap->end; bitno--)
ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap);
}
if (new_real_end == bmap->real_end) {
bmap->end = new_end;
return 0;
}
size = ((bmap->real_end - bmap->start) / 8) + 1;
new_size = ((new_real_end - bmap->start) / 8) + 1;
if (size != new_size) {
retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap);
if (retval)
return retval;
}
if (new_size > size)
memset(bmap->bitmap + size, 0, new_size - size);
bmap->end = new_end;
bmap->real_end = new_real_end;
return 0;
}
errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
ext2fs_generic_bitmap bm1,
ext2fs_generic_bitmap bm2)
{
blk_t i;
if (!bm1 || bm1->magic != magic)
return magic;
if (!bm2 || bm2->magic != magic)
return magic;
if ((bm1->start != bm2->start) ||
(bm1->end != bm2->end) ||
(memcmp(bm1->bitmap, bm2->bitmap,
(size_t) (bm1->end - bm1->start)/8)))
return neq;
for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
if (ext2fs_fast_test_block_bitmap(bm1, i) !=
ext2fs_fast_test_block_bitmap(bm2, i))
return neq;
return 0;
}
void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map)
{
__u32 i, j;
/* Protect loop from wrap-around if map->real_end is maxed */
for (i=map->end+1, j = i - map->start;
i <= map->real_end && i > map->end;
i++, j++)
ext2fs_set_bit(j, map->bitmap);
}
errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
errcode_t magic,
__u32 start, __u32 num,
void *out)
{
if (!bmap || (bmap->magic != magic))
return magic;
if ((start < bmap->start) || (start+num-1 > bmap->real_end))
return EXT2_ET_INVALID_ARGUMENT;
memcpy(out, bmap->bitmap + (start >> 3), (num+7) >> 3);
return 0;
}
errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
errcode_t magic,
__u32 start, __u32 num,
void *in)
{
if (!bmap || (bmap->magic != magic))
return magic;
if ((start < bmap->start) || (start+num-1 > bmap->real_end))
return EXT2_ET_INVALID_ARGUMENT;
memcpy(bmap->bitmap + (start >> 3), in, (num+7) >> 3);
return 0;
}
/*
* Compare @mem to zero buffer by 256 bytes.
* Return 1 if @mem is zeroed memory, otherwise return 0.
*/
int ext2fs_mem_is_zero(const char *mem, size_t len)
{
static const char zero_buf[256];
while (len >= sizeof(zero_buf)) {
if (memcmp(mem, zero_buf, sizeof(zero_buf)))
return 0;
len -= sizeof(zero_buf);
mem += sizeof(zero_buf);
}
/* Deal with leftover bytes. */
if (len)
return !memcmp(mem, zero_buf, len);
return 1;
}
/*
* Return true if all of the bits in a specified range are clear
*/
static int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap bitmap,
unsigned int start,
unsigned int len)
{
size_t start_byte, len_byte = len >> 3;
unsigned int start_bit, len_bit = len % 8;
int first_bit = 0;
int last_bit = 0;
int mark_count = 0;
int mark_bit = 0;
int i;
const char *ADDR = bitmap->bitmap;
start -= bitmap->start;
start_byte = start >> 3;
start_bit = start % 8;
if (start_bit != 0) {
/*
* The compared start block number or start inode number
* is not the first bit in a byte.
*/
mark_count = 8 - start_bit;
if (len < 8 - start_bit) {
mark_count = (int)len;
mark_bit = len + start_bit - 1;
} else
mark_bit = 7;
for (i = mark_count; i > 0; i--, mark_bit--)
first_bit |= 1 << mark_bit;
/*
* Compare blocks or inodes in the first byte.
* If there is any marked bit, this function returns 0.
*/
if (first_bit & ADDR[start_byte])
return 0;
else if (len <= 8 - start_bit)
return 1;
start_byte++;
len_bit = (len - mark_count) % 8;
len_byte = (len - mark_count) >> 3;
}
/*
* The compared start block number or start inode number is
* the first bit in a byte.
*/
if (len_bit != 0) {
/*
* The compared end block number or end inode number is
* not the last bit in a byte.
*/
for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
last_bit |= 1 << mark_bit;
/*
* Compare blocks or inodes in the last byte.
* If there is any marked bit, this function returns 0.
*/
if (last_bit & ADDR[start_byte + len_byte])
return 0;
else if (len_byte == 0)
return 1;
}
/* Check whether all bytes are 0 */
return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
}
errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 start, __u32 end,
__u32 *out)
{
blk_t b;
if (start < bitmap->start || end > bitmap->end || start > end) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
return EINVAL;
}
while (start <= end) {
b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap);
if (!b) {
*out = start;
return 0;
}
start++;
}
return ENOENT;
}
errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 start, __u32 end,
__u32 *out)
{
blk_t b;
if (start < bitmap->start || end > bitmap->end || start > end) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
return EINVAL;
}
while (start <= end) {
b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap);
if (b) {
*out = start;
return 0;
}
start++;
}
return ENOENT;
}
int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
block, bitmap->description);
return 0;
}
return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
bitmap, block, num);
}
int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
ext2_ino_t inode, int num)
{
EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
if ((inode < bitmap->start) || (inode+num-1 > bitmap->real_end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
inode, bitmap->description);
return 0;
}
return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap)
bitmap, inode, num);
}
void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
bitmap->description);
return;
}
for (i=0; i < num; i++)
ext2fs_fast_set_bit(block + i - bitmap->start, bitmap->bitmap);
}
void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
bitmap->description);
return;
}
for (i=0; i < num; i++)
ext2fs_fast_clear_bit(block + i - bitmap->start,
bitmap->bitmap);
}

907
src/ext2fs/gen_bitmap64.c Normal file
View File

@ -0,0 +1,907 @@
/*
* gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and
* block bitmaps.
*
* Copyright (C) 2007, 2008 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
#include "bmap64.h"
/*
* Design of 64-bit bitmaps
*
* In order maintain ABI compatibility with programs that don't
* understand about 64-bit blocks/inodes,
* ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
* will create old-style bitmaps unless the application passes the
* flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is
* passed, then we know the application has been recompiled, so we can
* use the new-style bitmaps. If it is not passed, we have to return
* an error if trying to open a filesystem which needs 64-bit bitmaps.
*
* The new bitmaps use a new set of structure magic numbers, so that
* both the old-style and new-style interfaces can identify which
* version of the data structure was used. Both the old-style and
* new-style interfaces will support either type of bitmap, although
* of course 64-bit operation will only be possible when both the
* new-style interface and the new-style bitmap are used.
*
* For example, the new bitmap interfaces will check the structure
* magic numbers and so will be able to detect old-stype bitmap. If
* they see an old-style bitmap, they will pass it to the gen_bitmap.c
* functions for handling. The same will be true for the old
* interfaces as well.
*
* The new-style interfaces will have several different back-end
* implementations, so we can support different encodings that are
* appropriate for different applications. In general the default
* should be whatever makes sense, and what the application/library
* will use. However, e2fsck may need specialized implementations for
* its own uses. For example, when doing parent directory pointer
* loop detections in pass 3, the bitmap will *always* be sparse, so
* e2fsck can request an encoding which is optimized for that.
*/
static void warn_bitmap(ext2fs_generic_bitmap bitmap,
int code, __u64 arg)
{
#ifndef OMIT_COM_ERR
if (bitmap->description)
com_err(0, bitmap->base_error_code+code,
"#%llu for %s", arg, bitmap->description);
else
com_err(0, bitmap->base_error_code + code, "#%llu", arg);
#endif
}
#ifdef ENABLE_BMAP_STATS_OPS
#define INC_STAT(map, name) map->stats.name
#else
#define INC_STAT(map, name) ;;
#endif
errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
int type, __u64 start, __u64 end,
__u64 real_end,
const char *descr,
ext2fs_generic_bitmap *ret)
{
ext2fs_generic_bitmap bitmap;
struct ext2_bitmap_ops *ops;
ext2_ino_t num_dirs;
errcode_t retval;
if (!type)
type = EXT2FS_BMAP64_BITARRAY;
switch (type) {
case EXT2FS_BMAP64_BITARRAY:
ops = &ext2fs_blkmap64_bitarray;
break;
case EXT2FS_BMAP64_RBTREE:
ops = &ext2fs_blkmap64_rbtree;
break;
case EXT2FS_BMAP64_AUTODIR:
retval = ext2fs_get_num_dirs(fs, &num_dirs);
if (retval || num_dirs > (fs->super->s_inodes_count / 320))
ops = &ext2fs_blkmap64_bitarray;
else
ops = &ext2fs_blkmap64_rbtree;
break;
default:
return EINVAL;
}
retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap),
&bitmap);
if (retval)
return retval;
#ifdef ENABLE_BMAP_STATS
if (gettimeofday(&bitmap->stats.created,
(struct timezone *) NULL) == -1) {
perror("gettimeofday");
ext2fs_free_mem(&bitmap);
return 1;
}
bitmap->stats.type = type;
#endif
/* XXX factor out, repeated in copy_bmap */
bitmap->magic = magic;
bitmap->fs = fs;
bitmap->start = start;
bitmap->end = end;
bitmap->real_end = real_end;
bitmap->bitmap_ops = ops;
bitmap->cluster_bits = 0;
switch (magic) {
case EXT2_ET_MAGIC_INODE_BITMAP64:
bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
break;
case EXT2_ET_MAGIC_BLOCK_BITMAP64:
bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
bitmap->cluster_bits = fs->cluster_ratio_bits;
break;
default:
bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
}
if (descr) {
retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
if (retval) {
ext2fs_free_mem(&bitmap);
return retval;
}
strcpy(bitmap->description, descr);
} else
bitmap->description = 0;
retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
if (retval) {
ext2fs_free_mem(&bitmap->description);
ext2fs_free_mem(&bitmap);
return retval;
}
*ret = bitmap;
return 0;
}
#ifdef ENABLE_BMAP_STATS
static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
{
struct ext2_bmap_statistics *stats = &bitmap->stats;
#ifdef ENABLE_BMAP_STATS_OPS
float mark_seq_perc = 0.0, test_seq_perc = 0.0;
float mark_back_perc = 0.0, test_back_perc = 0.0;
#endif
double inuse;
struct timeval now;
#ifdef ENABLE_BMAP_STATS_OPS
if (stats->test_count) {
test_seq_perc = ((float)stats->test_seq /
stats->test_count) * 100;
test_back_perc = ((float)stats->test_back /
stats->test_count) * 100;
}
if (stats->mark_count) {
mark_seq_perc = ((float)stats->mark_seq /
stats->mark_count) * 100;
mark_back_perc = ((float)stats->mark_back /
stats->mark_count) * 100;
}
#endif
if (gettimeofday(&now, (struct timezone *) NULL) == -1) {
perror("gettimeofday");
return;
}
inuse = (double) now.tv_sec + \
(((double) now.tv_usec) * 0.000001);
inuse -= (double) stats->created.tv_sec + \
(((double) stats->created.tv_usec) * 0.000001);
fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description,
stats->type);
fprintf(stderr, "=================================================\n");
#ifdef ENABLE_BMAP_STATS_OPS
fprintf(stderr, "%16llu bits long\n",
bitmap->real_end - bitmap->start);
fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n",
stats->copy_count, stats->resize_count);
fprintf(stderr, "%16lu mark bmap\n%16lu unmark_bmap\n",
stats->mark_count, stats->unmark_count);
fprintf(stderr, "%16lu test_bmap\n%16lu mark_bmap_extent\n",
stats->test_count, stats->mark_ext_count);
fprintf(stderr, "%16lu unmark_bmap_extent\n"
"%16lu test_clear_bmap_extent\n",
stats->unmark_ext_count, stats->test_ext_count);
fprintf(stderr, "%16lu set_bmap_range\n%16lu set_bmap_range\n",
stats->set_range_count, stats->get_range_count);
fprintf(stderr, "%16lu clear_bmap\n%16lu contiguous bit test (%.2f%%)\n",
stats->clear_count, stats->test_seq, test_seq_perc);
fprintf(stderr, "%16lu contiguous bit mark (%.2f%%)\n"
"%16llu bits tested backwards (%.2f%%)\n",
stats->mark_seq, mark_seq_perc,
stats->test_back, test_back_perc);
fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n"
"%16.2f seconds in use\n",
stats->mark_back, mark_back_perc, inuse);
#endif /* ENABLE_BMAP_STATS_OPS */
}
#endif
void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap)
{
if (!bmap)
return;
if (EXT2FS_IS_32_BITMAP(bmap)) {
ext2fs_free_generic_bitmap(bmap);
return;
}
if (!EXT2FS_IS_64_BITMAP(bmap))
return;
#ifdef ENABLE_BMAP_STATS
if (getenv("E2FSPROGS_BITMAP_STATS")) {
ext2fs_print_bmap_statistics(bmap);
bmap->bitmap_ops->print_stats(bmap);
}
#endif
bmap->bitmap_ops->free_bmap(bmap);
if (bmap->description) {
ext2fs_free_mem(&bmap->description);
bmap->description = 0;
}
bmap->magic = 0;
ext2fs_free_mem(&bmap);
}
errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
ext2fs_generic_bitmap *dest)
{
char *descr, *new_descr;
ext2fs_generic_bitmap new_bmap;
errcode_t retval;
if (!src)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(src))
return ext2fs_copy_generic_bitmap(src, dest);
if (!EXT2FS_IS_64_BITMAP(src))
return EINVAL;
/* Allocate a new bitmap struct */
retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap),
&new_bmap);
if (retval)
return retval;
#ifdef ENABLE_BMAP_STATS_OPS
src->stats.copy_count++;
#endif
#ifdef ENABLE_BMAP_STATS
if (gettimeofday(&new_bmap->stats.created,
(struct timezone *) NULL) == -1) {
perror("gettimeofday");
ext2fs_free_mem(&new_bmap);
return 1;
}
new_bmap->stats.type = src->stats.type;
#endif
/* Copy all the high-level parts over */
new_bmap->magic = src->magic;
new_bmap->fs = src->fs;
new_bmap->start = src->start;
new_bmap->end = src->end;
new_bmap->real_end = src->real_end;
new_bmap->bitmap_ops = src->bitmap_ops;
new_bmap->base_error_code = src->base_error_code;
new_bmap->cluster_bits = src->cluster_bits;
descr = src->description;
if (descr) {
retval = ext2fs_get_mem(strlen(descr)+10, &new_descr);
if (retval) {
ext2fs_free_mem(&new_bmap);
return retval;
}
strcpy(new_descr, "copy of ");
strcat(new_descr, descr);
new_bmap->description = new_descr;
}
retval = src->bitmap_ops->copy_bmap(src, new_bmap);
if (retval) {
ext2fs_free_mem(&new_bmap->description);
ext2fs_free_mem(&new_bmap);
return retval;
}
*dest = new_bmap;
return 0;
}
errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
__u64 new_end,
__u64 new_real_end)
{
if (!bmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bmap))
return ext2fs_resize_generic_bitmap(bmap->magic, new_end,
new_real_end, bmap);
if (!EXT2FS_IS_64_BITMAP(bmap))
return EINVAL;
INC_STAT(bmap, resize_count);
return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
}
errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
errcode_t neq,
__u64 end, __u64 *oend)
{
if (!bitmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bitmap)) {
ext2_ino_t tmp_oend;
int retval;
retval = ext2fs_fudge_generic_bitmap_end(bitmap, bitmap->magic,
neq, end, &tmp_oend);
if (oend)
*oend = tmp_oend;
return retval;
}
if (!EXT2FS_IS_64_BITMAP(bitmap))
return EINVAL;
if (end > bitmap->real_end)
return neq;
if (oend)
*oend = bitmap->end;
bitmap->end = end;
return 0;
}
__u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
{
if (!bitmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bitmap))
return ext2fs_get_generic_bitmap_start(bitmap);
if (!EXT2FS_IS_64_BITMAP(bitmap))
return EINVAL;
return bitmap->start;
}
__u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
{
if (!bitmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bitmap))
return ext2fs_get_generic_bitmap_end(bitmap);
if (!EXT2FS_IS_64_BITMAP(bitmap))
return EINVAL;
return bitmap->end;
}
void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap)
{
if (EXT2FS_IS_32_BITMAP(bitmap))
ext2fs_clear_generic_bitmap(bitmap);
else
bitmap->bitmap_ops->clear_bmap (bitmap);
}
int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 arg)
{
if (!bitmap)
return 0;
if (EXT2FS_IS_32_BITMAP(bitmap)) {
if (arg & ~0xffffffffULL) {
ext2fs_warn_bitmap2(bitmap,
EXT2FS_MARK_ERROR, 0xffffffff);
return 0;
}
return ext2fs_mark_generic_bitmap(bitmap, arg);
}
if (!EXT2FS_IS_64_BITMAP(bitmap))
return 0;
arg >>= bitmap->cluster_bits;
#ifdef ENABLE_BMAP_STATS_OPS
if (arg == bitmap->stats.last_marked + 1)
bitmap->stats.mark_seq++;
if (arg < bitmap->stats.last_marked)
bitmap->stats.mark_back++;
bitmap->stats.last_marked = arg;
bitmap->stats.mark_count++;
#endif
if ((arg < bitmap->start) || (arg > bitmap->end)) {
warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg);
return 0;
}
return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
}
int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 arg)
{
if (!bitmap)
return 0;
if (EXT2FS_IS_32_BITMAP(bitmap)) {
if (arg & ~0xffffffffULL) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR,
0xffffffff);
return 0;
}
return ext2fs_unmark_generic_bitmap(bitmap, arg);
}
if (!EXT2FS_IS_64_BITMAP(bitmap))
return 0;
arg >>= bitmap->cluster_bits;
INC_STAT(bitmap, unmark_count);
if ((arg < bitmap->start) || (arg > bitmap->end)) {
warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
return 0;
}
return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
}
int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 arg)
{
if (!bitmap)
return 0;
if (EXT2FS_IS_32_BITMAP(bitmap)) {
if (arg & ~0xffffffffULL) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR,
0xffffffff);
return 0;
}
return ext2fs_test_generic_bitmap(bitmap, arg);
}
if (!EXT2FS_IS_64_BITMAP(bitmap))
return 0;
arg >>= bitmap->cluster_bits;
#ifdef ENABLE_BMAP_STATS_OPS
bitmap->stats.test_count++;
if (arg == bitmap->stats.last_tested + 1)
bitmap->stats.test_seq++;
if (arg < bitmap->stats.last_tested)
bitmap->stats.test_back++;
bitmap->stats.last_tested = arg;
#endif
if ((arg < bitmap->start) || (arg > bitmap->end)) {
warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
return 0;
}
return bitmap->bitmap_ops->test_bmap(bitmap, arg);
}
errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
__u64 start, unsigned int num,
void *in)
{
if (!bmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bmap)) {
if ((start+num-1) & ~0xffffffffULL) {
ext2fs_warn_bitmap2(bmap, EXT2FS_UNMARK_ERROR,
0xffffffff);
return EINVAL;
}
return ext2fs_set_generic_bitmap_range(bmap, bmap->magic,
start, num, in);
}
if (!EXT2FS_IS_64_BITMAP(bmap))
return EINVAL;
INC_STAT(bmap, set_range_count);
return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
}
errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
__u64 start, unsigned int num,
void *out)
{
if (!bmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bmap)) {
if ((start+num-1) & ~0xffffffffULL) {
ext2fs_warn_bitmap2(bmap,
EXT2FS_UNMARK_ERROR, 0xffffffff);
return EINVAL;
}
return ext2fs_get_generic_bitmap_range(bmap, bmap->magic,
start, num, out);
}
if (!EXT2FS_IS_64_BITMAP(bmap))
return EINVAL;
INC_STAT(bmap, get_range_count);
return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
}
errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
ext2fs_generic_bitmap bm1,
ext2fs_generic_bitmap bm2)
{
blk64_t i;
if (!bm1 || !bm2)
return EINVAL;
if (bm1->magic != bm2->magic)
return EINVAL;
/* Now we know both bitmaps have the same magic */
if (EXT2FS_IS_32_BITMAP(bm1))
return ext2fs_compare_generic_bitmap(bm1->magic, neq, bm1, bm2);
if (!EXT2FS_IS_64_BITMAP(bm1))
return EINVAL;
if ((bm1->start != bm2->start) ||
(bm1->end != bm2->end))
return neq;
for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
if (ext2fs_test_generic_bmap(bm1, i) !=
ext2fs_test_generic_bmap(bm2, i))
return neq;
return 0;
}
void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
{
__u64 start, num;
if (EXT2FS_IS_32_BITMAP(bmap)) {
ext2fs_set_generic_bitmap_padding(bmap);
return;
}
start = bmap->end + 1;
num = bmap->real_end - bmap->end;
bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
/* XXX ought to warn on error */
}
int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t block, unsigned int num)
{
__u64 end = block + num;
if (!bmap)
return EINVAL;
if (num == 1)
return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
bmap, block);
if (EXT2FS_IS_32_BITMAP(bmap)) {
if ((block+num-1) & ~0xffffffffULL) {
ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
EXT2FS_UNMARK_ERROR, 0xffffffff);
return EINVAL;
}
return ext2fs_test_block_bitmap_range(
(ext2fs_generic_bitmap) bmap, block, num);
}
if (!EXT2FS_IS_64_BITMAP(bmap))
return EINVAL;
INC_STAT(bmap, test_ext_count);
/* convert to clusters if necessary */
block >>= bmap->cluster_bits;
end += (1 << bmap->cluster_bits) - 1;
end >>= bmap->cluster_bits;
num = end - block;
if ((block < bmap->start) || (block+num-1 > bmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block,
bmap->description);
return EINVAL;
}
return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
}
void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t block, unsigned int num)
{
__u64 end = block + num;
if (!bmap)
return;
if (EXT2FS_IS_32_BITMAP(bmap)) {
if ((block+num-1) & ~0xffffffffULL) {
ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
EXT2FS_UNMARK_ERROR, 0xffffffff);
return;
}
ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
block, num);
}
if (!EXT2FS_IS_64_BITMAP(bmap))
return;
INC_STAT(bmap, mark_ext_count);
/* convert to clusters if necessary */
block >>= bmap->cluster_bits;
end += (1 << bmap->cluster_bits) - 1;
end >>= bmap->cluster_bits;
num = end - block;
if ((block < bmap->start) || (block+num-1 > bmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
bmap->description);
return;
}
bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
}
void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
blk64_t block, unsigned int num)
{
__u64 end = block + num;
if (!bmap)
return;
if (EXT2FS_IS_32_BITMAP(bmap)) {
if ((block+num-1) & ~0xffffffffULL) {
ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
EXT2FS_UNMARK_ERROR, 0xffffffff);
return;
}
ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
block, num);
}
if (!EXT2FS_IS_64_BITMAP(bmap))
return;
INC_STAT(bmap, unmark_ext_count);
/* convert to clusters if necessary */
block >>= bmap->cluster_bits;
end += (1 << bmap->cluster_bits) - 1;
end >>= bmap->cluster_bits;
num = end - block;
if ((block < bmap->start) || (block+num-1 > bmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
bmap->description);
return;
}
bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
}
void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
{
#ifndef OMIT_COM_ERR
if (bitmap && bitmap->description)
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"called %s with 64-bit bitmap for %s", func,
bitmap->description);
else
com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
"called %s with 64-bit bitmap", func);
#endif
}
errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
ext2fs_block_bitmap *bitmap)
{
ext2fs_block_bitmap cmap, bmap;
errcode_t retval;
blk64_t i, b_end, c_end;
int n, ratio;
bmap = *bitmap;
if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(bmap))
return 0; /* Nothing to do */
retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap",
&cmap);
if (retval)
return retval;
i = bmap->start;
b_end = bmap->end;
bmap->end = bmap->real_end;
c_end = cmap->end;
cmap->end = cmap->real_end;
n = 0;
ratio = 1 << fs->cluster_ratio_bits;
while (i < bmap->real_end) {
if (ext2fs_test_block_bitmap2(bmap, i)) {
ext2fs_mark_block_bitmap2(cmap, i);
i += ratio - n;
n = 0;
continue;
}
i++; n++;
if (n >= ratio)
n = 0;
}
bmap->end = b_end;
cmap->end = c_end;
ext2fs_free_block_bitmap(bmap);
*bitmap = cmap;
return 0;
}
errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
__u64 cstart, cend, cout;
errcode_t retval;
if (!bitmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bitmap)) {
blk_t blk = 0;
if (((start) & ~0xffffffffULL) ||
((end) & ~0xffffffffULL)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
return EINVAL;
}
retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start,
end, &blk);
if (retval == 0)
*out = blk;
return retval;
}
if (!EXT2FS_IS_64_BITMAP(bitmap))
return EINVAL;
cstart = start >> bitmap->cluster_bits;
cend = end >> bitmap->cluster_bits;
if (cstart < bitmap->start || cend > bitmap->end || start > end) {
warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
return EINVAL;
}
if (bitmap->bitmap_ops->find_first_zero) {
retval = bitmap->bitmap_ops->find_first_zero(bitmap, cstart,
cend, &cout);
if (retval)
return retval;
found:
cout <<= bitmap->cluster_bits;
*out = (cout >= start) ? cout : start;
return 0;
}
for (cout = cstart; cout <= cend; cout++)
if (!bitmap->bitmap_ops->test_bmap(bitmap, cout))
goto found;
return ENOENT;
}
errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
__u64 start, __u64 end, __u64 *out)
{
__u64 cstart, cend, cout;
errcode_t retval;
if (!bitmap)
return EINVAL;
if (EXT2FS_IS_32_BITMAP(bitmap)) {
blk_t blk = 0;
if (((start) & ~0xffffffffULL) ||
((end) & ~0xffffffffULL)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
return EINVAL;
}
retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
end, &blk);
if (retval == 0)
*out = blk;
return retval;
}
if (!EXT2FS_IS_64_BITMAP(bitmap))
return EINVAL;
cstart = start >> bitmap->cluster_bits;
cend = end >> bitmap->cluster_bits;
if (cstart < bitmap->start || cend > bitmap->end || start > end) {
warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
return EINVAL;
}
if (bitmap->bitmap_ops->find_first_set) {
retval = bitmap->bitmap_ops->find_first_set(bitmap, cstart,
cend, &cout);
if (retval)
return retval;
found:
cout <<= bitmap->cluster_bits;
*out = (cout >= start) ? cout : start;
return 0;
}
for (cout = cstart; cout <= cend; cout++)
if (bitmap->bitmap_ops->test_bmap(bitmap, cout))
goto found;
return ENOENT;
}

50
src/ext2fs/get_num_dirs.c Normal file
View File

@ -0,0 +1,50 @@
/*
* get_num_dirs.c -- calculate number of directories
*
* Copyright 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "ext2_fs.h"
#include "ext2fsP.h"
/*
* Returns the number of directories in the filesystem as reported by
* the group descriptors. Of course, the group descriptors could be
* wrong!
*/
errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs)
{
dgrp_t i;
ext2_ino_t num_dirs, max_dirs;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
num_dirs = 0;
max_dirs = fs->super->s_inodes_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
if (ext2fs_bg_used_dirs_count(fs, i) > max_dirs)
num_dirs += max_dirs / 8;
else
num_dirs += ext2fs_bg_used_dirs_count(fs, i);
}
if (num_dirs > fs->super->s_inodes_count)
num_dirs = fs->super->s_inodes_count;
*ret_num_dirs = num_dirs;
return 0;
}

90
src/ext2fs/i_block.c Normal file
View File

@ -0,0 +1,90 @@
/*
* i_block.c --- Manage the i_block field for i_blocks
*
* Copyright (C) 2008 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <string.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <errno.h>
#include "ext2_fs.h"
#include "ext2fs.h"
errcode_t ext2fs_iblk_add_blocks(ext2_filsys fs, struct ext2_inode *inode,
blk64_t num_blocks)
{
unsigned long long b = inode->i_blocks;
if (ext2fs_has_feature_huge_file(fs->super))
b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
if (!ext2fs_has_feature_huge_file(fs->super) ||
!(inode->i_flags & EXT4_HUGE_FILE_FL))
num_blocks *= fs->blocksize / 512;
num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
b += num_blocks;
if (ext2fs_has_feature_huge_file(fs->super))
inode->osd2.linux2.l_i_blocks_hi = b >> 32;
else if (b > 0xFFFFFFFF)
return EOVERFLOW;
inode->i_blocks = b & 0xFFFFFFFF;
return 0;
}
errcode_t ext2fs_iblk_sub_blocks(ext2_filsys fs, struct ext2_inode *inode,
blk64_t num_blocks)
{
unsigned long long b = inode->i_blocks;
if (ext2fs_has_feature_huge_file(fs->super))
b += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
if (!ext2fs_has_feature_huge_file(fs->super) ||
!(inode->i_flags & EXT4_HUGE_FILE_FL))
num_blocks *= fs->blocksize / 512;
num_blocks *= EXT2FS_CLUSTER_RATIO(fs);
if (num_blocks > b)
return EOVERFLOW;
b -= num_blocks;
if (ext2fs_has_feature_huge_file(fs->super))
inode->osd2.linux2.l_i_blocks_hi = b >> 32;
inode->i_blocks = b & 0xFFFFFFFF;
return 0;
}
errcode_t ext2fs_iblk_set(ext2_filsys fs, struct ext2_inode *inode, blk64_t b)
{
if (!ext2fs_has_feature_huge_file(fs->super) ||
!(inode->i_flags & EXT4_HUGE_FILE_FL))
b *= fs->blocksize / 512;
b *= EXT2FS_CLUSTER_RATIO(fs);
inode->i_blocks = b & 0xFFFFFFFF;
if (ext2fs_has_feature_huge_file(fs->super))
inode->osd2.linux2.l_i_blocks_hi = b >> 32;
else if (b >> 32)
return EOVERFLOW;
return 0;
}

67
src/ext2fs/ind_block.c Normal file
View File

@ -0,0 +1,67 @@
/*
* ind_block.c --- indirect block I/O routines
*
* Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
* 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf)
{
errcode_t retval;
#ifdef WORDS_BIGENDIAN
blk_t *block_nr;
int i;
int limit = fs->blocksize >> 2;
#endif
if ((fs->flags & EXT2_FLAG_IMAGE_FILE) &&
(fs->io != fs->image_io))
memset(buf, 0, fs->blocksize);
else {
retval = io_channel_read_blk(fs->io, blk, 1, buf);
if (retval)
return retval;
}
#ifdef WORDS_BIGENDIAN
block_nr = (blk_t *) buf;
for (i = 0; i < limit; i++, block_nr++)
*block_nr = ext2fs_swab32(*block_nr);
#endif
return 0;
}
errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf)
{
#ifdef WORDS_BIGENDIAN
blk_t *block_nr;
int i;
int limit = fs->blocksize >> 2;
#endif
if (fs->flags & EXT2_FLAG_IMAGE_FILE)
return 0;
#ifdef WORDS_BIGENDIAN
block_nr = (blk_t *) buf;
for (i = 0; i < limit; i++, block_nr++)
*block_nr = ext2fs_swab32(*block_nr);
#endif
return io_channel_write_blk(fs->io, blk, 1, buf);
}

575
src/ext2fs/initialize.c Normal file
View File

@ -0,0 +1,575 @@
/*
* initialize.c --- initialize a filesystem handle given superblock
* parameters. Used by mke2fs when initializing a filesystem.
*
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#if defined(__linux__) && defined(EXT2_OS_LINUX)
#define CREATOR_OS EXT2_OS_LINUX
#else
#if defined(__GNU__) && defined(EXT2_OS_HURD)
#define CREATOR_OS EXT2_OS_HURD
#else
#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD)
#define CREATOR_OS EXT2_OS_FREEBSD
#else
#if defined(LITES) && defined(EXT2_OS_LITES)
#define CREATOR_OS EXT2_OS_LITES
#else
#define CREATOR_OS EXT2_OS_LINUX /* by default */
#endif /* defined(LITES) && defined(EXT2_OS_LITES) */
#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */
#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */
#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */
/*
* Calculate the number of GDT blocks to reserve for online filesystem growth.
* The absolute maximum number of GDT blocks we can reserve is determined by
* the number of block pointers that can fit into a single block.
*/
static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs)
{
struct ext2_super_block *sb = fs->super;
unsigned long bpg = sb->s_blocks_per_group;
unsigned int gdpb = EXT2_DESC_PER_BLOCK(sb);
unsigned long max_blocks = 0xffffffff;
unsigned long rsv_groups;
unsigned int rsv_gdb;
/* We set it at 1024x the current filesystem size, or
* the upper block count limit (2^32), whichever is lower.
*/
if (ext2fs_blocks_count(sb) < max_blocks / 1024)
max_blocks = ext2fs_blocks_count(sb) * 1024;
/*
* ext2fs_div64_ceil() is unnecessary because max_blocks is
* max _GDT_ blocks, which is limited to 32 bits.
*/
rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg);
rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks;
if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
#ifdef RES_GDT_DEBUG
printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %u\n",
max_blocks, rsv_groups, rsv_gdb);
#endif
return rsv_gdb;
}
errcode_t ext2fs_initialize(const char *name, int flags,
struct ext2_super_block *param,
io_manager manager, ext2_filsys *ret_fs)
{
ext2_filsys fs;
errcode_t retval;
struct ext2_super_block *super;
unsigned int rem;
unsigned int overhead = 0;
unsigned int ipg;
dgrp_t i;
blk64_t free_blocks;
blk_t numblocks;
int rsv_gdt;
int csum_flag;
int bigalloc_flag;
int io_flags;
int has_bg;
unsigned reserved_inos;
char *buf = 0;
char c;
double reserved_ratio;
char *time_env;
if (!name || !param || !ext2fs_blocks_count(param)) {
com_err("ext2fs_initialize", EXT2_ET_INVALID_ARGUMENT, "invalid argument");
return EXT2_ET_INVALID_ARGUMENT;
}
if (!name || !param || !ext2fs_blocks_count(param)) {
com_err("ext2fs_initialize", EXT2_ET_INVALID_ARGUMENT, "invalid argument");
return EXT2_ET_INVALID_ARGUMENT;
}
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
if (retval)
return retval;
memset(fs, 0, sizeof(struct struct_ext2_filsys));
fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
fs->flags = flags | EXT2_FLAG_RW;
fs->umask = 022;
fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
#ifdef WORDS_BIGENDIAN
fs->flags |= EXT2_FLAG_SWAP_BYTES;
#endif
time_env = getenv("E2FSPROGS_FAKE_TIME");
if (time_env)
fs->now = strtoul(time_env, NULL, 0);
io_flags = IO_FLAG_RW;
if (flags & EXT2_FLAG_EXCLUSIVE)
io_flags |= IO_FLAG_EXCLUSIVE;
if (flags & EXT2_FLAG_DIRECT_IO)
io_flags |= IO_FLAG_DIRECT_IO;
io_flags |= O_BINARY;
retval = manager->open(name, io_flags, &fs->io);
if (retval)
goto cleanup;
fs->image_io = fs->io;
fs->io->app_data = fs;
retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
if (retval)
goto cleanup;
strcpy(fs->device_name, name);
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super);
if (retval)
goto cleanup;
fs->super = super;
memset(super, 0, SUPERBLOCK_SIZE);
#define set_field(field, default) (super->field = param->field ? \
param->field : (default))
#define assign_field(field) (super->field = param->field)
super->s_magic = EXT2_SUPER_MAGIC;
super->s_state = EXT2_VALID_FS;
bigalloc_flag = ext2fs_has_feature_bigalloc(param);
assign_field(s_log_block_size);
if (bigalloc_flag) {
set_field(s_log_cluster_size, super->s_log_block_size+4);
if (super->s_log_block_size > super->s_log_cluster_size) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
} else
super->s_log_cluster_size = super->s_log_block_size;
set_field(s_first_data_block, super->s_log_cluster_size ? 0 : 1);
set_field(s_max_mnt_count, 0);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
set_field(s_feature_compat, 0);
set_field(s_feature_incompat, 0);
set_field(s_feature_ro_compat, 0);
set_field(s_default_mount_opts, 0);
set_field(s_first_meta_bg, 0);
set_field(s_raid_stride, 0); /* default stride size: 0 */
set_field(s_raid_stripe_width, 0); /* default stripe width: 0 */
set_field(s_log_groups_per_flex, 0);
set_field(s_flags, 0);
assign_field(s_backup_bgs[0]);
assign_field(s_backup_bgs[1]);
if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
retval = EXT2_ET_UNSUPP_FEATURE;
goto cleanup;
}
if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
retval = EXT2_ET_RO_UNSUPP_FEATURE;
goto cleanup;
}
set_field(s_rev_level, EXT2_GOOD_OLD_REV);
if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE);
if (super->s_inode_size >= sizeof(struct ext2_inode_large)) {
int extra_isize = sizeof(struct ext2_inode_large) -
EXT2_GOOD_OLD_INODE_SIZE;
set_field(s_min_extra_isize, extra_isize);
set_field(s_want_extra_isize, extra_isize);
}
} else {
super->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
super->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
}
set_field(s_checkinterval, 0);
super->s_mkfs_time = super->s_lastcheck = fs->now ? fs->now : time(NULL);
super->s_creator_os = CREATOR_OS;
fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(super);
fs->cluster_ratio_bits = super->s_log_cluster_size -
super->s_log_block_size;
if (bigalloc_flag) {
unsigned long long bpg;
if (param->s_blocks_per_group &&
param->s_clusters_per_group &&
((param->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs)) !=
param->s_blocks_per_group)) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
if (param->s_clusters_per_group)
assign_field(s_clusters_per_group);
else if (param->s_blocks_per_group)
super->s_clusters_per_group =
param->s_blocks_per_group /
EXT2FS_CLUSTER_RATIO(fs);
else if (super->s_log_cluster_size + 15 < 32)
super->s_clusters_per_group = fs->blocksize * 8;
else
super->s_clusters_per_group = (fs->blocksize - 1) * 8;
if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super))
super->s_clusters_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super);
bpg = EXT2FS_C2B(fs,
(unsigned long long) super->s_clusters_per_group);
if (bpg >= (((unsigned long long) 1) << 32)) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
super->s_blocks_per_group = bpg;
} else {
set_field(s_blocks_per_group, fs->blocksize * 8);
if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
super->s_clusters_per_group = super->s_blocks_per_group;
}
ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) &
~((blk64_t) EXT2FS_CLUSTER_MASK(fs)));
ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param));
if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
set_field(s_mmp_update_interval, 0);
/*
* If we're creating an external journal device, we don't need
* to bother with the rest.
*/
if (ext2fs_has_feature_journal_dev(super)) {
fs->group_desc_count = 0;
ext2fs_mark_super_dirty(fs);
*ret_fs = fs;
return 0;
}
retry:
fs->group_desc_count = (dgrp_t) ext2fs_div64_ceil(
ext2fs_blocks_count(super) - super->s_first_data_block,
EXT2_BLOCKS_PER_GROUP(super));
if (fs->group_desc_count == 0) {
retval = EXT2_ET_TOOSMALL;
goto cleanup;
}
set_field(s_desc_size,
ext2fs_has_feature_64bit(super) ?
EXT2_MIN_DESC_SIZE_64BIT : 0);
fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
EXT2_DESC_PER_BLOCK(super));
i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
if (ext2fs_has_feature_64bit(super) &&
(ext2fs_blocks_count(super) / i) > (1ULL << 32))
set_field(s_inodes_count, ~0U);
else
set_field(s_inodes_count, ext2fs_blocks_count(super) / i);
/*
* Make sure we have at least EXT2_FIRST_INO + 1 inodes, so
* that we have enough inodes for the filesystem(!)
*/
if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1)
super->s_inodes_count = EXT2_FIRST_INODE(super)+1;
/*
* There should be at least as many inodes as the user
* requested. Figure out how many inodes per group that
* should be. But make sure that we don't allocate more than
* one bitmap's worth of inodes each group.
*/
ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count);
if (ipg > fs->blocksize * 8) {
if (!bigalloc_flag && super->s_blocks_per_group >= 256) {
/* Try again with slightly different parameters */
super->s_blocks_per_group -= 8;
ext2fs_blocks_count_set(super,
ext2fs_blocks_count(param));
super->s_clusters_per_group = super->s_blocks_per_group;
goto retry;
} else {
retval = EXT2_ET_TOO_MANY_INODES;
goto cleanup;
}
}
if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super))
ipg = EXT2_MAX_INODES_PER_GROUP(super);
ipg_retry:
super->s_inodes_per_group = ipg;
/*
* Make sure the number of inodes per group completely fills
* the inode table blocks in the descriptor. If not, add some
* additional inodes/group. Waste not, want not...
*/
fs->inode_blocks_per_group = (((super->s_inodes_per_group *
EXT2_INODE_SIZE(super)) +
EXT2_BLOCK_SIZE(super) - 1) /
EXT2_BLOCK_SIZE(super));
super->s_inodes_per_group = ((fs->inode_blocks_per_group *
EXT2_BLOCK_SIZE(super)) /
EXT2_INODE_SIZE(super));
/*
* Finally, make sure the number of inodes per group is a
* multiple of 8. This is needed to simplify the bitmap
* splicing code.
*/
if (super->s_inodes_per_group < 8)
super->s_inodes_per_group = 8;
super->s_inodes_per_group &= ~7;
fs->inode_blocks_per_group = (((super->s_inodes_per_group *
EXT2_INODE_SIZE(super)) +
EXT2_BLOCK_SIZE(super) - 1) /
EXT2_BLOCK_SIZE(super));
/*
* adjust inode count to reflect the adjusted inodes_per_group
*/
if ((__u64)super->s_inodes_per_group * fs->group_desc_count > ~0U) {
ipg--;
goto ipg_retry;
}
super->s_inodes_count = super->s_inodes_per_group *
fs->group_desc_count;
super->s_free_inodes_count = super->s_inodes_count;
/*
* check the number of reserved group descriptor table blocks
*/
if (ext2fs_has_feature_resize_inode(super))
rsv_gdt = calc_reserved_gdt_blocks(fs);
else
rsv_gdt = 0;
set_field(s_reserved_gdt_blocks, rsv_gdt);
if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) {
retval = EXT2_ET_RES_GDT_BLOCKS;
goto cleanup;
}
/*
* Calculate the maximum number of bookkeeping blocks per
* group. It includes the superblock, the block group
* descriptors, the block bitmap, the inode bitmap, the inode
* table, and the reserved gdt blocks.
*/
overhead = (int) (3 + fs->inode_blocks_per_group +
super->s_reserved_gdt_blocks);
/* Enable meta_bg if we'd lose more than 3/4 of a BG to GDT blocks. */
if (super->s_reserved_gdt_blocks + fs->desc_blocks >
super->s_blocks_per_group * 3 / 4)
ext2fs_set_feature_meta_bg(fs->super);
if (ext2fs_has_feature_meta_bg(fs->super))
overhead++;
else
overhead += fs->desc_blocks;
/* This can only happen if the user requested too many inodes */
if (overhead > super->s_blocks_per_group) {
retval = EXT2_ET_TOO_MANY_INODES;
goto cleanup;
}
/*
* See if the last group is big enough to support the
* necessary data structures. If not, we need to get rid of
* it. We need to recalculate the overhead for the last block
* group, since it might or might not have a superblock
* backup.
*/
overhead = (int) (2 + fs->inode_blocks_per_group);
has_bg = 0;
if (ext2fs_has_feature_sparse_super2(super)) {
/*
* We have to do this manually since
* super->s_backup_bgs hasn't been set up yet.
*/
if (fs->group_desc_count == 2)
has_bg = param->s_backup_bgs[0] != 0;
else
has_bg = param->s_backup_bgs[1] != 0;
} else
has_bg = ext2fs_bg_has_super(fs, fs->group_desc_count - 1);
if (has_bg)
overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks;
rem = ((ext2fs_blocks_count(super) - super->s_first_data_block) %
super->s_blocks_per_group);
if ((fs->group_desc_count == 1) && rem && (rem < overhead)) {
retval = EXT2_ET_TOOSMALL;
goto cleanup;
}
if (rem && (rem < overhead+50)) {
ext2fs_blocks_count_set(super, ext2fs_blocks_count(super) -
rem);
/*
* If blocks count is changed, we need to recalculate
* reserved blocks count not to exceed 50%.
*/
reserved_ratio = 100.0 * ext2fs_r_blocks_count(param) /
ext2fs_blocks_count(param);
ext2fs_r_blocks_count_set(super, reserved_ratio *
ext2fs_blocks_count(super) / 100.0);
goto retry;
}
/*
* At this point we know how big the filesystem will be. So
* we can do any and all allocations that depend on the block
* count.
*/
/* Set up the locations of the backup superblocks */
if (ext2fs_has_feature_sparse_super2(super)) {
if (super->s_backup_bgs[0] >= fs->group_desc_count)
super->s_backup_bgs[0] = fs->group_desc_count - 1;
if (super->s_backup_bgs[1] >= fs->group_desc_count)
super->s_backup_bgs[1] = fs->group_desc_count - 1;
if (super->s_backup_bgs[0] == super->s_backup_bgs[1])
super->s_backup_bgs[1] = 0;
if (super->s_backup_bgs[0] > super->s_backup_bgs[1]) {
__u32 t = super->s_backup_bgs[0];
super->s_backup_bgs[0] = super->s_backup_bgs[1];
super->s_backup_bgs[1] = t;
}
}
retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
if (retval)
goto cleanup;
strcpy(buf, "block bitmap for ");
strcat(buf, fs->device_name);
retval = ext2fs_allocate_subcluster_bitmap(fs, buf, &fs->block_map);
if (retval)
goto cleanup;
strcpy(buf, "inode bitmap for ");
strcat(buf, fs->device_name);
retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
if (retval)
goto cleanup;
ext2fs_free_mem(&buf);
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&fs->group_desc);
if (retval)
goto cleanup;
memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
/*
* Reserve the superblock and group descriptors for each
* group, and fill in the correct group statistics for group.
* Note that although the block bitmap, inode bitmap, and
* inode table have not been allocated (and in fact won't be
* by this routine), they are accounted for nevertheless.
*
* If FLEX_BG meta-data grouping is used, only account for the
* superblock and group descriptors (the inode tables and
* bitmaps will be accounted for when allocated).
*/
free_blocks = 0;
csum_flag = ext2fs_has_group_desc_csum(fs);
reserved_inos = super->s_first_ino;
for (i = 0; i < fs->group_desc_count; i++) {
/*
* Don't set the BLOCK_UNINIT group for the last group
* because the block bitmap needs to be padded.
*/
if (csum_flag) {
if (i != fs->group_desc_count - 1)
ext2fs_bg_flags_set(fs, i,
EXT2_BG_BLOCK_UNINIT);
ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
numblocks = super->s_inodes_per_group;
if (reserved_inos) {
if (numblocks > reserved_inos) {
numblocks -= reserved_inos;
reserved_inos = 0;
} else {
reserved_inos -= numblocks;
numblocks = 0;
}
}
ext2fs_bg_itable_unused_set(fs, i, numblocks);
}
numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
if (fs->super->s_log_groups_per_flex)
numblocks += 2 + fs->inode_blocks_per_group;
free_blocks += numblocks;
ext2fs_bg_free_blocks_count_set(fs, i, numblocks);
ext2fs_bg_free_inodes_count_set(fs, i, fs->super->s_inodes_per_group);
ext2fs_bg_used_dirs_count_set(fs, i, 0);
ext2fs_group_desc_csum_set(fs, i);
}
free_blocks &= ~EXT2FS_CLUSTER_MASK(fs);
ext2fs_free_blocks_count_set(super, free_blocks);
c = (char) 255;
if (((int) c) == -1) {
super->s_flags |= EXT2_FLAGS_SIGNED_HASH;
} else {
super->s_flags |= EXT2_FLAGS_UNSIGNED_HASH;
}
ext2fs_mark_super_dirty(fs);
ext2fs_mark_bb_dirty(fs);
ext2fs_mark_ib_dirty(fs);
io_channel_set_blksize(fs->io, fs->blocksize);
*ret_fs = fs;
return 0;
cleanup:
free(buf);
ext2fs_free(fs);
return retval;
}

118
src/ext2fs/inline.c Normal file
View File

@ -0,0 +1,118 @@
/*
* inline.c --- Includes the inlined functions defined in the header
* files as standalone functions, in case the application program
* is compiled with inlining turned off.
*
* Copyright (C) 1993, 1994 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 /* for posix_memalign() */
#endif
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "ext2_fs.h"
#define INCLUDE_INLINE_FUNCS
#include "ext2fs.h"
/*
* We used to define this as an inline, but since we are now using
* autoconf-defined #ifdef's, we need to export this as a
* library-provided function exclusively.
*/
errcode_t ext2fs_get_memalign(unsigned long size,
unsigned long align, void *ptr)
{
errcode_t retval = 0;
void **p = ptr;
if (align < 8)
align = 8;
#ifdef HAVE_POSIX_MEMALIGN
retval = posix_memalign(p, align, size);
if (retval == ENOMEM)
return EXT2_ET_NO_MEMORY;
#else /* !HAVE_POSIX_MEMALIGN */
#ifdef HAVE_MEMALIGN
*p = memalign(align, size);
if (*p == NULL) {
if (errno)
return errno;
else
return EXT2_ET_NO_MEMORY;
}
#else /* !HAVE_MEMALIGN */
#ifdef HAVE_VALLOC
if (align > sizeof(long long))
*p = valloc(size);
else
#endif
*p = malloc(size);
if ((uintptr_t) *p & (align - 1)) {
free(*p);
*p = 0;
}
if (*p == 0)
return EXT2_ET_NO_MEMORY;
#endif /* HAVE_MEMALIGN */
#endif /* HAVE_POSIX_MEMALIGN */
return retval;
}
#ifdef DEBUG
static int isaligned(void *ptr, unsigned long align)
{
return (((unsigned long) ptr & (align - 1)) == 0);
}
static errcode_t test_memalign(unsigned long align)
{
void *ptr = 0;
errcode_t retval;
retval = ext2fs_get_memalign(32, align, &ptr);
if (!retval && !isaligned(ptr, align))
retval = EINVAL;
free(ptr);
printf("tst_memalign(%lu) is %s\n", align,
retval ? error_message(retval) : "OK");
return retval;
}
int main(int argc, char **argv)
{
int err = 0;
if (test_memalign(4))
err++;
if (test_memalign(32))
err++;
if (test_memalign(1024))
err++;
if (test_memalign(4096))
err++;
return err;
}
#endif

842
src/ext2fs/inline_data.c Normal file
View File

@ -0,0 +1,842 @@
/*
* inline_data.c --- data in inode
*
* Copyright (C) 2012 Zheng Liu <wenqing.lz@taobao.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <time.h>
#include <limits.h> /* for PATH_MAX */
#include "ext2_fs.h"
#include "ext2_ext_attr.h"
#include "ext2fs.h"
#include "ext2fsP.h"
struct ext2_inline_data {
ext2_filsys fs;
ext2_ino_t ino;
size_t ea_size; /* the size of inline data in ea area */
void *ea_data;
};
static errcode_t ext2fs_inline_data_ea_set(struct ext2_inline_data *data)
{
struct ext2_xattr_handle *handle;
errcode_t retval;
retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
if (retval)
return retval;
retval = ext2fs_xattrs_read(handle);
if (retval)
goto err;
retval = ext2fs_xattr_set(handle, "system.data",
data->ea_data, data->ea_size);
err:
(void) ext2fs_xattrs_close(&handle);
return retval;
}
static errcode_t ext2fs_inline_data_ea_get(struct ext2_inline_data *data)
{
struct ext2_xattr_handle *handle;
errcode_t retval;
data->ea_size = 0;
data->ea_data = 0;
retval = ext2fs_xattrs_open(data->fs, data->ino, &handle);
if (retval)
return retval;
retval = ext2fs_xattrs_read(handle);
if (retval)
goto err;
retval = ext2fs_xattr_get(handle, "system.data",
(void **)&data->ea_data, &data->ea_size);
if (retval == EXT2_ET_EA_KEY_NOT_FOUND) {
data->ea_size = 0;
data->ea_data = NULL;
retval = 0;
} else if (retval)
goto err;
err:
(void) ext2fs_xattrs_close(&handle);
return retval;
}
errcode_t ext2fs_inline_data_init(ext2_filsys fs, ext2_ino_t ino)
{
struct ext2_inline_data data;
char empty[1] = { '\0' };
data.fs = fs;
data.ino = ino;
data.ea_size = 0;
data.ea_data = empty;
return ext2fs_inline_data_ea_set(&data);
}
errcode_t ext2fs_inline_data_size(ext2_filsys fs, ext2_ino_t ino, size_t *size)
{
struct ext2_inode inode;
struct ext2_inline_data data;
errcode_t retval;
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval)
return retval;
if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
return EXT2_ET_NO_INLINE_DATA;
data.fs = fs;
data.ino = ino;
retval = ext2fs_inline_data_ea_get(&data);
if (retval)
return retval;
*size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
return ext2fs_free_mem(&data.ea_data);
}
int ext2fs_inline_data_dir_iterate(ext2_filsys fs, ext2_ino_t ino,
void *priv_data)
{
struct dir_context *ctx;
struct ext2_inode inode;
struct ext2_dir_entry dirent;
struct ext2_inline_data data;
int ret = BLOCK_ABORT;
e2_blkcnt_t blockcnt = 0;
char *old_buf;
unsigned int old_buflen;
int old_flags;
ctx = (struct dir_context *)priv_data;
old_buf = ctx->buf;
old_buflen = ctx->buflen;
old_flags = ctx->flags;
ctx->flags |= DIRENT_FLAG_INCLUDE_INLINE_DATA;
ctx->errcode = ext2fs_read_inode(fs, ino, &inode);
if (ctx->errcode)
goto out;
if (!(inode.i_flags & EXT4_INLINE_DATA_FL)) {
ctx->errcode = EXT2_ET_NO_INLINE_DATA;
goto out;
}
if (!LINUX_S_ISDIR(inode.i_mode)) {
ctx->errcode = EXT2_ET_NO_DIRECTORY;
goto out;
}
ret = 0;
/* we first check '.' and '..' dir */
dirent.inode = ino;
dirent.name_len = 1;
ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(2), &dirent);
dirent.name[0] = '.';
dirent.name[1] = '\0';
ctx->buf = (char *)&dirent;
ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
if (ret & BLOCK_ABORT)
goto out;
dirent.inode = ext2fs_le32_to_cpu(inode.i_block[0]);
dirent.name_len = 2;
ext2fs_set_rec_len(fs, EXT2_DIR_REC_LEN(3), &dirent);
dirent.name[0] = '.';
dirent.name[1] = '.';
dirent.name[2] = '\0';
ctx->buf = (char *)&dirent;
ext2fs_get_rec_len(fs, &dirent, &ctx->buflen);
ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
if (ret & BLOCK_INLINE_DATA_CHANGED) {
errcode_t err;
inode.i_block[0] = ext2fs_cpu_to_le32(dirent.inode);
err = ext2fs_write_inode(fs, ino, &inode);
if (err)
goto out;
ret &= ~BLOCK_INLINE_DATA_CHANGED;
}
if (ret & BLOCK_ABORT)
goto out;
ctx->buf = (char *)inode.i_block + EXT4_INLINE_DATA_DOTDOT_SIZE;
ctx->buflen = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
#ifdef WORDS_BIGENDIAN
ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
if (ctx->errcode) {
ret |= BLOCK_ABORT;
goto out;
}
#endif
ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
if (ret & BLOCK_INLINE_DATA_CHANGED) {
#ifdef WORDS_BIGENDIAN
ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
ctx->buflen, 0);
if (ctx->errcode) {
ret |= BLOCK_ABORT;
goto out;
}
#endif
ctx->errcode = ext2fs_write_inode(fs, ino, &inode);
if (ctx->errcode)
ret |= BLOCK_ABORT;
ret &= ~BLOCK_INLINE_DATA_CHANGED;
}
if (ret & BLOCK_ABORT)
goto out;
data.fs = fs;
data.ino = ino;
ctx->errcode = ext2fs_inline_data_ea_get(&data);
if (ctx->errcode) {
ret |= BLOCK_ABORT;
goto out;
}
if (data.ea_size <= 0)
goto out1;
ctx->buf = data.ea_data;
ctx->buflen = data.ea_size;
#ifdef WORDS_BIGENDIAN
ctx->errcode = ext2fs_dirent_swab_in2(fs, ctx->buf, ctx->buflen, 0);
if (ctx->errcode) {
ret |= BLOCK_ABORT;
goto out1;
}
#endif
ret |= ext2fs_process_dir_block(fs, 0, blockcnt++, 0, 0, priv_data);
if (ret & BLOCK_INLINE_DATA_CHANGED) {
#ifdef WORDS_BIGENDIAN
ctx->errcode = ext2fs_dirent_swab_out2(fs, ctx->buf,
ctx->buflen, 0);
if (ctx->errcode) {
ret |= BLOCK_ABORT;
goto out1;
}
#endif
ctx->errcode = ext2fs_inline_data_ea_set(&data);
if (ctx->errcode)
ret |= BLOCK_ABORT;
}
out1:
ext2fs_free_mem(&data.ea_data);
out:
ctx->buf = old_buf;
ctx->buflen = old_buflen;
ctx->flags = old_flags;
ret &= ~(BLOCK_ABORT | BLOCK_INLINE_DATA_CHANGED);
return ret;
}
errcode_t ext2fs_inline_data_ea_remove(ext2_filsys fs, ext2_ino_t ino)
{
struct ext2_xattr_handle *handle;
errcode_t retval;
retval = ext2fs_xattrs_open(fs, ino, &handle);
if (retval)
return retval;
retval = ext2fs_xattrs_read(handle);
if (retval)
goto err;
retval = ext2fs_xattr_remove(handle, "system.data");
err:
(void) ext2fs_xattrs_close(&handle);
return retval;
}
static errcode_t ext2fs_inline_data_convert_dir(ext2_filsys fs, ext2_ino_t ino,
char *bbuf, char *ibuf, int size)
{
struct ext2_dir_entry *dir, *dir2;
struct ext2_dir_entry_tail *t;
errcode_t retval;
int offset;
unsigned int rec_len;
int csum_size = 0;
int filetype = 0;
if (ext2fs_has_feature_metadata_csum(fs->super))
csum_size = sizeof(struct ext2_dir_entry_tail);
/* Create '.' and '..' */
if (ext2fs_has_feature_filetype(fs->super))
filetype = EXT2_FT_DIR;
/*
* Set up entry for '.'
*/
dir = (struct ext2_dir_entry *) bbuf;
dir->inode = ino;
ext2fs_dirent_set_name_len(dir, 1);
ext2fs_dirent_set_file_type(dir, filetype);
dir->name[0] = '.';
rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1);
dir->rec_len = EXT2_DIR_REC_LEN(1);
/*
* Set up entry for '..'
*/
dir = (struct ext2_dir_entry *) (bbuf + dir->rec_len);
dir->rec_len = EXT2_DIR_REC_LEN(2);
dir->inode = ext2fs_le32_to_cpu(((__u32 *)ibuf)[0]);
ext2fs_dirent_set_name_len(dir, 2);
ext2fs_dirent_set_file_type(dir, filetype);
dir->name[0] = '.';
dir->name[1] = '.';
/*
* Adjust the last rec_len
*/
offset = EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2);
dir = (struct ext2_dir_entry *) (bbuf + offset);
memcpy(bbuf + offset, ibuf + EXT4_INLINE_DATA_DOTDOT_SIZE,
size - EXT4_INLINE_DATA_DOTDOT_SIZE);
size += EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) -
EXT4_INLINE_DATA_DOTDOT_SIZE;
do {
dir2 = dir;
retval = ext2fs_get_rec_len(fs, dir, &rec_len);
if (retval)
goto err;
offset += rec_len;
dir = (struct ext2_dir_entry *) (bbuf + offset);
} while (offset < size);
rec_len += fs->blocksize - csum_size - offset;
retval = ext2fs_set_rec_len(fs, rec_len, dir2);
if (retval)
goto err;
if (csum_size) {
t = EXT2_DIRENT_TAIL(bbuf, fs->blocksize);
ext2fs_initialize_dirent_tail(fs, t);
}
err:
return retval;
}
static errcode_t
ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, char *buf, size_t size)
{
errcode_t retval;
blk64_t blk;
char *blk_buf;
retval = ext2fs_get_memzero(fs->blocksize, &blk_buf);
if (retval)
return retval;
#ifdef WORDS_BIGENDIAN
retval = ext2fs_dirent_swab_in2(fs, buf + EXT4_INLINE_DATA_DOTDOT_SIZE,
size, 0);
if (retval)
goto errout;
#endif
/* Adjust the rec_len */
retval = ext2fs_inline_data_convert_dir(fs, ino, blk_buf, buf, size);
if (retval)
goto errout;
/* Allocate a new block */
retval = ext2fs_new_block2(fs, 0, 0, &blk);
if (retval)
goto errout;
retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
if (retval)
goto errout;
/* Update inode */
if (ext2fs_has_feature_extents(fs->super))
inode->i_flags |= EXT4_EXTENTS_FL;
inode->i_flags &= ~EXT4_INLINE_DATA_FL;
retval = ext2fs_iblk_add_blocks(fs, inode, 1);
if (retval)
goto errout;
inode->i_size = fs->blocksize;
retval = ext2fs_bmap2(fs, ino, inode, 0, BMAP_SET, 0, 0, &blk);
if (retval)
goto errout;
retval = ext2fs_write_inode(fs, ino, inode);
if (retval)
goto errout;
ext2fs_block_alloc_stats(fs, blk, +1);
errout:
ext2fs_free_mem(&blk_buf);
return retval;
}
static errcode_t
ext2fs_inline_data_file_expand(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, char *buf, size_t size)
{
ext2_file_t e2_file;
errcode_t retval;
/* Update inode */
memset(inode->i_block, 0, sizeof(inode->i_block));
if (ext2fs_has_feature_extents(fs->super)) {
ext2_extent_handle_t handle;
inode->i_flags &= ~EXT4_EXTENTS_FL;
retval = ext2fs_extent_open2(fs, ino, inode, &handle);
if (retval)
return retval;
ext2fs_extent_free(handle);
}
inode->i_flags &= ~EXT4_INLINE_DATA_FL;
inode->i_size = 0;
retval = ext2fs_write_inode(fs, ino, inode);
if (retval)
return retval;
/* Write out the block buffer */
retval = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &e2_file);
if (retval)
return retval;
retval = ext2fs_file_write(e2_file, buf, size, 0);
ext2fs_file_close(e2_file);
return retval;
}
errcode_t ext2fs_inline_data_expand(ext2_filsys fs, ext2_ino_t ino)
{
struct ext2_inode inode;
struct ext2_inline_data data;
errcode_t retval;
size_t inline_size;
char *inline_buf = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval)
return retval;
if (!(inode.i_flags & EXT4_INLINE_DATA_FL))
return EXT2_ET_NO_INLINE_DATA;
data.fs = fs;
data.ino = ino;
retval = ext2fs_inline_data_ea_get(&data);
if (retval)
return retval;
inline_size = data.ea_size + EXT4_MIN_INLINE_DATA_SIZE;
retval = ext2fs_get_mem(inline_size, &inline_buf);
if (retval)
goto errout;
memcpy(inline_buf, (void *)inode.i_block, EXT4_MIN_INLINE_DATA_SIZE);
if (data.ea_size > 0) {
memcpy(inline_buf + EXT4_MIN_INLINE_DATA_SIZE,
data.ea_data, data.ea_size);
}
memset((void *)inode.i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
/*
* NOTE: We must do this write -> ea_remove -> read cycle here because
* removing the inline data EA can free the EA block, which is a change
* that our stack copy of the inode will never see. If that happens,
* we can end up with the EA block and lblk 0 pointing to the same
* pblk, which is bad news.
*/
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval)
goto errout;
retval = ext2fs_inline_data_ea_remove(fs, ino);
if (retval)
goto errout;
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval)
goto errout;
if (LINUX_S_ISDIR(inode.i_mode)) {
retval = ext2fs_inline_data_dir_expand(fs, ino, &inode,
inline_buf, inline_size);
} else {
retval = ext2fs_inline_data_file_expand(fs, ino, &inode,
inline_buf, inline_size);
}
errout:
if (inline_buf)
ext2fs_free_mem(&inline_buf);
ext2fs_free_mem(&data.ea_data);
return retval;
}
/*
* When caller uses this function to retrieve the inline data, it must
* allocate a buffer which has the size of inline data. The size of
* inline data can be know by ext2fs_inline_data_get_size().
*/
errcode_t ext2fs_inline_data_get(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
void *buf, size_t *size)
{
struct ext2_inode inode_buf;
struct ext2_inline_data data;
errcode_t retval;
if (!inode) {
retval = ext2fs_read_inode(fs, ino, &inode_buf);
if (retval)
return retval;
inode = &inode_buf;
}
data.fs = fs;
data.ino = ino;
retval = ext2fs_inline_data_ea_get(&data);
if (retval)
return retval;
memcpy(buf, (void *)inode->i_block, EXT4_MIN_INLINE_DATA_SIZE);
if (data.ea_size > 0)
memcpy((char *) buf + EXT4_MIN_INLINE_DATA_SIZE,
data.ea_data, data.ea_size);
if (size)
*size = EXT4_MIN_INLINE_DATA_SIZE + data.ea_size;
ext2fs_free_mem(&data.ea_data);
return 0;
}
errcode_t ext2fs_inline_data_set(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
void *buf, size_t size)
{
struct ext2_inode inode_buf;
struct ext2_inline_data data = {
.fs = fs,
.ino = ino,
};
errcode_t retval;
size_t free_ea_size, existing_size, free_inode_size;
if (!inode) {
retval = ext2fs_read_inode(fs, ino, &inode_buf);
if (retval)
return retval;
inode = &inode_buf;
}
if (size <= EXT4_MIN_INLINE_DATA_SIZE) {
memcpy((void *)inode->i_block, buf, size);
} else {
retval = ext2fs_xattr_inode_max_size(fs, ino, &free_ea_size);
if (retval)
return retval;
retval = ext2fs_inline_data_size(fs, ino, &existing_size);
if (retval)
return retval;
if (existing_size < EXT4_MIN_INLINE_DATA_SIZE) {
free_inode_size = EXT4_MIN_INLINE_DATA_SIZE -
existing_size;
} else {
free_inode_size = 0;
}
if (size != existing_size &&
size > existing_size + free_ea_size + free_inode_size)
return EXT2_ET_INLINE_DATA_NO_SPACE;
memcpy((void *)inode->i_block, buf, EXT4_MIN_INLINE_DATA_SIZE);
if (size > EXT4_MIN_INLINE_DATA_SIZE)
data.ea_size = size - EXT4_MIN_INLINE_DATA_SIZE;
data.ea_data = (char *) buf + EXT4_MIN_INLINE_DATA_SIZE;
}
retval = ext2fs_write_inode(fs, ino, inode);
if (retval)
return retval;
return ext2fs_inline_data_ea_set(&data);
}
#ifdef DEBUG
#include "e2p/e2p.h"
/*
* The length of buffer is set to 64 because in inode's i_block member it only
* can save 60 bytes. Thus this value can let the data being saved in extra
* space.
*/
#define BUFF_SIZE (64)
static errcode_t file_test(ext2_filsys fs)
{
struct ext2_inode inode;
ext2_ino_t newfile;
errcode_t retval;
size_t size;
char *buf = 0, *cmpbuf = 0;
/* create a new file */
retval = ext2fs_new_inode(fs, 2, 010755, 0, &newfile);
if (retval) {
com_err("file_test", retval, "while allocating a new inode");
return 1;
}
memset(&inode, 0, sizeof(inode));
inode.i_flags |= EXT4_INLINE_DATA_FL;
inode.i_size = EXT4_MIN_INLINE_DATA_SIZE;
inode.i_mode = LINUX_S_IFREG;
retval = ext2fs_write_new_inode(fs, newfile, &inode);
if (retval) {
com_err("file_test", retval, "while writing a new inode");
return 1;
}
retval = ext2fs_inline_data_init(fs, newfile);
if (retval) {
com_err("file_test", retval, "while init 'system.data'");
return 1;
}
retval = ext2fs_inline_data_size(fs, newfile, &size);
if (retval) {
com_err("file_test", retval, "while getting size");
return 1;
}
if (size != EXT4_MIN_INLINE_DATA_SIZE) {
fprintf(stderr,
"tst_inline_data: size of inline data is wrong\n");
return 1;
}
ext2fs_get_mem(BUFF_SIZE, &buf);
memset(buf, 'a', BUFF_SIZE);
retval = ext2fs_inline_data_set(fs, newfile, 0, buf, BUFF_SIZE);
if (retval) {
com_err("file_test", retval,
"while setting inline data %s", buf);
goto err;
}
ext2fs_get_mem(BUFF_SIZE, &cmpbuf);
retval = ext2fs_inline_data_get(fs, newfile, 0, cmpbuf, &size);
if (retval) {
com_err("file_test", retval, "while getting inline data");
goto err;
}
if (size != BUFF_SIZE) {
fprintf(stderr,
"tst_inline_data: size %lu != buflen %u\n",
size, BUFF_SIZE);
retval = 1;
goto err;
}
if (memcmp(buf, cmpbuf, BUFF_SIZE)) {
fprintf(stderr, "tst_inline_data: buf != cmpbuf\n");
retval = 1;
goto err;
}
retval = ext2fs_punch(fs, newfile, 0, 0, 0, ~0ULL);
if (retval) {
com_err("file_test", retval, "while truncating inode");
goto err;
}
/* reload inode and check isize */
ext2fs_read_inode(fs, newfile, &inode);
if (inode.i_size != 0) {
fprintf(stderr, "tst_inline_data: i_size should be 0\n");
retval = 1;
}
err:
if (cmpbuf)
ext2fs_free_mem(&cmpbuf);
if (buf)
ext2fs_free_mem(&buf);
return retval;
}
static errcode_t dir_test(ext2_filsys fs)
{
const char *dot_name = ".";
const char *stub_name = "stub";
const char *parent_name = "test";
ext2_ino_t parent, dir, tmp;
errcode_t retval;
char dirname[32];
int i;
retval = ext2fs_mkdir(fs, 11, 11, stub_name);
if (retval) {
com_err("dir_test", retval, "while creating %s dir", stub_name);
return retval;
}
retval = ext2fs_mkdir(fs, 11, 0, parent_name);
if (retval) {
com_err("dir_test", retval,
"while creating %s dir", parent_name);
return retval;
}
retval = ext2fs_lookup(fs, 11, parent_name, strlen(parent_name),
0, &parent);
if (retval) {
com_err("dir_test", retval,
"while looking up %s dir", parent_name);
return retval;
}
retval = ext2fs_lookup(fs, parent, dot_name, strlen(dot_name),
0, &tmp);
if (retval) {
com_err("dir_test", retval,
"while looking up %s dir", parent_name);
return retval;
}
if (parent != tmp) {
fprintf(stderr, "tst_inline_data: parent (%u) != tmp (%u)\n",
parent, tmp);
return 1;
}
for (i = 0, dir = 13; i < 4; i++, dir++) {
tmp = 0;
snprintf(dirname, sizeof(dirname), "%d", i);
retval = ext2fs_mkdir(fs, parent, 0, dirname);
if (retval) {
com_err("dir_test", retval,
"while creating %s dir", dirname);
return retval;
}
retval = ext2fs_lookup(fs, parent, dirname, strlen(dirname),
0, &tmp);
if (retval) {
com_err("dir_test", retval,
"while looking up %s dir", parent_name);
return retval;
}
if (dir != tmp) {
fprintf(stderr,
"tst_inline_data: dir (%u) != tmp (%u)\n",
dir, tmp);
return 1;
}
}
snprintf(dirname, sizeof(dirname), "%d", i);
retval = ext2fs_mkdir(fs, parent, 0, dirname);
if (retval && retval != EXT2_ET_DIR_NO_SPACE) {
com_err("dir_test", retval, "while creating %s dir", dirname);
return retval;
}
retval = ext2fs_expand_dir(fs, parent);
if (retval) {
com_err("dir_test", retval, "while expanding %s dir", parent_name);
return retval;
}
return 0;
}
int main(int argc, char *argv[])
{
ext2_filsys fs;
struct ext2_super_block param;
errcode_t retval;
/* setup */
initialize_ext2_error_table();
memset(&param, 0, sizeof(param));
ext2fs_blocks_count_set(&param, 32768);
param.s_inodes_count = 100;
param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_INLINE_DATA;
param.s_rev_level = EXT2_DYNAMIC_REV;
param.s_inode_size = 256;
retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, &param,
test_io_manager, &fs);
if (retval) {
com_err("setup", retval,
"while initializing filesystem");
exit(1);
}
retval = ext2fs_allocate_tables(fs);
if (retval) {
com_err("setup", retval,
"while allocating tables for test filesystem");
exit(1);
}
/* initialize inode cache */
if (!fs->icache) {
ext2_ino_t first_ino = EXT2_FIRST_INO(fs->super);
int i;
/* we just want to init inode cache. So ignore error */
ext2fs_create_inode_cache(fs, 16);
if (!fs->icache) {
fprintf(stderr,
"tst_inline_data: init inode cache failed\n");
exit(1);
}
/* setup inode cache */
for (i = 0; i < fs->icache->cache_size; i++)
fs->icache->cache[i].ino = first_ino++;
}
/* test */
if (file_test(fs)) {
fprintf(stderr, "tst_inline_data(FILE): FAILED\n");
return 1;
}
printf("tst_inline_data(FILE): OK\n");
if (dir_test(fs)) {
fprintf(stderr, "tst_inline_data(DIR): FAILED\n");
return 1;
}
printf("tst_inline_data(DIR): OK\n");
ext2fs_free(fs);
return 0;
}
#endif

1062
src/ext2fs/inode.c Normal file

File diff suppressed because it is too large Load Diff

150
src/ext2fs/io_manager.c Normal file
View File

@ -0,0 +1,150 @@
/*
* io_manager.c --- the I/O manager abstraction
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
errcode_t io_channel_set_options(io_channel channel, const char *opts)
{
errcode_t retval = 0;
char *next, *ptr, *options, *arg;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
if (!opts)
return 0;
if (!channel->manager->set_option)
return EXT2_ET_INVALID_ARGUMENT;
options = malloc(strlen(opts)+1);
if (!options)
return EXT2_ET_NO_MEMORY;
strcpy(options, opts);
ptr = options;
while (ptr && *ptr) {
next = strchr(ptr, '&');
if (next)
*next++ = 0;
arg = strchr(ptr, '=');
if (arg)
*arg++ = 0;
retval = (channel->manager->set_option)(channel, ptr, arg);
if (retval)
break;
ptr = next;
}
free(options);
return retval;
}
errcode_t io_channel_write_byte(io_channel channel, unsigned long offset,
int count, const void *data)
{
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
if (channel->manager->write_byte)
return channel->manager->write_byte(channel, offset,
count, data);
return EXT2_ET_UNIMPLEMENTED;
}
errcode_t io_channel_read_blk64(io_channel channel, unsigned long long block,
int count, void *data)
{
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
if (channel->manager->read_blk64)
return (channel->manager->read_blk64)(channel, block,
count, data);
if ((block >> 32) != 0)
return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64;
return (channel->manager->read_blk)(channel, (unsigned long) block,
count, data);
}
errcode_t io_channel_write_blk64(io_channel channel, unsigned long long block,
int count, const void *data)
{
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
if (channel->manager->write_blk64)
return (channel->manager->write_blk64)(channel, block,
count, data);
if ((block >> 32) != 0)
return EXT2_ET_IO_CHANNEL_NO_SUPPORT_64;
return (channel->manager->write_blk)(channel, (unsigned long) block,
count, data);
}
errcode_t io_channel_discard(io_channel channel, unsigned long long block,
unsigned long long count)
{
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
if (channel->manager->discard)
return (channel->manager->discard)(channel, block, count);
return EXT2_ET_UNIMPLEMENTED;
}
errcode_t io_channel_zeroout(io_channel channel, unsigned long long block,
unsigned long long count)
{
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
if (channel->manager->zeroout)
return (channel->manager->zeroout)(channel, block, count);
return EXT2_ET_UNIMPLEMENTED;
}
errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr)
{
size_t size;
if (count == 0)
size = io->block_size;
else if (count > 0)
size = io->block_size * count;
else
size = -count;
if (io->align)
return ext2fs_get_memalign(size, io->align, ptr);
else
return ext2fs_get_mem(size, ptr);
}
errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block,
unsigned long long count)
{
if (!io->manager->cache_readahead)
return EXT2_ET_OP_NOT_SUPPORTED;
return io->manager->cache_readahead(io, block, count);
}

201
src/ext2fs/link.c Normal file
View File

@ -0,0 +1,201 @@
/*
* link.c --- create links in a ext2fs directory
*
* Copyright (C) 1993, 1994 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct link_struct {
ext2_filsys fs;
const char *name;
int namelen;
ext2_ino_t inode;
int flags;
int done;
unsigned int blocksize;
errcode_t err;
struct ext2_super_block *sb;
};
static int link_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *priv_data)
{
struct link_struct *ls = (struct link_struct *) priv_data;
struct ext2_dir_entry *next;
unsigned int rec_len, min_rec_len, curr_rec_len;
int ret = 0;
int csum_size = 0;
struct ext2_dir_entry_tail *t;
if (ls->done)
return DIRENT_ABORT;
rec_len = EXT2_DIR_REC_LEN(ls->namelen);
ls->err = ext2fs_get_rec_len(ls->fs, dirent, &curr_rec_len);
if (ls->err)
return DIRENT_ABORT;
if (ext2fs_has_feature_metadata_csum(ls->fs->super))
csum_size = sizeof(struct ext2_dir_entry_tail);
/*
* See if the following directory entry (if any) is unused;
* if so, absorb it into this one.
*/
next = (struct ext2_dir_entry *) (buf + offset + curr_rec_len);
if ((offset + (int) curr_rec_len < blocksize - (8 + csum_size)) &&
(next->inode == 0) &&
(offset + (int) curr_rec_len + (int) next->rec_len <= blocksize)) {
curr_rec_len += next->rec_len;
ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
if (ls->err)
return DIRENT_ABORT;
ret = DIRENT_CHANGED;
}
/*
* Since ext2fs_link blows away htree data, we need to be
* careful -- if metadata_csum is enabled and we're passed in
* a dirent that contains htree data, we need to create the
* fake entry at the end of the block that hides the checksum.
*/
/* De-convert a dx_node block */
if (csum_size &&
curr_rec_len == ls->fs->blocksize &&
!dirent->inode) {
curr_rec_len -= csum_size;
ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
if (ls->err)
return DIRENT_ABORT;
t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize);
ext2fs_initialize_dirent_tail(ls->fs, t);
ret = DIRENT_CHANGED;
}
/* De-convert a dx_root block */
if (csum_size &&
curr_rec_len == ls->fs->blocksize - EXT2_DIR_REC_LEN(1) &&
offset == EXT2_DIR_REC_LEN(1) &&
dirent->name[0] == '.' && dirent->name[1] == '.') {
curr_rec_len -= csum_size;
ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent);
if (ls->err)
return DIRENT_ABORT;
t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize);
ext2fs_initialize_dirent_tail(ls->fs, t);
ret = DIRENT_CHANGED;
}
/*
* If the directory entry is used, see if we can split the
* directory entry to make room for the new name. If so,
* truncate it and return.
*/
if (dirent->inode) {
min_rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(dirent));
if (curr_rec_len < (min_rec_len + rec_len))
return ret;
rec_len = curr_rec_len - min_rec_len;
ls->err = ext2fs_set_rec_len(ls->fs, min_rec_len, dirent);
if (ls->err)
return DIRENT_ABORT;
next = (struct ext2_dir_entry *) (buf + offset +
dirent->rec_len);
next->inode = 0;
ext2fs_dirent_set_name_len(next, 0);
ext2fs_dirent_set_file_type(next, 0);
ls->err = ext2fs_set_rec_len(ls->fs, rec_len, next);
if (ls->err)
return DIRENT_ABORT;
return DIRENT_CHANGED;
}
/*
* If we get this far, then the directory entry is not used.
* See if we can fit the request entry in. If so, do it.
*/
if (curr_rec_len < rec_len)
return ret;
dirent->inode = ls->inode;
ext2fs_dirent_set_name_len(dirent, ls->namelen);
strncpy(dirent->name, ls->name, ls->namelen);
if (ext2fs_has_feature_filetype(ls->sb))
ext2fs_dirent_set_file_type(dirent, ls->flags & 0x7);
ls->done++;
return DIRENT_ABORT|DIRENT_CHANGED;
}
/*
* Note: the low 3 bits of the flags field are used as the directory
* entry filetype.
*/
#ifdef __TURBOC__
#pragma argsused
#endif
errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
ext2_ino_t ino, int flags)
{
errcode_t retval;
struct link_struct ls;
struct ext2_inode inode;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
ls.fs = fs;
ls.name = name;
ls.namelen = name ? strlen(name) : 0;
ls.inode = ino;
ls.flags = flags;
ls.done = 0;
ls.sb = fs->super;
ls.blocksize = fs->blocksize;
ls.err = 0;
retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
0, link_proc, &ls);
if (retval)
return retval;
if (ls.err)
return ls.err;
if (!ls.done)
return EXT2_ET_DIR_NO_SPACE;
if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0)
return retval;
/*
* If this function changes to preserve the htree, remove the
* two hunks in link_proc that shove checksum tails into the
* former dx_root/dx_node blocks.
*/
if (inode.i_flags & EXT2_INDEX_FL) {
inode.i_flags &= ~EXT2_INDEX_FL;
if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0)
return retval;
}
return 0;
}

70
src/ext2fs/lookup.c Normal file
View File

@ -0,0 +1,70 @@
/*
* lookup.c --- ext2fs directory lookup operations
*
* Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct lookup_struct {
const char *name;
int len;
ext2_ino_t *inode;
int found;
};
#ifdef __TURBOC__
#pragma argsused
#endif
static int lookup_proc(struct ext2_dir_entry *dirent,
int offset EXT2FS_ATTR((unused)),
int blocksize EXT2FS_ATTR((unused)),
char *buf EXT2FS_ATTR((unused)),
void *priv_data)
{
struct lookup_struct *ls = (struct lookup_struct *) priv_data;
if (ls->len != ext2fs_dirent_name_len(dirent))
return 0;
if (strncmp(ls->name, dirent->name, ext2fs_dirent_name_len(dirent)))
return 0;
*ls->inode = dirent->inode;
ls->found++;
return DIRENT_ABORT;
}
errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name,
int namelen, char *buf, ext2_ino_t *inode)
{
errcode_t retval;
struct lookup_struct ls;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
ls.name = name;
ls.len = namelen;
ls.inode = inode;
ls.found = 0;
retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
if (retval)
return retval;
return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND;
}

102
src/ext2fs/missing.c Normal file
View File

@ -0,0 +1,102 @@
/*
* missing.c --- stuff we need from features we don't care about (journal)
*
* Copyright (C) 2000 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include "ext2fs.h"
/*
* Convenience function which zeros out _num_ blocks starting at
* _blk_. In case of an error, the details of the error is returned
* via _ret_blk_ and _ret_count_ if they are non-NULL pointers.
* Returns 0 on success, and an error code on an error.
*
* As a special case, if the first argument is NULL, then it will
* attempt to free the static zeroizing buffer. (This is to keep
* programs that check for memory leaks happy.)
*/
#define MAX_STRIDE_LENGTH (4194304 / (int) fs->blocksize)
errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
blk64_t *ret_blk, int *ret_count)
{
int j, count;
static void *buf;
static int stride_length;
errcode_t retval;
/* If fs is null, clean up the static buffer and return */
if (!fs) {
if (buf) {
free(buf);
buf = 0;
stride_length = 0;
}
return 0;
}
/* Deal with zeroing less than 1 block */
if (num <= 0)
return 0;
/* Try a zero out command, if supported */
retval = io_channel_zeroout(fs->io, blk, num);
if (retval == 0)
return 0;
/* Allocate the zeroizing buffer if necessary */
if (num > stride_length && stride_length < MAX_STRIDE_LENGTH) {
void *p;
int new_stride = num;
if (new_stride > MAX_STRIDE_LENGTH)
new_stride = MAX_STRIDE_LENGTH;
p = realloc(buf, fs->blocksize * new_stride);
if (!p)
return EXT2_ET_NO_MEMORY;
buf = p;
stride_length = new_stride;
memset(buf, 0, fs->blocksize * stride_length);
}
/* OK, do the write loop */
j=0;
while (j < num) {
if (blk % stride_length) {
count = stride_length - (blk % stride_length);
if (count > (num - j))
count = num - j;
} else {
count = num - j;
if (count > stride_length)
count = stride_length;
}
retval = io_channel_write_blk64(fs->io, blk, count, buf);
if (retval) {
if (ret_count)
*ret_count = count;
if (ret_blk)
*ret_blk = blk;
return retval;
}
j += count; blk += count;
}
return 0;
}
errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
blk_t *ret_blk, int *ret_count)
{
blk64_t ret_blk2;
errcode_t retval;
retval = ext2fs_zero_blocks2(fs, blk, num, &ret_blk2, ret_count);
if (retval)
*ret_blk = (blk_t) ret_blk2;
return retval;
}

192
src/ext2fs/mkdir.c Normal file
View File

@ -0,0 +1,192 @@
/*
* mkdir.c --- make a directory in the filesystem
*
* Copyright (C) 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
#ifndef EXT2_FT_DIR
#define EXT2_FT_DIR 2
#endif
errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
const char *name)
{
ext2_extent_handle_t handle;
errcode_t retval;
struct ext2_inode parent_inode, inode;
ext2_ino_t ino = inum;
ext2_ino_t scratch_ino;
blk64_t blk;
char *block = 0;
int inline_data = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
/*
* Create a new dir with inline data iff this feature is enabled
* and ino >= EXT2_FIRST_INO.
*/
if ((!ino || ino >= EXT2_FIRST_INO(fs->super)) &&
ext2fs_has_feature_inline_data(fs->super))
inline_data = 1;
/*
* Allocate an inode, if necessary
*/
if (!ino) {
retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755,
0, &ino);
if (retval)
goto cleanup;
}
/*
* Allocate a data block for the directory
*/
memset(&inode, 0, sizeof(struct ext2_inode));
if (!inline_data) {
retval = ext2fs_new_block2(fs, ext2fs_find_inode_goal(fs, ino,
&inode,
0),
NULL, &blk);
if (retval)
goto cleanup;
}
/*
* Create a scratch template for the directory
*/
if (inline_data)
retval = ext2fs_new_dir_inline_data(fs, ino, parent,
inode.i_block);
else
retval = ext2fs_new_dir_block(fs, ino, parent, &block);
if (retval)
goto cleanup;
/*
* Get the parent's inode, if necessary
*/
if (parent != ino) {
retval = ext2fs_read_inode(fs, parent, &parent_inode);
if (retval)
goto cleanup;
} else
memset(&parent_inode, 0, sizeof(parent_inode));
/*
* Create the inode structure....
*/
inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask);
inode.i_uid = inode.i_gid = 0;
if (inline_data) {
inode.i_flags |= EXT4_INLINE_DATA_FL;
inode.i_size = EXT4_MIN_INLINE_DATA_SIZE;
} else {
if (ext2fs_has_feature_extents(fs->super))
inode.i_flags |= EXT4_EXTENTS_FL;
else
inode.i_block[0] = blk;
inode.i_size = fs->blocksize;
ext2fs_iblk_set(fs, &inode, 1);
}
inode.i_links_count = 2;
/*
* Write out the inode and inode data block. The inode generation
* number is assigned by write_new_inode, which means that the call
* to write_dir_block must come after that.
*/
retval = ext2fs_write_new_inode(fs, ino, &inode);
if (retval)
goto cleanup;
if (inline_data) {
/* init "system.data" for new dir */
retval = ext2fs_inline_data_init(fs, ino);
} else {
retval = ext2fs_write_dir_block4(fs, blk, block, 0, ino);
if (retval)
goto cleanup;
if (ext2fs_has_feature_extents(fs->super)) {
retval = ext2fs_extent_open2(fs, ino, &inode, &handle);
if (retval)
goto cleanup;
retval = ext2fs_extent_set_bmap(handle, 0, blk, 0);
ext2fs_extent_free(handle);
if (retval)
goto cleanup;
}
}
/*
* Link the directory into the filesystem hierarchy
*/
if (name) {
retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
&scratch_ino);
if (!retval) {
retval = EXT2_ET_DIR_EXISTS;
name = 0;
goto cleanup;
}
if (retval != EXT2_ET_FILE_NOT_FOUND)
goto cleanup;
retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR);
if (retval)
goto cleanup;
}
/*
* Update parent inode's counts
*/
if (parent != ino) {
/* reload parent inode due to inline data */
retval = ext2fs_read_inode(fs, parent, &parent_inode);
if (retval)
goto cleanup;
parent_inode.i_links_count++;
retval = ext2fs_write_inode(fs, parent, &parent_inode);
if (retval)
goto cleanup;
}
/*
* Update accounting....
*/
if (!inline_data)
ext2fs_block_alloc_stats2(fs, blk, +1);
ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
cleanup:
if (block)
ext2fs_free_mem(&block);
return retval;
}

470
src/ext2fs/mmp.c Normal file
View File

@ -0,0 +1,470 @@
/*
* Helper functions for multiple mount protection (MMP).
*
* Copyright (C) 2011 Whamcloud, Inc.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */
#endif
#include "config.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ext2fs/ext2_fs.h"
#include "ext2fs/ext2fs.h"
#ifndef O_DIRECT
#define O_DIRECT 0
#endif
#ifndef _MSC_VER
#pragma GCC diagnostic push
#ifndef CONFIG_MMP
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#endif
errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf)
{
#ifdef CONFIG_MMP
struct mmp_struct *mmp_cmp;
errcode_t retval = 0;
if ((mmp_blk <= fs->super->s_first_data_block) ||
(mmp_blk >= ext2fs_blocks_count(fs->super)))
return EXT2_ET_MMP_BAD_BLOCK;
/* ext2fs_open() reserves fd0,1,2 to avoid stdio collision, so checking
* mmp_fd <= 0 is OK to validate that the fd is valid. This opens its
* own fd to read the MMP block to ensure that it is using O_DIRECT,
* regardless of how the io_manager is doing reads, to avoid caching of
* the MMP block by the io_manager or the VM. It needs to be fresh. */
if (fs->mmp_fd <= 0) {
fs->mmp_fd = open(fs->device_name, O_RDWR | O_DIRECT);
if (fs->mmp_fd < 0) {
retval = EXT2_ET_MMP_OPEN_DIRECT;
goto out;
}
}
if (fs->mmp_cmp == NULL) {
int align = ext2fs_get_dio_alignment(fs->mmp_fd);
retval = ext2fs_get_memalign(fs->blocksize, align,
&fs->mmp_cmp);
if (retval)
return retval;
}
if ((blk64_t) ext2fs_llseek(fs->mmp_fd, mmp_blk * fs->blocksize,
SEEK_SET) !=
mmp_blk * fs->blocksize) {
retval = EXT2_ET_LLSEEK_FAILED;
goto out;
}
if (read(fs->mmp_fd, fs->mmp_cmp, fs->blocksize) != fs->blocksize) {
retval = EXT2_ET_SHORT_READ;
goto out;
}
mmp_cmp = fs->mmp_cmp;
if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
!ext2fs_mmp_csum_verify(fs, mmp_cmp))
retval = EXT2_ET_MMP_CSUM_INVALID;
#ifdef WORDS_BIGENDIAN
ext2fs_swap_mmp(mmp_cmp);
#endif
if (buf != NULL && buf != fs->mmp_cmp)
memcpy(buf, fs->mmp_cmp, fs->blocksize);
if (mmp_cmp->mmp_magic != EXT4_MMP_MAGIC) {
retval = EXT2_ET_MMP_MAGIC_INVALID;
goto out;
}
out:
return retval;
#else
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_t mmp_blk, void *buf)
{
#ifdef CONFIG_MMP
struct mmp_struct *mmp_s = buf;
struct timeval tv;
errcode_t retval = 0;
gettimeofday(&tv, 0);
mmp_s->mmp_time = tv.tv_sec;
fs->mmp_last_written = tv.tv_sec;
if (fs->super->s_mmp_block < fs->super->s_first_data_block ||
fs->super->s_mmp_block > ext2fs_blocks_count(fs->super))
return EXT2_ET_MMP_BAD_BLOCK;
#ifdef WORDS_BIGENDIAN
ext2fs_swap_mmp(mmp_s);
#endif
retval = ext2fs_mmp_csum_set(fs, mmp_s);
if (retval)
return retval;
/* I was tempted to make this use O_DIRECT and the mmp_fd, but
* this caused no end of grief, while leaving it as-is works. */
retval = io_channel_write_blk64(fs->io, mmp_blk, -(int)sizeof(struct mmp_struct), buf);
#ifdef WORDS_BIGENDIAN
ext2fs_swap_mmp(mmp_s);
#endif
/* Make sure the block gets to disk quickly */
io_channel_flush(fs->io);
return retval;
#else
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
#ifdef HAVE_SRANDOM
#define srand(x) srandom(x)
#define rand() random()
#endif
unsigned ext2fs_mmp_new_seq(void)
{
#ifdef CONFIG_MMP
unsigned new_seq;
struct timeval tv;
gettimeofday(&tv, 0);
srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
gettimeofday(&tv, 0);
/* Crank the random number generator a few times */
for (new_seq = (tv.tv_sec ^ tv.tv_usec) & 0x1F; new_seq > 0; new_seq--)
rand();
do {
new_seq = rand();
} while (new_seq > EXT4_MMP_SEQ_MAX);
return new_seq;
#else
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
#ifdef CONFIG_MMP
static errcode_t ext2fs_mmp_reset(ext2_filsys fs)
{
struct mmp_struct *mmp_s = NULL;
errcode_t retval = 0;
if (fs->mmp_buf == NULL) {
retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
if (retval)
goto out;
}
memset(fs->mmp_buf, 0, fs->blocksize);
mmp_s = fs->mmp_buf;
mmp_s->mmp_magic = EXT4_MMP_MAGIC;
mmp_s->mmp_seq = EXT4_MMP_SEQ_CLEAN;
mmp_s->mmp_time = 0;
#if _BSD_SOURCE || _XOPEN_SOURCE >= 500
gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename));
#else
mmp_s->mmp_nodename[0] = '\0';
#endif
strncpy(mmp_s->mmp_bdevname, fs->device_name,
sizeof(mmp_s->mmp_bdevname));
mmp_s->mmp_check_interval = fs->super->s_mmp_update_interval;
if (mmp_s->mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL)
mmp_s->mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL;
retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
out:
return retval;
}
#endif
errcode_t ext2fs_mmp_update(ext2_filsys fs)
{
return ext2fs_mmp_update2(fs, 0);
}
errcode_t ext2fs_mmp_clear(ext2_filsys fs)
{
#ifdef CONFIG_MMP
errcode_t retval = 0;
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
retval = ext2fs_mmp_reset(fs);
return retval;
#else
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
errcode_t ext2fs_mmp_init(ext2_filsys fs)
{
#ifdef CONFIG_MMP
struct ext2_super_block *sb = fs->super;
blk64_t mmp_block;
errcode_t retval;
if (sb->s_mmp_update_interval == 0)
sb->s_mmp_update_interval = EXT4_MMP_UPDATE_INTERVAL;
/* This is probably excessively large, but who knows? */
else if (sb->s_mmp_update_interval > EXT4_MMP_MAX_UPDATE_INTERVAL)
return EXT2_ET_INVALID_ARGUMENT;
if (fs->mmp_buf == NULL) {
retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
if (retval)
goto out;
}
retval = ext2fs_alloc_block2(fs, 0, fs->mmp_buf, &mmp_block);
if (retval)
goto out;
sb->s_mmp_block = mmp_block;
retval = ext2fs_mmp_reset(fs);
if (retval)
goto out;
out:
return retval;
#else
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
/*
* Make sure that the fs is not mounted or being fsck'ed while opening the fs.
*/
errcode_t ext2fs_mmp_start(ext2_filsys fs)
{
#ifdef CONFIG_MMP
struct mmp_struct *mmp_s;
unsigned seq;
unsigned int mmp_check_interval;
errcode_t retval = 0;
if (fs->mmp_buf == NULL) {
retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
if (retval)
goto mmp_error;
}
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
mmp_s = fs->mmp_buf;
mmp_check_interval = fs->super->s_mmp_update_interval;
if (mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL)
mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL;
seq = mmp_s->mmp_seq;
if (seq == EXT4_MMP_SEQ_CLEAN)
goto clean_seq;
if (seq == EXT4_MMP_SEQ_FSCK) {
retval = EXT2_ET_MMP_FSCK_ON;
goto mmp_error;
}
if (seq > EXT4_MMP_SEQ_FSCK) {
retval = EXT2_ET_MMP_UNKNOWN_SEQ;
goto mmp_error;
}
/*
* If check_interval in MMP block is larger, use that instead of
* check_interval from the superblock.
*/
if (mmp_s->mmp_check_interval > mmp_check_interval)
mmp_check_interval = mmp_s->mmp_check_interval;
sleep(2 * mmp_check_interval + 1);
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
if (seq != mmp_s->mmp_seq) {
retval = EXT2_ET_MMP_FAILED;
goto mmp_error;
}
clean_seq:
if (!(fs->flags & EXT2_FLAG_RW))
goto mmp_error;
mmp_s->mmp_seq = seq = ext2fs_mmp_new_seq();
#if _BSD_SOURCE || _XOPEN_SOURCE >= 500
gethostname(mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename));
#else
strcpy(mmp_s->mmp_nodename, "unknown host");
#endif
strncpy(mmp_s->mmp_bdevname, fs->device_name,
sizeof(mmp_s->mmp_bdevname));
retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
sleep(2 * mmp_check_interval + 1);
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
if (seq != mmp_s->mmp_seq) {
retval = EXT2_ET_MMP_FAILED;
goto mmp_error;
}
mmp_s->mmp_seq = EXT4_MMP_SEQ_FSCK;
retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
return 0;
mmp_error:
return retval;
#else
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
/*
* Clear the MMP usage in the filesystem. If this function returns an
* error EXT2_ET_MMP_CHANGE_ABORT it means the filesystem was modified
* by some other process while in use, and changes should be dropped, or
* risk filesystem corruption.
*/
errcode_t ext2fs_mmp_stop(ext2_filsys fs)
{
#ifdef CONFIG_MMP
struct mmp_struct *mmp, *mmp_cmp;
errcode_t retval = 0;
if (!ext2fs_has_feature_mmp(fs->super) ||
!(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
goto mmp_error;
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
if (retval)
goto mmp_error;
/* Check if the MMP block is not changed. */
mmp = fs->mmp_buf;
mmp_cmp = fs->mmp_cmp;
if (memcmp(mmp, mmp_cmp, sizeof(*mmp_cmp))) {
retval = EXT2_ET_MMP_CHANGE_ABORT;
goto mmp_error;
}
mmp_cmp->mmp_seq = EXT4_MMP_SEQ_CLEAN;
retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_cmp);
mmp_error:
if (fs->mmp_fd > 0) {
close(fs->mmp_fd);
fs->mmp_fd = -1;
}
return retval;
#else
if (!ext2fs_has_feature_mmp(fs->super) ||
!(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
return 0;
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
#define EXT2_MIN_MMP_UPDATE_INTERVAL 60
/*
* Update the on-disk mmp buffer, after checking that it hasn't been changed.
*/
errcode_t ext2fs_mmp_update2(ext2_filsys fs, int immediately)
{
#ifdef CONFIG_MMP
struct mmp_struct *mmp, *mmp_cmp;
struct timeval tv;
errcode_t retval = 0;
if (!ext2fs_has_feature_mmp(fs->super) ||
!(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
return 0;
gettimeofday(&tv, 0);
if (!immediately &&
tv.tv_sec - fs->mmp_last_written < EXT2_MIN_MMP_UPDATE_INTERVAL)
return 0;
retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, NULL);
if (retval)
goto mmp_error;
mmp = fs->mmp_buf;
mmp_cmp = fs->mmp_cmp;
if (memcmp(mmp, mmp_cmp, sizeof(*mmp_cmp)))
return EXT2_ET_MMP_CHANGE_ABORT;
mmp->mmp_time = tv.tv_sec;
mmp->mmp_seq = EXT4_MMP_SEQ_FSCK;
retval = ext2fs_mmp_write(fs, fs->super->s_mmp_block, fs->mmp_buf);
mmp_error:
return retval;
#else
if (!ext2fs_has_feature_mmp(fs->super) ||
!(fs->flags & EXT2_FLAG_RW) || (fs->flags & EXT2_FLAG_SKIP_MMP))
return 0;
return EXT2_ET_OP_NOT_SUPPORTED;
#endif
}
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif

126
src/ext2fs/newdir.c Normal file
View File

@ -0,0 +1,126 @@
/*
* newdir.c --- create a new directory block
*
* Copyright (C) 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#ifndef EXT2_FT_DIR
#define EXT2_FT_DIR 2
#endif
/*
* Create new directory block
*/
errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
ext2_ino_t parent_ino, char **block)
{
struct ext2_dir_entry *dir = NULL;
errcode_t retval;
char *buf;
int rec_len;
int filetype = 0;
struct ext2_dir_entry_tail *t;
int csum_size = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_get_mem(fs->blocksize, &buf);
if (retval)
return retval;
memset(buf, 0, fs->blocksize);
dir = (struct ext2_dir_entry *) buf;
if (ext2fs_has_feature_metadata_csum(fs->super))
csum_size = sizeof(struct ext2_dir_entry_tail);
retval = ext2fs_set_rec_len(fs, fs->blocksize - csum_size, dir);
if (retval) {
ext2fs_free_mem(&buf);
return retval;
}
if (dir_ino) {
if (ext2fs_has_feature_filetype(fs->super))
filetype = EXT2_FT_DIR;
/*
* Set up entry for '.'
*/
dir->inode = dir_ino;
ext2fs_dirent_set_name_len(dir, 1);
ext2fs_dirent_set_file_type(dir, filetype);
dir->name[0] = '.';
rec_len = (fs->blocksize - csum_size) - EXT2_DIR_REC_LEN(1);
dir->rec_len = EXT2_DIR_REC_LEN(1);
/*
* Set up entry for '..'
*/
dir = (struct ext2_dir_entry *) (buf + dir->rec_len);
retval = ext2fs_set_rec_len(fs, rec_len, dir);
if (retval) {
ext2fs_free_mem(&buf);
return retval;
}
dir->inode = parent_ino;
ext2fs_dirent_set_name_len(dir, 2);
ext2fs_dirent_set_file_type(dir, filetype);
dir->name[0] = '.';
dir->name[1] = '.';
}
if (csum_size) {
t = EXT2_DIRENT_TAIL(buf, fs->blocksize);
ext2fs_initialize_dirent_tail(fs, t);
}
*block = buf;
return 0;
}
/*
* Create new directory on inline data
*/
errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs,
ext2_ino_t dir_ino EXT2FS_ATTR((unused)),
ext2_ino_t parent_ino, __u32 *iblock)
{
struct ext2_dir_entry *dir = NULL;
errcode_t retval;
int rec_len;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
iblock[0] = ext2fs_cpu_to_le32(parent_ino);
dir = (struct ext2_dir_entry *)((char *)iblock +
EXT4_INLINE_DATA_DOTDOT_SIZE);
dir->inode = 0;
rec_len = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DATA_DOTDOT_SIZE;
retval = ext2fs_set_rec_len(fs, rec_len, dir);
if (retval)
goto errout;
#ifdef WORDS_BIGENDIAN
retval = ext2fs_dirent_swab_out2(fs, (char *)dir, rec_len, 0);
if (retval)
goto errout;
#endif
errout:
return retval;
}

831
src/ext2fs/nt_io.c Normal file
View File

@ -0,0 +1,831 @@
/*
* nt_io.c --- This is the Nt I/O interface to the I/O manager.
*
* Implements a one-block write-through cache.
*
* Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
* Copyright (C) 1998 Andrey Shedel <andreys@ns.cr.cyco.com>
* Copyright (C) 2018-2019 Pete Batard <pete@akeo.ie>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <errno.h>
#include <sys/types.h>
#include <windows.h>
#include <winternl.h>
#include "config.h"
#include "ext2fs.h"
#include "rufus.h"
#include "msapi_utf8.h"
extern char* NtStatusError(NTSTATUS Status);
PF_TYPE_DECL(NTAPI, ULONG, RtlNtStatusToDosError, (NTSTATUS));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtOpenFile, (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtFlushBuffersFile, (HANDLE, PIO_STATUS_BLOCK));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtReadFile, (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtWriteFile, (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtDeviceIoControlFile, (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtFsControlFile, (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, ULONG, PVOID, ULONG, PVOID, ULONG));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtDelayExecution, (BOOLEAN, PLARGE_INTEGER));
// TODO: Sort out ASSERT and __attribute__(align)
#define ASSERT(x)
#define ARGUMENT_PRESENT(ArgumentPointer) ((CHAR *)((ULONG_PTR)(ArgumentPointer)) != (CHAR *)(NULL))
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
#define BooleanFlagOn(Flags, SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0)))
#define EXT2_CHECK_MAGIC(struct, code) if ((struct)->magic != (code)) return (code)
#define EXT2_ET_MAGIC_NT_IO_CHANNEL 0x10ed
// Private data block
typedef struct _NT_PRIVATE_DATA {
int magic;
HANDLE handle;
int flags;
char* buffer;
__u32 buffer_block_number;
ULONG buffer_size;
BOOLEAN read_only;
BOOLEAN written;
} NT_PRIVATE_DATA, *PNT_PRIVATE_DATA;
//
// Standard interface prototypes
//
static errcode_t nt_open(const char *name, int flags, io_channel *channel);
static errcode_t nt_close(io_channel channel);
static errcode_t nt_set_blksize(io_channel channel, int blksize);
static errcode_t nt_read_blk(io_channel channel, unsigned long block, int count, void *data);
static errcode_t nt_write_blk(io_channel channel, unsigned long block, int count, const void *data);
static errcode_t nt_flush(io_channel channel);
static struct struct_io_manager struct_nt_manager = {
.magic = EXT2_ET_MAGIC_IO_MANAGER,
.name = "NT I/O Manager",
.open = nt_open,
.close = nt_close,
.set_blksize = nt_set_blksize,
.read_blk = nt_read_blk,
.write_blk = nt_write_blk,
.flush = nt_flush
};
io_manager nt_io_manager(void)
{
return &struct_nt_manager;
}
// Convert Win32 errors to unix errno
typedef struct {
ULONG WinError;
int errnocode;
}ERROR_ENTRY;
static ERROR_ENTRY ErrorTable[] = {
{ ERROR_INVALID_FUNCTION, EINVAL },
{ ERROR_FILE_NOT_FOUND, ENOENT },
{ ERROR_PATH_NOT_FOUND, ENOENT },
{ ERROR_TOO_MANY_OPEN_FILES, EMFILE },
{ ERROR_ACCESS_DENIED, EACCES },
{ ERROR_INVALID_HANDLE, EBADF },
{ ERROR_ARENA_TRASHED, ENOMEM },
{ ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
{ ERROR_INVALID_BLOCK, ENOMEM },
{ ERROR_BAD_ENVIRONMENT, E2BIG },
{ ERROR_BAD_FORMAT, ENOEXEC },
{ ERROR_INVALID_ACCESS, EINVAL },
{ ERROR_INVALID_DATA, EINVAL },
{ ERROR_INVALID_DRIVE, ENOENT },
{ ERROR_CURRENT_DIRECTORY, EACCES },
{ ERROR_NOT_SAME_DEVICE, EXDEV },
{ ERROR_NO_MORE_FILES, ENOENT },
{ ERROR_LOCK_VIOLATION, EACCES },
{ ERROR_BAD_NETPATH, ENOENT },
{ ERROR_NETWORK_ACCESS_DENIED, EACCES },
{ ERROR_BAD_NET_NAME, ENOENT },
{ ERROR_FILE_EXISTS, EEXIST },
{ ERROR_CANNOT_MAKE, EACCES },
{ ERROR_FAIL_I24, EACCES },
{ ERROR_INVALID_PARAMETER, EINVAL },
{ ERROR_NO_PROC_SLOTS, EAGAIN },
{ ERROR_DRIVE_LOCKED, EACCES },
{ ERROR_BROKEN_PIPE, EPIPE },
{ ERROR_DISK_FULL, ENOSPC },
{ ERROR_INVALID_TARGET_HANDLE, EBADF },
{ ERROR_INVALID_HANDLE, EINVAL },
{ ERROR_WAIT_NO_CHILDREN, ECHILD },
{ ERROR_CHILD_NOT_COMPLETE, ECHILD },
{ ERROR_DIRECT_ACCESS_HANDLE, EBADF },
{ ERROR_NEGATIVE_SEEK, EINVAL },
{ ERROR_SEEK_ON_DEVICE, EACCES },
{ ERROR_DIR_NOT_EMPTY, ENOTEMPTY },
{ ERROR_NOT_LOCKED, EACCES },
{ ERROR_BAD_PATHNAME, ENOENT },
{ ERROR_MAX_THRDS_REACHED, EAGAIN },
{ ERROR_LOCK_FAILED, EACCES },
{ ERROR_ALREADY_EXISTS, EEXIST },
{ ERROR_FILENAME_EXCED_RANGE, ENOENT },
{ ERROR_NESTING_NOT_ALLOWED, EAGAIN },
{ ERROR_NOT_ENOUGH_QUOTA, ENOMEM }
};
static unsigned _MapDosError (IN ULONG WinError)
{
int i;
for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i) {
if (WinError == ErrorTable[i].WinError) {
return ErrorTable[i].errnocode;
}
}
// Not in table. Check ranges
if ((WinError >= ERROR_WRITE_PROTECT) && (WinError <= ERROR_SHARING_BUFFER_EXCEEDED))
return EACCES;
else if ((WinError >= ERROR_INVALID_STARTING_CODESEG) && (WinError <= ERROR_INFLOOP_IN_RELOC_CHAIN))
return ENOEXEC;
else
return EINVAL;
}
// Map NT status to dos error.
static __inline unsigned _MapNtStatus(IN NTSTATUS Status)
{
PF_INIT(RtlNtStatusToDosError, Ntdll);
return (pfRtlNtStatusToDosError == NULL) ? EFAULT: _MapDosError(pfRtlNtStatusToDosError(Status));
}
//
// Helper functions
//
static NTSTATUS _OpenNtName(IN PCSTR Name, IN BOOLEAN Readonly, OUT PHANDLE Handle, OUT PBOOLEAN OpenedReadonly OPTIONAL)
{
// ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
WCHAR Buffer[512];
NTSTATUS Status = EFAULT;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
PF_INIT(NtDelayExecution, Ntdll);
PF_INIT_OR_OUT(NtOpenFile, Ntdll);
utf8_to_wchar_no_alloc(Name, Buffer, ARRAYSIZE(Buffer));
// Make Unicode name from input string
UnicodeString.Buffer = Buffer;
UnicodeString.Length = (USHORT) wcslen(Buffer) * 2;
UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!!
// Initialize object
InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
// Try to open it in initial mode
if (ARGUMENT_PRESENT(OpenedReadonly))
*OpenedReadonly = Readonly;
Status = pfNtOpenFile(Handle, SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA),
&ObjectAttributes, &IoStatusBlock, FILE_SHARE_WRITE | FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status)) {
uprintf("_OpenNtName: [%x] %s", Status, NtStatusError(Status));
// Maybe was just mounted? wait 0.5 sec and retry.
LARGE_INTEGER Interval;
Interval.QuadPart = -5000000; // 0.5 sec. from now
if (pfNtDelayExecution != NULL)
pfNtDelayExecution(FALSE, &Interval);
else
Sleep(500);
Status = pfNtOpenFile(Handle, SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA),
&ObjectAttributes, &IoStatusBlock, FILE_SHARE_WRITE | FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
// Try to satisfy mode
if ((Status == STATUS_ACCESS_DENIED) && !Readonly) {
if (ARGUMENT_PRESENT(OpenedReadonly))
*OpenedReadonly = TRUE;
Status = pfNtOpenFile(Handle, SYNCHRONIZE | FILE_READ_DATA, &ObjectAttributes,
&IoStatusBlock, FILE_SHARE_WRITE | FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
}
}
out:
return Status;
}
static NTSTATUS _OpenDriveLetter(IN CHAR Letter, IN BOOLEAN ReadOnly, OUT PHANDLE Handle, OUT PBOOLEAN OpenedReadonly OPTIONAL)
{
CHAR Buffer[100];
sprintf(Buffer, "\\DosDevices\\%c:", Letter);
return _OpenNtName(Buffer, ReadOnly, Handle, OpenedReadonly);
}
static __inline NTSTATUS _FlushDrive(IN HANDLE Handle)
{
IO_STATUS_BLOCK IoStatusBlock;
PF_INIT(NtFlushBuffersFile, NtDll);
return (pfNtFlushBuffersFile == NULL) ? STATUS_DLL_NOT_FOUND : pfNtFlushBuffersFile(Handle, &IoStatusBlock);
}
static __inline NTSTATUS _LockDrive(IN HANDLE Handle)
{
IO_STATUS_BLOCK IoStatusBlock;
PF_INIT(NtFsControlFile, NtDll);
return (pfNtFsControlFile == NULL) ? STATUS_DLL_NOT_FOUND : pfNtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_LOCK_VOLUME, 0, 0, 0, 0);
}
static __inline NTSTATUS _UnlockDrive(IN HANDLE Handle)
{
IO_STATUS_BLOCK IoStatusBlock;
PF_INIT(NtFsControlFile, NtDll);
return (pfNtFsControlFile == NULL) ? STATUS_DLL_NOT_FOUND : pfNtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0);
}
static __inline NTSTATUS _DismountDrive(IN HANDLE Handle)
{
IO_STATUS_BLOCK IoStatusBlock;
PF_INIT(NtFsControlFile, NtDll);
return (pfNtFsControlFile == NULL) ? STATUS_DLL_NOT_FOUND : pfNtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0);
}
static __inline BOOLEAN _IsMounted(IN HANDLE Handle)
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status = STATUS_DLL_NOT_FOUND;
PF_INIT(NtFsControlFile, NtDll);
if (pfNtFsControlFile != NULL)
pfNtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0);
return (BOOLEAN)(Status == STATUS_SUCCESS);
}
static __inline NTSTATUS _CloseDisk(IN HANDLE Handle)
{
PF_INIT(NtClose, Ntdll);
return (pfNtClose == NULL) ? STATUS_DLL_NOT_FOUND : pfNtClose(Handle);
}
//
// Make NT name from any recognized name
//
static PCSTR _NormalizeDeviceName(IN PCSTR Device, IN PSTR NormalizedDeviceNameBuffer)
{
int PartitionNumber = -1;
UCHAR DiskNumber;
PSTR p;
// Convert non NT paths to NT
if (Device[0] == '\\') {
if ((strlen(Device) < 4) || (Device[3] != '\\'))
return Device;
strcpy(NormalizedDeviceNameBuffer, Device);
if ((NormalizedDeviceNameBuffer[1] == '\\') || (NormalizedDeviceNameBuffer[1] == '.'))
NormalizedDeviceNameBuffer[1] = '?';
if (NormalizedDeviceNameBuffer[2] == '.')
NormalizedDeviceNameBuffer[2] = '?';
return NormalizedDeviceNameBuffer;
}
// For now, don't allow the conversion of non absolute paths.
// Too easy to get a C:\ drive altered on a mishap otherwise...
return NULL;
// Strip leading '/dev/' if any
if ((Device[0] == '/') &&
(Device[1] == 'd') &&
(Device[2] == 'e') &&
(Device[3] == 'v') &&
(Device[4] == '/')) {
Device = &Device[5];
}
if (Device[0] == '\0') {
return NULL;
}
// forms: hda[n], sda[n], fd[n]
if (Device[1] != 'd') {
return NULL;
}
if ((Device[0] == 'h') || (Device[0] == 's')) {
if ((Device[2] < 'a') || (Device[2] > ('a' + 9)) ||
((Device[3] != '\0') &&
((Device[4] != '\0') ||
((Device[3] < '0') || (Device[3] > '9'))
)
)
) {
return NULL;
}
DiskNumber = (UCHAR)(Device[2] - 'a');
if(Device[3] != '\0') {
PartitionNumber = (*(Device + 3) - '0');
}
} else if (Device[0] == 'f') {
// 3-d letter should be a digit.
if ((Device[3] != '\0') ||
(Device[2] < '0') || (Device[2] > '9')) {
return NULL;
}
DiskNumber = (UCHAR)(*(Device + 2) - '0');
} else {
// invalid prefix
return NULL;
}
// Prefix
strcpy(NormalizedDeviceNameBuffer, "\\Device\\");
// Media name
switch(*Device) {
case 'f':
strcat(NormalizedDeviceNameBuffer, "Floppy0");
break;
case 'h':
strcat(NormalizedDeviceNameBuffer, "Harddisk0");
break;
}
p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1;
p[0] = (CHAR)(p[0] + DiskNumber);
// Partition nr.
if (PartitionNumber >= 0) {
strcat(NormalizedDeviceNameBuffer, "\\Partition0");
p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1;
p[0] = (CHAR)(p[0] + PartitionNumber);
}
return NormalizedDeviceNameBuffer;
}
static VOID _GetDeviceSize(IN HANDLE h, OUT unsigned __int64 *FsSize)
{
PARTITION_INFORMATION_EX pi;
DISK_GEOMETRY_EX gi;
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER li;
*FsSize = 0;
PF_INIT(NtDeviceIoControlFile, NtDll);
if (pfNtDeviceIoControlFile == NULL)
return;
RtlZeroMemory(&pi, sizeof(pi));
Status = pfNtDeviceIoControlFile(h, NULL, NULL, NULL, &IoStatusBlock,
IOCTL_DISK_GET_PARTITION_INFO_EX,
&pi, sizeof(pi), &pi, sizeof(pi));
if (NT_SUCCESS(Status)) {
uprintf("Size retrieved with: IOCTL_DISK_GET_PARTITION_INFO_EX");
*FsSize = pi.PartitionLength.QuadPart;
} else if (Status == STATUS_INVALID_DEVICE_REQUEST) {
// No partitions: Try a drive geometry request
uprintf("IOCTL_DISK_GET_PARTITION_INFO_EX failed, trying with IOCTL_DISK_GET_DRIVE_GEOMETRY_EX");
RtlZeroMemory(&gi, sizeof(gi));
Status = pfNtDeviceIoControlFile(h, NULL, NULL, NULL, &IoStatusBlock,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
&gi, sizeof(gi), &gi, sizeof(gi));
if (NT_SUCCESS(Status)) {
uprintf("Size retrieved with: IOCTL_DISK_GET_DRIVE_GEOMETRY_EX");
*FsSize = gi.DiskSize.QuadPart;
} else {
uprintf("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: [%x] %s", Status, NtStatusError(Status));
}
} else if (Status == STATUS_INVALID_PARAMETER) {
// Possibly a straight image file
if (GetFileSizeEx(h, &li))
*FsSize = li.QuadPart;
}
}
static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE Handle, OUT PBOOLEAN OpenedReadonly OPTIONAL, OUT errcode_t *Errno OPTIONAL)
{
CHAR NormalizedDeviceName[512];
NTSTATUS Status;
if (Name == NULL) {
if (ARGUMENT_PRESENT(Errno))
*Errno = ENOENT;
return FALSE;
}
if ((((*Name) | 0x20) >= 'a') && (((*Name) | 0x20) <= 'z') &&
(':' == *(Name + 1)) && ('\0' == *(Name + 2))) {
Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly);
} else {
Name = _NormalizeDeviceName(Name, NormalizedDeviceName);
if (Name == NULL) {
if (ARGUMENT_PRESENT(Errno))
*Errno = ENOENT;
return FALSE;
}
Status = _OpenNtName(Name, ReadOnly, Handle, OpenedReadonly);
}
if (!NT_SUCCESS(Status)) {
if (ARGUMENT_PRESENT(Errno))
*Errno = _MapNtStatus(Status);
return FALSE;
}
return TRUE;
}
static BOOLEAN _BlockIo(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, IN OUT PCHAR Buffer, IN BOOLEAN Read, OUT unsigned* Errno)
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status = STATUS_DLL_NOT_FOUND;
PF_INIT_OR_OUT(NtReadFile, NtDll);
PF_INIT_OR_OUT(NtWriteFile, NtDll);
// Should be aligned
ASSERT(0 == (Bytes % 512));
ASSERT(0 == (Offset.LowPart % 512));
// Perform io
if(Read) {
Status = pfNtReadFile(Handle, NULL, NULL, NULL,
&IoStatusBlock, Buffer, Bytes, &Offset, NULL);
} else {
Status = pfNtWriteFile(Handle, NULL, NULL, NULL,
&IoStatusBlock, Buffer, Bytes, &Offset, NULL);
}
out:
if (NT_SUCCESS(Status)) {
*Errno = 0;
return TRUE;
}
*Errno = _MapNtStatus(Status);
return FALSE;
}
static BOOLEAN _RawWrite(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, OUT const CHAR* Buffer, OUT unsigned* Errno)
{
return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno);
}
static BOOLEAN _RawRead(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, IN PCHAR Buffer, OUT unsigned* Errno)
{
return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno);
}
static BOOLEAN _SetPartType(IN HANDLE Handle, IN UCHAR Type)
{
IO_STATUS_BLOCK IoStatusBlock;
PF_INIT(NtDeviceIoControlFile, NtDll);
if (pfNtDeviceIoControlFile == NULL)
return FALSE;
return NT_SUCCESS(pfNtDeviceIoControlFile(Handle, NULL, NULL, NULL, &IoStatusBlock,
IOCTL_DISK_SET_PARTITION_INFO, &Type,
sizeof(Type), NULL, 0));
}
//
// Interface functions.
// Is_mounted is set to 1 if the device is mounted, 0 otherwise
//
errcode_t
ext2fs_check_if_mounted(const char *file, int *mount_flags)
{
HANDLE h;
BOOLEAN Readonly;
*mount_flags = 0;
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL))
return 0;
*mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0;
_CloseDisk(h);
return 0;
}
// Returns the number of blocks in a partition
// Note: Do *NOT* be tempted to cache the device size according to the NT path as
// different removable devices (e.g. UFD) may be remounted under the same path.
errcode_t ext2fs_get_device_size(const char *file, int blocksize, blk64_t *retblocks)
{
__int64 fs_size = 0;
HANDLE h;
BOOLEAN Readonly;
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) {
uprintf("FAILED TO OPEN '%s'", file);
return EACCES;
}
_GetDeviceSize(h, &fs_size);
_CloseDisk(h);
*retblocks = (blk64_t)(fs_size / blocksize);
return 0;
}
//
// Table elements
//
static errcode_t nt_open(const char *name, int flags, io_channel *channel)
{
io_channel io = NULL;
PNT_PRIVATE_DATA nt_data = NULL;
errcode_t errcode = 0;
if (name == NULL)
return EXT2_ET_BAD_DEVICE_NAME;
// Allocate channel handle
io = (io_channel) malloc(sizeof(struct struct_io_channel));
if (io == NULL) {
errcode = ENOMEM;
goto out;
}
RtlZeroMemory(io, sizeof(struct struct_io_channel));
io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
nt_data = (PNT_PRIVATE_DATA) malloc(sizeof(NT_PRIVATE_DATA));
if (nt_data == NULL) {
errcode = ENOMEM;
goto out;
}
io->manager = nt_io_manager();
io->name = malloc(strlen(name) + 1);
if (io->name == NULL) {
errcode = ENOMEM;
goto out;
}
strcpy(io->name, name);
io->private_data = nt_data;
io->block_size = 1024;
io->read_error = 0;
io->write_error = 0;
io->refcount = 1;
// Initialize data
RtlZeroMemory(nt_data, sizeof(NT_PRIVATE_DATA));
nt_data->magic = EXT2_ET_MAGIC_NT_IO_CHANNEL;
nt_data->buffer_block_number = 0xffffffff;
nt_data->buffer_size = 1024;
nt_data->buffer = malloc(nt_data->buffer_size);
if (nt_data->buffer == NULL) {
errcode = ENOMEM;
goto out;
}
// Open the device
if (!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &nt_data->handle, &nt_data->read_only, &errcode))
goto out;
// Get the size
// _GetDeviceSize(nt_data->handle, &fs_size);
// strcpy(known_device, name);
// Lock/dismount
// if (!NT_SUCCESS(_LockDrive(nt_data->handle)) /*|| !NT_SUCCESS(_DismountDrive(NtData->Handle))*/)
// nt_data->read_only = TRUE;
// Done
*channel = io;
out:
if (errcode) {
if (io != NULL) {
free(io->name);
free(io);
}
if (nt_data != NULL) {
if (nt_data->handle != NULL) {
_UnlockDrive(nt_data->handle);
_CloseDisk(nt_data->handle);
}
free(nt_data->buffer);
free(nt_data);
}
}
return errcode;
}
static errcode_t nt_close(io_channel channel)
{
PNT_PRIVATE_DATA nt_data = NULL;
if (channel == NULL)
return 0;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;
EXT2_CHECK_MAGIC(nt_data, EXT2_ET_MAGIC_NT_IO_CHANNEL);
if (--channel->refcount > 0)
return 0;
free(channel->name);
free(channel);
if (nt_data != NULL) {
if (nt_data->handle != NULL)
CloseHandle(nt_data->handle);
free(nt_data->buffer);
free(nt_data);
}
return 0;
}
static errcode_t nt_set_blksize(io_channel channel, int blksize)
{
PNT_PRIVATE_DATA nt_data = NULL;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;
EXT2_CHECK_MAGIC(nt_data, EXT2_ET_MAGIC_NT_IO_CHANNEL);
if (channel->block_size != blksize) {
channel->block_size = blksize;
free(nt_data->buffer);
nt_data->buffer_block_number = 0xffffffff;
nt_data->buffer_size = channel->block_size;
ASSERT(0 == (nt_data->BufferSize % 512));
nt_data->buffer = malloc(nt_data->buffer_size);
if (nt_data->buffer == NULL)
return ENOMEM;
}
return 0;
}
static errcode_t nt_read_blk(io_channel channel, unsigned long block, int count, void *buf)
{
PVOID read_buffer;
ULONG read_size;
ULONG size;
LARGE_INTEGER offset;
PNT_PRIVATE_DATA nt_data = NULL;
unsigned errcode = 0;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;
EXT2_CHECK_MAGIC(nt_data, EXT2_ET_MAGIC_NT_IO_CHANNEL);
// If it's in the cache, use it!
if ((count == 1) && (block == nt_data->buffer_block_number) &&
(nt_data->buffer_block_number != 0xffffffff)) {
memcpy(buf, nt_data->buffer, channel->block_size);
return 0;
}
size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size);
offset.QuadPart = block * channel->block_size;
// If not fit to the block
if (size <= nt_data->buffer_size) {
// Update the cache
nt_data->buffer_block_number = block;
read_buffer = nt_data->buffer;
read_size = nt_data->buffer_size;
} else {
read_size = size;
read_buffer = buf;
ASSERT((read_size % channel->block_size) == 0);
}
if (!_RawRead(nt_data->handle, offset, read_size, read_buffer, &errcode)) {
if (channel->read_error)
return (channel->read_error)(channel, block, count, buf, size, 0, errcode);
else
return errcode;
}
if (read_buffer != buf) {
ASSERT(size <= read_size);
memcpy(buf, read_buffer, size);
}
return 0;
}
// TODO: Add an nt_write_blk64()
static errcode_t nt_write_blk(io_channel channel, unsigned long block, int count, const void *buf)
{
ULONG write_size;
LARGE_INTEGER offset;
PNT_PRIVATE_DATA nt_data = NULL;
unsigned errcode = 0;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;
EXT2_CHECK_MAGIC(nt_data, EXT2_ET_MAGIC_NT_IO_CHANNEL);
if (nt_data->read_only)
return EACCES;
if (count == 1) {
write_size = channel->block_size;
} else {
nt_data->buffer_block_number = 0xffffffff;
if (count < 0)
write_size = (ULONG)(-count);
else
write_size = (ULONG)(count * channel->block_size);
}
ASSERT(0 == (write_size % 512));
offset.QuadPart = block * channel->block_size;
if (!_RawWrite(nt_data->handle, offset, write_size, buf, &errcode)) {
if (channel->write_error)
return (channel->write_error)(channel, block, count, buf, write_size, 0, errcode);
else
return errcode;
}
// Stash a copy.
if(write_size >= nt_data->buffer_size) {
nt_data->buffer_block_number = block;
memcpy(nt_data->buffer, buf, nt_data->buffer_size);
}
nt_data->written = TRUE;
return 0;
}
static errcode_t nt_flush(io_channel channel)
{
PNT_PRIVATE_DATA nt_data = NULL;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;
EXT2_CHECK_MAGIC(nt_data, EXT2_ET_MAGIC_NT_IO_CHANNEL);
if(nt_data->read_only)
return 0;
// Flush file buffers.
_FlushDrive(nt_data->handle);
// Test and correct partition type.
if (nt_data->written)
_SetPartType(nt_data->handle, 0x83);
return 0;
}

509
src/ext2fs/punch.c Normal file
View File

@ -0,0 +1,509 @@
/*
* punch.c --- deallocate blocks allocated to an inode
*
* Copyright (C) 2010 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
#undef PUNCH_DEBUG
/*
* This function returns 1 if the specified block is all zeros
*/
static int check_zero_block(char *buf, int blocksize)
{
char *cp = buf;
int left = blocksize;
while (left > 0) {
if (*cp++)
return 0;
left--;
}
return 1;
}
/*
* This clever recursive function handles i_blocks[] as well as
* indirect, double indirect, and triple indirect blocks. It iterates
* over the entries in the i_blocks array or indirect blocks, and for
* each one, will recursively handle any indirect blocks and then
* frees and deallocates the blocks.
*/
static errcode_t ind_punch(ext2_filsys fs, struct ext2_inode *inode,
char *block_buf, blk_t *p, int level,
blk64_t start, blk64_t count, int max)
{
errcode_t retval;
blk_t b;
int i;
blk64_t offset, incr;
int freed = 0;
#ifdef PUNCH_DEBUG
printf("Entering ind_punch, level %d, start %llu, count %llu, "
"max %d\n", level, start, count, max);
#endif
incr = 1ULL << ((EXT2_BLOCK_SIZE_BITS(fs->super) - 2) * level);
for (i = 0, offset = 0; i < max; i++, p++, offset += incr) {
if (offset >= start + count)
break;
if (*p == 0 || (offset+incr) <= start)
continue;
b = *p;
if (level > 0) {
blk_t start2;
#ifdef PUNCH_DEBUG
printf("Reading indirect block %u\n", b);
#endif
retval = ext2fs_read_ind_block(fs, b, block_buf);
if (retval)
return retval;
start2 = (start > offset) ? start - offset : 0;
retval = ind_punch(fs, inode, block_buf + fs->blocksize,
(blk_t *) block_buf, level - 1,
start2, count - offset,
fs->blocksize >> 2);
if (retval)
return retval;
retval = ext2fs_write_ind_block(fs, b, block_buf);
if (retval)
return retval;
if (!check_zero_block(block_buf, fs->blocksize))
continue;
}
#ifdef PUNCH_DEBUG
printf("Freeing block %u (offset %llu)\n", b, offset);
#endif
ext2fs_block_alloc_stats(fs, b, -1);
*p = 0;
freed++;
}
#ifdef PUNCH_DEBUG
printf("Freed %d blocks\n", freed);
#endif
return ext2fs_iblk_sub_blocks(fs, inode, freed);
}
#define BLK_T_MAX ((blk_t)~0ULL)
static errcode_t ext2fs_punch_ind(ext2_filsys fs, struct ext2_inode *inode,
char *block_buf, blk64_t start, blk64_t end)
{
errcode_t retval;
char *buf = 0;
int level;
int num = EXT2_NDIR_BLOCKS;
blk_t *bp = inode->i_block;
blk_t addr_per_block;
blk64_t max = EXT2_NDIR_BLOCKS;
blk_t count;
/* Check start/end don't overflow the 2^32-1 indirect block limit */
if (start > BLK_T_MAX)
return 0;
if (end >= BLK_T_MAX || end - start + 1 >= BLK_T_MAX)
count = BLK_T_MAX - start;
else
count = end - start + 1;
if (!block_buf) {
retval = ext2fs_get_array(3, fs->blocksize, &buf);
if (retval)
return retval;
block_buf = buf;
}
addr_per_block = (blk_t)fs->blocksize >> 2;
for (level = 0; level < 4; level++, max *= (blk64_t)addr_per_block) {
#ifdef PUNCH_DEBUG
printf("Main loop level %d, start %llu count %u "
"max %llu num %d\n", level, start, count, max, num);
#endif
if (start < max) {
retval = ind_punch(fs, inode, block_buf, bp, level,
start, count, num);
if (retval)
goto errout;
if (count > max)
count -= max - start;
else
break;
start = 0;
} else
start -= max;
bp += num;
if (level == 0) {
num = 1;
max = 1;
}
}
retval = 0;
errout:
if (buf)
ext2fs_free_mem(&buf);
return retval;
}
#undef BLK_T_MAX
#ifdef PUNCH_DEBUG
#define dbg_printf(f, a...) printf(f, ## a)
static void dbg_print_extent(char *desc, struct ext2fs_extent *extent)
{
if (desc)
printf("%s: ", desc);
printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ",
extent->e_lblk, extent->e_lblk + extent->e_len - 1,
extent->e_len, extent->e_pblk);
if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF)
fputs("LEAF ", stdout);
if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT)
fputs("UNINIT ", stdout);
if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)
fputs("2ND_VISIT ", stdout);
if (!extent->e_flags)
fputs("(none)", stdout);
fputc('\n', stdout);
}
#else
#define dbg_print_extent(desc, ex) do { } while (0)
#define dbg_printf(f, ...) do { } while (0)
#endif
/* Free a range of blocks, respecting cluster boundaries */
static errcode_t punch_extent_blocks(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
blk64_t lfree_start, blk64_t free_start,
__u32 free_count, int *freed)
{
blk64_t pblk;
int freed_now = 0;
__u32 cluster_freed;
errcode_t retval = 0;
/* No bigalloc? Just free each block. */
if (EXT2FS_CLUSTER_RATIO(fs) == 1) {
*freed += free_count;
while (free_count-- > 0)
ext2fs_block_alloc_stats2(fs, free_start++, -1);
return retval;
}
/*
* Try to free up to the next cluster boundary. We assume that all
* blocks in a logical cluster map to blocks from the same physical
* cluster, and that the offsets within the [pl]clusters match.
*/
if (free_start & EXT2FS_CLUSTER_MASK(fs)) {
retval = ext2fs_map_cluster_block(fs, ino, inode,
lfree_start, &pblk);
if (retval)
goto errout;
if (!pblk) {
ext2fs_block_alloc_stats2(fs, free_start, -1);
freed_now++;
}
cluster_freed = EXT2FS_CLUSTER_RATIO(fs) -
(free_start & EXT2FS_CLUSTER_MASK(fs));
if (cluster_freed > free_count)
cluster_freed = free_count;
free_count -= cluster_freed;
free_start += cluster_freed;
lfree_start += cluster_freed;
}
/* Free whole clusters from the middle of the range. */
while (free_count > 0 && free_count >= (unsigned) EXT2FS_CLUSTER_RATIO(fs)) {
ext2fs_block_alloc_stats2(fs, free_start, -1);
freed_now++;
cluster_freed = EXT2FS_CLUSTER_RATIO(fs);
free_count -= cluster_freed;
free_start += cluster_freed;
lfree_start += cluster_freed;
}
/* Try to free the last cluster. */
if (free_count > 0) {
retval = ext2fs_map_cluster_block(fs, ino, inode,
lfree_start, &pblk);
if (retval)
goto errout;
if (!pblk) {
ext2fs_block_alloc_stats2(fs, free_start, -1);
freed_now++;
}
}
errout:
*freed += freed_now;
return retval;
}
static errcode_t ext2fs_punch_extent(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
blk64_t start, blk64_t end)
{
ext2_extent_handle_t handle = 0;
struct ext2fs_extent extent;
errcode_t retval;
blk64_t free_start, next, lfree_start;
__u32 free_count, newlen;
int freed = 0;
int op;
retval = ext2fs_extent_open2(fs, ino, inode, &handle);
if (retval)
return retval;
/*
* Find the extent closest to the start of the punch range. We don't
* check the return value because _goto() sets the current node to the
* next-lowest extent if 'start' is in a hole, and doesn't set a
* current node if there was a real error reading the extent tree.
* In that case, _get() will error out.
*
* Note: If _get() returns 'no current node', that simply means that
* there aren't any blocks mapped past this point in the file, so we're
* done.
*/
ext2fs_extent_goto(handle, start);
retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &extent);
if (retval == EXT2_ET_NO_CURRENT_NODE) {
retval = 0;
goto errout;
} else if (retval)
goto errout;
while (1) {
op = EXT2_EXTENT_NEXT_LEAF;
dbg_print_extent("main loop", &extent);
next = extent.e_lblk + extent.e_len;
dbg_printf("start %llu, end %llu, next %llu\n",
(unsigned long long) start,
(unsigned long long) end,
(unsigned long long) next);
if (start <= extent.e_lblk) {
/*
* Have we iterated past the end of the punch region?
* If so, we can stop.
*/
if (end < extent.e_lblk)
break;
dbg_printf("Case #%d\n", 1);
/* Start of deleted region before extent;
adjust beginning of extent */
free_start = extent.e_pblk;
lfree_start = extent.e_lblk;
if (next > end)
free_count = end - extent.e_lblk + 1;
else
free_count = extent.e_len;
extent.e_len -= free_count;
extent.e_lblk += free_count;
extent.e_pblk += free_count;
} else if (end >= next-1) {
/*
* Is the punch region beyond this extent? This can
* happen if start is already inside a hole. Try to
* advance to the next extent if this is the case.
*/
if (start >= next)
goto next_extent;
/* End of deleted region after extent;
adjust end of extent */
dbg_printf("Case #%d\n", 2);
newlen = start - extent.e_lblk;
free_start = extent.e_pblk + newlen;
lfree_start = extent.e_lblk + newlen;
free_count = extent.e_len - newlen;
extent.e_len = newlen;
} else {
struct ext2fs_extent newex;
dbg_printf("Case #%d\n", 3);
/* The hard case; we need to split the extent */
newex.e_pblk = extent.e_pblk +
(end + 1 - extent.e_lblk);
newex.e_lblk = end + 1;
newex.e_len = next - end - 1;
newex.e_flags = extent.e_flags;
extent.e_len = start - extent.e_lblk;
free_start = extent.e_pblk + extent.e_len;
lfree_start = extent.e_lblk + extent.e_len;
free_count = end - start + 1;
dbg_print_extent("inserting", &newex);
retval = ext2fs_extent_insert(handle,
EXT2_EXTENT_INSERT_AFTER, &newex);
if (retval)
goto errout;
retval = ext2fs_extent_fix_parents(handle);
if (retval)
goto errout;
/*
* Now pointing at inserted extent; so go back.
*
* We cannot use EXT2_EXTENT_PREV to go back; note the
* subtlety in the comment for fix_parents().
*/
retval = ext2fs_extent_goto(handle, extent.e_lblk);
if (retval)
goto errout;
}
if (extent.e_len) {
dbg_print_extent("replacing", &extent);
retval = ext2fs_extent_replace(handle, 0, &extent);
if (retval)
goto errout;
retval = ext2fs_extent_fix_parents(handle);
} else {
struct ext2fs_extent newex;
blk64_t old_lblk, next_lblk;
dbg_printf("deleting current extent%s\n", "");
/*
* Save the location of the next leaf, then slip
* back to the current extent.
*/
retval = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT,
&newex);
if (retval)
goto errout;
old_lblk = newex.e_lblk;
retval = ext2fs_extent_get(handle,
EXT2_EXTENT_NEXT_LEAF,
&newex);
if (retval == EXT2_ET_EXTENT_NO_NEXT)
next_lblk = old_lblk;
else if (retval)
goto errout;
else
next_lblk = newex.e_lblk;
retval = ext2fs_extent_goto(handle, old_lblk);
if (retval)
goto errout;
/* Now delete the extent. */
retval = ext2fs_extent_delete(handle, 0);
if (retval)
goto errout;
retval = ext2fs_extent_fix_parents(handle);
if (retval && retval != EXT2_ET_NO_CURRENT_NODE)
goto errout;
retval = 0;
/*
* Jump forward to the next extent. If there are
* errors, the ext2fs_extent_get down below will
* capture them for us.
*/
(void)ext2fs_extent_goto(handle, next_lblk);
op = EXT2_EXTENT_CURRENT;
}
if (retval)
goto errout;
dbg_printf("Free start %llu, free count = %u\n",
free_start, free_count);
retval = punch_extent_blocks(fs, ino, inode, lfree_start,
free_start, free_count, &freed);
if (retval)
goto errout;
next_extent:
retval = ext2fs_extent_get(handle, op,
&extent);
if (retval == EXT2_ET_EXTENT_NO_NEXT ||
retval == EXT2_ET_NO_CURRENT_NODE)
break;
if (retval)
goto errout;
}
dbg_printf("Freed %d blocks\n", freed);
retval = ext2fs_iblk_sub_blocks(fs, inode, freed);
errout:
ext2fs_extent_free(handle);
return retval;
}
static errcode_t ext2fs_punch_inline_data(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
blk64_t start,
blk64_t end EXT2FS_ATTR((unused)))
{
errcode_t retval;
/*
* In libext2fs ext2fs_punch is based on block unit. So that
* means that if start > 0 we don't need to do nothing. Due
* to this we will remove all inline data in ext2fs_punch()
* now.
*/
if (start > 0)
return 0;
memset((char *)inode->i_block, 0, EXT4_MIN_INLINE_DATA_SIZE);
inode->i_size = 0;
retval = ext2fs_write_inode(fs, ino, inode);
if (retval)
return retval;
return ext2fs_inline_data_ea_remove(fs, ino);
}
/*
* Deallocate all logical _blocks_ starting at start to end, inclusive.
* If end is ~0ULL, then this is effectively truncate.
*/
errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
char *block_buf, blk64_t start,
blk64_t end)
{
errcode_t retval;
struct ext2_inode inode_buf;
if (start > end)
return EINVAL;
/* Read inode structure if necessary */
if (!inode) {
retval = ext2fs_read_inode(fs, ino, &inode_buf);
if (retval)
return retval;
inode = &inode_buf;
}
if (inode->i_flags & EXT4_INLINE_DATA_FL)
return ext2fs_punch_inline_data(fs, ino, inode, start, end);
else if (inode->i_flags & EXT4_EXTENTS_FL)
retval = ext2fs_punch_extent(fs, ino, inode, start, end);
else
retval = ext2fs_punch_ind(fs, inode, block_buf, start, end);
if (retval)
return retval;
#ifdef PUNCH_DEBUG
printf("%u: write inode size now %u blocks %u\n",
ino, inode->i_size, inode->i_blocks);
#endif
return ext2fs_write_inode(fs, ino, inode);
}

451
src/ext2fs/rbtree.c Normal file
View File

@ -0,0 +1,451 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
linux/lib/rbtree.c
*/
#include "rbtree.h"
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = ext2fs_rb_parent(node);
if ((node->rb_right = right->rb_left))
ext2fs_rb_set_parent(right->rb_left, node);
right->rb_left = node;
ext2fs_rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
ext2fs_rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = ext2fs_rb_parent(node);
if ((node->rb_left = left->rb_right))
ext2fs_rb_set_parent(left->rb_right, node);
left->rb_right = node;
ext2fs_rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
ext2fs_rb_set_parent(node, left);
}
void ext2fs_rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = ext2fs_rb_parent(node)) && ext2fs_rb_is_red(parent))
{
gparent = ext2fs_rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && ext2fs_rb_is_red(uncle))
{
ext2fs_rb_set_black(uncle);
ext2fs_rb_set_black(parent);
ext2fs_rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
ext2fs_rb_set_black(parent);
ext2fs_rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && ext2fs_rb_is_red(uncle))
{
ext2fs_rb_set_black(uncle);
ext2fs_rb_set_black(parent);
ext2fs_rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
ext2fs_rb_set_black(parent);
ext2fs_rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
ext2fs_rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || ext2fs_rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (ext2fs_rb_is_red(other))
{
ext2fs_rb_set_black(other);
ext2fs_rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || ext2fs_rb_is_black(other->rb_left)) &&
(!other->rb_right || ext2fs_rb_is_black(other->rb_right)))
{
ext2fs_rb_set_red(other);
node = parent;
parent = ext2fs_rb_parent(node);
}
else
{
if (!other->rb_right || ext2fs_rb_is_black(other->rb_right))
{
ext2fs_rb_set_black(other->rb_left);
ext2fs_rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
ext2fs_rb_set_color(other, ext2fs_rb_color(parent));
ext2fs_rb_set_black(parent);
ext2fs_rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (ext2fs_rb_is_red(other))
{
ext2fs_rb_set_black(other);
ext2fs_rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || ext2fs_rb_is_black(other->rb_left)) &&
(!other->rb_right || ext2fs_rb_is_black(other->rb_right)))
{
ext2fs_rb_set_red(other);
node = parent;
parent = ext2fs_rb_parent(node);
}
else
{
if (!other->rb_left || ext2fs_rb_is_black(other->rb_left))
{
ext2fs_rb_set_black(other->rb_right);
ext2fs_rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
ext2fs_rb_set_color(other, ext2fs_rb_color(parent));
ext2fs_rb_set_black(parent);
ext2fs_rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
ext2fs_rb_set_black(node);
}
void ext2fs_rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (ext2fs_rb_parent(old)) {
if (ext2fs_rb_parent(old)->rb_left == old)
ext2fs_rb_parent(old)->rb_left = node;
else
ext2fs_rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = ext2fs_rb_parent(node);
color = ext2fs_rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
ext2fs_rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
ext2fs_rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
ext2fs_rb_set_parent(old->rb_left, node);
goto color;
}
parent = ext2fs_rb_parent(node);
color = ext2fs_rb_color(node);
if (child)
ext2fs_rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
static void ext2fs_rb_augment_path(struct rb_node *node, rb_augment_f func, void *data)
{
struct rb_node *parent;
up:
func(node, data);
parent = ext2fs_rb_parent(node);
if (!parent)
return;
if (node == parent->rb_left && parent->rb_right)
func(parent->rb_right, data);
else if (parent->rb_left)
func(parent->rb_left, data);
node = parent;
goto up;
}
/*
* after inserting @node into the tree, update the tree to account for
* both the new entry and any damage done by rebalance
*/
void ext2fs_rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data)
{
if (node->rb_left)
node = node->rb_left;
else if (node->rb_right)
node = node->rb_right;
ext2fs_rb_augment_path(node, func, data);
}
/*
* before removing the node, find the deepest node on the rebalance path
* that will still be there after @node gets removed
*/
struct rb_node *ext2fs_rb_augment_erase_begin(struct rb_node *node)
{
struct rb_node *deepest;
if (!node->rb_right && !node->rb_left)
deepest = ext2fs_rb_parent(node);
else if (!node->rb_right)
deepest = node->rb_left;
else if (!node->rb_left)
deepest = node->rb_right;
else {
deepest = ext2fs_rb_next(node);
if (deepest->rb_right)
deepest = deepest->rb_right;
else if (ext2fs_rb_parent(deepest) != node)
deepest = ext2fs_rb_parent(deepest);
}
return deepest;
}
/*
* after removal, update the tree to account for the removed entry
* and any rebalance damage.
*/
void ext2fs_rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data)
{
if (node)
ext2fs_rb_augment_path(node, func, data);
}
/*
* This function returns the first node (in sort order) of the tree.
*/
struct rb_node *ext2fs_rb_first(const struct rb_root *root)
{
struct rb_node *n;
n = root->rb_node;
if (!n)
return NULL;
while (n->rb_left)
n = n->rb_left;
return n;
}
struct rb_node *ext2fs_rb_last(const struct rb_root *root)
{
struct rb_node *n;
n = root->rb_node;
if (!n)
return NULL;
while (n->rb_right)
n = n->rb_right;
return n;
}
struct rb_node *ext2fs_rb_next(struct rb_node *node)
{
struct rb_node *parent;
if (ext2fs_rb_parent(node) == node)
return NULL;
/* If we have a right-hand child, go down and then left as far
as we can. */
if (node->rb_right) {
node = node->rb_right;
while (node->rb_left)
node=node->rb_left;
return (struct rb_node *)node;
}
/* No right-hand children. Everything down and left is
smaller than us, so any 'next' node must be in the general
direction of our parent. Go up the tree; any time the
ancestor is a right-hand child of its parent, keep going
up. First time it's a left-hand child of its parent, said
parent is our 'next' node. */
while ((parent = ext2fs_rb_parent(node)) && node == parent->rb_right)
node = parent;
return parent;
}
struct rb_node *ext2fs_rb_prev(struct rb_node *node)
{
struct rb_node *parent;
if (ext2fs_rb_parent(node) == node)
return NULL;
/* If we have a left-hand child, go down and then right as far
as we can. */
if (node->rb_left) {
node = node->rb_left;
while (node->rb_right)
node=node->rb_right;
return (struct rb_node *)node;
}
/* No left-hand children. Go up till we find an ancestor which
is a right-hand child of its parent */
while ((parent = ext2fs_rb_parent(node)) && node == parent->rb_left)
node = parent;
return parent;
}
void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root)
{
struct rb_node *parent = ext2fs_rb_parent(victim);
/* Set the surrounding nodes to point to the replacement */
if (parent) {
if (victim == parent->rb_left)
parent->rb_left = new;
else
parent->rb_right = new;
} else {
root->rb_node = new;
}
if (victim->rb_left)
ext2fs_rb_set_parent(victim->rb_left, new);
if (victim->rb_right)
ext2fs_rb_set_parent(victim->rb_right, new);
/* Copy the pointers/colour from the victim to the replacement */
*new = *victim;
}

195
src/ext2fs/rbtree.h Normal file
View File

@ -0,0 +1,195 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
linux/include/linux/rbtree.h
To use rbtrees you'll have to implement your own insert and search cores.
This will avoid us to use callbacks and to drop dramatically performances.
I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity...
Some example of insert and search follows here. The search is a plain
normal search over an ordered tree. The insert instead must be implemented
in two steps: First, the code must insert the element in order as a red leaf
in the tree, and then the support library function rb_insert_color() must
be called. Such function will do the not trivial work to rebalance the
rbtree, if necessary.
-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
unsigned long offset)
{
struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page;
while (n)
{
page = rb_entry(n, struct page, rb_page_cache);
if (offset < page->offset)
n = n->rb_left;
else if (offset > page->offset)
n = n->rb_right;
else
return page;
}
return NULL;
}
static inline struct page * __rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL;
struct page * page;
while (*p)
{
parent = *p;
page = rb_entry(parent, struct page, rb_page_cache);
if (offset < page->offset)
p = &(*p)->rb_left;
else if (offset > page->offset)
p = &(*p)->rb_right;
else
return page;
}
rb_link_node(node, parent, p);
return NULL;
}
static inline struct page * rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out;
rb_insert_color(node, &inode->i_rb_page_cache);
out:
return ret;
}
-----------------------------------------------------------------------
*/
#ifndef _LINUX_RBTREE_H
#define _LINUX_RBTREE_H
#include <stdlib.h>
#include <stdint.h>
// TODO: MSVC __attribute__(x)
#define __attribute__(x)
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define container_of(ptr, type, member) ({ \
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct rb_node
{
uintptr_t rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define ext2fs_rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define ext2fs_rb_color(r) ((r)->rb_parent_color & 1)
#define ext2fs_rb_is_red(r) (!ext2fs_rb_color(r))
#define ext2fs_rb_is_black(r) ext2fs_rb_color(r)
#define ext2fs_rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define ext2fs_rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void ext2fs_rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (uintptr_t)p;
}
static inline void ext2fs_rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
#define RB_ROOT (struct rb_root) { NULL, }
#define ext2fs_rb_entry(ptr, type, member) container_of(ptr, type, member)
static inline int ext2fs_rb_empty_root(struct rb_root *root)
{
return root->rb_node == NULL;
}
static inline int ext2fs_rb_empty_node(struct rb_node *node)
{
return ext2fs_rb_parent(node) == node;
}
static inline void ext2fs_rb_clear_node(struct rb_node *node)
{
ext2fs_rb_set_parent(node, node);
}
extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *);
extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *);
typedef void (*rb_augment_f)(struct rb_node *node, void *data);
extern void ext2fs_rb_augment_insert(struct rb_node *node,
rb_augment_f func, void *data);
extern struct rb_node *ext2fs_rb_augment_erase_begin(struct rb_node *node);
extern void ext2fs_rb_augment_erase_end(struct rb_node *node,
rb_augment_f func, void *data);
/* Find logical next and previous nodes in a tree */
extern struct rb_node *ext2fs_rb_next(struct rb_node *);
extern struct rb_node *ext2fs_rb_prev(struct rb_node *);
extern struct rb_node *ext2fs_rb_first(const struct rb_root *);
extern struct rb_node *ext2fs_rb_last(const struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root);
static inline void ext2fs_rb_link_node(struct rb_node * node,
struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (uintptr_t)parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
#endif /* _LINUX_RBTREE_H */

102
src/ext2fs/read_bb.c Normal file
View File

@ -0,0 +1,102 @@
/*
* read_bb --- read the bad blocks inode
*
* Copyright (C) 1994 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
struct read_bb_record {
ext2_badblocks_list bb_list;
errcode_t err;
};
/*
* Helper function for ext2fs_read_bb_inode()
*/
#ifdef __TURBOC__
#pragma argsused
#endif
static int mark_bad_block(ext2_filsys fs, blk_t *block_nr,
e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
blk_t ref_block EXT2FS_ATTR((unused)),
int ref_offset EXT2FS_ATTR((unused)),
void *priv_data)
{
struct read_bb_record *rb = (struct read_bb_record *) priv_data;
if (blockcnt < 0)
return 0;
if ((*block_nr < fs->super->s_first_data_block) ||
(*block_nr >= ext2fs_blocks_count(fs->super)))
return 0; /* Ignore illegal blocks */
rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
if (rb->err)
return BLOCK_ABORT;
return 0;
}
/*
* Reads the current bad blocks from the bad blocks inode.
*/
errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
{
errcode_t retval;
struct read_bb_record rb;
struct ext2_inode inode;
blk_t numblocks;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!*bb_list) {
retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
return retval;
numblocks = inode.i_blocks;
if (!(ext2fs_has_feature_huge_file(fs->super) &&
(inode.i_flags & EXT4_HUGE_FILE_FL)))
numblocks = numblocks / (fs->blocksize / 512);
numblocks += 20;
if (numblocks < 50)
numblocks = 50;
if (numblocks > 50000)
numblocks = 500;
retval = ext2fs_badblocks_list_create(bb_list, numblocks);
if (retval)
return retval;
}
rb.bb_list = *bb_list;
rb.err = 0;
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_READ_ONLY,
0, mark_bad_block, &rb);
if (retval)
return retval;
return rb.err;
}

430
src/ext2fs/rw_bitmaps.c Normal file
View File

@ -0,0 +1,430 @@
/*
* rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
*
* Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#include "e2image.h"
static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
{
dgrp_t i;
unsigned int j;
int block_nbytes, inode_nbytes;
unsigned int nbits;
errcode_t retval;
char *block_buf = NULL, *inode_buf = NULL;
int csum_flag;
blk64_t blk;
blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
ext2_ino_t ino_itr = 1;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
csum_flag = ext2fs_has_group_desc_csum(fs);
inode_nbytes = block_nbytes = 0;
if (do_block) {
block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
retval = io_channel_alloc_buf(fs->io, 0, &block_buf);
if (retval)
goto errout;
memset(block_buf, 0xff, fs->blocksize);
}
if (do_inode) {
inode_nbytes = (size_t)
((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
retval = io_channel_alloc_buf(fs->io, 0, &inode_buf);
if (retval)
goto errout;
memset(inode_buf, 0xff, fs->blocksize);
}
for (i = 0; i < fs->group_desc_count; i++) {
if (!do_block)
goto skip_block_bitmap;
if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT)
)
goto skip_this_block_bitmap;
retval = ext2fs_get_block_bitmap_range2(fs->block_map,
blk_itr, block_nbytes << 3, block_buf);
if (retval)
goto errout;
if (i == fs->group_desc_count - 1) {
/* Force bitmap padding for the last group */
nbits = EXT2FS_NUM_B2C(fs,
((ext2fs_blocks_count(fs->super)
- (__u64) fs->super->s_first_data_block)
% (__u64) EXT2_BLOCKS_PER_GROUP(fs->super)));
if (nbits)
for (j = nbits; j < fs->blocksize * 8; j++)
ext2fs_set_bit(j, block_buf);
}
retval = ext2fs_block_bitmap_csum_set(fs, i, block_buf,
block_nbytes);
if (retval)
return retval;
ext2fs_group_desc_csum_set(fs, i);
fs->flags |= EXT2_FLAG_DIRTY;
blk = ext2fs_block_bitmap_loc(fs, i);
if (blk) {
retval = io_channel_write_blk64(fs->io, blk, 1,
block_buf);
if (retval) {
retval = EXT2_ET_BLOCK_BITMAP_WRITE;
goto errout;
}
}
skip_this_block_bitmap:
blk_itr += block_nbytes << 3;
skip_block_bitmap:
if (!do_inode)
continue;
if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)
)
goto skip_this_inode_bitmap;
retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
ino_itr, inode_nbytes << 3, inode_buf);
if (retval)
goto errout;
retval = ext2fs_inode_bitmap_csum_set(fs, i, inode_buf,
inode_nbytes);
if (retval)
goto errout;
ext2fs_group_desc_csum_set(fs, i);
fs->flags |= EXT2_FLAG_DIRTY;
blk = ext2fs_inode_bitmap_loc(fs, i);
if (blk) {
retval = io_channel_write_blk64(fs->io, blk, 1,
inode_buf);
if (retval) {
retval = EXT2_ET_INODE_BITMAP_WRITE;
goto errout;
}
}
skip_this_inode_bitmap:
ino_itr += inode_nbytes << 3;
}
if (do_block) {
fs->flags &= ~EXT2_FLAG_BB_DIRTY;
ext2fs_free_mem(&block_buf);
}
if (do_inode) {
fs->flags &= ~EXT2_FLAG_IB_DIRTY;
ext2fs_free_mem(&inode_buf);
}
return 0;
errout:
if (inode_buf)
ext2fs_free_mem(&inode_buf);
if (block_buf)
ext2fs_free_mem(&block_buf);
return retval;
}
static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs)
{
dgrp_t i;
blk64_t blk;
ext2fs_block_bitmap bmap = fs->block_map;
for (i = 0; i < fs->group_desc_count; i++) {
if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT))
continue;
ext2fs_reserve_super_and_bgd(fs, i, bmap);
/*
* Mark the blocks used for the inode table
*/
blk = ext2fs_inode_table_loc(fs, i);
if (blk)
ext2fs_mark_block_bitmap_range2(bmap, blk,
fs->inode_blocks_per_group);
/*
* Mark block used for the block bitmap
*/
blk = ext2fs_block_bitmap_loc(fs, i);
if (blk)
ext2fs_mark_block_bitmap2(bmap, blk);
/*
* Mark block used for the inode bitmap
*/
blk = ext2fs_inode_bitmap_loc(fs, i);
if (blk)
ext2fs_mark_block_bitmap2(bmap, blk);
}
return 0;
}
static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
{
dgrp_t i;
char *block_bitmap = 0, *inode_bitmap = 0;
char *buf;
errcode_t retval;
int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
int csum_flag;
unsigned int cnt;
blk64_t blk;
blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
blk64_t blk_cnt;
ext2_ino_t ino_itr = 1;
ext2_ino_t ino_cnt;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if ((block_nbytes > (int) fs->blocksize) ||
(inode_nbytes > (int) fs->blocksize))
return EXT2_ET_CORRUPT_SUPERBLOCK;
fs->write_bitmaps = ext2fs_write_bitmaps;
csum_flag = ext2fs_has_group_desc_csum(fs);
retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf);
if (retval)
return retval;
if (do_block) {
if (fs->block_map)
ext2fs_free_block_bitmap(fs->block_map);
strcpy(buf, "block bitmap for ");
strcat(buf, fs->device_name);
retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
if (retval)
goto cleanup;
retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap);
if (retval)
goto cleanup;
} else
block_nbytes = 0;
if (do_inode) {
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
strcpy(buf, "inode bitmap for ");
strcat(buf, fs->device_name);
retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
if (retval)
goto cleanup;
retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap);
if (retval)
goto cleanup;
} else
inode_nbytes = 0;
ext2fs_free_mem(&buf);
if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize);
ino_cnt = fs->super->s_inodes_count;
while (inode_bitmap && ino_cnt > 0) {
retval = io_channel_read_blk64(fs->image_io, blk++,
1, inode_bitmap);
if (retval)
goto cleanup;
cnt = fs->blocksize << 3;
if (cnt > ino_cnt)
cnt = ino_cnt;
retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
ino_itr, cnt, inode_bitmap);
if (retval)
goto cleanup;
ino_itr += cnt;
ino_cnt -= cnt;
}
blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) /
fs->blocksize);
blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super,
fs->group_desc_count);
while (block_bitmap && blk_cnt > 0) {
retval = io_channel_read_blk64(fs->image_io, blk++,
1, block_bitmap);
if (retval)
goto cleanup;
cnt = fs->blocksize << 3;
if (cnt > blk_cnt)
cnt = blk_cnt;
retval = ext2fs_set_block_bitmap_range2(fs->block_map,
blk_itr, cnt, block_bitmap);
if (retval)
goto cleanup;
blk_itr += cnt;
blk_cnt -= cnt;
}
goto success_cleanup;
}
for (i = 0; i < fs->group_desc_count; i++) {
if (block_bitmap) {
blk = ext2fs_block_bitmap_loc(fs, i);
if (csum_flag &&
ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
ext2fs_group_desc_csum_verify(fs, i))
blk = 0;
if (blk) {
retval = io_channel_read_blk64(fs->io, blk,
1, block_bitmap);
if (retval) {
retval = EXT2_ET_BLOCK_BITMAP_READ;
goto cleanup;
}
/* verify block bitmap checksum */
if (!(fs->flags &
EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
!ext2fs_block_bitmap_csum_verify(fs, i,
block_bitmap, block_nbytes)) {
retval =
EXT2_ET_BLOCK_BITMAP_CSUM_INVALID;
goto cleanup;
}
} else
memset(block_bitmap, 0, block_nbytes);
cnt = block_nbytes << 3;
retval = ext2fs_set_block_bitmap_range2(fs->block_map,
blk_itr, cnt, block_bitmap);
if (retval)
goto cleanup;
blk_itr += block_nbytes << 3;
}
if (inode_bitmap) {
blk = ext2fs_inode_bitmap_loc(fs, i);
if (csum_flag &&
ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
ext2fs_group_desc_csum_verify(fs, i))
blk = 0;
if (blk) {
retval = io_channel_read_blk64(fs->io, blk,
1, inode_bitmap);
if (retval) {
retval = EXT2_ET_INODE_BITMAP_READ;
goto cleanup;
}
/* verify inode bitmap checksum */
if (!(fs->flags &
EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
!ext2fs_inode_bitmap_csum_verify(fs, i,
inode_bitmap, inode_nbytes)) {
retval =
EXT2_ET_INODE_BITMAP_CSUM_INVALID;
goto cleanup;
}
} else
memset(inode_bitmap, 0, inode_nbytes);
cnt = inode_nbytes << 3;
retval = ext2fs_set_inode_bitmap_range2(fs->inode_map,
ino_itr, cnt, inode_bitmap);
if (retval)
goto cleanup;
ino_itr += inode_nbytes << 3;
}
}
/* Mark group blocks for any BLOCK_UNINIT groups */
if (do_block) {
retval = mark_uninit_bg_group_blocks(fs);
if (retval)
goto cleanup;
}
success_cleanup:
if (inode_bitmap)
ext2fs_free_mem(&inode_bitmap);
if (block_bitmap)
ext2fs_free_mem(&block_bitmap);
return 0;
cleanup:
if (do_block) {
ext2fs_free_mem(&fs->block_map);
fs->block_map = 0;
}
if (do_inode) {
ext2fs_free_mem(&fs->inode_map);
fs->inode_map = 0;
}
if (inode_bitmap)
ext2fs_free_mem(&inode_bitmap);
if (block_bitmap)
ext2fs_free_mem(&block_bitmap);
if (buf)
ext2fs_free_mem(&buf);
return retval;
}
errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs)
{
return read_bitmaps(fs, 1, 0);
}
errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
{
return read_bitmaps(fs, 0, 1);
}
errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
{
return write_bitmaps(fs, 1, 0);
}
errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
{
return write_bitmaps(fs, 0, 1);
}
errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
{
if (fs->inode_map && fs->block_map)
return 0;
return read_bitmaps(fs, !fs->inode_map, !fs->block_map);
}
errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
{
int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs);
int do_block = fs->block_map && ext2fs_test_bb_dirty(fs);
if (!do_inode && !do_block)
return 0;
return write_bitmaps(fs, do_inode, do_block);
}

204
src/ext2fs/symlink.c Normal file
View File

@ -0,0 +1,204 @@
/*
* symlink.c --- make a symlink in the filesystem, based on mkdir.c
*
* Copyright (c) 2012, Intel Corporation.
* All Rights Reserved.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "ext2_fs.h"
#include "ext2fs.h"
#ifndef HAVE_STRNLEN
/*
* Incredibly, libc5 doesn't appear to have strnlen. So we have to
* provide our own.
*/
static int my_strnlen(const char * s, int count)
{
const char *cp = s;
while (count-- && *cp)
cp++;
return cp - s;
}
#define strnlen(str, x) my_strnlen((str),(x))
#endif
errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
const char *name, const char *target)
{
errcode_t retval;
struct ext2_inode inode;
ext2_ino_t scratch_ino;
blk64_t blk;
int fastlink, inlinelink;
unsigned int target_len;
char *block_buf = 0;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
/*
* The Linux kernel doesn't allow for links longer than a block
* (counting the NUL terminator)
*/
target_len = strnlen(target, fs->blocksize + 1);
if (target_len >= fs->blocksize) {
retval = EXT2_ET_INVALID_ARGUMENT;
goto cleanup;
}
/*
* Allocate a data block for slow links
*/
retval = ext2fs_get_mem(fs->blocksize, &block_buf);
if (retval)
goto cleanup;
memset(block_buf, 0, fs->blocksize);
strncpy(block_buf, target, fs->blocksize);
memset(&inode, 0, sizeof(struct ext2_inode));
fastlink = (target_len < sizeof(inode.i_block));
if (!fastlink) {
retval = ext2fs_new_block2(fs, ext2fs_find_inode_goal(fs, ino,
&inode,
0),
NULL, &blk);
if (retval)
goto cleanup;
}
/*
* Allocate an inode, if necessary
*/
if (!ino) {
retval = ext2fs_new_inode(fs, parent, LINUX_S_IFLNK | 0755,
0, &ino);
if (retval)
goto cleanup;
}
/*
* Create the inode structure....
*/
inode.i_mode = LINUX_S_IFLNK | 0777;
inode.i_uid = inode.i_gid = 0;
inode.i_links_count = 1;
ext2fs_inode_size_set(fs, &inode, target_len);
/* The time fields are set by ext2fs_write_new_inode() */
inlinelink = !fastlink && ext2fs_has_feature_inline_data(fs->super);
if (fastlink) {
/* Fast symlinks, target stored in inode */
strcpy((char *)&inode.i_block, target);
} else if (inlinelink) {
/* Try inserting an inline data symlink */
inode.i_flags |= EXT4_INLINE_DATA_FL;
retval = ext2fs_write_new_inode(fs, ino, &inode);
if (retval)
goto cleanup;
retval = ext2fs_inline_data_set(fs, ino, &inode, block_buf,
target_len);
if (retval) {
inode.i_flags &= ~EXT4_INLINE_DATA_FL;
inlinelink = 0;
goto need_block;
}
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval)
goto cleanup;
} else {
need_block:
/* Slow symlinks, target stored in the first block */
ext2fs_iblk_set(fs, &inode, 1);
if (ext2fs_has_feature_extents(fs->super)) {
/*
* The extent bmap is setup after the inode and block
* have been written out below.
*/
inode.i_flags |= EXT4_EXTENTS_FL;
}
}
/*
* Write out the inode and inode data block. The inode generation
* number is assigned by write_new_inode, which means that the
* operations using ino must come after it.
*/
if (inlinelink)
retval = ext2fs_write_inode(fs, ino, &inode);
else
retval = ext2fs_write_new_inode(fs, ino, &inode);
if (retval)
goto cleanup;
if (!fastlink && !inlinelink) {
retval = ext2fs_bmap2(fs, ino, &inode, NULL, BMAP_SET, 0, NULL,
&blk);
if (retval)
goto cleanup;
retval = io_channel_write_blk64(fs->io, blk, 1, block_buf);
if (retval)
goto cleanup;
}
/*
* Link the symlink into the filesystem hierarchy
*/
if (name) {
retval = ext2fs_lookup(fs, parent, name, strlen(name), 0,
&scratch_ino);
if (!retval) {
retval = EXT2_ET_FILE_EXISTS;
goto cleanup;
}
if (retval != EXT2_ET_FILE_NOT_FOUND)
goto cleanup;
retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_SYMLINK);
if (retval)
goto cleanup;
}
/*
* Update accounting....
*/
if (!fastlink && !inlinelink)
ext2fs_block_alloc_stats2(fs, blk, +1);
ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
cleanup:
if (block_buf)
ext2fs_free_mem(&block_buf);
return retval;
}
/*
* Test whether an inode is a fast symlink.
*
* A fast symlink has its symlink data stored in inode->i_block.
*/
int ext2fs_is_fast_symlink(struct ext2_inode *inode)
{
return LINUX_S_ISLNK(inode->i_mode) && EXT2_I_SIZE(inode) &&
EXT2_I_SIZE(inode) < sizeof(inode->i_block);
}

68
src/ext2fs/valid_blk.c Normal file
View File

@ -0,0 +1,68 @@
/*
* valid_blk.c --- does the inode have valid blocks?
*
* Copyright 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <time.h>
#include "ext2_fs.h"
#include "ext2fs.h"
/*
* This function returns 1 if the inode's block entries actually
* contain block entries.
*/
int ext2fs_inode_has_valid_blocks2(ext2_filsys fs, struct ext2_inode *inode)
{
/*
* Only directories, regular files, and some symbolic links
* have valid block entries.
*/
if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
!LINUX_S_ISLNK(inode->i_mode))
return 0;
/*
* If the symbolic link is a "fast symlink", then the symlink
* target is stored in the block entries.
*/
if (LINUX_S_ISLNK (inode->i_mode)) {
if (ext2fs_file_acl_block(fs, inode) == 0) {
/* With no EA block, we can rely on i_blocks */
if (inode->i_blocks == 0)
return 0;
} else {
/* With an EA block, life gets more tricky */
if (inode->i_size >= EXT2_N_BLOCKS*4)
return 1; /* definitely using i_block[] */
if (inode->i_size > 4 && inode->i_block[1] == 0)
return 1; /* definitely using i_block[] */
return 0; /* Probably a fast symlink */
}
}
/*
* If this inode has inline data, it shouldn't have valid block
* entries.
*/
if (inode->i_flags & EXT4_INLINE_DATA_FL)
return 0;
return 1;
}
int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
{
return ext2fs_inode_has_valid_blocks2(NULL, inode);
}

View File

@ -49,6 +49,7 @@
#include "format.h"
#include "badblocks.h"
#include "bled/bled.h"
#include "ext2fs/ext2fs.h"
#include "../res/grub/grub_version.h"
/*
@ -664,6 +665,124 @@ out:
return r;
}
extern io_manager nt_io_manager(void);
BOOL FormatExt2Fs(void)
{
const char* path = "\\??\\C:\\tmp\\disk.img";
int i, count;
struct ext2_super_block features = { 0 };
io_manager manager = nt_io_manager();
blk64_t size = 0, cur;
ext2_filsys ext2fs;
errcode_t r;
HANDLE h;
DWORD dwSize;
const uint8_t buf[1024] = { 0 };
// Create a 32 MB zeroed file to test
h = CreateFileU(path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
for (i = 0; i < 32 * 1024; i++) {
if (!WriteFile(h, buf, sizeof(buf), &dwSize, NULL) || (dwSize != sizeof(buf))) {
uprintf("Write error: %s", WindowsErrorString());
break;
}
}
CloseHandle(h);
// TODO: We could probably remove that call and get our size from a different means
r = ext2fs_get_device_size(path, EXT2_BLOCK_SIZE(&features), &size);
uprintf("ext2fs_get_device_size: %d", r);
// TODO: ERROR HANDLING
// Set the number of blocks and reserved blocks
ext2fs_blocks_count_set(&features, size);
ext2fs_r_blocks_count_set(&features, (blk64_t)(0.05f * ext2fs_blocks_count(&features)));
features.s_rev_level = 1;
features.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
// TODO: This needs to be computed according to volume size
features.s_inodes_count = 8192;
// TODO: Set a volume label
// Initialize the superblock
r = ext2fs_initialize(path, EXT2_FLAG_EXCLUSIVE | EXT2_FLAG_64BITS, &features, manager, &ext2fs);
uprintf("ext2fs_initialize: %d", r);
// TODO: ERROR HANDLING
// TODO: Erase superblock data
// Now that the superblock has been initialized, set it up
CoCreateGuid((GUID*)ext2fs->super->s_uuid);
ext2fs_init_csum_seed(ext2fs);
ext2fs->super->s_def_hash_version = EXT2_HASH_HALF_MD4;
CoCreateGuid((GUID*)ext2fs->super->s_hash_seed);
ext2fs->super->s_max_mnt_count = -1;
ext2fs->super->s_creator_os = EXT2_OS_WINDOWS;
ext2fs->super->s_errors = EXT2_ERRORS_CONTINUE;
// TODO: ext2 + journaling = ext3, so the way to set ext3 is to add features:
// ext_attr, resize_inode, dir_index, filetype, sparse_super, has_journal, needs_recovery
ext2fs_set_feature_xattr(&features);
// ext2fs_set_feature_resize_inode(&sb);
// ext2fs_set_feature_dir_index(&sb);
ext2fs_set_feature_filetype(&features);
// ext2fs_set_feature_sparse_super(&sb);
// ext2fs_set_feature_journal(&sb);
// ext2fs_set_feature_journal_needs_recovery(&sb);
// Optional we may want to add:
// ext2fs_set_feature_64bit(&sb);
// NB: the following is not needed as it is set by the OS automatically when creating a > 2GB file
// ext2fs_set_feature_large_file(&sb);
r = ext2fs_allocate_tables(ext2fs);
uprintf("ext2fs_allocate_tables: %d", r);
// TODO: ERROR HANDLING
r = ext2fs_convert_subcluster_bitmap(ext2fs, &ext2fs->block_map);
uprintf("ext2fs_convert_subcluster_bitmap: %d", r);
// TODO: ERROR HANDLING
// Wipe inode table
for (i = 0; i < (int)ext2fs->group_desc_count; i++) {
cur = ext2fs_inode_table_loc(ext2fs, i);
count = ext2fs_div_ceil((ext2fs->super->s_inodes_per_group - ext2fs_bg_itable_unused(ext2fs, i))
* EXT2_GOOD_OLD_INODE_SIZE, EXT2_GOOD_OLD_INODE_SIZE);
r = ext2fs_zero_blocks2(ext2fs, cur, count, &cur, &count);
if (r != 0) {
uprintf("Could not zero inode at %llu (%d blocks): %d\n", cur, count, r);
// TODO: ERROR HANDLING
break;
}
}
// Create root dir
r = ext2fs_mkdir(ext2fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
uprintf("ext2fs_mkdir(root): %d", r);
// TODO: ERROR HANDLING
// Create 'lost+found'
ext2fs->umask = 077;
r = ext2fs_mkdir(ext2fs, EXT2_ROOT_INO, 0, "lost+found");
uprintf("ext2fs_mkdir(lost+found): %d", r);
// TODO: ERROR HANDLING
for (i = EXT2_ROOT_INO + 1; i < (int)EXT2_FIRST_INODE(ext2fs->super); i++)
ext2fs_inode_alloc_stats2(ext2fs, i, +1, 0);
ext2fs_mark_ib_dirty(ext2fs);
r = ext2fs_mark_inode_bitmap2(ext2fs->inode_map, EXT2_BAD_INO);
uprintf("ext2fs_mark_inode_bitmap2: %d", r);
// TODO: ERROR HANDLING
ext2fs_inode_alloc_stats2(ext2fs, EXT2_BAD_INO, 1, 0);
r = ext2fs_update_bb_inode(ext2fs, NULL);
uprintf("ext2fs_update_bb_inode: %d", r);
// TODO: ERROR HANDLING
r = ext2fs_close_free(&ext2fs);
uprintf("ext2fs_close_free: %d", r);
// TODO: ERROR HANDLING
return TRUE;
}
/*
* Call on fmifs.dll's FormatEx() to format the drive
*/

View File

@ -73,7 +73,7 @@ const char* additional_copyrights =
"http://svn.reactos.org/svn/reactos/trunk/reactos\\line\n"
"GNU General Public License (GPL) v2 or later\\line\n"
"\\line\n"
"Bad blocks testing from e2fsprogs by Theodore T'so et al.:\\line\n"
"Bad blocks testing and ext2/ext3 formattinmg from e2fsprogs by Theodore T'so et al.:\\line\n"
"http://e2fsprogs.sourceforge.net\\line\n"
"GNU General Public License (GPL) v3 compatible\\line\n"
"\\line\n"

View File

@ -31,4 +31,12 @@ typedef int ssize_t;
#endif /* _WIN64 */
#endif /* _SSIZE_T_DEFINED */
#endif
/* ext2fs needs this, which we picked from libcdio-driver/filemode.h */
#if !defined S_IFBLK && defined _WIN32
# define S_IFBLK 0x3000
#endif
#if !defined S_ISBLK && defined S_IFBLK
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
#endif

View File

@ -69,7 +69,7 @@ extern StrArray BlockingProcess;
* \return An error message string.
*
*/
static char* NtStatusError(NTSTATUS Status) {
char* NtStatusError(NTSTATUS Status) {
static char unknown[32];
switch (Status) {

View File

@ -1860,9 +1860,11 @@ out:
return ret;
}
/*
* Main dialog callback
*/
extern BOOL FormatExt2Fs(void);
static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static DWORD DeviceNum = 0;
@ -1895,10 +1897,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case WM_COMMAND:
#ifdef RUFUS_TEST
if (LOWORD(wParam) == IDC_TEST) {
image_path = "C:\\Downloads\\fat.iso";
strcpy(img_report.efi_img_path, "efi.img");
DumpFatDir("C:\\tmp", 0);
image_path = NULL;
FormatExt2Fs();
break;
}
#endif

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.6.1517"
CAPTION "Rufus 3.6.1518"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -394,8 +394,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,6,1517,0
PRODUCTVERSION 3,6,1517,0
FILEVERSION 3,6,1518,0
PRODUCTVERSION 3,6,1518,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -413,13 +413,13 @@ BEGIN
VALUE "Comments", "https://akeo.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.6.1517"
VALUE "FileVersion", "3.6.1518"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus-3.6.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.6.1517"
VALUE "ProductVersion", "3.6.1518"
END
END
BLOCK "VarFileInfo"