mirror of https://github.com/pbatard/rufus.git
[ext2fs] initial ext2fs support
This commit is contained in:
parent
f4d70345af
commit
cda716c1ff
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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" ;;
|
||||
|
|
|
@ -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
102
rufus.sln
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
16
src/drive.c
16
src/drive.c
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[*]
|
||||
tab_width = 8
|
|
@ -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
|
|
@ -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:
|
|
@ -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;
|
||||
}
|
|
@ -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 ;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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
|
||||
};
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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__)*/
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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];
|
||||
};
|
|
@ -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
|
|
@ -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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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)]))
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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(¶m, 0, sizeof(param));
|
||||
ext2fs_blocks_count_set(¶m, 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, ¶m,
|
||||
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
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
119
src/format.c
119
src/format.c
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue