1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

[cmp] add decompression support

* Adds .Z, .gz, .lzma, .xz and .bz2 decompression support for DD images
  using the Bled library (https://github.com/pbatard/bled).
* Closes #269
This commit is contained in:
Pete Batard 2014-12-29 20:34:41 +00:00
parent 3f0e71f3ba
commit 7599715ae6
56 changed files with 10020 additions and 89 deletions

1
.gitattributes vendored
View file

@ -12,6 +12,7 @@ install-sh eol=lf
*.txt eol=crlf
*.loc eol=crlf
*.sh export-ignore
*.cmd export-ignore
.gitattributes export-ignore
.gitignore export-ignore
*.creole export-ignore

6
.gitignore vendored
View file

@ -1,3 +1,4 @@
*.a
*.aps
*.dep
*.exe
@ -16,11 +17,16 @@
*.pdb
*.plg
*.res
*.sdf
*.suo
*.swp
*.tlog
*.user
*.opensdf
*.o_manifest
.deps
.libs
Makefile
x86_32
x86_64
autom4te.cache

19
configure vendored
View file

@ -3797,11 +3797,7 @@ ac_config_files="$ac_config_files Makefile"
ac_config_files="$ac_config_files src/Makefile"
ac_config_files="$ac_config_files src/ms-sys/Makefile"
ac_config_files="$ac_config_files src/syslinux/libfat/Makefile"
ac_config_files="$ac_config_files src/syslinux/libinstaller/Makefile"
ac_config_files="$ac_config_files src/bled/Makefile"
ac_config_files="$ac_config_files src/libcdio/iso9660/Makefile"
@ -3811,6 +3807,12 @@ ac_config_files="$ac_config_files src/libcdio/driver/Makefile"
ac_config_files="$ac_config_files res/localization/Makefile"
ac_config_files="$ac_config_files src/ms-sys/Makefile"
ac_config_files="$ac_config_files src/syslinux/libfat/Makefile"
ac_config_files="$ac_config_files src/syslinux/libinstaller/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@ -4538,13 +4540,14 @@ do
case $ac_config_target in
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
"src/ms-sys/Makefile") CONFIG_FILES="$CONFIG_FILES src/ms-sys/Makefile" ;;
"src/syslinux/libfat/Makefile") CONFIG_FILES="$CONFIG_FILES src/syslinux/libfat/Makefile" ;;
"src/syslinux/libinstaller/Makefile") CONFIG_FILES="$CONFIG_FILES src/syslinux/libinstaller/Makefile" ;;
"src/bled/Makefile") CONFIG_FILES="$CONFIG_FILES src/bled/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" ;;
"res/localization/Makefile") CONFIG_FILES="$CONFIG_FILES res/localization/Makefile" ;;
"src/ms-sys/Makefile") CONFIG_FILES="$CONFIG_FILES src/ms-sys/Makefile" ;;
"src/syslinux/libfat/Makefile") CONFIG_FILES="$CONFIG_FILES src/syslinux/libfat/Makefile" ;;
"src/syslinux/libinstaller/Makefile") CONFIG_FILES="$CONFIG_FILES src/syslinux/libinstaller/Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View file

@ -63,11 +63,12 @@ AC_SUBST([SUFFIX])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([src/ms-sys/Makefile])
AC_CONFIG_FILES([src/syslinux/libfat/Makefile])
AC_CONFIG_FILES([src/syslinux/libinstaller/Makefile])
AC_CONFIG_FILES([src/bled/Makefile])
AC_CONFIG_FILES([src/libcdio/iso9660/Makefile])
AC_CONFIG_FILES([src/libcdio/udf/Makefile])
AC_CONFIG_FILES([src/libcdio/driver/Makefile])
AC_CONFIG_FILES([res/localization/Makefile])
AC_CONFIG_FILES([src/ms-sys/Makefile])
AC_CONFIG_FILES([src/syslinux/libfat/Makefile])
AC_CONFIG_FILES([src/syslinux/libinstaller/Makefile])
AC_OUTPUT

View file

@ -1,4 +1,3 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
@ -19,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcdio-driver", "src\libcd
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "src\getopt\.msvc\getopt.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bled", "src\bled\.msvc\bled.vcxproj", "{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -91,6 +92,14 @@ Global
{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|Win32.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
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|Win32.ActiveCfg = Debug|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Debug|Win32.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}.Release|Win32.ActiveCfg = Release|Win32
{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}.Release|Win32.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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -199,12 +199,12 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\badblocks.h" />
<ClInclude Include="..\bled\bled.h" />
<ClInclude Include="..\drive.h" />
<ClInclude Include="..\format.h" />
<ClInclude Include="..\hdd_vs_ufd.h" />
<ClInclude Include="..\libcdio\cdio\cdio.h" />
<ClInclude Include="..\libcdio\cdio\iso9660.h" />
<ClInclude Include="..\libcdio\cdio\logging.h" />
<ClInclude Include="..\libcdio\cdio\udf.h" />
<ClInclude Include="..\localization.h" />
<ClInclude Include="..\localization_data.h" />
@ -231,6 +231,9 @@
<ResourceCompile Include="..\rufus.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\bled\.msvc\bled.vcxproj">
<Project>{fb6d52d4-a2f8-c358-db85-bbcaecfddd7d}</Project>
</ProjectReference>
<ProjectReference Include="..\getopt\.msvc\getopt.vcxproj">
<Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project>
</ProjectReference>

View file

@ -98,9 +98,6 @@
<ClInclude Include="..\libcdio\cdio\cdio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libcdio\cdio\logging.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libcdio\cdio\iso9660.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -128,6 +125,9 @@
<ClInclude Include="..\usb.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\bled\bled.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\res\rufus.ico">

View file

@ -3,7 +3,7 @@ TARGETTYPE=PROGRAM
UMTYPE=windows
UMENTRY=winmain
INCLUDES=$(DDK_INC_PATH);.\ms-sys\inc;.\syslinux\libfat;.\syslinux\libinstaller;.\msvc-missing;.\libcdio;.\getopt
INCLUDES=$(DDK_INC_PATH);.\ms-sys\inc;.\syslinux\libfat;.\syslinux\libinstaller;.\msvc-missing;.\libcdio;.\getopt;.\bled
C_DEFINES = $(C_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DRUFUS_LOC /DISOLATION_AWARE_ENABLED
!IFNDEF MSC_WARNING_LEVEL
@ -19,6 +19,7 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\shell32.lib \
$(SDK_LIB_PATH)\wininet.lib \
$(SDK_LIB_PATH)\shlwapi.lib \
.\bled\bled.lib \
.\ms-sys\ms-sys.lib \
.\syslinux\libfat\libfat.lib \
.\syslinux\libinstaller\libinstaller.lib \

View file

@ -1,4 +1,4 @@
SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/udf libcdio/driver ../res/localization
SUBDIRS = bled ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/udf libcdio/driver ../res/localization
noinst_PROGRAMS = rufus
@ -13,5 +13,5 @@ AM_V_WINDRES = $(AM_V_WINDRES_$(V))
rufus_SOURCES = drive.c icon.c parser.c localization.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c usb.c vhd.c format.c smart.c stdio.c stdfn.c stdlg.c rufus.c
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS)
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi

View file

@ -97,7 +97,7 @@ am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \
rufus-stdfn.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
rufus-rufus.$(OBJEXT)
rufus_OBJECTS = $(am_rufus_OBJECTS)
rufus_DEPENDENCIES = rufus_rc.o ms-sys/libmssys.a \
rufus_DEPENDENCIES = rufus_rc.o bled/libbled.a ms-sys/libmssys.a \
syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a \
libcdio/driver/libdriver.a
@ -263,7 +263,7 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/udf libcdio/driver ../res/localization
SUBDIRS = bled ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/udf libcdio/driver ../res/localization
AM_V_WINDRES_0 = @echo " RC $@";$(WINDRES)
AM_V_WINDRES_1 = $(WINDRES)
AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY))
@ -271,7 +271,7 @@ AM_V_WINDRES = $(AM_V_WINDRES_$(V))
rufus_SOURCES = drive.c icon.c parser.c localization.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c usb.c vhd.c format.c smart.c stdio.c stdfn.c stdlg.c rufus.c
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS)
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
rufus_LDADD = rufus_rc.o bled/libbled.a ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi
all: all-recursive

176
src/bled/.msvc/bled.vcxproj Normal file
View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</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="..\bled.c" />
<ClCompile Include="..\crc32.c" />
<ClCompile Include="..\data_align.c" />
<ClCompile Include="..\data_extract_all.c" />
<ClCompile Include="..\data_skip.c" />
<ClCompile Include="..\decompress_bunzip2.c" />
<ClCompile Include="..\decompress_gunzip.c" />
<ClCompile Include="..\decompress_uncompress.c" />
<ClCompile Include="..\decompress_unlzma.c" />
<ClCompile Include="..\decompress_unxz.c" />
<ClCompile Include="..\filter_accept_all.c" />
<ClCompile Include="..\filter_accept_list.c" />
<ClCompile Include="..\filter_accept_reject_list.c" />
<ClCompile Include="..\find_list_entry.c" />
<ClCompile Include="..\header_list.c" />
<ClCompile Include="..\header_skip.c" />
<ClCompile Include="..\header_verbose_list.c" />
<ClCompile Include="..\init_handle.c" />
<ClCompile Include="..\open_transformer.c" />
<ClCompile Include="..\seek_by_jump.c" />
<ClCompile Include="..\seek_by_read.c" />
<ClCompile Include="..\xz_dec_bcj.c" />
<ClCompile Include="..\xz_dec_lzma2.c" />
<ClCompile Include="..\xz_dec_stream.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\bb_archive.h" />
<ClInclude Include="..\bled.h" />
<ClInclude Include="..\libbb.h" />
<ClInclude Include="..\platform.h" />
<ClInclude Include="..\xz.h" />
<ClInclude Include="..\xz_config.h" />
<ClInclude Include="..\xz_lzma2.h" />
<ClInclude Include="..\xz_private.h" />
<ClInclude Include="..\xz_stream.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>bled</ProjectName>
<ProjectGuid>{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}</ProjectGuid>
<RootNamespace>bled</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)x86_32\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)x86_32\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)x86_32\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)x86_64\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)x86_64\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)x86_64\$(Configuration)\$(ProjectName)\</IntDir>
<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>
<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>
<AdditionalIncludeDirectories>..\..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<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>
<AdditionalIncludeDirectories>..\..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\..</AdditionalIncludeDirectories>
</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|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\..</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>.\7z.def</ModuleDefinitionFile>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View file

@ -0,0 +1,114 @@
<?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="..\bled.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\crc32.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\data_extract_all.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\data_skip.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\data_align.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\filter_accept_all.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\filter_accept_list.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\filter_accept_reject_list.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\find_list_entry.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\header_list.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\header_skip.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\header_verbose_list.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\init_handle.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\seek_by_jump.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\seek_by_read.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\decompress_bunzip2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\decompress_gunzip.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\decompress_uncompress.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\decompress_unlzma.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\decompress_unxz.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\open_transformer.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\xz_dec_bcj.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\xz_dec_lzma2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\xz_dec_stream.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\bb_archive.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\bled.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\libbb.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\platform.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\xz.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\xz_config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\xz_lzma2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\xz_private.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\xz_stream.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -0,0 +1,20 @@
TARGETNAME=bled
TARGETTYPE=LIBRARY
INCLUDES=$(DDK_INC_PATH);.;..;..\msvc-missing
BLED_DEFINES = /D_OFF_T_DEFINED /D_off_t=__int64 /Doff_t=_off_t /D_FILE_OFFSET_BITS=64
C_DEFINES=$(C_DEFINES) $(BLED_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DISOLATION_AWARE_ENABLED
!IFNDEF MSC_WARNING_LEVEL
MSC_WARNING_LEVEL=/W3
!ENDIF
USE_MSVCRT=1
TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\user32.lib
SOURCES=bled.c crc32.c data_align.c data_extract_all.c data_skip.c decompress_bunzip2.c \
decompress_gunzip.c decompress_uncompress.c decompress_unlzma.c decompress_unxz.c \
filter_accept_all.c filter_accept_list.c filter_accept_reject_list.c find_list_entry.c \
header_list.c header_skip.c header_verbose_list.c init_handle.c open_transformer.c \
seek_by_jump.c seek_by_read.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c

8
src/bled/Makefile.am Normal file
View file

@ -0,0 +1,8 @@
noinst_LIBRARIES = libbled.a
libbled_a_SOURCES = bled.c crc32.c data_align.c data_extract_all.c data_skip.c decompress_bunzip2.c \
decompress_gunzip.c decompress_uncompress.c decompress_unlzma.c decompress_unxz.c \
filter_accept_all.c filter_accept_list.c filter_accept_reject_list.c find_list_entry.c \
header_list.c header_skip.c header_verbose_list.c init_handle.c open_transformer.c \
seek_by_jump.c seek_by_read.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c
libbled_a_CFLAGS = $(AM_CFLAGS) -I.. -Wno-undef -Wno-strict-aliasing

642
src/bled/Makefile.in Normal file
View file

@ -0,0 +1,642 @@
# 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/bled
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)
AR = ar
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 =
libbled_a_AR = $(AR) $(ARFLAGS)
libbled_a_LIBADD =
am_libbled_a_OBJECTS = libbled_a-bled.$(OBJEXT) \
libbled_a-crc32.$(OBJEXT) libbled_a-data_align.$(OBJEXT) \
libbled_a-data_extract_all.$(OBJEXT) \
libbled_a-data_skip.$(OBJEXT) \
libbled_a-decompress_bunzip2.$(OBJEXT) \
libbled_a-decompress_gunzip.$(OBJEXT) \
libbled_a-decompress_uncompress.$(OBJEXT) \
libbled_a-decompress_unlzma.$(OBJEXT) \
libbled_a-decompress_unxz.$(OBJEXT) \
libbled_a-filter_accept_all.$(OBJEXT) \
libbled_a-filter_accept_list.$(OBJEXT) \
libbled_a-filter_accept_reject_list.$(OBJEXT) \
libbled_a-find_list_entry.$(OBJEXT) \
libbled_a-header_list.$(OBJEXT) \
libbled_a-header_skip.$(OBJEXT) \
libbled_a-header_verbose_list.$(OBJEXT) \
libbled_a-init_handle.$(OBJEXT) \
libbled_a-open_transformer.$(OBJEXT) \
libbled_a-seek_by_jump.$(OBJEXT) \
libbled_a-seek_by_read.$(OBJEXT) \
libbled_a-xz_dec_bcj.$(OBJEXT) \
libbled_a-xz_dec_lzma2.$(OBJEXT) \
libbled_a-xz_dec_stream.$(OBJEXT)
libbled_a_OBJECTS = $(am_libbled_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 = $(libbled_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@
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 = libbled.a
libbled_a_SOURCES = bled.c crc32.c data_align.c data_extract_all.c data_skip.c decompress_bunzip2.c \
decompress_gunzip.c decompress_uncompress.c decompress_unlzma.c decompress_unxz.c \
filter_accept_all.c filter_accept_list.c filter_accept_reject_list.c find_list_entry.c \
header_list.c header_skip.c header_verbose_list.c init_handle.c open_transformer.c \
seek_by_jump.c seek_by_read.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c
libbled_a_CFLAGS = $(AM_CFLAGS) -I.. -Wno-undef -Wno-strict-aliasing
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/bled/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign --ignore-deps src/bled/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)
libbled.a: $(libbled_a_OBJECTS) $(libbled_a_DEPENDENCIES) $(EXTRA_libbled_a_DEPENDENCIES)
$(AM_V_at)-rm -f libbled.a
$(AM_V_AR)$(libbled_a_AR) libbled.a $(libbled_a_OBJECTS) $(libbled_a_LIBADD)
$(AM_V_at)$(RANLIB) libbled.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) '$<'`
libbled_a-bled.o: bled.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-bled.o `test -f 'bled.c' || echo '$(srcdir)/'`bled.c
libbled_a-bled.obj: bled.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-bled.obj `if test -f 'bled.c'; then $(CYGPATH_W) 'bled.c'; else $(CYGPATH_W) '$(srcdir)/bled.c'; fi`
libbled_a-crc32.o: crc32.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-crc32.o `test -f 'crc32.c' || echo '$(srcdir)/'`crc32.c
libbled_a-crc32.obj: crc32.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-crc32.obj `if test -f 'crc32.c'; then $(CYGPATH_W) 'crc32.c'; else $(CYGPATH_W) '$(srcdir)/crc32.c'; fi`
libbled_a-data_align.o: data_align.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-data_align.o `test -f 'data_align.c' || echo '$(srcdir)/'`data_align.c
libbled_a-data_align.obj: data_align.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-data_align.obj `if test -f 'data_align.c'; then $(CYGPATH_W) 'data_align.c'; else $(CYGPATH_W) '$(srcdir)/data_align.c'; fi`
libbled_a-data_extract_all.o: data_extract_all.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-data_extract_all.o `test -f 'data_extract_all.c' || echo '$(srcdir)/'`data_extract_all.c
libbled_a-data_extract_all.obj: data_extract_all.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-data_extract_all.obj `if test -f 'data_extract_all.c'; then $(CYGPATH_W) 'data_extract_all.c'; else $(CYGPATH_W) '$(srcdir)/data_extract_all.c'; fi`
libbled_a-data_skip.o: data_skip.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-data_skip.o `test -f 'data_skip.c' || echo '$(srcdir)/'`data_skip.c
libbled_a-data_skip.obj: data_skip.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-data_skip.obj `if test -f 'data_skip.c'; then $(CYGPATH_W) 'data_skip.c'; else $(CYGPATH_W) '$(srcdir)/data_skip.c'; fi`
libbled_a-decompress_bunzip2.o: decompress_bunzip2.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_bunzip2.o `test -f 'decompress_bunzip2.c' || echo '$(srcdir)/'`decompress_bunzip2.c
libbled_a-decompress_bunzip2.obj: decompress_bunzip2.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_bunzip2.obj `if test -f 'decompress_bunzip2.c'; then $(CYGPATH_W) 'decompress_bunzip2.c'; else $(CYGPATH_W) '$(srcdir)/decompress_bunzip2.c'; fi`
libbled_a-decompress_gunzip.o: decompress_gunzip.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_gunzip.o `test -f 'decompress_gunzip.c' || echo '$(srcdir)/'`decompress_gunzip.c
libbled_a-decompress_gunzip.obj: decompress_gunzip.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_gunzip.obj `if test -f 'decompress_gunzip.c'; then $(CYGPATH_W) 'decompress_gunzip.c'; else $(CYGPATH_W) '$(srcdir)/decompress_gunzip.c'; fi`
libbled_a-decompress_uncompress.o: decompress_uncompress.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_uncompress.o `test -f 'decompress_uncompress.c' || echo '$(srcdir)/'`decompress_uncompress.c
libbled_a-decompress_uncompress.obj: decompress_uncompress.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_uncompress.obj `if test -f 'decompress_uncompress.c'; then $(CYGPATH_W) 'decompress_uncompress.c'; else $(CYGPATH_W) '$(srcdir)/decompress_uncompress.c'; fi`
libbled_a-decompress_unlzma.o: decompress_unlzma.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_unlzma.o `test -f 'decompress_unlzma.c' || echo '$(srcdir)/'`decompress_unlzma.c
libbled_a-decompress_unlzma.obj: decompress_unlzma.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_unlzma.obj `if test -f 'decompress_unlzma.c'; then $(CYGPATH_W) 'decompress_unlzma.c'; else $(CYGPATH_W) '$(srcdir)/decompress_unlzma.c'; fi`
libbled_a-decompress_unxz.o: decompress_unxz.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_unxz.o `test -f 'decompress_unxz.c' || echo '$(srcdir)/'`decompress_unxz.c
libbled_a-decompress_unxz.obj: decompress_unxz.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-decompress_unxz.obj `if test -f 'decompress_unxz.c'; then $(CYGPATH_W) 'decompress_unxz.c'; else $(CYGPATH_W) '$(srcdir)/decompress_unxz.c'; fi`
libbled_a-filter_accept_all.o: filter_accept_all.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-filter_accept_all.o `test -f 'filter_accept_all.c' || echo '$(srcdir)/'`filter_accept_all.c
libbled_a-filter_accept_all.obj: filter_accept_all.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-filter_accept_all.obj `if test -f 'filter_accept_all.c'; then $(CYGPATH_W) 'filter_accept_all.c'; else $(CYGPATH_W) '$(srcdir)/filter_accept_all.c'; fi`
libbled_a-filter_accept_list.o: filter_accept_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-filter_accept_list.o `test -f 'filter_accept_list.c' || echo '$(srcdir)/'`filter_accept_list.c
libbled_a-filter_accept_list.obj: filter_accept_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-filter_accept_list.obj `if test -f 'filter_accept_list.c'; then $(CYGPATH_W) 'filter_accept_list.c'; else $(CYGPATH_W) '$(srcdir)/filter_accept_list.c'; fi`
libbled_a-filter_accept_reject_list.o: filter_accept_reject_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-filter_accept_reject_list.o `test -f 'filter_accept_reject_list.c' || echo '$(srcdir)/'`filter_accept_reject_list.c
libbled_a-filter_accept_reject_list.obj: filter_accept_reject_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-filter_accept_reject_list.obj `if test -f 'filter_accept_reject_list.c'; then $(CYGPATH_W) 'filter_accept_reject_list.c'; else $(CYGPATH_W) '$(srcdir)/filter_accept_reject_list.c'; fi`
libbled_a-find_list_entry.o: find_list_entry.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-find_list_entry.o `test -f 'find_list_entry.c' || echo '$(srcdir)/'`find_list_entry.c
libbled_a-find_list_entry.obj: find_list_entry.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-find_list_entry.obj `if test -f 'find_list_entry.c'; then $(CYGPATH_W) 'find_list_entry.c'; else $(CYGPATH_W) '$(srcdir)/find_list_entry.c'; fi`
libbled_a-header_list.o: header_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-header_list.o `test -f 'header_list.c' || echo '$(srcdir)/'`header_list.c
libbled_a-header_list.obj: header_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-header_list.obj `if test -f 'header_list.c'; then $(CYGPATH_W) 'header_list.c'; else $(CYGPATH_W) '$(srcdir)/header_list.c'; fi`
libbled_a-header_skip.o: header_skip.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-header_skip.o `test -f 'header_skip.c' || echo '$(srcdir)/'`header_skip.c
libbled_a-header_skip.obj: header_skip.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-header_skip.obj `if test -f 'header_skip.c'; then $(CYGPATH_W) 'header_skip.c'; else $(CYGPATH_W) '$(srcdir)/header_skip.c'; fi`
libbled_a-header_verbose_list.o: header_verbose_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-header_verbose_list.o `test -f 'header_verbose_list.c' || echo '$(srcdir)/'`header_verbose_list.c
libbled_a-header_verbose_list.obj: header_verbose_list.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-header_verbose_list.obj `if test -f 'header_verbose_list.c'; then $(CYGPATH_W) 'header_verbose_list.c'; else $(CYGPATH_W) '$(srcdir)/header_verbose_list.c'; fi`
libbled_a-init_handle.o: init_handle.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-init_handle.o `test -f 'init_handle.c' || echo '$(srcdir)/'`init_handle.c
libbled_a-init_handle.obj: init_handle.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-init_handle.obj `if test -f 'init_handle.c'; then $(CYGPATH_W) 'init_handle.c'; else $(CYGPATH_W) '$(srcdir)/init_handle.c'; fi`
libbled_a-open_transformer.o: open_transformer.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-open_transformer.o `test -f 'open_transformer.c' || echo '$(srcdir)/'`open_transformer.c
libbled_a-open_transformer.obj: open_transformer.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-open_transformer.obj `if test -f 'open_transformer.c'; then $(CYGPATH_W) 'open_transformer.c'; else $(CYGPATH_W) '$(srcdir)/open_transformer.c'; fi`
libbled_a-seek_by_jump.o: seek_by_jump.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-seek_by_jump.o `test -f 'seek_by_jump.c' || echo '$(srcdir)/'`seek_by_jump.c
libbled_a-seek_by_jump.obj: seek_by_jump.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-seek_by_jump.obj `if test -f 'seek_by_jump.c'; then $(CYGPATH_W) 'seek_by_jump.c'; else $(CYGPATH_W) '$(srcdir)/seek_by_jump.c'; fi`
libbled_a-seek_by_read.o: seek_by_read.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-seek_by_read.o `test -f 'seek_by_read.c' || echo '$(srcdir)/'`seek_by_read.c
libbled_a-seek_by_read.obj: seek_by_read.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-seek_by_read.obj `if test -f 'seek_by_read.c'; then $(CYGPATH_W) 'seek_by_read.c'; else $(CYGPATH_W) '$(srcdir)/seek_by_read.c'; fi`
libbled_a-xz_dec_bcj.o: xz_dec_bcj.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-xz_dec_bcj.o `test -f 'xz_dec_bcj.c' || echo '$(srcdir)/'`xz_dec_bcj.c
libbled_a-xz_dec_bcj.obj: xz_dec_bcj.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-xz_dec_bcj.obj `if test -f 'xz_dec_bcj.c'; then $(CYGPATH_W) 'xz_dec_bcj.c'; else $(CYGPATH_W) '$(srcdir)/xz_dec_bcj.c'; fi`
libbled_a-xz_dec_lzma2.o: xz_dec_lzma2.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-xz_dec_lzma2.o `test -f 'xz_dec_lzma2.c' || echo '$(srcdir)/'`xz_dec_lzma2.c
libbled_a-xz_dec_lzma2.obj: xz_dec_lzma2.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-xz_dec_lzma2.obj `if test -f 'xz_dec_lzma2.c'; then $(CYGPATH_W) 'xz_dec_lzma2.c'; else $(CYGPATH_W) '$(srcdir)/xz_dec_lzma2.c'; fi`
libbled_a-xz_dec_stream.o: xz_dec_stream.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-xz_dec_stream.o `test -f 'xz_dec_stream.c' || echo '$(srcdir)/'`xz_dec_stream.c
libbled_a-xz_dec_stream.obj: xz_dec_stream.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbled_a_CFLAGS) $(CFLAGS) -c -o libbled_a-xz_dec_stream.obj `if test -f 'xz_dec_stream.c'; then $(CYGPATH_W) 'xz_dec_stream.c'; else $(CYGPATH_W) '$(srcdir)/xz_dec_stream.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:

262
src/bled/bb_archive.h Normal file
View file

@ -0,0 +1,262 @@
/* vi: set sw=4 ts=4: */
#ifndef UNARCHIVE_H
#define UNARCHIVE_H 1
PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
enum {
#if BB_BIG_ENDIAN
COMPRESS_MAGIC = 0x1f9d,
GZIP_MAGIC = 0x1f8b,
BZIP2_MAGIC = 256 * 'B' + 'Z',
/* .xz signature: 0xfd, '7', 'z', 'X', 'Z', 0x00 */
/* More info at: http://tukaani.org/xz/xz-file-format.txt */
XZ_MAGIC1 = 256 * 0xfd + '7',
XZ_MAGIC2 = 256 * (unsigned)(256 * (256 * 'z' + 'X') + 'Z') + 0,
/* Different form: 32 bits, then 16 bits: */
/* (unsigned) cast suppresses "integer overflow in expression" warning */
XZ_MAGIC1a = 256 * (unsigned)(256 * (256 * 0xfd + '7') + 'z') + 'X',
XZ_MAGIC2a = 256 * 'Z' + 0,
#else
COMPRESS_MAGIC = 0x9d1f,
GZIP_MAGIC = 0x8b1f,
BZIP2_MAGIC = 'B' + 'Z' * 256,
XZ_MAGIC1 = 0xfd + '7' * 256,
XZ_MAGIC2 = 'z' + ('X' + ('Z' + 0 * 256) * 256) * 256,
XZ_MAGIC1a = 0xfd + ('7' + ('z' + 'X' * 256) * 256) * 256,
XZ_MAGIC2a = 'Z' + 0 * 256,
#endif
};
typedef struct file_header_t {
char *name;
char *link_target;
#if ENABLE_FEATURE_TAR_UNAME_GNAME
char *tar__uname;
char *tar__gname;
#endif
off_t size;
uid_t uid;
gid_t gid;
mode_t mode;
time_t mtime;
dev_t device;
} file_header_t;
struct hardlinks_t;
typedef struct archive_handle_t {
/* Flags. 1st since it is most used member */
unsigned ah_flags;
/* The raw stream as read from disk or stdin */
int src_fd;
/* Define if the header and data component should be processed */
char FAST_FUNC (*filter)(struct archive_handle_t *);
/* List of files that have been accepted */
llist_t *accept;
/* List of files that have been rejected */
llist_t *reject;
/* List of files that have successfully been worked on */
llist_t *passed;
/* Currently processed file's header */
file_header_t *file_header;
/* Process the header component, e.g. tar -t */
void FAST_FUNC (*action_header)(const file_header_t *);
/* Process the data component, e.g. extract to filesystem */
void FAST_FUNC (*action_data)(struct archive_handle_t *);
/* Function that skips data */
void FAST_FUNC (*seek)(int fd, off_t amount);
/* Count processed bytes */
off_t offset;
/* Archiver specific. Can make it a union if it ever gets big */
#define PAX_NEXT_FILE 0
#define PAX_GLOBAL 1
#if ENABLE_TAR || ENABLE_DPKG || ENABLE_DPKG_DEB
smallint tar__end;
# if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
char* tar__longname;
char* tar__linkname;
# endif
# if ENABLE_FEATURE_TAR_TO_COMMAND
char* tar__to_command;
const char* tar__to_command_shell;
# endif
# if ENABLE_FEATURE_TAR_SELINUX
char* tar__sctx[2];
# endif
#endif
#if ENABLE_CPIO || ENABLE_RPM2CPIO || ENABLE_RPM
uoff_t cpio__blocks;
struct hardlinks_t *cpio__hardlinks_to_create;
struct hardlinks_t *cpio__created_hardlinks;
#endif
#if ENABLE_DPKG || ENABLE_DPKG_DEB
/* Temporary storage */
char *dpkg__buffer;
/* How to process any sub archive, e.g. get_header_tar_gz */
char FAST_FUNC (*dpkg__action_data_subarchive)(struct archive_handle_t *);
/* Contains the handle to a sub archive */
struct archive_handle_t *dpkg__sub_archive;
#endif
#if ENABLE_FEATURE_AR_CREATE
const char *ar__name;
struct archive_handle_t *ar__out;
#endif
} archive_handle_t;
/* bits in ah_flags */
#define ARCHIVE_RESTORE_DATE (1 << 0)
#define ARCHIVE_CREATE_LEADING_DIRS (1 << 1)
#define ARCHIVE_UNLINK_OLD (1 << 2)
#define ARCHIVE_EXTRACT_QUIET (1 << 3)
#define ARCHIVE_EXTRACT_NEWER (1 << 4)
#define ARCHIVE_DONT_RESTORE_OWNER (1 << 5)
#define ARCHIVE_DONT_RESTORE_PERM (1 << 6)
#define ARCHIVE_NUMERIC_OWNER (1 << 7)
#define ARCHIVE_O_TRUNC (1 << 8)
#define ARCHIVE_REMEMBER_NAMES (1 << 9)
#if ENABLE_RPM
#define ARCHIVE_REPLACE_VIA_RENAME (1 << 10)
#endif
/* POSIX tar Header Block, from POSIX 1003.1-1990 */
#define TAR_BLOCK_SIZE 512
#define NAME_SIZE 100
#define NAME_SIZE_STR "100"
typedef struct tar_header_t { /* byte offset */
char name[NAME_SIZE]; /* 0-99 */
char mode[8]; /* 100-107 */
char uid[8]; /* 108-115 */
char gid[8]; /* 116-123 */
char size[12]; /* 124-135 */
char mtime[12]; /* 136-147 */
char chksum[8]; /* 148-155 */
char typeflag; /* 156-156 */
char linkname[NAME_SIZE]; /* 157-256 */
/* POSIX: "ustar" NUL "00" */
/* GNU tar: "ustar " NUL */
/* Normally it's defined as magic[6] followed by
* version[2], but we put them together to save code.
*/
char magic[8]; /* 257-264 */
char uname[32]; /* 265-296 */
char gname[32]; /* 297-328 */
char devmajor[8]; /* 329-336 */
char devminor[8]; /* 337-344 */
char prefix[155]; /* 345-499 */
char padding[12]; /* 500-512 (pad to exactly TAR_BLOCK_SIZE) */
} tar_header_t;
struct BUG_tar_header {
char c[sizeof(tar_header_t) == TAR_BLOCK_SIZE ? 1 : -1];
};
archive_handle_t *init_handle(void) FAST_FUNC;
char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC;
char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC;
char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC;
char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC;
void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC;
void data_skip(archive_handle_t *archive_handle) FAST_FUNC;
void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC;
void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC;
void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC;
void header_skip(const file_header_t *file_header) FAST_FUNC;
void header_list(const file_header_t *file_header) FAST_FUNC;
void header_verbose_list(const file_header_t *file_header) FAST_FUNC;
char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC;
char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC;
void seek_by_jump(int fd, off_t amount) FAST_FUNC;
void seek_by_read(int fd, off_t amount) FAST_FUNC;
const char *strip_unsafe_prefix(const char *str) FAST_FUNC;
void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC;
const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC;
const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC;
/* A bit of bunzip2 internals are exposed for compressed help support: */
typedef struct bunzip_data bunzip_data;
int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC;
/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
* in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */
int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
/* Meaning and direction (input/output) of the fields are transformer-specific */
typedef struct transformer_state_t {
smallint check_signature; /* most often referenced member */
IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
USE_FOR_NOMMU(const char *xformer_prog;)
/* Source */
int src_fd;
/* Output */
int dst_fd;
size_t mem_output_size_max; /* if non-zero, decompress to RAM instead of fd */
size_t mem_output_size;
char *mem_output_buf;
off_t bytes_out;
off_t bytes_in; /* used in unzip code only: needs to know packed size */
uint32_t crc32;
time_t mtime; /* gunzip code may set this on exit */
} transformer_state_t;
void init_transformer_state(transformer_state_t *xstate) FAST_FUNC;
ssize_t transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC;
ssize_t xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC;
int check_signature16(transformer_state_t *xstate, unsigned magic16) FAST_FUNC;
IF_DESKTOP(long long) int inflate_unzip(transformer_state_t *xstate) FAST_FUNC;
IF_DESKTOP(long long) int unpack_Z_stream(transformer_state_t *xstate) FAST_FUNC;
IF_DESKTOP(long long) int unpack_gz_stream(transformer_state_t *xstate) FAST_FUNC;
IF_DESKTOP(long long) int unpack_bz2_stream(transformer_state_t *xstate) FAST_FUNC;
IF_DESKTOP(long long) int unpack_lzma_stream(transformer_state_t *xstate) FAST_FUNC;
IF_DESKTOP(long long) int unpack_xz_stream(transformer_state_t *xstate) FAST_FUNC;
char* append_ext(char *filename, const char *expected_ext) FAST_FUNC;
int bbunpack(char **argv,
IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(transformer_state_t *xstate),
char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext),
const char *expected_ext
) FAST_FUNC;
void check_errors_in_children(int signo);
#if BB_MMU
void fork_transformer(int fd,
int check_signature,
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
) FAST_FUNC;
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer))
#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer))
#else
void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))
/* fork_transformer_with_no_sig() does not exist on NOMMU */
#endif
POP_SAVED_FUNCTION_VISIBILITY
#endif

139
src/bled/bled.c Normal file
View file

@ -0,0 +1,139 @@
/*
* Bled (Busybox Library for Easy Decompression)
*
* Copyright © 2014 Pete Batard <pete@akeo.ie>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#ifdef _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#include "libbb.h"
#include "bb_archive.h"
#include "bled.h"
typedef long long int(*unpacker_t)(transformer_state_t *xstate);
/* Globals */
smallint bb_got_signal;
uint64_t bb_total_rb;
printf_t bled_printf = NULL;
progress_t bled_progress = NULL;
static bool bled_initialized = 0;
static long long int unpack_none(transformer_state_t *xstate)
{
bb_printf("BLED_COMPRESSION_NONE is not supported");
return -1;
}
unpacker_t unpacker[BLED_COMPRESSION_MAX] = {
unpack_none,
inflate_unzip,
unpack_Z_stream,
unpack_gz_stream,
unpack_lzma_stream,
unpack_bz2_stream,
unpack_xz_stream
};
/* Uncompress file 'src', compressed using 'type', to file 'dst' */
int64_t bled_uncompress(const char* src, const char* dst, int type)
{
transformer_state_t xstate;
int64_t ret;
if (!bled_initialized)
return -1;
bb_total_rb = 0;
init_transformer_state(&xstate);
xstate.src_fd = -1;
xstate.dst_fd = -1;
xstate.check_signature = 1;
xstate.src_fd = _openU(src, _O_RDONLY | _O_BINARY, 0);
if (xstate.src_fd < 0) {
bb_printf("Could not open '%s' (errno: %d)", src, errno);
goto err;
}
xstate.dst_fd = _openU(dst, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, _S_IREAD | _S_IWRITE);
if (xstate.dst_fd < 0) {
bb_printf("Could not open '%s' (errno: %d)", dst, errno);
goto err;
}
if ((type < 0) || (type >= BLED_COMPRESSION_MAX)) {
bb_printf("unsupported compression format");
goto err;
}
ret = unpacker[type](&xstate);
_close(xstate.src_fd);
_close(xstate.dst_fd);
return ret;
err:
if (xstate.src_fd > 0)
_close(xstate.src_fd);
if (xstate.dst_fd > 0)
_close(xstate.dst_fd);
return -1;
}
/* Uncompress using Windows handles */
int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type)
{
transformer_state_t xstate;
if (!bled_initialized)
return -1;
bb_total_rb = 0;
init_transformer_state(&xstate);
xstate.src_fd = -1;
xstate.dst_fd = -1;
xstate.check_signature = 1;
xstate.src_fd = _open_osfhandle((intptr_t)hSrc, _O_RDONLY);
if (xstate.src_fd < 0) {
bb_printf("Could not get source descriptor (errno: %d)", errno);
return -1;
}
xstate.dst_fd = _open_osfhandle((intptr_t)hDst, 0);
if (xstate.dst_fd < 0) {
bb_printf("Could not get target descriptor (errno: %d)", errno);
return -1;
}
if ((type < 0) || (type >= BLED_COMPRESSION_MAX)) {
bb_printf("unsupported compression format");
return -1;
}
return unpacker[type](&xstate);
}
int bled_init(printf_t print_function, progress_t progress_function)
{
if (bled_initialized)
return -1;
bled_initialized = true;
bled_printf = print_function;
bled_progress = progress_function;
return 0;
}
void bled_exit(void)
{
bled_printf = NULL;
bled_progress = NULL;
if (global_crc32_table)
free(global_crc32_table);
bled_initialized = false;
}

41
src/bled/bled.h Normal file
View file

@ -0,0 +1,41 @@
/*
* Bled (Busybox Library for Easy Decompression)
*
* Copyright © 2014 Pete Batard <pete@akeo.ie>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include <windows.h>
#include <stdint.h>
#pragma once
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
typedef void (*printf_t) (const char* format, ...);
typedef void (*progress_t) (const uint64_t processed_bytes);
typedef enum {
BLED_COMPRESSION_NONE = 0,
BLED_COMPRESSION_ZIP, // .zip
BLED_COMPRESSION_LZW, // .Z
BLED_COMPRESSION_GZIP, // .gz
BLED_COMPRESSION_LZMA, // .lzma
BLED_COMPRESSION_BZIP2, // .bz2
BLED_COMPRESSION_XZ, // .xz
// BLED_COMPRESSION_7ZIP // .7z
BLED_COMPRESSION_MAX
} bled_compression_type;
/* Uncompress file 'src', compressed using 'type', to file 'dst' */
int64_t bled_uncompress(const char* src, const char* dst, int type);
int64_t bled_uncompress_with_handles(HANDLE hSrc, HANDLE hDst, int type);
/* Initialize the library */
int bled_init(printf_t print_function, progress_t progress_function);
void bled_exit(void);

257
src/bled/crc32.c Normal file
View file

@ -0,0 +1,257 @@
/*
* GPLv2+ CRC32 implementation for busybox
*
* Based on crc32.c from util-linux v2.17's partx v2.17 - Public Domain
* Adjusted for busybox' by Pete Batard <pete@akeo.ie>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#if __GNUC__ >= 3 /* 2.x has "attribute", but only 3.0 has "pure */
#define attribute(x) __attribute__(x)
#else
#define attribute(x)
#endif
/* Do NOT alter these */
#define CRC_LE_BITS 8
#define CRC_BE_BITS 8
/*
* 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 needs to be defined somewhere */
uint32_t *global_crc32_table;
static void crc32init_le(uint32_t *crc32table_le)
{
unsigned i, j;
uint32_t crc = 1;
crc32table_le[0] = 0;
for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) {
crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
for (j = 0; j < 1 << CRC_LE_BITS; j += 2 * i)
crc32table_le[i + j] = crc ^ crc32table_le[j];
}
}
/**
* 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
*
*/
uint32_t attribute((pure)) crc32_le(uint32_t crc, unsigned char const *p, size_t len, uint32_t *crc32table_le)
{
while (len--) {
# if CRC_LE_BITS == 8
crc = (crc >> 8) ^ crc32table_le[(crc ^ *p++) & 255];
# elif CRC_LE_BITS == 4
crc ^= *p++;
crc = (crc >> 4) ^ crc32table_le[crc & 15];
crc = (crc >> 4) ^ crc32table_le[crc & 15];
# elif CRC_LE_BITS == 2
crc ^= *p++;
crc = (crc >> 2) ^ crc32table_le[crc & 3];
crc = (crc >> 2) ^ crc32table_le[crc & 3];
crc = (crc >> 2) ^ crc32table_le[crc & 3];
crc = (crc >> 2) ^ crc32table_le[crc & 3];
# endif
}
return crc;
}
/**
* crc32init_be() - allocate and initialize BE table data
*/
static void crc32init_be(uint32_t *crc32table_be)
{
unsigned i, j;
uint32_t crc = 0x80000000;
for (i = 1; i < 1 << CRC_BE_BITS; i <<= 1) {
crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0);
for (j = 0; j < i; j++)
crc32table_be[i + j] = crc ^ crc32table_be[j];
}
}
/**
* 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
*
*/
uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t len, uint32_t *crc32table_be)
{
while (len--) {
# if CRC_BE_BITS == 8
crc = (crc << 8) ^ crc32table_be[(crc >> 24) ^ *p++];
# elif CRC_BE_BITS == 4
crc ^= *p++ << 24;
crc = (crc << 4) ^ crc32table_be[crc >> 28];
crc = (crc << 4) ^ crc32table_be[crc >> 28];
# elif CRC_BE_BITS == 2
crc ^= *p++ << 24;
crc = (crc << 2) ^ crc32table_be[crc >> 30];
crc = (crc << 2) ^ crc32table_be[crc >> 30];
crc = (crc << 2) ^ crc32table_be[crc >> 30];
crc = (crc << 2) ^ crc32table_be[crc >> 30];
# endif
}
return crc;
}
uint32_t* crc32_filltable(uint32_t *crc_table, int endian)
{
/* Expects the caller to do the cleanup */
if (!crc_table)
crc_table = malloc((1 << CRC_LE_BITS) * sizeof(uint32_t));
if (crc_table) {
if (endian)
crc32init_be(crc_table);
else
crc32init_le(crc_table);
}
return crc_table;
}
/*
* A brief CRC tutorial.
*
* A CRC is a long-division remainder. You add the CRC to the message,
* and the whole thing (message+CRC) is a multiple of the given
* CRC polynomial. To check the CRC, you can either check that the
* CRC matches the recomputed value, *or* you can check that the
* remainder computed on the message+CRC is 0. This latter approach
* is used by a lot of hardware implementations, and is why so many
* protocols put the end-of-frame flag after the CRC.
*
* It's actually the same long division you learned in school, except that
* - We're working in binary, so the digits are only 0 and 1, and
* - When dividing polynomials, there are no carries. Rather than add and
* subtract, we just xor. Thus, we tend to get a bit sloppy about
* the difference between adding and subtracting.
*
* A 32-bit CRC polynomial is actually 33 bits long. But since it's
* 33 bits long, bit 32 is always going to be set, so usually the CRC
* is written in hex with the most significant bit omitted. (If you're
* familiar with the IEEE 754 floating-point format, it's the same idea.)
*
* Note that a CRC is computed over a string of *bits*, so you have
* to decide on the endianness of the bits within each byte. To get
* the best error-detecting properties, this should correspond to the
* order they're actually sent. For example, standard RS-232 serial is
* little-endian; the most significant bit (sometimes used for parity)
* is sent last. And when appending a CRC word to a message, you should
* do it in the right order, matching the endianness.
*
* Just like with ordinary division, the remainder is always smaller than
* the divisor (the CRC polynomial) you're dividing by. Each step of the
* division, you take one more digit (bit) of the dividend and append it
* to the current remainder. Then you figure out the appropriate multiple
* of the divisor to subtract to being the remainder back into range.
* In binary, it's easy - it has to be either 0 or 1, and to make the
* XOR cancel, it's just a copy of bit 32 of the remainder.
*
* When computing a CRC, we don't care about the quotient, so we can
* throw the quotient bit away, but subtract the appropriate multiple of
* the polynomial from the remainder and we're back to where we started,
* ready to process the next bit.
*
* A big-endian CRC written this way would be coded like:
* for (i = 0; i < input_bits; i++) {
* multiple = remainder & 0x80000000 ? CRCPOLY : 0;
* remainder = (remainder << 1 | next_input_bit()) ^ multiple;
* }
* Notice how, to get at bit 32 of the shifted remainder, we look
* at bit 31 of the remainder *before* shifting it.
*
* But also notice how the next_input_bit() bits we're shifting into
* the remainder don't actually affect any decision-making until
* 32 bits later. Thus, the first 32 cycles of this are pretty boring.
* Also, to add the CRC to a message, we need a 32-bit-long hole for it at
* the end, so we have to add 32 extra cycles shifting in zeros at the
* end of every message,
*
* So the standard trick is to rearrage merging in the next_input_bit()
* until the moment it's needed. Then the first 32 cycles can be precomputed,
* and merging in the final 32 zero bits to make room for the CRC can be
* skipped entirely.
* This changes the code to:
* for (i = 0; i < input_bits; i++) {
* remainder ^= next_input_bit() << 31;
* multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
* remainder = (remainder << 1) ^ multiple;
* }
* With this optimization, the little-endian code is simpler:
* for (i = 0; i < input_bits; i++) {
* remainder ^= next_input_bit();
* multiple = (remainder & 1) ? CRCPOLY : 0;
* remainder = (remainder >> 1) ^ multiple;
* }
*
* Note that the other details of endianness have been hidden in CRCPOLY
* (which must be bit-reversed) and next_input_bit().
*
* However, as long as next_input_bit is returning the bits in a sensible
* order, we can actually do the merging 8 or more bits at a time rather
* than one bit at a time:
* for (i = 0; i < input_bytes; i++) {
* remainder ^= next_input_byte() << 24;
* for (j = 0; j < 8; j++) {
* multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
* remainder = (remainder << 1) ^ multiple;
* }
* }
* Or in little-endian:
* for (i = 0; i < input_bytes; i++) {
* remainder ^= next_input_byte();
* for (j = 0; j < 8; j++) {
* multiple = (remainder & 1) ? CRCPOLY : 0;
* remainder = (remainder << 1) ^ multiple;
* }
* }
* If the input is a multiple of 32 bits, you can even XOR in a 32-bit
* word at a time and increase the inner loop count to 32.
*
* You can also mix and match the two loop styles, for example doing the
* bulk of a message byte-at-a-time and adding bit-at-a-time processing
* for any fractional bytes at the end.
*
* The only remaining optimization is to the byte-at-a-time table method.
* Here, rather than just shifting one bit of the remainder to decide
* in the correct multiple to subtract, we can shift a byte at a time.
* This produces a 40-bit (rather than a 33-bit) intermediate remainder,
* but again the multiple of the polynomial to subtract depends only on
* the high bits, the high 8 bits in this case.
*
* The multile we need in that case is the low 32 bits of a 40-bit
* value whose high 8 bits are given, and which is a multiple of the
* generator polynomial. This is simply the CRC-32 of the given
* one-byte message.
*
* Two more details: normally, appending zero bits to a message which
* is already a multiple of a polynomial produces a larger multiple of that
* polynomial. To enable a CRC to detect this condition, it's common to
* invert the CRC before appending it. This makes the remainder of the
* message+crc come out not as zero, but some fixed non-zero value.
*
* The same problem applies to zero bits prepended to the message, and
* a similar solution is used. Instead of starting with a remainder of
* 0, an initial remainder of all ones is used. As long as you start
* the same way on decoding, it doesn't make a difference.
*/

15
src/bled/data_align.c Normal file
View file

@ -0,0 +1,15 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC data_align(archive_handle_t *archive_handle, unsigned boundary)
{
unsigned skip_amount = (boundary - (archive_handle->offset % boundary)) % boundary;
archive_handle->seek(archive_handle->src_fd, skip_amount);
archive_handle->offset += skip_amount;
}

213
src/bled/data_extract_all.c Normal file
View file

@ -0,0 +1,213 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
{
file_header_t *file_header = archive_handle->file_header;
int dst_fd;
int res;
#if ENABLE_FEATURE_TAR_SELINUX
char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
if (!sctx)
sctx = archive_handle->tar__sctx[PAX_GLOBAL];
if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
setfscreatecon(sctx);
free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
}
#endif
if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
char *slash = strrchr(file_header->name, '/');
if (slash) {
*slash = '\0';
bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
*slash = '/';
}
}
if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
/* Remove the entry if it exists */
if (!S_ISDIR(file_header->mode)) {
/* Is it hardlink?
* We encode hard links as regular files of size 0 with a symlink */
if (S_ISREG(file_header->mode)
&& file_header->link_target
&& file_header->size == 0
) {
/* Ugly special case:
* tar cf t.tar hardlink1 hardlink2 hardlink1
* results in this tarball structure:
* hardlink1
* hardlink2 -> hardlink1
* hardlink1 -> hardlink1 <== !!!
*/
if (strcmp(file_header->link_target, file_header->name) == 0)
goto ret;
}
/* Proceed with deleting */
if (unlink(file_header->name) == -1
&& errno != ENOENT
) {
bb_perror_msg_and_die("can't remove old file %s",
file_header->name);
}
}
}
else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
/* Remove the existing entry if its older than the extracted entry */
struct stat existing_sb;
if (lstat(file_header->name, &existing_sb) == -1) {
if (errno != ENOENT) {
bb_perror_msg_and_die("can't stat old file");
}
}
else if (existing_sb.st_mtime >= file_header->mtime) {
if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
&& !S_ISDIR(file_header->mode)
) {
bb_error_msg("%s not created: newer or "
"same age file exists", file_header->name);
}
data_skip(archive_handle);
goto ret;
}
else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
bb_perror_msg_and_die("can't remove old file %s",
file_header->name);
}
}
/* Handle hard links separately
* We encode hard links as regular files of size 0 with a symlink */
if (S_ISREG(file_header->mode)
&& file_header->link_target
&& file_header->size == 0
) {
/* hard link */
res = link(file_header->link_target, file_header->name);
if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
bb_perror_msg("can't create %slink "
"from %s to %s", "hard",
file_header->name,
file_header->link_target);
}
/* Hardlinks have no separate mode/ownership, skip chown/chmod */
goto ret;
}
/* Create the filesystem entry */
switch (file_header->mode & S_IFMT) {
case S_IFREG: {
/* Regular file */
char *dst_name;
int flags = O_WRONLY | O_CREAT | O_EXCL;
if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
flags = O_WRONLY | O_CREAT | O_TRUNC;
dst_name = file_header->name;
#ifdef ARCHIVE_REPLACE_VIA_RENAME
if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME)
/* rpm-style temp file name */
dst_name = xasprintf("%s;%x", dst_name, (int)getpid());
#endif
dst_fd = xopen3(dst_name,
flags,
file_header->mode
);
bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
close(dst_fd);
#ifdef ARCHIVE_REPLACE_VIA_RENAME
if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) {
xrename(dst_name, file_header->name);
free(dst_name);
}
#endif
break;
}
case S_IFDIR:
res = mkdir(file_header->name, file_header->mode);
if ((res == -1)
&& (errno != EISDIR) /* btw, Linux doesn't return this */
&& (errno != EEXIST)
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
) {
bb_perror_msg("can't make dir %s", file_header->name);
}
break;
case S_IFLNK:
/* Symlink */
//TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
res = symlink(file_header->link_target, file_header->name);
if ((res == -1)
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
) {
bb_perror_msg("can't create %slink "
"from %s to %s", "sym",
file_header->name,
file_header->link_target);
}
break;
case S_IFSOCK:
case S_IFBLK:
case S_IFCHR:
case S_IFIFO:
res = mknod(file_header->name, file_header->mode, file_header->device);
if ((res == -1)
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
) {
bb_perror_msg("can't create node %s", file_header->name);
}
break;
default:
bb_error_msg_and_die("unrecognized file type");
}
if (!S_ISLNK(file_header->mode)) {
if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
uid_t uid = file_header->uid;
gid_t gid = file_header->gid;
#if ENABLE_FEATURE_TAR_UNAME_GNAME
if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
if (file_header->tar__uname) {
//TODO: cache last name/id pair?
struct passwd *pwd = getpwnam(file_header->tar__uname);
if (pwd) uid = pwd->pw_uid;
}
if (file_header->tar__gname) {
struct group *grp = getgrnam(file_header->tar__gname);
if (grp) gid = grp->gr_gid;
}
}
#endif
/* GNU tar 1.15.1 uses chown, not lchown */
chown(file_header->name, uid, gid);
}
/* uclibc has no lchmod, glibc is even stranger -
* it has lchmod which seems to do nothing!
* so we use chmod... */
if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
chmod(file_header->name, file_header->mode);
}
if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
struct timeval t[2];
t[1].tv_sec = t[0].tv_sec = file_header->mtime;
t[1].tv_usec = t[0].tv_usec = 0;
utimes(file_header->name, t);
}
}
ret: ;
#if ENABLE_FEATURE_TAR_SELINUX
if (sctx) {
/* reset the context after creating an entry */
setfscreatecon(NULL);
}
#endif
}

12
src/bled/data_skip.c Normal file
View file

@ -0,0 +1,12 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC data_skip(archive_handle_t *archive_handle)
{
archive_handle->seek(archive_handle->src_fd, archive_handle->file_header->size);
}

View file

@ -0,0 +1,829 @@
/* vi: set sw=4 ts=4: */
/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
which also acknowledges contributions by Mike Burrows, David Wheeler,
Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
Robert Sedgewick, and Jon L. Bentley.
Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
/*
Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org).
More efficient reading of Huffman codes, a streamlined read_bunzip()
function, and various other tweaks. In (limited) tests, approximately
20% faster than bzcat on x86 and about 10% faster on arm.
Note that about 2/3 of the time is spent in read_bunzip() reversing
the Burrows-Wheeler transformation. Much of that time is delay
resulting from cache misses.
(2010 update by vda: profiled "bzcat <84mbyte.bz2 >/dev/null"
on x86-64 CPU with L2 > 1M: get_next_block is hotter than read_bunzip:
%time seconds calls function
71.01 12.69 444 get_next_block
28.65 5.12 93065 read_bunzip
00.22 0.04 7736490 get_bits
00.11 0.02 47 dealloc_bunzip
00.00 0.00 93018 full_write
...)
I would ask that anyone benefiting from this work, especially those
using it in commercial products, consider making a donation to my local
non-profit hospice organization (www.hospiceacadiana.com) in the name of
the woman I loved, Toni W. Hagan, who passed away Feb. 12, 2003.
Manuel
*/
#include "libbb.h"
#include "bb_archive.h"
#if 0
# define dbg(...) bb_error_msg(__VA_ARGS__)
#else
# define dbg(...) ((void)0)
#endif
/* Constants for Huffman coding */
#define MAX_GROUPS 6
#define GROUP_SIZE 50 /* 64 would have been more efficient */
#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */
#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */
#define SYMBOL_RUNA 0
#define SYMBOL_RUNB 1
/* Status return values */
#define RETVAL_OK 0
#define RETVAL_LAST_BLOCK (dbg("%d", __LINE__), -1)
#define RETVAL_NOT_BZIP_DATA (dbg("%d", __LINE__), -2)
#define RETVAL_UNEXPECTED_INPUT_EOF (dbg("%d", __LINE__), -3)
#define RETVAL_SHORT_WRITE (dbg("%d", __LINE__), -4)
#define RETVAL_DATA_ERROR (dbg("%d", __LINE__), -5)
#define RETVAL_OUT_OF_MEMORY (dbg("%d", __LINE__), -6)
#define RETVAL_OBSOLETE_INPUT (dbg("%d", __LINE__), -7)
/* Other housekeeping constants */
#define IOBUF_SIZE 4096
/* This is what we know about each Huffman coding group */
struct group_data {
/* We have an extra slot at the end of limit[] for a sentinel value. */
int limit[MAX_HUFCODE_BITS+1], base[MAX_HUFCODE_BITS], permute[MAX_SYMBOLS];
int minLen, maxLen;
};
/* Structure holding all the housekeeping data, including IO buffers and
* memory that persists between calls to bunzip
* Found the most used member:
* cat this_file.c | sed -e 's/"/ /g' -e "s/'/ /g" | xargs -n1 \
* | grep 'bd->' | sed 's/^.*bd->/bd->/' | sort | $PAGER
* and moved it (inbufBitCount) to offset 0.
*/
struct bunzip_data {
/* I/O tracking data (file handles, buffers, positions, etc.) */
unsigned inbufBitCount, inbufBits;
int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/;
uint8_t *inbuf /*,*outbuf*/;
/* State for interrupting output loop */
int writeCopies, writePos, writeRunCountdown, writeCount;
int writeCurrent; /* actually a uint8_t */
/* The CRC values stored in the block header and calculated from the data */
uint32_t headerCRC, totalCRC, writeCRC;
/* Intermediate buffer and its size (in bytes) */
uint32_t *dbuf;
unsigned dbufSize;
/* For I/O error handling */
jmp_buf jmpbuf;
/* Big things go last (register-relative addressing can be larger for big offsets) */
uint32_t crc32Table[256];
uint8_t selectors[32768]; /* nSelectors=15 bits */
struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */
};
/* typedef struct bunzip_data bunzip_data; -- done in .h file */
/* Return the next nnn bits of input. All reads from the compressed input
are done through this function. All reads are big endian */
static unsigned get_bits(bunzip_data *bd, int bits_wanted)
{
unsigned bits = 0;
/* Cache bd->inbufBitCount in a CPU register (hopefully): */
int bit_count = bd->inbufBitCount;
/* If we need to get more data from the byte buffer, do so. (Loop getting
one byte at a time to enforce endianness and avoid unaligned access.) */
while (bit_count < bits_wanted) {
/* If we need to read more data from file into byte buffer, do so */
if (bd->inbufPos == bd->inbufCount) {
/* if "no input fd" case: in_fd == -1, read fails, we jump */
bd->inbufCount = safe_read(bd->in_fd, bd->inbuf, IOBUF_SIZE);
if (bd->inbufCount <= 0)
longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF);
bd->inbufPos = 0;
}
/* Avoid 32-bit overflow (dump bit buffer to top of output) */
if (bit_count >= 24) {
bits = bd->inbufBits & ((1 << bit_count) - 1);
bits_wanted -= bit_count;
bits <<= bits_wanted;
bit_count = 0;
}
/* Grab next 8 bits of input from buffer. */
bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++];
bit_count += 8;
}
/* Calculate result */
bit_count -= bits_wanted;
bd->inbufBitCount = bit_count;
bits |= (bd->inbufBits >> bit_count) & ((1 << bits_wanted) - 1);
return bits;
}
/* Unpacks the next block and sets up for the inverse Burrows-Wheeler step. */
static int get_next_block(bunzip_data *bd)
{
struct group_data *hufGroup;
int dbufCount, dbufSize, groupCount, *base, *limit, selector,
i, j, t, runPos, symCount, symTotal, nSelectors, byteCount[256];
int runCnt;
uint8_t uc, symToByte[256], mtfSymbol[256], *selectors;
uint32_t *dbuf;
unsigned origPtr;
dbuf = bd->dbuf;
dbufSize = bd->dbufSize;
selectors = bd->selectors;
/* In bbox, we are ok with aborting through setjmp which is set up in start_bunzip */
#if 0
/* Reset longjmp I/O error handling */
i = setjmp(bd->jmpbuf);
if (i) return i;
#endif
/* Read in header signature and CRC, then validate signature.
(last block signature means CRC is for whole file, return now) */
i = get_bits(bd, 24);
j = get_bits(bd, 24);
bd->headerCRC = get_bits(bd, 32);
if ((i == 0x177245) && (j == 0x385090)) return RETVAL_LAST_BLOCK;
if ((i != 0x314159) || (j != 0x265359)) return RETVAL_NOT_BZIP_DATA;
/* We can add support for blockRandomised if anybody complains. There was
some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
it didn't actually work. */
if (get_bits(bd, 1)) return RETVAL_OBSOLETE_INPUT;
origPtr = get_bits(bd, 24);
if ((int)origPtr > dbufSize) return RETVAL_DATA_ERROR;
/* mapping table: if some byte values are never used (encoding things
like ascii text), the compression code removes the gaps to have fewer
symbols to deal with, and writes a sparse bitfield indicating which
values were present. We make a translation table to convert the symbols
back to the corresponding bytes. */
symTotal = 0;
i = 0;
t = get_bits(bd, 16);
do {
if (t & (1 << 15)) {
unsigned inner_map = get_bits(bd, 16);
do {
if (inner_map & (1 << 15))
symToByte[symTotal++] = i;
inner_map <<= 1;
i++;
} while (i & 15);
i -= 16;
}
t <<= 1;
i += 16;
} while (i < 256);
/* How many different Huffman coding groups does this block use? */
groupCount = get_bits(bd, 3);
if (groupCount < 2 || groupCount > MAX_GROUPS)
return RETVAL_DATA_ERROR;
/* nSelectors: Every GROUP_SIZE many symbols we select a new Huffman coding
group. Read in the group selector list, which is stored as MTF encoded
bit runs. (MTF=Move To Front, as each value is used it's moved to the
start of the list.) */
for (i = 0; i < groupCount; i++)
mtfSymbol[i] = i;
nSelectors = get_bits(bd, 15);
if (!nSelectors)
return RETVAL_DATA_ERROR;
for (i = 0; i < nSelectors; i++) {
uint8_t tmp_byte;
/* Get next value */
int n = 0;
while (get_bits(bd, 1)) {
if (n >= groupCount) return RETVAL_DATA_ERROR;
n++;
}
/* Decode MTF to get the next selector */
tmp_byte = mtfSymbol[n];
while (--n >= 0)
mtfSymbol[n + 1] = mtfSymbol[n];
mtfSymbol[0] = selectors[i] = tmp_byte;
}
/* Read the Huffman coding tables for each group, which code for symTotal
literal symbols, plus two run symbols (RUNA, RUNB) */
symCount = symTotal + 2;
for (j = 0; j < groupCount; j++) {
uint8_t length[MAX_SYMBOLS];
/* 8 bits is ALMOST enough for temp[], see below */
unsigned temp[MAX_HUFCODE_BITS+1];
int minLen, maxLen, pp, len_m1;
/* Read Huffman code lengths for each symbol. They're stored in
a way similar to mtf; record a starting value for the first symbol,
and an offset from the previous value for every symbol after that.
(Subtracting 1 before the loop and then adding it back at the end is
an optimization that makes the test inside the loop simpler: symbol
length 0 becomes negative, so an unsigned inequality catches it.) */
len_m1 = get_bits(bd, 5) - 1;
for (i = 0; i < symCount; i++) {
for (;;) {
int two_bits;
if ((unsigned)len_m1 > (MAX_HUFCODE_BITS-1))
return RETVAL_DATA_ERROR;
/* If first bit is 0, stop. Else second bit indicates whether
to increment or decrement the value. Optimization: grab 2
bits and unget the second if the first was 0. */
two_bits = get_bits(bd, 2);
if (two_bits < 2) {
bd->inbufBitCount++;
break;
}
/* Add one if second bit 1, else subtract 1. Avoids if/else */
len_m1 += (((two_bits+1) & 2) - 1);
}
/* Correct for the initial -1, to get the final symbol length */
length[i] = len_m1 + 1;
}
/* Find largest and smallest lengths in this group */
minLen = maxLen = length[0];
for (i = 1; i < symCount; i++) {
if (length[i] > maxLen) maxLen = length[i];
else if (length[i] < minLen) minLen = length[i];
}
/* Calculate permute[], base[], and limit[] tables from length[].
*
* permute[] is the lookup table for converting Huffman coded symbols
* into decoded symbols. base[] is the amount to subtract from the
* value of a Huffman symbol of a given length when using permute[].
*
* limit[] indicates the largest numerical value a symbol with a given
* number of bits can have. This is how the Huffman codes can vary in
* length: each code with a value>limit[length] needs another bit.
*/
hufGroup = bd->groups + j;
hufGroup->minLen = minLen;
hufGroup->maxLen = maxLen;
/* Note that minLen can't be smaller than 1, so we adjust the base
and limit array pointers so we're not always wasting the first
entry. We do this again when using them (during symbol decoding). */
base = hufGroup->base - 1;
limit = hufGroup->limit - 1;
/* Calculate permute[]. Concurently, initialize temp[] and limit[]. */
pp = 0;
for (i = minLen; i <= maxLen; i++) {
int k;
temp[i] = limit[i] = 0;
for (k = 0; k < symCount; k++)
if (length[k] == i)
hufGroup->permute[pp++] = k;
}
/* Count symbols coded for at each bit length */
/* NB: in pathological cases, temp[8] can end ip being 256.
* That's why uint8_t is too small for temp[]. */
for (i = 0; i < symCount; i++) temp[length[i]]++;
/* Calculate limit[] (the largest symbol-coding value at each bit
* length, which is (previous limit<<1)+symbols at this level), and
* base[] (number of symbols to ignore at each bit length, which is
* limit minus the cumulative count of symbols coded for already). */
pp = t = 0;
for (i = minLen; i < maxLen;) {
unsigned temp_i = temp[i];
pp += temp_i;
/* We read the largest possible symbol size and then unget bits
after determining how many we need, and those extra bits could
be set to anything. (They're noise from future symbols.) At
each level we're really only interested in the first few bits,
so here we set all the trailing to-be-ignored bits to 1 so they
don't affect the value>limit[length] comparison. */
limit[i] = (pp << (maxLen - i)) - 1;
pp <<= 1;
t += temp_i;
base[++i] = pp - t;
}
limit[maxLen] = pp + temp[maxLen] - 1;
limit[maxLen+1] = INT_MAX; /* Sentinel value for reading next sym. */
base[minLen] = 0;
}
/* We've finished reading and digesting the block header. Now read this
block's Huffman coded symbols from the file and undo the Huffman coding
and run length encoding, saving the result into dbuf[dbufCount++] = uc */
/* Initialize symbol occurrence counters and symbol Move To Front table */
/*memset(byteCount, 0, sizeof(byteCount)); - smaller, but slower */
for (i = 0; i < 256; i++) {
byteCount[i] = 0;
mtfSymbol[i] = (uint8_t)i;
}
/* Loop through compressed symbols. */
runPos = dbufCount = selector = 0;
for (;;) {
int nextSym;
/* Fetch next Huffman coding group from list. */
symCount = GROUP_SIZE - 1;
if (selector >= nSelectors) return RETVAL_DATA_ERROR;
hufGroup = bd->groups + selectors[selector++];
base = hufGroup->base - 1;
limit = hufGroup->limit - 1;
continue_this_group:
/* Read next Huffman-coded symbol. */
/* Note: It is far cheaper to read maxLen bits and back up than it is
to read minLen bits and then add additional bit at a time, testing
as we go. Because there is a trailing last block (with file CRC),
there is no danger of the overread causing an unexpected EOF for a
valid compressed file.
*/
if (1) {
/* As a further optimization, we do the read inline
(falling back to a call to get_bits if the buffer runs dry).
*/
int new_cnt;
while ((new_cnt = bd->inbufBitCount - hufGroup->maxLen) < 0) {
/* bd->inbufBitCount < hufGroup->maxLen */
if (bd->inbufPos == bd->inbufCount) {
nextSym = get_bits(bd, hufGroup->maxLen);
goto got_huff_bits;
}
bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++];
bd->inbufBitCount += 8;
};
bd->inbufBitCount = new_cnt; /* "bd->inbufBitCount -= hufGroup->maxLen;" */
nextSym = (bd->inbufBits >> new_cnt) & ((1 << hufGroup->maxLen) - 1);
got_huff_bits: ;
} else { /* unoptimized equivalent */
nextSym = get_bits(bd, hufGroup->maxLen);
}
/* Figure how many bits are in next symbol and unget extras */
i = hufGroup->minLen;
while (nextSym > limit[i]) ++i;
j = hufGroup->maxLen - i;
if (j < 0)
return RETVAL_DATA_ERROR;
bd->inbufBitCount += j;
/* Huffman decode value to get nextSym (with bounds checking) */
nextSym = (nextSym >> j) - base[i];
if ((unsigned)nextSym >= MAX_SYMBOLS)
return RETVAL_DATA_ERROR;
nextSym = hufGroup->permute[nextSym];
/* We have now decoded the symbol, which indicates either a new literal
byte, or a repeated run of the most recent literal byte. First,
check if nextSym indicates a repeated run, and if so loop collecting
how many times to repeat the last literal. */
if ((unsigned)nextSym <= SYMBOL_RUNB) { /* RUNA or RUNB */
/* If this is the start of a new run, zero out counter */
if (runPos == 0) {
runPos = 1;
runCnt = 0;
}
/* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at
each bit position, add 1 or 2 instead. For example,
1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2.
You can make any bit pattern that way using 1 less symbol than
the basic or 0/1 method (except all bits 0, which would use no
symbols, but a run of length 0 doesn't mean anything in this
context). Thus space is saved. */
runCnt += (runPos << nextSym); /* +runPos if RUNA; +2*runPos if RUNB */
if (runPos < dbufSize) runPos <<= 1;
goto end_of_huffman_loop;
}
/* When we hit the first non-run symbol after a run, we now know
how many times to repeat the last literal, so append that many
copies to our buffer of decoded symbols (dbuf) now. (The last
literal used is the one at the head of the mtfSymbol array.) */
if (runPos != 0) {
uint8_t tmp_byte;
if (dbufCount + runCnt > dbufSize) {
dbg("dbufCount:%d+runCnt:%d %d > dbufSize:%d RETVAL_DATA_ERROR",
dbufCount, runCnt, dbufCount + runCnt, dbufSize);
return RETVAL_DATA_ERROR;
}
tmp_byte = symToByte[mtfSymbol[0]];
byteCount[tmp_byte] += runCnt;
while (--runCnt >= 0) dbuf[dbufCount++] = (uint32_t)tmp_byte;
runPos = 0;
}
/* Is this the terminating symbol? */
if (nextSym > symTotal) break;
/* At this point, nextSym indicates a new literal character. Subtract
one to get the position in the MTF array at which this literal is
currently to be found. (Note that the result can't be -1 or 0,
because 0 and 1 are RUNA and RUNB. But another instance of the
first symbol in the mtf array, position 0, would have been handled
as part of a run above. Therefore 1 unused mtf position minus
2 non-literal nextSym values equals -1.) */
if (dbufCount >= dbufSize) return RETVAL_DATA_ERROR;
i = nextSym - 1;
uc = mtfSymbol[i];
/* Adjust the MTF array. Since we typically expect to move only a
* small number of symbols, and are bound by 256 in any case, using
* memmove here would typically be bigger and slower due to function
* call overhead and other assorted setup costs. */
do {
mtfSymbol[i] = mtfSymbol[i-1];
} while (--i);
mtfSymbol[0] = uc;
uc = symToByte[uc];
/* We have our literal byte. Save it into dbuf. */
byteCount[uc]++;
dbuf[dbufCount++] = (uint32_t)uc;
/* Skip group initialization if we're not done with this group. Done
* this way to avoid compiler warning. */
end_of_huffman_loop:
if (--symCount >= 0) goto continue_this_group;
}
/* At this point, we've read all the Huffman-coded symbols (and repeated
runs) for this block from the input stream, and decoded them into the
intermediate buffer. There are dbufCount many decoded bytes in dbuf[].
Now undo the Burrows-Wheeler transform on dbuf.
See http://dogma.net/markn/articles/bwt/bwt.htm
*/
/* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
j = 0;
for (i = 0; i < 256; i++) {
int tmp_count = j + byteCount[i];
byteCount[i] = j;
j = tmp_count;
}
/* Figure out what order dbuf would be in if we sorted it. */
for (i = 0; i < dbufCount; i++) {
uint8_t tmp_byte = (uint8_t)dbuf[i];
int tmp_count = byteCount[tmp_byte];
dbuf[tmp_count] |= (i << 8);
byteCount[tmp_byte] = tmp_count + 1;
}
/* Decode first byte by hand to initialize "previous" byte. Note that it
doesn't get output, and if the first three characters are identical
it doesn't qualify as a run (hence writeRunCountdown=5). */
if (dbufCount) {
uint32_t tmp;
if ((int)origPtr >= dbufCount) return RETVAL_DATA_ERROR;
tmp = dbuf[origPtr];
bd->writeCurrent = (uint8_t)tmp;
bd->writePos = (tmp >> 8);
bd->writeRunCountdown = 5;
}
bd->writeCount = dbufCount;
return RETVAL_OK;
}
/* Undo Burrows-Wheeler transform on intermediate buffer to produce output.
If start_bunzip was initialized with out_fd=-1, then up to len bytes of
data are written to outbuf. Return value is number of bytes written or
error (all errors are negative numbers). If out_fd!=-1, outbuf and len
are ignored, data is written to out_fd and return is RETVAL_OK or error.
NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0.
(Why? This allows to get rid of one local variable)
*/
int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
{
const uint32_t *dbuf;
int pos, current, previous;
uint32_t CRC;
/* If we already have error/end indicator, return it */
if (bd->writeCount < 0)
return bd->writeCount;
dbuf = bd->dbuf;
/* Register-cached state (hopefully): */
pos = bd->writePos;
current = bd->writeCurrent;
CRC = bd->writeCRC; /* small loss on x86-32 (not enough regs), win on x86-64 */
/* We will always have pending decoded data to write into the output
buffer unless this is the very first call (in which case we haven't
Huffman-decoded a block into the intermediate buffer yet). */
if (bd->writeCopies) {
dec_writeCopies:
/* Inside the loop, writeCopies means extra copies (beyond 1) */
--bd->writeCopies;
/* Loop outputting bytes */
for (;;) {
/* If the output buffer is full, save cached state and return */
if (--len < 0) {
/* Unlikely branch.
* Use of "goto" instead of keeping code here
* helps compiler to realize this. */
goto outbuf_full;
}
/* Write next byte into output buffer, updating CRC */
*outbuf++ = current;
CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current];
/* Loop now if we're outputting multiple copies of this byte */
if (bd->writeCopies) {
/* Unlikely branch */
/*--bd->writeCopies;*/
/*continue;*/
/* Same, but (ab)using other existing --writeCopies operation
* (and this if() compiles into just test+branch pair): */
goto dec_writeCopies;
}
decode_next_byte:
if (--bd->writeCount < 0)
break; /* input block is fully consumed, need next one */
/* Follow sequence vector to undo Burrows-Wheeler transform */
previous = current;
pos = dbuf[pos];
current = (uint8_t)pos;
pos >>= 8;
/* After 3 consecutive copies of the same byte, the 4th
* is a repeat count. We count down from 4 instead
* of counting up because testing for non-zero is faster */
if (--bd->writeRunCountdown != 0) {
if (current != previous)
bd->writeRunCountdown = 4;
} else {
/* Unlikely branch */
/* We have a repeated run, this byte indicates the count */
bd->writeCopies = current;
current = previous;
bd->writeRunCountdown = 5;
/* Sometimes there are just 3 bytes (run length 0) */
if (!bd->writeCopies) goto decode_next_byte;
/* Subtract the 1 copy we'd output anyway to get extras */
--bd->writeCopies;
}
} /* for(;;) */
/* Decompression of this input block completed successfully */
bd->writeCRC = CRC = ~CRC;
bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) ^ CRC;
/* If this block had a CRC error, force file level CRC error */
if (CRC != bd->headerCRC) {
bd->totalCRC = bd->headerCRC + 1;
return RETVAL_LAST_BLOCK;
}
}
/* Refill the intermediate buffer by Huffman-decoding next block of input */
{
int r = get_next_block(bd);
if (r) { /* error/end */
bd->writeCount = r;
return (r != RETVAL_LAST_BLOCK) ? r : len;
}
}
CRC = ~0;
pos = bd->writePos;
current = bd->writeCurrent;
goto decode_next_byte;
outbuf_full:
/* Output buffer is full, save cached state and return */
bd->writePos = pos;
bd->writeCurrent = current;
bd->writeCRC = CRC;
bd->writeCopies++;
return 0;
}
/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain
a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are
ignored, and data is read from file handle into temporary buffer. */
/* Because bunzip2 is used for help text unpacking, and because bb_show_usage()
should work for NOFORK applets too, we must be extremely careful to not leak
any allocations! */
int FAST_FUNC start_bunzip(bunzip_data **bdp, int in_fd,
const void *inbuf, int len)
{
bunzip_data *bd;
unsigned i;
enum {
BZh0 = ('B' << 24) + ('Z' << 16) + ('h' << 8) + '0',
h0 = ('h' << 8) + '0',
};
/* Figure out how much data to allocate */
i = sizeof(bunzip_data);
if (in_fd != -1) i += IOBUF_SIZE;
/* Allocate bunzip_data. Most fields initialize to zero. */
bd = *bdp = xzalloc(i);
/* Setup input buffer */
bd->in_fd = in_fd;
if (-1 == in_fd) {
/* in this case, bd->inbuf is read-only */
bd->inbuf = (void*)inbuf; /* cast away const-ness */
} else {
bd->inbuf = (uint8_t*)(bd + 1);
memcpy(bd->inbuf, inbuf, len);
}
bd->inbufCount = len;
/* Init the CRC32 table (big endian) */
crc32_filltable(bd->crc32Table, 1);
/* Setup for I/O error handling via longjmp */
i = setjmp(bd->jmpbuf);
if (i) return i;
/* Ensure that file starts with "BZh['1'-'9']." */
/* Update: now caller verifies 1st two bytes, makes .gz/.bz2
* integration easier */
/* was: */
/* i = get_bits(bd, 32); */
/* if ((unsigned)(i - BZh0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA; */
i = get_bits(bd, 16);
if ((unsigned)(i - h0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA;
/* Fourth byte (ascii '1'-'9') indicates block size in units of 100k of
uncompressed data. Allocate intermediate buffer for block. */
/* bd->dbufSize = 100000 * (i - BZh0); */
bd->dbufSize = 100000 * (i - h0);
/* Cannot use xmalloc - may leak bd in NOFORK case! */
bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(bd->dbuf[0]));
if (!bd->dbuf) {
free(bd);
xfunc_die();
}
return RETVAL_OK;
}
void FAST_FUNC dealloc_bunzip(bunzip_data *bd)
{
free(bd->dbuf);
free(bd);
}
/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */
IF_DESKTOP(long long) int FAST_FUNC
unpack_bz2_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long total_written = 0;)
bunzip_data *bd;
char *outbuf;
int i;
unsigned len;
if (check_signature16(xstate, BZIP2_MAGIC))
return -1;
outbuf = xmalloc(IOBUF_SIZE);
len = 0;
while (1) { /* "Process one BZ... stream" loop */
i = start_bunzip(&bd, xstate->src_fd, outbuf + 2, len);
if (i == 0) {
while (1) { /* "Produce some output bytes" loop */
i = read_bunzip(bd, outbuf, IOBUF_SIZE);
if (i < 0) /* error? */
break;
i = IOBUF_SIZE - i; /* number of bytes produced */
if (i == 0) /* EOF? */
break;
if (i != transformer_write(xstate, outbuf, i)) {
i = RETVAL_SHORT_WRITE;
goto release_mem;
}
IF_DESKTOP(total_written += i;)
}
}
if (i != RETVAL_LAST_BLOCK
/* Observed case when i == RETVAL_OK:
* "bzcat z.bz2", where "z.bz2" is a bzipped zero-length file
* (to be exact, z.bz2 is exactly these 14 bytes:
* 42 5a 68 39 17 72 45 38 50 90 00 00 00 00).
*/
&& i != RETVAL_OK
) {
bb_error_msg("bunzip error %d", i);
break;
}
if (bd->headerCRC != bd->totalCRC) {
bb_error_msg("CRC error");
break;
}
/* Successfully unpacked one BZ stream */
i = RETVAL_OK;
/* Do we have "BZ..." after last processed byte?
* pbzip2 (parallelized bzip2) produces such files.
*/
len = bd->inbufCount - bd->inbufPos;
memcpy(outbuf, &bd->inbuf[bd->inbufPos], len);
if (len < 2) {
if (safe_read(xstate->src_fd, outbuf + len, 2 - len) != 2 - len)
break;
len = 2;
}
if (*(uint16_t*)outbuf != BZIP2_MAGIC) /* "BZ"? */
break;
dealloc_bunzip(bd);
len -= 2;
}
release_mem:
dealloc_bunzip(bd);
free(outbuf);
return i ? i : IF_DESKTOP(total_written) + 0;
}
#ifdef TESTING
static char *const bunzip_errors[] = {
NULL, "Bad file checksum", "Not bzip data",
"Unexpected input EOF", "Unexpected output EOF", "Data error",
"Out of memory", "Obsolete (pre 0.9.5) bzip format not supported"
};
/* Dumb little test thing, decompress stdin to stdout */
int main(int argc, char **argv)
{
char c;
int i = unpack_bz2_stream(0, 1);
if (i < 0)
fprintf(stderr, "%s\n", bunzip_errors[-i]);
else if (read(STDIN_FILENO, &c, 1))
fprintf(stderr, "Trailing garbage ignored\n");
return -i;
}
#endif

1271
src/bled/decompress_gunzip.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,315 @@
/* vi: set sw=4 ts=4: */
/* uncompress for busybox -- (c) 2002 Robert Griebl
*
* based on the original compress42.c source
* (see disclaimer below)
*/
/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
*
* Authors:
* Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
* Jim McKie (decvax!mcvax!jim)
* Steve Davies (decvax!vax135!petsd!peora!srd)
* Ken Turkowski (decvax!decwrl!turtlevax!ken)
* James A. Woods (decvax!ihnp4!ames!jaw)
* Joe Orost (decvax!vax135!petsd!joe)
* Dave Mack (csu@alembic.acs.com)
* Peter Jannesen, Network Communication Systems
* (peter@ncs.nl)
*
* marc@suse.de : a small security fix for a buffer overflow
*
* [... History snipped ...]
*
*/
#include "libbb.h"
#include "bb_archive.h"
/* Default input buffer size */
#define IBUFSIZ 2048
/* Default output buffer size */
#define OBUFSIZ 2048
/* Defines for third byte of header */
#define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */
/* Masks 0x20 and 0x40 are free. */
/* I think 0x20 should mean that there is */
/* a fourth header byte (for expansion). */
#define BLOCK_MODE 0x80 /* Block compression if table is full and */
/* compression rate is dropping flush tables */
/* the next two codes should not be changed lightly, as they must not */
/* lie within the contiguous general code space. */
#define FIRST 257 /* first free entry */
#define CLEAR 256 /* table clear output code */
#define INIT_BITS 9 /* initial number of bits/code */
/* machine variants which require cc -Dmachine: pdp11, z8000, DOS */
#define HBITS 17 /* 50% occupancy */
#define HSIZE (1<<HBITS)
#define HMASK (HSIZE-1) /* unused */
#define HPRIME 9941 /* unused */
#define BITS 16
#define BITS_STR "16"
#undef MAXSEG_64K /* unused */
#define MAXCODE(n) (1L << (n))
#define htabof(i) htab[i]
#define codetabof(i) codetab[i]
#define tab_prefixof(i) codetabof(i)
#define tab_suffixof(i) ((unsigned char *)(htab))[i]
#define de_stack ((unsigned char *)&(htab[HSIZE-1]))
#define clear_tab_prefixof() memset(codetab, 0, 256)
/*
* Decompress stdin to stdout. This routine adapts to the codes in the
* file building the "string" table on-the-fly; requiring no table to
* be stored in the compressed file.
*/
IF_DESKTOP(long long) int FAST_FUNC
unpack_Z_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long total_written = 0;)
IF_DESKTOP(long long) int retval = -1;
unsigned char *stackp;
int finchar;
long oldcode;
long incode;
int inbits;
int posbits;
int outpos;
int insize;
int bitmask;
long free_ent;
long maxcode;
long maxmaxcode;
int n_bits;
int rsize = 0;
unsigned char *inbuf; /* were eating insane amounts of stack - */
unsigned char *outbuf; /* bad for some embedded targets */
unsigned char *htab;
unsigned short *codetab;
/* Hmm, these were statics - why?! */
/* user settable max # bits/code */
int maxbits; /* = BITS; */
/* block compress mode -C compatible with 2.0 */
int block_mode; /* = BLOCK_MODE; */
if (check_signature16(xstate, COMPRESS_MAGIC))
return -1;
inbuf = xzalloc(IBUFSIZ + 64);
outbuf = xzalloc(OBUFSIZ + 2048);
htab = xzalloc(HSIZE); /* wasn't zeroed out before, maybe can xmalloc? */
codetab = xzalloc(HSIZE * sizeof(codetab[0]));
insize = 0;
/* xread isn't good here, we have to return - caller may want
* to do some cleanup (e.g. delete incomplete unpacked file etc) */
if (full_read(xstate->src_fd, inbuf, 1) != 1) {
bb_error_msg("short read");
goto err;
}
maxbits = inbuf[0] & BIT_MASK;
block_mode = inbuf[0] & BLOCK_MODE;
maxmaxcode = MAXCODE(maxbits);
if (maxbits > BITS) {
bb_error_msg("compressed with %d bits, can only handle "
BITS_STR" bits", maxbits);
goto err;
}
n_bits = INIT_BITS;
maxcode = MAXCODE(INIT_BITS) - 1;
bitmask = (1 << INIT_BITS) - 1;
oldcode = -1;
finchar = 0;
outpos = 0;
posbits = 0 << 3;
free_ent = ((block_mode) ? FIRST : 256);
/* As above, initialize the first 256 entries in the table. */
/*clear_tab_prefixof(); - done by xzalloc */
{
int i;
for (i = 255; i >= 0; --i)
tab_suffixof(i) = (unsigned char) i;
}
do {
resetbuf:
{
int i;
int e;
int o;
o = posbits >> 3;
e = insize - o;
for (i = 0; i < e; ++i)
inbuf[i] = inbuf[i + o];
insize = e;
posbits = 0;
}
if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
rsize = safe_read(xstate->src_fd, inbuf + insize, IBUFSIZ);
if (rsize < 0)
bb_error_msg_and_err(bb_msg_read_error);
insize += rsize;
}
inbits = ((rsize > 0) ? (insize - insize % n_bits) << 3 :
(insize << 3) - (n_bits - 1));
while (inbits > posbits) {
long code;
if (free_ent > maxcode) {
posbits =
((posbits - 1) +
((n_bits << 3) -
(posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
++n_bits;
if (n_bits == maxbits) {
maxcode = maxmaxcode;
} else {
maxcode = MAXCODE(n_bits) - 1;
}
bitmask = (1 << n_bits) - 1;
goto resetbuf;
}
{
unsigned char *p = &inbuf[posbits >> 3];
code = ((p[0]
| ((long) (p[1]) << 8)
| ((long) (p[2]) << 16)) >> (posbits & 0x7)) & bitmask;
}
posbits += n_bits;
if (oldcode == -1) {
if (code >= 256)
bb_error_msg_and_err("corrupted data"); /* %ld", code); */
oldcode = code;
finchar = (int) oldcode;
outbuf[outpos++] = (unsigned char) finchar;
continue;
}
if (code == CLEAR && block_mode) {
clear_tab_prefixof();
free_ent = FIRST - 1;
posbits =
((posbits - 1) +
((n_bits << 3) -
(posbits - 1 + (n_bits << 3)) % (n_bits << 3)));
n_bits = INIT_BITS;
maxcode = MAXCODE(INIT_BITS) - 1;
bitmask = (1 << INIT_BITS) - 1;
goto resetbuf;
}
incode = code;
stackp = de_stack;
/* Special case for KwKwK string. */
if (code >= free_ent) {
if (code > free_ent) {
/*
unsigned char *p;
posbits -= n_bits;
p = &inbuf[posbits >> 3];
bb_error_msg
("insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)",
insize, posbits, p[-1], p[0], p[1], p[2], p[3],
(posbits & 07));
*/
bb_error_msg("corrupted data");
goto err;
}
*--stackp = (unsigned char) finchar;
code = oldcode;
}
/* Generate output characters in reverse order */
while (code >= 256) {
if (stackp <= &htabof(0))
bb_error_msg_and_err("corrupted data");
*--stackp = tab_suffixof(code);
code = tab_prefixof(code);
}
finchar = tab_suffixof(code);
*--stackp = (unsigned char) finchar;
/* And put them out in forward order */
{
int i;
i = de_stack - stackp;
if (outpos + i >= OBUFSIZ) {
do {
if (i > OBUFSIZ - outpos) {
i = OBUFSIZ - outpos;
}
if (i > 0) {
memcpy(outbuf + outpos, stackp, i);
outpos += i;
}
if (outpos >= OBUFSIZ) {
xtransformer_write(xstate, outbuf, outpos);
IF_DESKTOP(total_written += outpos;)
outpos = 0;
}
stackp += i;
i = de_stack - stackp;
} while (i > 0);
} else {
memcpy(outbuf + outpos, stackp, i);
outpos += i;
}
}
/* Generate the new entry. */
if (free_ent < maxmaxcode) {
tab_prefixof(free_ent) = (unsigned short) oldcode;
tab_suffixof(free_ent) = (unsigned char) finchar;
free_ent++;
}
/* Remember previous code. */
oldcode = incode;
}
} while (rsize > 0);
if (outpos > 0) {
xtransformer_write(xstate, outbuf, outpos);
IF_DESKTOP(total_written += outpos;)
}
retval = IF_DESKTOP(total_written) + 0;
err:
free(inbuf);
free(outbuf);
free(htab);
free(codetab);
return retval;
}

View file

@ -0,0 +1,468 @@
/* vi: set sw=4 ts=4: */
/*
* Small lzma deflate implementation.
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
* Copyright (C) 1999-2005 Igor Pavlov
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
#if ENABLE_FEATURE_LZMA_FAST
# define speed_inline ALWAYS_INLINE
# define size_inline
#else
# define speed_inline
# define size_inline ALWAYS_INLINE
#endif
typedef struct {
int fd;
uint8_t *ptr;
/* Was keeping rc on stack in unlzma and separately allocating buffer,
* but with "buffer 'attached to' allocated rc" code is smaller: */
/* uint8_t *buffer; */
#define RC_BUFFER ((uint8_t*)(rc+1))
uint8_t *buffer_end;
/* Had provisions for variable buffer, but we don't need it here */
/* int buffer_size; */
#define RC_BUFFER_SIZE 0x10000
uint32_t code;
uint32_t range;
uint32_t bound;
} rc_t;
#define RC_TOP_BITS 24
#define RC_MOVE_BITS 5
#define RC_MODEL_TOTAL_BITS 11
/* Called once in rc_do_normalize() */
static void rc_read(rc_t *rc)
{
int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE);
//TODO: return -1 instead
//This will make unlzma delete broken unpacked file on unpack errors
if (buffer_size <= 0)
bb_error_msg_and_die("unexpected EOF");
rc->buffer_end = RC_BUFFER + buffer_size;
rc->ptr = RC_BUFFER;
}
/* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */
static void rc_do_normalize(rc_t *rc)
{
if (rc->ptr >= rc->buffer_end)
rc_read(rc);
rc->range <<= 8;
rc->code = (rc->code << 8) | *rc->ptr++;
}
static ALWAYS_INLINE void rc_normalize(rc_t *rc)
{
if (rc->range < (1 << RC_TOP_BITS)) {
rc_do_normalize(rc);
}
}
/* Called once */
static ALWAYS_INLINE rc_t* rc_init(int fd) /*, int buffer_size) */
{
int i;
rc_t *rc;
rc = xzalloc(sizeof(*rc) + RC_BUFFER_SIZE);
rc->fd = fd;
/* rc->ptr = rc->buffer_end; */
for (i = 0; i < 5; i++) {
rc_do_normalize(rc);
}
rc->range = 0xffffffff;
return rc;
}
/* Called once */
static ALWAYS_INLINE void rc_free(rc_t *rc)
{
free(rc);
}
/* rc_is_bit_1 is called 9 times */
static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p)
{
rc_normalize(rc);
rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
if (rc->code < rc->bound) {
rc->range = rc->bound;
*p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
return 0;
}
rc->range -= rc->bound;
rc->code -= rc->bound;
*p -= *p >> RC_MOVE_BITS;
return 1;
}
/* Called 4 times in unlzma loop */
static ALWAYS_INLINE int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
{
int ret = rc_is_bit_1(rc, p);
*symbol = *symbol * 2 + ret;
return ret;
}
/* Called once */
static ALWAYS_INLINE int rc_direct_bit(rc_t *rc)
{
rc_normalize(rc);
rc->range >>= 1;
if (rc->code >= rc->range) {
rc->code -= rc->range;
return 1;
}
return 0;
}
/* Called twice */
static speed_inline void
rc_bit_tree_decode(rc_t *rc, uint16_t *p, int num_levels, int *symbol)
{
int i = num_levels;
*symbol = 1;
while (i--)
rc_get_bit(rc, p + *symbol, symbol);
*symbol -= 1 << num_levels;
}
PRAGMA_BEGIN_PACKED
typedef struct {
uint8_t pos;
uint32_t dict_size;
uint64_t dst_size;
} PACKED lzma_header_t;
PRAGMA_END_PACKED
/* #defines will force compiler to compute/optimize each one with each usage.
* Have heart and use enum instead. */
enum {
LZMA_BASE_SIZE = 1846,
LZMA_LIT_SIZE = 768,
LZMA_NUM_POS_BITS_MAX = 4,
LZMA_LEN_NUM_LOW_BITS = 3,
LZMA_LEN_NUM_MID_BITS = 3,
LZMA_LEN_NUM_HIGH_BITS = 8,
LZMA_LEN_CHOICE = 0,
LZMA_LEN_CHOICE_2 = (LZMA_LEN_CHOICE + 1),
LZMA_LEN_LOW = (LZMA_LEN_CHOICE_2 + 1),
LZMA_LEN_MID = (LZMA_LEN_LOW \
+ (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))),
LZMA_LEN_HIGH = (LZMA_LEN_MID \
+ (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))),
LZMA_NUM_LEN_PROBS = (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)),
LZMA_NUM_STATES = 12,
LZMA_NUM_LIT_STATES = 7,
LZMA_START_POS_MODEL_INDEX = 4,
LZMA_END_POS_MODEL_INDEX = 14,
LZMA_NUM_FULL_DISTANCES = (1 << (LZMA_END_POS_MODEL_INDEX >> 1)),
LZMA_NUM_POS_SLOT_BITS = 6,
LZMA_NUM_LEN_TO_POS_STATES = 4,
LZMA_NUM_ALIGN_BITS = 4,
LZMA_MATCH_MIN_LEN = 2,
LZMA_IS_MATCH = 0,
LZMA_IS_REP = (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
LZMA_IS_REP_G0 = (LZMA_IS_REP + LZMA_NUM_STATES),
LZMA_IS_REP_G1 = (LZMA_IS_REP_G0 + LZMA_NUM_STATES),
LZMA_IS_REP_G2 = (LZMA_IS_REP_G1 + LZMA_NUM_STATES),
LZMA_IS_REP_0_LONG = (LZMA_IS_REP_G2 + LZMA_NUM_STATES),
LZMA_POS_SLOT = (LZMA_IS_REP_0_LONG \
+ (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
LZMA_SPEC_POS = (LZMA_POS_SLOT \
+ (LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)),
LZMA_ALIGN = (LZMA_SPEC_POS \
+ LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX),
LZMA_LEN_CODER = (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)),
LZMA_REP_LEN_CODER = (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS),
LZMA_LITERAL = (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS),
};
IF_DESKTOP(long long) int FAST_FUNC
unpack_lzma_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long total_written = 0;)
lzma_header_t header;
int lc, pb, lp;
uint32_t pos_state_mask;
uint32_t literal_pos_mask;
uint16_t *p;
rc_t *rc;
int i;
uint8_t *buffer;
uint8_t previous_byte = 0;
size_t buffer_pos = 0, global_pos = 0;
int len = 0;
int state = 0;
uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
if (full_read(xstate->src_fd, &header, sizeof(header)) != sizeof(header)
|| header.pos >= (9 * 5 * 5)
) {
bb_error_msg("bad lzma header");
return -1;
}
i = header.pos / 9;
lc = header.pos % 9;
pb = i / 5;
lp = i % 5;
pos_state_mask = (1 << pb) - 1;
literal_pos_mask = (1 << lp) - 1;
/* Example values from linux-3.3.4.tar.lzma:
* dict_size: 64M, dst_size: 2^64-1
*/
header.dict_size = SWAP_LE32(header.dict_size);
header.dst_size = SWAP_LE64(header.dst_size);
if (header.dict_size == 0)
header.dict_size++;
buffer = xmalloc(MIN(header.dst_size, header.dict_size));
{
int num_probs;
num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
p = xmalloc(num_probs * sizeof(*p));
num_probs += LZMA_LITERAL - LZMA_BASE_SIZE;
for (i = 0; i < num_probs; i++)
p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
}
rc = rc_init(xstate->src_fd); /*, RC_BUFFER_SIZE); */
while (global_pos + buffer_pos < header.dst_size) {
int pos_state = (buffer_pos + global_pos) & pos_state_mask;
uint16_t *prob = p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
if (!rc_is_bit_1(rc, prob)) {
static const char next_state[LZMA_NUM_STATES] =
{ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
int mi = 1;
prob = (p + LZMA_LITERAL
+ (LZMA_LIT_SIZE * ((((buffer_pos + global_pos) & literal_pos_mask) << lc)
+ (previous_byte >> (8 - lc))
)
)
);
if (state >= LZMA_NUM_LIT_STATES) {
int match_byte;
uint32_t pos = buffer_pos - rep0;
while (pos >= header.dict_size)
pos += header.dict_size;
match_byte = buffer[pos];
do {
int bit;
match_byte <<= 1;
bit = match_byte & 0x100;
bit ^= (rc_get_bit(rc, prob + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */
if (bit)
break;
} while (mi < 0x100);
}
while (mi < 0x100) {
rc_get_bit(rc, prob + mi, &mi);
}
state = next_state[state];
previous_byte = (uint8_t) mi;
#if ENABLE_FEATURE_LZMA_FAST
one_byte1:
buffer[buffer_pos++] = previous_byte;
if (buffer_pos == header.dict_size) {
buffer_pos = 0;
global_pos += header.dict_size;
if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size)
goto bad;
IF_DESKTOP(total_written += header.dict_size;)
}
#else
len = 1;
goto one_byte2;
#endif
} else {
int num_bits;
int offset;
uint16_t *prob2;
#define prob_len prob2
prob2 = p + LZMA_IS_REP + state;
if (!rc_is_bit_1(rc, prob2)) {
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < LZMA_NUM_LIT_STATES ? 0 : 3;
prob2 = p + LZMA_LEN_CODER;
} else {
prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP;
if (!rc_is_bit_1(rc, prob2)) {
prob2 = (p + LZMA_IS_REP_0_LONG
+ (state << LZMA_NUM_POS_BITS_MAX)
+ pos_state
);
if (!rc_is_bit_1(rc, prob2)) {
#if ENABLE_FEATURE_LZMA_FAST
uint32_t pos = buffer_pos - rep0;
state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
while (pos >= header.dict_size)
pos += header.dict_size;
previous_byte = buffer[pos];
goto one_byte1;
#else
state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
len = 1;
goto string;
#endif
}
} else {
uint32_t distance;
prob2 += LZMA_IS_REP_G1 - LZMA_IS_REP_G0;
distance = rep1;
if (rc_is_bit_1(rc, prob2)) {
prob2 += LZMA_IS_REP_G2 - LZMA_IS_REP_G1;
distance = rep2;
if (rc_is_bit_1(rc, prob2)) {
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < LZMA_NUM_LIT_STATES ? 8 : 11;
prob2 = p + LZMA_REP_LEN_CODER;
}
prob_len = prob2 + LZMA_LEN_CHOICE;
num_bits = LZMA_LEN_NUM_LOW_BITS;
if (!rc_is_bit_1(rc, prob_len)) {
prob_len += LZMA_LEN_LOW - LZMA_LEN_CHOICE
+ (pos_state << LZMA_LEN_NUM_LOW_BITS);
offset = 0;
} else {
prob_len += LZMA_LEN_CHOICE_2 - LZMA_LEN_CHOICE;
if (!rc_is_bit_1(rc, prob_len)) {
prob_len += LZMA_LEN_MID - LZMA_LEN_CHOICE_2
+ (pos_state << LZMA_LEN_NUM_MID_BITS);
offset = 1 << LZMA_LEN_NUM_LOW_BITS;
num_bits += LZMA_LEN_NUM_MID_BITS - LZMA_LEN_NUM_LOW_BITS;
} else {
prob_len += LZMA_LEN_HIGH - LZMA_LEN_CHOICE_2;
offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
+ (1 << LZMA_LEN_NUM_MID_BITS));
num_bits += LZMA_LEN_NUM_HIGH_BITS - LZMA_LEN_NUM_LOW_BITS;
}
}
rc_bit_tree_decode(rc, prob_len, num_bits, &len);
len += offset;
if (state < 4) {
int pos_slot;
uint16_t *prob3;
state += LZMA_NUM_LIT_STATES;
prob3 = p + LZMA_POS_SLOT +
((len < LZMA_NUM_LEN_TO_POS_STATES ? len :
LZMA_NUM_LEN_TO_POS_STATES - 1)
<< LZMA_NUM_POS_SLOT_BITS);
rc_bit_tree_decode(rc, prob3,
LZMA_NUM_POS_SLOT_BITS, &pos_slot);
rep0 = pos_slot;
if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
int i2, mi2, num_bits2 = (pos_slot >> 1) - 1;
rep0 = 2 | (pos_slot & 1);
if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
rep0 <<= num_bits2;
prob3 = p + LZMA_SPEC_POS + rep0 - pos_slot - 1;
} else {
for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--)
rep0 = (rep0 << 1) | rc_direct_bit(rc);
rep0 <<= LZMA_NUM_ALIGN_BITS;
prob3 = p + LZMA_ALIGN;
}
i2 = 1;
mi2 = 1;
while (num_bits2--) {
if (rc_get_bit(rc, prob3 + mi2, &mi2))
rep0 |= i2;
i2 <<= 1;
}
}
if (++rep0 == 0)
break;
}
len += LZMA_MATCH_MIN_LEN;
IF_NOT_FEATURE_LZMA_FAST(string:)
do {
uint32_t pos = buffer_pos - rep0;
while (pos >= header.dict_size)
pos += header.dict_size;
previous_byte = buffer[pos];
IF_NOT_FEATURE_LZMA_FAST(one_byte2:)
buffer[buffer_pos++] = previous_byte;
if (buffer_pos == header.dict_size) {
buffer_pos = 0;
global_pos += header.dict_size;
if (transformer_write(xstate, buffer, header.dict_size) != (ssize_t)header.dict_size)
goto bad;
IF_DESKTOP(total_written += header.dict_size;)
}
len--;
} while (len != 0 && buffer_pos < header.dst_size);
/* FIXME: ...........^^^^^
* shouldn't it be "global_pos + buffer_pos < header.dst_size"?
*/
}
}
{
IF_NOT_DESKTOP(int total_written = 0; /* success */)
IF_DESKTOP(total_written += buffer_pos;)
if (transformer_write(xstate, buffer, buffer_pos) != (ssize_t)buffer_pos) {
bad:
total_written = -1; /* failure */
}
rc_free(rc);
free(p);
free(buffer);
return total_written;
}
}

131
src/bled/decompress_unxz.c Normal file
View file

@ -0,0 +1,131 @@
/*
* unxz implementation for busybox
*
* Based on xz-embedded (C) Lasse Collin <lasse.collin@tukaani.org> - Public Domain
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
#define XZ_EXTERN static
// We get XZ_OPTIONS_ERROR in xz_dec_stream if this is not defined
#define XZ_DEC_ANY_CHECK
#include "xz_dec_bcj.c"
#include "xz_dec_lzma2.c"
#include "xz_dec_stream.c"
static void XZ_FUNC xz_crc32_init(void)
{
if (!global_crc32_table)
global_crc32_table = crc32_filltable(NULL, 0);
}
static uint32_t XZ_FUNC xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
{
// The XZ CRC32 is INVERTED!
return ~crc32_block_endian0(~crc, buf, size, global_crc32_table);
}
IF_DESKTOP(long long) int FAST_FUNC unpack_xz_stream(transformer_state_t *xstate)
{
IF_DESKTOP(long long) int n = 0;
struct xz_buf b;
struct xz_dec *s;
enum xz_ret ret = XZ_STREAM_END;
uint8_t *in = NULL, *out = NULL;
ssize_t nwrote;
xz_crc32_init();
/*
* Support up to 64 MiB dictionary. The actually needed memory
* is allocated once the headers have been parsed.
*/
s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
if (!s)
bb_error_msg_and_err("memory allocation failed");
// TODO: this is set very low on Windows...
in = xmalloc(BUFSIZ);
out = xmalloc(BUFSIZ);
b.in = in;
b.in_pos = 0;
b.in_size = 0;
b.out = out;
b.out_pos = 0;
b.out_size = BUFSIZ;
while (true) {
if (b.in_pos == b.in_size) {
b.in_size = safe_read(xstate->src_fd, in, BUFSIZ);
if ((int)b.in_size < 0)
bb_error_msg_and_err(bb_msg_read_error);
b.in_pos = 0;
}
ret = xz_dec_run(s, &b);
if (b.out_pos == BUFSIZ) {
nwrote = transformer_write(xstate, b.out, b.out_pos);
if (nwrote == (ssize_t)-1) {
ret = XZ_DATA_ERROR;
bb_error_msg_and_err("write error");
}
IF_DESKTOP(n += nwrote;)
b.out_pos = 0;
}
if (ret == XZ_OK)
continue;
#ifdef XZ_DEC_ANY_CHECK
if (ret == XZ_UNSUPPORTED_CHECK) {
bb_error_msg("unsupported check; not verifying file integrity");
continue;
}
#endif
nwrote = transformer_write(xstate, b.out, b.out_pos);
if (nwrote == (ssize_t)-1) {
ret = XZ_DATA_ERROR;
bb_error_msg_and_err("write error");
}
IF_DESKTOP(n += nwrote;)
switch (ret) {
case XZ_STREAM_END:
ret = XZ_OK;
goto out;
case XZ_MEM_ERROR:
bb_error_msg_and_err("memory allocation failed");
case XZ_MEMLIMIT_ERROR:
bb_error_msg_and_err("memory usage limit reached");
case XZ_FORMAT_ERROR:
bb_error_msg_and_err("not a .xz file");
case XZ_OPTIONS_ERROR:
bb_error_msg_and_err("unsupported options in the .xz headers");
case XZ_DATA_ERROR:
bb_error_msg_and_err("file is corrupt");
case XZ_BUF_ERROR:
bb_error_msg_and_err("buf is corrupt");
default:
bb_error_msg_and_err("bug!");
}
}
out:
err:
xz_dec_end(s);
free(in);
free(out);
return (ret == XZ_OK)?n:-ret;
}

View file

@ -0,0 +1,17 @@
/* vi: set sw=4 ts=4: */
/*
* Copyright (C) 2002 by Glenn McGrath
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
/* Accept any non-null name, its not really a filter at all */
char FAST_FUNC filter_accept_all(archive_handle_t *archive_handle)
{
if (archive_handle->file_header->name)
return EXIT_SUCCESS;
return EXIT_FAILURE;
}

View file

@ -0,0 +1,19 @@
/* vi: set sw=4 ts=4: */
/*
* Copyright (C) 2002 by Glenn McGrath
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
/*
* Accept names that are in the accept list, ignoring reject list.
*/
char FAST_FUNC filter_accept_list(archive_handle_t *archive_handle)
{
if (find_list_entry(archive_handle->accept, archive_handle->file_header->name))
return EXIT_SUCCESS;
return EXIT_FAILURE;
}

View file

@ -0,0 +1,38 @@
/* vi: set sw=4 ts=4: */
/*
* Copyright (C) 2002 by Glenn McGrath
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
/*
* Accept names that are in the accept list and not in the reject list
*/
char FAST_FUNC filter_accept_reject_list(archive_handle_t *archive_handle)
{
const char *key;
const llist_t *reject_entry;
const llist_t *accept_entry;
key = archive_handle->file_header->name;
/* If the key is in a reject list fail */
reject_entry = find_list_entry2(archive_handle->reject, key);
if (reject_entry) {
return EXIT_FAILURE;
}
/* Fail if an accept list was specified and the key wasnt in there */
if (archive_handle->accept) {
accept_entry = find_list_entry2(archive_handle->accept, key);
if (!accept_entry) {
return EXIT_FAILURE;
}
}
/* Accepted */
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,54 @@
/* vi: set sw=4 ts=4: */
/*
* Copyright (C) 2002 by Glenn McGrath
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
//#include <fnmatch.h>
#include "libbb.h"
#include "bb_archive.h"
/* Find a string in a shell pattern list */
const llist_t* FAST_FUNC find_list_entry(const llist_t *list, const char *filename)
{
while (list) {
if (fnmatch(list->data, filename, 0) == 0) {
return list;
}
list = list->link;
}
return NULL;
}
/* Same, but compares only path components present in pattern
* (extra trailing path components in filename are assumed to match)
*/
const llist_t* FAST_FUNC find_list_entry2(const llist_t *list, const char *filename)
{
char buf[PATH_MAX];
int pattern_slash_cnt;
const char *c;
char *d;
while (list) {
c = list->data;
pattern_slash_cnt = 0;
while (*c)
if (*c++ == '/') pattern_slash_cnt++;
c = filename;
d = buf;
/* paranoia is better than buffer overflows */
while (*c && d != buf + sizeof(buf)-1) {
if (*c == '/' && --pattern_slash_cnt < 0)
break;
*d++ = *c++;
}
*d = '\0';
if (fnmatch(list->data, buf, 0) == 0) {
return list;
}
list = list->link;
}
return NULL;
}

12
src/bled/header_list.c Normal file
View file

@ -0,0 +1,12 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC header_list(const file_header_t *file_header)
{
//TODO: cpio -vp DIR should output "DIR/NAME", not just "NAME" */
puts(file_header->name);
}

10
src/bled/header_skip.c Normal file
View file

@ -0,0 +1,10 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC header_skip(const file_header_t *file_header UNUSED_PARAM)
{
}

View file

@ -0,0 +1,69 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC header_verbose_list(const file_header_t *file_header)
{
struct tm tm_time;
struct tm *ptm = &tm_time; //localtime(&file_header->mtime);
#if ENABLE_FEATURE_TAR_UNAME_GNAME
char uid[sizeof(int)*3 + 2];
/*char gid[sizeof(int)*3 + 2];*/
char *user;
char *group;
localtime_r(&file_header->mtime, ptm);
user = file_header->tar__uname;
if (user == NULL) {
sprintf(uid, "%u", (unsigned)file_header->uid);
user = uid;
}
group = file_header->tar__gname;
if (group == NULL) {
/*sprintf(gid, "%u", (unsigned)file_header->gid);*/
group = utoa(file_header->gid);
}
printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
bb_mode_string(file_header->mode),
user,
group,
file_header->size,
1900 + ptm->tm_year,
1 + ptm->tm_mon,
ptm->tm_mday,
ptm->tm_hour,
ptm->tm_min,
ptm->tm_sec,
file_header->name);
#else /* !FEATURE_TAR_UNAME_GNAME */
localtime_r(&file_header->mtime, ptm);
printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
bb_mode_string(file_header->mode),
(unsigned)file_header->uid,
(unsigned)file_header->gid,
file_header->size,
1900 + ptm->tm_year,
1 + ptm->tm_mon,
ptm->tm_mday,
ptm->tm_hour,
ptm->tm_min,
ptm->tm_sec,
file_header->name);
#endif /* FEATURE_TAR_UNAME_GNAME */
/* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */
if (file_header->link_target) {
printf(" -> %s", file_header->link_target);
}
bb_putchar('\n');
}

22
src/bled/init_handle.c Normal file
View file

@ -0,0 +1,22 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
archive_handle_t* FAST_FUNC init_handle(void)
{
archive_handle_t *archive_handle;
/* Initialize default values */
archive_handle = xzalloc(sizeof(archive_handle_t));
archive_handle->file_header = xzalloc(sizeof(file_header_t));
archive_handle->action_header = header_skip;
archive_handle->action_data = data_skip;
archive_handle->filter = filter_accept_all;
archive_handle->seek = seek_by_jump;
return archive_handle;
}

233
src/bled/libbb.h Normal file
View file

@ -0,0 +1,233 @@
/*
* Library header for busybox
*
* Rewritten for Bled (Busybox Library for Easy Decompression)
* Copyright © 2014 Pete Batard <pete@akeo.ie>
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */
#ifdef _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#ifndef LIBBB_H
#define LIBBB_H 1
#ifndef _WIN32
#error Only Windows platforms are supported
#endif
#if defined(_MSC_VER)
#pragma warning(disable: 4715) // not all control paths return a value
#pragma warning(disable: 4996) // Ignore deprecated
#if defined(DDKBUILD)
#pragma warning(disable: 4242) // "Conversion from x to y, possible loss of data"
#pragma warning(disable: 4244)
struct timeval {
long tv_sec;
long tv_usec;
};
#endif
#endif
#include "platform.h"
#include "msapi_utf8.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <time.h>
#include <direct.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <io.h>
#ifdef BUFSIZ
#undef BUFSIZ
#endif
#define BUFSIZ 65536
#define IF_DESKTOP(x) x
#define IF_NOT_DESKTOP(x)
#define IF_NOT_FEATURE_LZMA_FAST(x) x
#define uoff_t unsigned off_t
#define OFF_FMT "I64"
#ifndef _MODE_T_
#define _MODE_T_
typedef unsigned short mode_t;
#endif
#ifndef _PID_T_
#define _PID_T_
typedef int pid_t;
#endif
#ifndef _GID_T_
#define _GID_T_
typedef unsigned int gid_t;
#endif
#ifndef _UID_T_
#define _UID_T_
typedef unsigned int uid_t;
#endif
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
#ifndef get_le64
#define get_le64(ptr) (*(const uint64_t *)(ptr))
#endif
#ifndef get_le32
#define get_le32(ptr) (*(const uint32_t *)(ptr))
#endif
#ifndef get_le16
#define get_le16(ptr) (*(const uint16_t *)(ptr))
#endif
extern smallint bb_got_signal;
extern uint32_t *global_crc32_table;
uint32_t* crc32_filltable(uint32_t *crc_table, int endian);
uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len, uint32_t *crc32table_le);
uint32_t crc32_be(uint32_t crc, unsigned char const *p, size_t len, uint32_t *crc32table_be);
#define crc32_block_endian0 crc32_le
#define crc32_block_endian1 crc32_be
#if defined(_MSC_VER)
#if _FILE_OFFSET_BITS == 64
#define stat _stat32i64
#define lseek _lseeki64
#else
#define stat _stat32
#define lseek _lseek
#endif
#endif
typedef struct _llist_t {
struct _llist_t *link;
char *data;
} llist_t;
extern void (*bled_printf) (const char* format, ...);
extern void (*bled_progress) (const uint64_t processed_bytes);
#define bb_printf(...) do { if (bled_printf != NULL) bled_printf(__VA_ARGS__); \
else { printf(__VA_ARGS__); putchar('\n'); } } while(0)
#define bb_error_msg bb_printf
#define bb_error_msg_and_die(...) do {bb_printf(__VA_ARGS__); return;} while(0)
#define bb_error_msg_and_err(...) do {bb_printf(__VA_ARGS__); goto err;} while(0)
#define bb_perror_msg bb_error_msg
#define bb_perror_msg_and_die bb_error_msg_and_die
#define bb_putchar putchar
static inline void *xrealloc(void *ptr, size_t size) {
void *ret = realloc(ptr, size);
if (!ret)
free(ptr);
return ret;
}
#define bb_msg_read_error "read error"
#define bb_msg_write_error "write error"
#define bb_mode_string(mode) "[not implemented]"
#define bb_copyfd_exact_size(fd1, fd2, size) bb_printf("not implemented")
#define bb_make_directory(path, mode, flags) SHCreateDirectoryExU(NULL, path, NULL)
static inline int link(const char *oldpath, const char *newpath) {errno = ENOSYS; return -1;}
static inline int symlink(const char *oldpath, const char *newpath) {errno = ENOSYS; return -1;}
static inline int chown(const char *path, uid_t owner, gid_t group) {errno = ENOSYS; return -1;}
static inline int mknod(const char *pathname, mode_t mode, dev_t dev) {errno = ENOSYS; return -1;}
static inline int utimes(const char *filename, const struct timeval times[2]) {errno = ENOSYS; return -1;}
static inline int fnmatch(const char *pattern, const char *string, int flags) {return PathMatchSpecA(string, pattern)?0:1;}
static inline pid_t wait(int* status) { *status = 4; return -1; }
#define wait_any_nohang wait
/* This override enables the display of a progress based on the number of bytes read */
extern uint64_t bb_total_rb;
static inline ssize_t full_read(int fd, void *buf, size_t count) {
ssize_t rb = _read(fd, buf, count);
if (rb > 0) {
bb_total_rb += rb;
if (bled_progress != NULL)
bled_progress(bb_total_rb);
}
return rb;
}
#define full_write _write
#define safe_read full_read
#define lstat stat
#define xmalloc malloc
#define xzalloc(x) calloc(x, 1)
#define malloc_or_warn malloc
#define xopen3 open
#define xfunc_die() do { bb_printf("not implemented"); return -1; } while(0)
#define mkdir(x, y) _mkdirU(x)
#if defined(_MSC_VER)
static inline struct tm *localtime_r(const time_t *timep, struct tm *result) {
result = localtime(timep);
return result;
}
#define _S_IFBLK 0x3000
#define S_IFMT _S_IFMT
#define S_IFDIR _S_IFDIR
#define S_IFCHR _S_IFCHR
#define S_IFIFO _S_IFIFO
#define S_IFREG _S_IFREG
#define S_IREAD _S_IREAD
#define S_IWRITE _S_IWRITE
#define S_IEXEC _S_IEXEC
#define S_IFBLK _S_IFBLK
#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
#define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO)
#define S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR)
#define S_ISBLK(m) (((m) & _S_IFMT) == _S_IFBLK)
#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY
#define O_RDWR _O_RDWR
#define O_APPEND _O_APPEND
#define O_CREAT _O_CREAT
#define O_TRUNC _O_TRUNC
#define O_EXCL _O_EXCL
#endif
/* MinGW doesn't know these */
#define _S_IFLNK 0xA000
#define _S_IFSOCK 0xC000
#define S_IFLNK _S_IFLNK
#define S_IFSOCK _S_IFSOCK
#define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK)
#define S_ISSOCK(m) (((m) & _S_IFMT) == _S_IFSOCK)
#endif

351
src/bled/open_transformer.c Normal file
View file

@ -0,0 +1,351 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC init_transformer_state(transformer_state_t *xstate)
{
memset(xstate, 0, sizeof(*xstate));
}
int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
{
if (xstate->check_signature) {
uint16_t magic2;
if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
bb_error_msg("invalid magic");
#if 0 /* possible future extension */
if (xstate->check_signature > 1)
xfunc_die();
#endif
return -1;
}
}
return 0;
}
ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize)
{
ssize_t nwrote;
if (xstate->mem_output_size_max != 0) {
size_t pos = xstate->mem_output_size;
size_t size;
size = (xstate->mem_output_size += bufsize);
if (size > xstate->mem_output_size_max) {
free(xstate->mem_output_buf);
xstate->mem_output_buf = NULL;
bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max);
nwrote = -1;
goto ret;
}
xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size + 1);
memcpy(xstate->mem_output_buf + pos, buf, bufsize);
xstate->mem_output_buf[size] = '\0';
nwrote = bufsize;
} else {
nwrote = full_write(xstate->dst_fd, buf, bufsize);
if (nwrote != (ssize_t)bufsize) {
bb_perror_msg("write");
nwrote = -1;
goto ret;
}
}
ret:
return nwrote;
}
ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize)
{
ssize_t nwrote = transformer_write(xstate, buf, bufsize);
if (nwrote != (ssize_t)bufsize) {
xfunc_die();
}
return nwrote;
}
void check_errors_in_children(int signo)
{
int status;
if (!signo) {
/* block waiting for any child */
if (wait(&status) < 0)
//FIXME: check EINTR?
return; /* probably there are no children */
goto check_status;
}
/* Wait for any child without blocking */
for (;;) {
if (wait_any_nohang(&status) < 0)
//FIXME: check EINTR?
/* wait failed?! I'm confused... */
return;
check_status:
/*if (WIFEXITED(status) && WEXITSTATUS(status) == 0)*/
/* On Linux, the above can be checked simply as: */
if (status == 0)
/* this child exited with 0 */
continue;
/* Cannot happen:
if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???;
*/
bb_got_signal = 1;
}
}
#if SEAMLESS_COMPRESSION
/* transformer(), more than meets the eye */
#if BB_MMU
void FAST_FUNC fork_transformer(int fd,
int check_signature,
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
)
#else
void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
#endif
{
struct fd_pair fd_pipe;
int pid;
xpiped_pair(fd_pipe);
pid = BB_MMU ? xfork() : xvfork();
if (pid == 0) {
/* Child */
close(fd_pipe.rd); /* we don't want to read from the parent */
// FIXME: error check?
#if BB_MMU
{
IF_DESKTOP(long long) int r;
transformer_state_t xstate;
init_transformer_state(&xstate);
xstate.check_signature = check_signature;
xstate.src_fd = fd;
xstate.dst_fd = fd_pipe.wr;
r = transformer(&xstate);
if (ENABLE_FEATURE_CLEAN_UP) {
close(fd_pipe.wr); /* send EOF */
close(fd);
}
/* must be _exit! bug was actually seen here */
_exit(/*error if:*/ r < 0);
}
#else
{
char *argv[4];
xmove_fd(fd, 0);
xmove_fd(fd_pipe.wr, 1);
argv[0] = (char*)transform_prog;
argv[1] = (char*)"-cf";
argv[2] = (char*)"-";
argv[3] = NULL;
BB_EXECVP(transform_prog, argv);
bb_perror_msg_and_die("can't execute '%s'", transform_prog);
}
#endif
/* notreached */
}
/* parent process */
close(fd_pipe.wr); /* don't want to write to the child */
xmove_fd(fd_pipe.rd, fd);
}
/* Used by e.g. rpm which gives us a fd without filename,
* thus we can't guess the format from filename's extension.
*/
static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed)
{
union {
uint8_t b[4];
uint16_t b16[2];
uint32_t b32[1];
} magic;
int offset;
transformer_state_t *xstate;
offset = -2;
xstate = xzalloc(sizeof(*xstate));
xstate->src_fd = fd;
/* .gz and .bz2 both have 2-byte signature, and their
* unpack_XXX_stream wants this header skipped. */
xread(fd, magic.b16, sizeof(magic.b16[0]));
if (ENABLE_FEATURE_SEAMLESS_GZ
&& magic.b16[0] == GZIP_MAGIC
) {
xstate->xformer = unpack_gz_stream;
USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";)
goto found_magic;
}
if (ENABLE_FEATURE_SEAMLESS_BZ2
&& magic.b16[0] == BZIP2_MAGIC
) {
xstate->xformer = unpack_bz2_stream;
USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";)
goto found_magic;
}
if (ENABLE_FEATURE_SEAMLESS_XZ
&& magic.b16[0] == XZ_MAGIC1
) {
offset = -6;
xread(fd, magic.b32, sizeof(magic.b32[0]));
if (magic.b32[0] == XZ_MAGIC2) {
xstate->xformer = unpack_xz_stream;
USE_FOR_NOMMU(xstate->xformer_prog = "unxz";)
goto found_magic;
}
}
/* No known magic seen */
if (fail_if_not_compressed)
bb_error_msg_and_die("no gzip"
IF_FEATURE_SEAMLESS_BZ2("/bzip2")
IF_FEATURE_SEAMLESS_XZ("/xz")
" magic");
/* Some callers expect this function to "consume" fd
* even if data is not compressed. In this case,
* we return a state with trivial transformer.
*/
// USE_FOR_MMU(xstate->xformer = copy_stream;)
// USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
/* fall through to seeking bck over bytes we read earlier */
USE_FOR_NOMMU(found_magic:)
/* NOMMU version of fork_transformer execs
* an external unzipper that wants
* file position at the start of the file.
*/
xlseek(fd, offset, SEEK_CUR);
USE_FOR_MMU(found_magic:)
/* In MMU case, if magic was found, seeking back is not necessary */
return xstate;
}
/* Used by e.g. rpm which gives us a fd without filename,
* thus we can't guess the format from filename's extension.
*/
int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
{
transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed);
if (!xstate || !xstate->xformer) {
free(xstate);
return 1;
}
# if BB_MMU
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
# else
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
# endif
free(xstate);
return 0;
}
static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed)
{
transformer_state_t *xstate;
int fd;
fd = open(fname, O_RDONLY);
if (fd < 0)
return NULL;
if (ENABLE_FEATURE_SEAMLESS_LZMA) {
/* .lzma has no header/signature, can only detect it by extension */
char *sfx = strrchr(fname, '.');
if (sfx && strcmp(sfx+1, "lzma") == 0) {
xstate = xzalloc(sizeof(*xstate));
xstate->src_fd = fd;
xstate->xformer = unpack_lzma_stream;
USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";)
return xstate;
}
}
xstate = setup_transformer_on_fd(fd, fail_if_not_compressed);
return xstate;
}
int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
{
int fd;
transformer_state_t *xstate;
xstate = open_transformer(fname, fail_if_not_compressed);
if (!xstate)
return -1;
fd = xstate->src_fd;
if (xstate->xformer) {
# if BB_MMU
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
# else
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
# endif
}
/* else: the file is not compressed */
free(xstate);
return fd;
}
void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
{
# if 1
transformer_state_t *xstate;
char *image;
xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0);
if (!xstate) /* file open error */
return NULL;
image = NULL;
if (xstate->xformer) {
/* In-memory decompression */
xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095);
xstate->xformer(xstate);
if (xstate->mem_output_buf) {
image = xstate->mem_output_buf;
if (maxsz_p)
*maxsz_p = xstate->mem_output_size;
}
} else {
/* File is not compressed */
image = xmalloc_read(xstate->src_fd, maxsz_p);
}
if (!image)
bb_perror_msg("read error from '%s'", fname);
close(xstate->src_fd);
free(xstate);
return image;
# else
/* This version forks a subprocess - much more expensive */
int fd;
char *image;
fd = open_zipped(fname, /*fail_if_not_compressed:*/ 0);
if (fd < 0)
return NULL;
image = xmalloc_read(fd, maxsz_p);
if (!image)
bb_perror_msg("read error from '%s'", fname);
close(fd);
return image;
# endif
}
#endif /* SEAMLESS_COMPRESSION */

621
src/bled/platform.h Normal file
View file

@ -0,0 +1,621 @@
/* vi: set sw=4 ts=4: */
/*
* Copyright 2006, Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#ifndef BB_PLATFORM_H
#define BB_PLATFORM_H 1
/* Convenience macros to test the version of gcc. */
#undef __GNUC_PREREQ
#if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define __GNUC_PREREQ(maj, min) 0
#endif
/* __restrict is known in EGCS 1.2 and above. */
#if !__GNUC_PREREQ(2,92)
# ifndef __restrict
# define __restrict
# endif
#endif
#if !__GNUC_PREREQ(2,7)
# ifndef __attribute__
# define __attribute__(x)
# endif
#endif
#undef inline
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L
/* it's a keyword */
#elif __GNUC_PREREQ(2,7)
# define inline __inline__
#elif defined(_MSC_VER)
#define inline __inline
#else
# define inline
#endif
#ifndef __const
# define __const const
#endif
#define UNUSED_PARAM __attribute__ ((__unused__))
#define NORETURN __attribute__ ((__noreturn__))
/* "The malloc attribute is used to tell the compiler that a function
* may be treated as if any non-NULL pointer it returns cannot alias
* any other pointer valid when the function returns. This will often
* improve optimization. Standard functions with this property include
* malloc and calloc. realloc-like functions have this property as long
* as the old pointer is never referred to (including comparing it
* to the new pointer) after the function returns a non-NULL value."
*/
#if defined(__GNUC__)
#define RETURNS_MALLOC __attribute__ ((malloc))
#ifdef __MINGW32__
#define PACKED __attribute__ ((packed, gcc_struct))
#else
#define PACKED __attribute__ ((__packed__))
#endif
#define ALIGNED(m) __attribute__ ((__aligned__(m)))
#define PRAGMA_BEGIN_PACKED
#define PRAGMA_END_PACKED
#elif defined(_MSC_VER)
#define RETURNS_MALLOC
#define PACKED
#define ALIGNED(m) __declspec(align(m))
#define PRAGMA_BEGIN_PACKED __pragma(pack(push, 1))
#define PRAGMA_END_PACKED __pragma(pack(pop))
#endif
/* __NO_INLINE__: some gcc's do not honor inlining! :( */
#if __GNUC_PREREQ(3,0) && !defined(__NO_INLINE__)
# define ALWAYS_INLINE __attribute__ ((always_inline)) inline
/* I've seen a toolchain where I needed __noinline__ instead of noinline */
# define NOINLINE __attribute__((__noinline__))
# if !ENABLE_WERROR
# define DEPRECATED __attribute__ ((__deprecated__))
# define UNUSED_PARAM_RESULT __attribute__ ((warn_unused_result))
# else
# define DEPRECATED
# define UNUSED_PARAM_RESULT
# endif
#else
# define ALWAYS_INLINE inline
# define NOINLINE
# define DEPRECATED
# define UNUSED_PARAM_RESULT
#endif
/* used by unit test machinery to run registration functions before calling main() */
#define INIT_FUNC __attribute__ ((constructor))
/* -fwhole-program makes all symbols local. The attribute externally_visible
* forces a symbol global. */
#if __GNUC_PREREQ(4,1)
# define EXTERNALLY_VISIBLE __attribute__(( visibility("default") ))
//__attribute__ ((__externally_visible__))
#else
# define EXTERNALLY_VISIBLE
#endif
/* At 4.4 gcc become much more anal about this, need to use "aliased" types */
#if __GNUC_PREREQ(4,4)
# define FIX_ALIASING __attribute__((__may_alias__))
#else
# define FIX_ALIASING
#endif
/* We use __extension__ in some places to suppress -pedantic warnings
* about GCC extensions. This feature didn't work properly before
* gcc 2.8. */
#if !__GNUC_PREREQ(2,8)
# ifndef __extension__
# define __extension__
# endif
#endif
/* FAST_FUNC is a qualifier which (possibly) makes function call faster
* and/or smaller by using modified ABI. It is usually only needed
* on non-static, busybox internal functions. Recent versions of gcc
* optimize statics automatically. FAST_FUNC on static is required
* only if you need to match a function pointer's type */
#if __GNUC_PREREQ(3,0) && !defined(__MINGW32__) && defined(i386) /* || defined(__x86_64__)? */
/* stdcall makes callee to pop arguments from stack, not caller */
# define FAST_FUNC __attribute__((regparm(3),stdcall))
/* #elif ... - add your favorite arch today! */
#else
# define FAST_FUNC
#endif
/* Make all declarations hidden (-fvisibility flag only affects definitions) */
/* (don't include system headers after this until corresponding pop!) */
#if __GNUC_PREREQ(4,1) && !defined(__CYGWIN__)
# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)")
# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop")
#else
# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
# define POP_SAVED_FUNCTION_VISIBILITY
#endif
/* gcc-2.95 had no va_copy but only __va_copy. */
#if !__GNUC_PREREQ(3,0)
# include <stdarg.h>
# if !defined va_copy && defined __va_copy
# define va_copy(d,s) __va_copy((d),(s))
# endif
#endif
/* ---- Endian Detection ------------------------------------ */
#include <limits.h>
#if defined(__digital__) && defined(__unix__)
# include <sex.h>
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
|| defined(__APPLE__)
# include <sys/resource.h> /* rlimit */
# include <machine/endian.h>
# define bswap_64 __bswap64
# define bswap_32 __bswap32
# define bswap_16 __bswap16
#elif defined(_MSC_VER) || defined(__MINGW32__)
#include <stdint.h>
#ifndef bswap_16
static __inline uint16_t bswap_16(uint16_t x)
{
x = (x>>8) | (x<<8);
return x;
}
#endif
#ifndef bswap_32
static __inline uint32_t bswap_32(uint32_t x)
{
x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
x = (x>>16) | (x<<16);
return x;
}
#endif
#ifndef bswap_64
static __inline uint64_t bswap_64(uint64_t x)
{
union {
uint64_t ll;
uint32_t l[2];
} w, r;
w.ll = x;
r.l[0] = bswap_32(w.l[1]);
r.l[1] = bswap_32(w.l[0]);
return r.ll;
}
#endif
#else
# include <byteswap.h>
# include <endian.h>
#endif
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
# define BB_BIG_ENDIAN 1
# define BB_LITTLE_ENDIAN 0
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
# define BB_BIG_ENDIAN 0
# define BB_LITTLE_ENDIAN 1
#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN
# define BB_BIG_ENDIAN 1
# define BB_LITTLE_ENDIAN 0
#elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN
# define BB_BIG_ENDIAN 0
# define BB_LITTLE_ENDIAN 1
#elif defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN
# define BB_BIG_ENDIAN 1
# define BB_LITTLE_ENDIAN 0
#elif defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN
# define BB_BIG_ENDIAN 0
# define BB_LITTLE_ENDIAN 1
#elif defined(__386__) || defined(_M_IX86) || defined(_M_AMD64)
# define BB_BIG_ENDIAN 0
# define BB_LITTLE_ENDIAN 1
#else
# error "Can't determine endianness"
#endif
#if ULONG_MAX > 0xffffffff
# define bb_bswap_64(x) bswap_64(x)
#endif
/* SWAP_LEnn means "convert CPU<->little_endian by swapping bytes" */
#if BB_BIG_ENDIAN
# define SWAP_BE16(x) (x)
# define SWAP_BE32(x) (x)
# define SWAP_BE64(x) (x)
# define SWAP_LE16(x) bswap_16(x)
# define SWAP_LE32(x) bswap_32(x)
# define SWAP_LE64(x) bb_bswap_64(x)
# define IF_BIG_ENDIAN(...) __VA_ARGS__
# define IF_LITTLE_ENDIAN(...)
#else
# define SWAP_BE16(x) bswap_16(x)
# define SWAP_BE32(x) bswap_32(x)
# define SWAP_BE64(x) bb_bswap_64(x)
# define SWAP_LE16(x) (x)
# define SWAP_LE32(x) (x)
# define SWAP_LE64(x) (x)
# define IF_BIG_ENDIAN(...)
# define IF_LITTLE_ENDIAN(...) __VA_ARGS__
#endif
/* ---- Unaligned access ------------------------------------ */
#include <stdint.h>
typedef int bb__aliased_int FIX_ALIASING;
typedef long bb__aliased_long FIX_ALIASING;
typedef uint16_t bb__aliased_uint16_t FIX_ALIASING;
typedef uint32_t bb__aliased_uint32_t FIX_ALIASING;
typedef uint64_t bb__aliased_uint64_t FIX_ALIASING;
/* NB: unaligned parameter should be a pointer, aligned one -
* a lvalue. This makes it more likely to not swap them by mistake
*/
#if defined(i386) || defined(__x86_64__) || defined(__powerpc__)
# define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp))
# define move_from_unaligned_long(v, longp) ((v) = *(bb__aliased_long*)(longp))
# define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p))
# define move_from_unaligned32(v, u32p) ((v) = *(bb__aliased_uint32_t*)(u32p))
# define move_to_unaligned16(u16p, v) (*(bb__aliased_uint16_t*)(u16p) = (v))
# define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v))
/* #elif ... - add your favorite arch today! */
#else
/* performs reasonably well (gcc usually inlines memcpy here) */
# define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int)))
# define move_from_unaligned_long(v, longp) (memcpy(&(v), (longp), sizeof(long)))
# define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2))
# define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4))
# define move_to_unaligned16(u16p, v) do { \
uint16_t __t = (v); \
memcpy((u16p), &__t, 2); \
} while (0)
# define move_to_unaligned32(u32p, v) do { \
uint32_t __t = (v); \
memcpy((u32p), &__t, 4); \
} while (0)
#endif
/* ---- Size-saving "small" ints (arch-dependent) ----------- */
#if defined(i386) || defined(__x86_64__) || defined(__mips__) || defined(__cris__)
/* add other arches which benefit from this... */
typedef signed char smallint;
typedef unsigned char smalluint;
#else
/* for arches where byte accesses generate larger code: */
typedef int smallint;
typedef unsigned smalluint;
#endif
/* ISO C Standard: 7.16 Boolean type and values <stdbool.h> */
#if (defined __digital__ && defined __unix__)
/* old system without (proper) C99 support */
# define bool smalluint
#else
/* modern system, so use it */
# include <stdbool.h>
#endif
/*----- Kernel versioning ------------------------------------*/
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#ifdef __UCLIBC__
# define UCLIBC_VERSION KERNEL_VERSION(__UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__)
#else
# define UCLIBC_VERSION 0
#endif
/* ---- Miscellaneous --------------------------------------- */
#if defined __GLIBC__ \
|| defined __UCLIBC__ \
|| defined __dietlibc__ \
|| defined __BIONIC__ \
|| defined _NEWLIB_VERSION
# include <features.h>
#endif
/* Define bb_setpgrp */
#if defined(__digital__) && defined(__unix__)
/* use legacy setpgrp(pid_t, pid_t) for now. move to platform.c */
# define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me, __me); } while (0)
#else
# define bb_setpgrp() setpgrp()
#endif
/* Useful for defeating gcc's alignment of "char message[]"-like data */
#if !defined(__s390__)
/* on s390[x], non-word-aligned data accesses require larger code */
# define ALIGN1 __attribute__((aligned(1)))
# define ALIGN2 __attribute__((aligned(2)))
# define ALIGN4 __attribute__((aligned(4)))
#else
/* Arches which MUST have 2 or 4 byte alignment for everything are here */
# define ALIGN1
# define ALIGN2
# define ALIGN4
#endif
/*
* For 0.9.29 and svn, __ARCH_USE_MMU__ indicates no-mmu reliably.
* For earlier versions there is no reliable way to check if we are building
* for a mmu-less system.
*/
#if ENABLE_NOMMU || \
(defined __UCLIBC__ && \
UCLIBC_VERSION > KERNEL_VERSION(0, 9, 28) && \
!defined __ARCH_USE_MMU__)
# define BB_MMU 0
# define USE_FOR_NOMMU(...) __VA_ARGS__
# define USE_FOR_MMU(...)
#else
# define BB_MMU 1
# define USE_FOR_NOMMU(...)
# define USE_FOR_MMU(...) __VA_ARGS__
#endif
#if defined(__digital__) && defined(__unix__)
# include <standards.h>
# include <inttypes.h>
# define PRIu32 "u"
# if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET
# define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET)
# endif
# if !defined ADJ_FREQUENCY && defined MOD_FREQUENCY
# define ADJ_FREQUENCY MOD_FREQUENCY
# endif
# if !defined ADJ_TIMECONST && defined MOD_TIMECONST
# define ADJ_TIMECONST MOD_TIMECONST
# endif
# if !defined ADJ_TICK && defined MOD_CLKB
# define ADJ_TICK MOD_CLKB
# endif
#endif
#if defined(__CYGWIN__)
# define MAXSYMLINKS SYMLOOP_MAX
#endif
#if defined(ANDROID) || defined(__ANDROID__)
# define BB_ADDITIONAL_PATH ":/system/sbin:/system/bin:/system/xbin"
# define SYS_ioprio_set __NR_ioprio_set
# define SYS_ioprio_get __NR_ioprio_get
#endif
/* ---- Who misses what? ------------------------------------ */
/* Assume all these functions and header files exist by default.
* Platforms where it is not true will #undef them below.
*/
#define HAVE_CLEARENV 1
#define HAVE_FDATASYNC 1
#define HAVE_DPRINTF 1
#define HAVE_MEMRCHR 1
#define HAVE_MKDTEMP 1
#define HAVE_PTSNAME_R 1
#define HAVE_SETBIT 1
#define HAVE_SIGHANDLER_T 1
#define HAVE_STPCPY 1
#define HAVE_STRCASESTR 1
#define HAVE_STRCHRNUL 1
#define HAVE_STRSEP 1
#define HAVE_STRSIGNAL 1
#define HAVE_STRVERSCMP 1
#define HAVE_VASPRINTF 1
#define HAVE_USLEEP 1
#define HAVE_UNLOCKED_STDIO 1
#define HAVE_UNLOCKED_LINE_OPS 1
#define HAVE_GETLINE 1
#define HAVE_XTABS 1
#define HAVE_MNTENT_H 1
#define HAVE_NET_ETHERNET_H 1
#define HAVE_SYS_STATFS_H 1
#if defined(__UCLIBC__)
# if UCLIBC_VERSION < KERNEL_VERSION(0, 9, 32)
# undef HAVE_STRVERSCMP
# endif
# if UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 30)
# ifndef __UCLIBC_SUSV3_LEGACY__
# undef HAVE_USLEEP
# endif
# endif
#endif
#if defined(__WATCOMC__)
# undef HAVE_DPRINTF
# undef HAVE_GETLINE
# undef HAVE_MEMRCHR
# undef HAVE_MKDTEMP
# undef HAVE_SETBIT
# undef HAVE_STPCPY
# undef HAVE_STRCASESTR
# undef HAVE_STRCHRNUL
# undef HAVE_STRSEP
# undef HAVE_STRSIGNAL
# undef HAVE_STRVERSCMP
# undef HAVE_VASPRINTF
# undef HAVE_UNLOCKED_STDIO
# undef HAVE_UNLOCKED_LINE_OPS
# undef HAVE_NET_ETHERNET_H
#endif
#if defined(_MSC_VER)
/* We need to define ssize_t before the getline declaration below (copy/paste from MinGW) */
#ifndef _SSIZE_T_DEFINED
#define _SSIZE_T_DEFINED
#undef ssize_t
#ifdef _WIN64
typedef __int64 ssize_t;
#else
typedef int ssize_t;
#endif
#endif
# undef HAVE_GETLINE
# undef HAVE_MEMRCHR
# undef HAVE_MKDTEMP
# undef HAVE_MNTENT_H
# undef HAVE_SETBIT
# undef HAVE_STPCPY
# undef HAVE_STRCASESTR
# undef HAVE_STRCHRNUL
# undef HAVE_STRSEP
# undef HAVE_STRSIGNAL
# undef HAVE_STRVERSCMP
# undef HAVE_SYS_STATFS_H
# undef HAVE_VASPRINTF
# undef HAVE_UNLOCKED_STDIO
# undef HAVE_UNLOCKED_LINE_OPS
# undef HAVE_NET_ETHERNET_H
#endif
#if defined(__CYGWIN__)
# undef HAVE_CLEARENV
# undef HAVE_FDPRINTF
# undef HAVE_MEMRCHR
# undef HAVE_PTSNAME_R
# undef HAVE_STRVERSCMP
# undef HAVE_UNLOCKED_LINE_OPS
#endif
/* These BSD-derived OSes share many similarities */
#if (defined __digital__ && defined __unix__) \
|| defined __APPLE__ \
|| defined __OpenBSD__ || defined __NetBSD__
# undef HAVE_CLEARENV
# undef HAVE_FDATASYNC
# undef HAVE_GETLINE
# undef HAVE_MNTENT_H
# undef HAVE_PTSNAME_R
# undef HAVE_SYS_STATFS_H
# undef HAVE_SIGHANDLER_T
# undef HAVE_STRVERSCMP
# undef HAVE_XTABS
# undef HAVE_DPRINTF
# undef HAVE_UNLOCKED_STDIO
# undef HAVE_UNLOCKED_LINE_OPS
#endif
#if defined(__dietlibc__)
# undef HAVE_STRCHRNUL
#endif
#if defined(__APPLE__)
# undef HAVE_STRCHRNUL
#endif
#if defined(__FreeBSD__)
# undef HAVE_CLEARENV
# undef HAVE_FDATASYNC
# undef HAVE_MNTENT_H
# undef HAVE_PTSNAME_R
# undef HAVE_SYS_STATFS_H
# undef HAVE_SIGHANDLER_T
# undef HAVE_STRVERSCMP
# undef HAVE_XTABS
# undef HAVE_UNLOCKED_LINE_OPS
# include <osreldate.h>
# if __FreeBSD_version < 1000029
# undef HAVE_STRCHRNUL /* FreeBSD added strchrnul() between 1000028 and 1000029 */
# endif
#endif
#if defined(__NetBSD__)
# define HAVE_GETLINE 1 /* Recent NetBSD versions have getline() */
#endif
#if defined(__digital__) && defined(__unix__)
# undef HAVE_STPCPY
#endif
#if defined(ANDROID) || defined(__ANDROID__)
# undef HAVE_DPRINTF
# undef HAVE_GETLINE
# undef HAVE_STPCPY
# undef HAVE_STRCHRNUL
# undef HAVE_STRVERSCMP
# undef HAVE_UNLOCKED_LINE_OPS
# undef HAVE_NET_ETHERNET_H
#endif
/*
* Now, define prototypes for all the functions defined in platform.c
* These must come after all the HAVE_* macros are defined (or not)
*/
#ifndef HAVE_DPRINTF
extern int dprintf(int fd, const char *format, ...);
#endif
#ifndef HAVE_MEMRCHR
extern void *memrchr(const void *s, int c, size_t n) FAST_FUNC;
#endif
#ifndef HAVE_MKDTEMP
extern char *mkdtemp(char *template) FAST_FUNC;
#endif
#ifndef HAVE_SETBIT
# define setbit(a, b) ((a)[(b) >> 3] |= 1 << ((b) & 7))
# define clrbit(a, b) ((a)[(b) >> 3] &= ~(1 << ((b) & 7)))
#endif
#ifndef HAVE_SIGHANDLER_T
typedef void (*sighandler_t)(int);
#endif
#ifndef HAVE_STPCPY
extern char *stpcpy(char *p, const char *to_add) FAST_FUNC;
#endif
#ifndef HAVE_STRCASESTR
extern char *strcasestr(const char *s, const char *pattern) FAST_FUNC;
#endif
#ifndef HAVE_STRCHRNUL
extern char *strchrnul(const char *s, int c) FAST_FUNC;
#endif
#ifndef HAVE_STRSEP
extern char *strsep(char **stringp, const char *delim) FAST_FUNC;
#endif
#ifndef HAVE_STRSIGNAL
/* Not exactly the same: instead of "Stopped" it shows "STOP" etc */
# define strsignal(sig) get_signame(sig)
#endif
#ifndef HAVE_USLEEP
extern int usleep(unsigned) FAST_FUNC;
#endif
#ifndef HAVE_VASPRINTF
extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC;
#endif
#ifndef HAVE_GETLINE
# include <stdio.h> /* for FILE */
# include <sys/types.h> /* size_t */
extern ssize_t getline(char **lineptr, size_t *n, FILE *stream) FAST_FUNC;
#endif
#endif

19
src/bled/seek_by_jump.c Normal file
View file

@ -0,0 +1,19 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
void FAST_FUNC seek_by_jump(int fd, off_t amount)
{
if (amount
&& lseek(fd, amount, SEEK_CUR) == (off_t) -1
) {
if (errno == ESPIPE)
seek_by_read(fd, amount);
else
bb_perror_msg_and_die("seek failure");
}
}

16
src/bled/seek_by_read.c Normal file
View file

@ -0,0 +1,16 @@
/* vi: set sw=4 ts=4: */
/*
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
#include "libbb.h"
#include "bb_archive.h"
/* If we are reading through a pipe, or from stdin then we can't lseek,
* we must read and discard the data to skip over it.
*/
void FAST_FUNC seek_by_read(int fd, off_t amount)
{
if (amount)
bb_copyfd_exact_size(fd, -1, amount);
}

282
src/bled/xz.h Normal file
View file

@ -0,0 +1,282 @@
/*
* XZ decompressor
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <http://7-zip.org/>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_H
#define XZ_H
#ifdef __KERNEL__
# include <linux/stddef.h>
# include <linux/types.h>
#else
# include <stddef.h>
# include <stdint.h>
#endif
#include "platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/* In Linux, this is used to make extern functions static when needed. */
#ifndef XZ_EXTERN
# define XZ_EXTERN extern
#endif
/* In Linux, this is used to mark the functions with __init when needed. */
#ifndef XZ_FUNC
# define XZ_FUNC
#endif
/**
* enum xz_mode - Operation mode
*
* @XZ_SINGLE: Single-call mode. This uses less RAM than
* than multi-call modes, because the LZMA2
* dictionary doesn't need to be allocated as
* part of the decoder state. All required data
* structures are allocated at initialization,
* so xz_dec_run() cannot return XZ_MEM_ERROR.
* @XZ_PREALLOC: Multi-call mode with preallocated LZMA2
* dictionary buffer. All data structures are
* allocated at initialization, so xz_dec_run()
* cannot return XZ_MEM_ERROR.
* @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is
* allocated once the required size has been
* parsed from the stream headers. If the
* allocation fails, xz_dec_run() will return
* XZ_MEM_ERROR.
*
* It is possible to enable support only for a subset of the above
* modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC,
* or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled
* with support for all operation modes, but the preboot code may
* be built with fewer features to minimize code size.
*/
enum xz_mode {
XZ_SINGLE,
XZ_PREALLOC,
XZ_DYNALLOC
};
/**
* enum xz_ret - Return codes
* @XZ_OK: Everything is OK so far. More input or more
* output space is required to continue. This
* return code is possible only in multi-call mode
* (XZ_PREALLOC or XZ_DYNALLOC).
* @XZ_STREAM_END: Operation finished successfully.
* @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
* is still possible in multi-call mode by simply
* calling xz_dec_run() again.
* Note that this return value is used only if
* XZ_DEC_ANY_CHECK was defined at build time,
* which is not used in the kernel. Unsupported
* check types return XZ_OPTIONS_ERROR if
* XZ_DEC_ANY_CHECK was not defined at build time.
* @XZ_MEM_ERROR: Allocating memory failed. This return code is
* possible only if the decoder was initialized
* with XZ_DYNALLOC. The amount of memory that was
* tried to be allocated was no more than the
* dict_max argument given to xz_dec_init().
* @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than
* allowed by the dict_max argument given to
* xz_dec_init(). This return value is possible
* only in multi-call mode (XZ_PREALLOC or
* XZ_DYNALLOC); the single-call mode (XZ_SINGLE)
* ignores the dict_max argument.
* @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
* bytes).
* @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
* compression options. In the decoder this means
* that the header CRC32 matches, but the header
* itself specifies something that we don't support.
* @XZ_DATA_ERROR: Compressed data is corrupt.
* @XZ_BUF_ERROR: Cannot make any progress. Details are slightly
* different between multi-call and single-call
* mode; more information below.
*
* In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls
* to XZ code cannot consume any input and cannot produce any new output.
* This happens when there is no new input available, or the output buffer
* is full while at least one output byte is still pending. Assuming your
* code is not buggy, you can get this error only when decoding a compressed
* stream that is truncated or otherwise corrupt.
*
* In single-call mode, XZ_BUF_ERROR is returned only when the output buffer
* is too small or the compressed input is corrupt in a way that makes the
* decoder produce more output than the caller expected. When it is
* (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR
* is used instead of XZ_BUF_ERROR.
*/
enum xz_ret {
XZ_OK,
XZ_STREAM_END,
XZ_UNSUPPORTED_CHECK,
XZ_MEM_ERROR,
XZ_MEMLIMIT_ERROR,
XZ_FORMAT_ERROR,
XZ_OPTIONS_ERROR,
XZ_DATA_ERROR,
XZ_BUF_ERROR
};
/**
* struct xz_buf - Passing input and output buffers to XZ code
* @in: Beginning of the input buffer. This may be NULL if and only
* if in_pos is equal to in_size.
* @in_pos: Current position in the input buffer. This must not exceed
* in_size.
* @in_size: Size of the input buffer
* @out: Beginning of the output buffer. This may be NULL if and only
* if out_pos is equal to out_size.
* @out_pos: Current position in the output buffer. This must not exceed
* out_size.
* @out_size: Size of the output buffer
*
* Only the contents of the output buffer from out[out_pos] onward, and
* the variables in_pos and out_pos are modified by the XZ code.
*/
struct xz_buf {
const uint8_t *in;
size_t in_pos;
size_t in_size;
uint8_t *out;
size_t out_pos;
size_t out_size;
};
/**
* struct xz_dec - Opaque type to hold the XZ decoder state
*/
struct xz_dec;
/**
* xz_dec_init() - Allocate and initialize a XZ decoder state
* @mode: Operation mode
* @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
* multi-call decoding. This is ignored in single-call mode
* (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes
* or 2^n + 2^(n-1) bytes (the latter sizes are less common
* in practice), so other values for dict_max don't make sense.
* In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB,
* 512 KiB, and 1 MiB are probably the only reasonable values,
* except for kernel and initramfs images where a bigger
* dictionary can be fine and useful.
*
* Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at
* once. The caller must provide enough output space or the decoding will
* fail. The output space is used as the dictionary buffer, which is why
* there is no need to allocate the dictionary as part of the decoder's
* internal state.
*
* Because the output buffer is used as the workspace, streams encoded using
* a big dictionary are not a problem in single-call mode. It is enough that
* the output buffer is big enough to hold the actual uncompressed data; it
* can be smaller than the dictionary size stored in the stream headers.
*
* Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes
* of memory is preallocated for the LZMA2 dictionary. This way there is no
* risk that xz_dec_run() could run out of memory, since xz_dec_run() will
* never allocate any memory. Instead, if the preallocated dictionary is too
* small for decoding the given input stream, xz_dec_run() will return
* XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be
* decoded to avoid allocating excessive amount of memory for the dictionary.
*
* Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC):
* dict_max specifies the maximum allowed dictionary size that xz_dec_run()
* may allocate once it has parsed the dictionary size from the stream
* headers. This way excessive allocations can be avoided while still
* limiting the maximum memory usage to a sane value to prevent running the
* system out of memory when decompressing streams from untrusted sources.
*
* On success, xz_dec_init() returns a pointer to struct xz_dec, which is
* ready to be used with xz_dec_run(). If memory allocation fails,
* xz_dec_init() returns NULL.
*/
XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
enum xz_mode mode, uint32_t dict_max);
/**
* xz_dec_run() - Run the XZ decoder
* @s: Decoder state allocated using xz_dec_init()
* @b: Input and output buffers
*
* The possible return values depend on build options and operation mode.
* See enum xz_ret for details.
*
* Note that if an error occurs in single-call mode (return value is not
* XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the
* contents of the output buffer from b->out[b->out_pos] onward are
* undefined. This is true even after XZ_BUF_ERROR, because with some filter
* chains, there may be a second pass over the output buffer, and this pass
* cannot be properly done if the output buffer is truncated. Thus, you
* cannot give the single-call decoder a too small buffer and then expect to
* get that amount valid data from the beginning of the stream. You must use
* the multi-call decoder if you don't want to uncompress the whole stream.
*/
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b);
/**
* xz_dec_reset() - Reset an already allocated decoder state
* @s: Decoder state allocated using xz_dec_init()
*
* This function can be used to reset the multi-call decoder state without
* freeing and reallocating memory with xz_dec_end() and xz_dec_init().
*
* In single-call mode, xz_dec_reset() is always called in the beginning of
* xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in
* multi-call mode.
*/
XZ_EXTERN void XZ_FUNC xz_dec_reset(struct xz_dec *s);
/**
* xz_dec_end() - Free the memory allocated for the decoder state
* @s: Decoder state allocated using xz_dec_init(). If s is NULL,
* this function does nothing.
*/
XZ_EXTERN void XZ_FUNC xz_dec_end(struct xz_dec *s);
/*
* Standalone build (userspace build or in-kernel build for boot time use)
* needs a CRC32 implementation. For normal in-kernel use, kernel's own
* CRC32 module is used instead, and users of this module don't need to
* care about the functions below.
*/
#ifndef XZ_INTERNAL_CRC32
# ifdef __KERNEL__
# define XZ_INTERNAL_CRC32 0
# else
# define XZ_INTERNAL_CRC32 1
# endif
#endif
#if XZ_INTERNAL_CRC32
/*
* This must be called before any other xz_* function to initialize
* the CRC32 lookup table.
*/
XZ_EXTERN void XZ_FUNC xz_crc32_init(void);
/*
* Update CRC32 value using the polynomial from IEEE-802.3. To start a new
* calculation, the third argument must be zero. To continue the calculation,
* the previously returned value is passed as the third argument.
*/
XZ_EXTERN uint32_t XZ_FUNC xz_crc32(
const uint8_t *buf, size_t size, uint32_t crc);
#endif
#ifdef __cplusplus
}
#endif
#endif

123
src/bled/xz_config.h Normal file
View file

@ -0,0 +1,123 @@
/*
* Private includes and definitions for userspace use of XZ Embedded
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_CONFIG_H
#define XZ_CONFIG_H
/* Uncomment as needed to enable BCJ filter decoders. */
#define XZ_DEC_X86
/* #define XZ_DEC_POWERPC */
/* #define XZ_DEC_IA64 */
/* #define XZ_DEC_ARM */
/* #define XZ_DEC_ARMTHUMB */
/* #define XZ_DEC_SPARC */
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "xz.h"
#define kmalloc(size, flags) malloc(size)
#define kfree(ptr) free(ptr)
#define vmalloc(size) malloc(size)
#define vfree(ptr) free(ptr)
#define memeq(a, b, size) (memcmp(a, b, size) == 0)
#define memzero(buf, size) memset(buf, 0, size)
#undef min
#undef min_t
#define min(x, y) ((x) < (y) ? (x) : (y))
#define min_t(type, x, y) min(x, y)
/*
* Some functions have been marked with __always_inline to keep the
* performance reasonable even when the compiler is optimizing for
* small code size. You may be able to save a few bytes by #defining
* __always_inline to plain inline, but don't complain if the code
* becomes slow.
*
* NOTE: System headers on GNU/Linux may #define this macro already,
* so if you want to change it, you need to #undef it first.
*/
#ifndef __always_inline
# ifdef __GNUC__
# define __always_inline \
inline __attribute__((__always_inline__))
# else
# define __always_inline inline
# endif
#endif
/*
* Some functions are marked to never be inlined to reduce stack usage.
* If you don't care about stack usage, you may want to modify this so
* that noinline_for_stack is #defined to be empty even when using GCC.
* Doing so may save a few bytes in binary size.
*/
#ifndef noinline_for_stack
# ifdef __GNUC__
# define noinline_for_stack __attribute__((__noinline__))
# else
# define noinline_for_stack
# endif
#endif
/* Inline functions to access unaligned unsigned 32-bit integers */
#ifndef get_unaligned_le32
static inline uint32_t XZ_FUNC get_unaligned_le32(const uint8_t *buf)
{
return (uint32_t)buf[0]
| ((uint32_t)buf[1] << 8)
| ((uint32_t)buf[2] << 16)
| ((uint32_t)buf[3] << 24);
}
#endif
#ifndef get_unaligned_be32
static inline uint32_t XZ_FUNC get_unaligned_be32(const uint8_t *buf)
{
return (uint32_t)(buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3];
}
#endif
#ifndef put_unaligned_le32
static inline void XZ_FUNC put_unaligned_le32(uint32_t val, uint8_t *buf)
{
buf[0] = (uint8_t)val;
buf[1] = (uint8_t)(val >> 8);
buf[2] = (uint8_t)(val >> 16);
buf[3] = (uint8_t)(val >> 24);
}
#endif
#ifndef put_unaligned_be32
static inline void XZ_FUNC put_unaligned_be32(uint32_t val, uint8_t *buf)
{
buf[0] = (uint8_t)(val >> 24);
buf[1] = (uint8_t)(val >> 16);
buf[2] = (uint8_t)(val >> 8);
buf[3] = (uint8_t)val;
}
#endif
/*
* Use get_unaligned_le32() also for aligned access for simplicity. On
* little endian systems, #define get_le32(ptr) (*(const uint32_t *)(ptr))
* could save a few bytes in code size.
*/
#ifndef get_le32
# define get_le32 get_unaligned_le32
#endif
#endif

580
src/bled/xz_dec_bcj.c Normal file
View file

@ -0,0 +1,580 @@
/*
* Branch/Call/Jump (BCJ) filter decoders
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <http://7-zip.org/>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#include "xz_private.h"
/*
* The rest of the file is inside this ifdef. It makes things a little more
* convenient when building without support for any BCJ filters.
*/
#ifdef XZ_DEC_BCJ
struct xz_dec_bcj {
/* Type of the BCJ filter being used */
enum {
BCJ_X86 = 4, /* x86 or x86-64 */
BCJ_POWERPC = 5, /* Big endian only */
BCJ_IA64 = 6, /* Big or little endian */
BCJ_ARM = 7, /* Little endian only */
BCJ_ARMTHUMB = 8, /* Little endian only */
BCJ_SPARC = 9 /* Big or little endian */
} type;
/*
* Return value of the next filter in the chain. We need to preserve
* this information across calls, because we must not call the next
* filter anymore once it has returned XZ_STREAM_END.
*/
enum xz_ret ret;
/* True if we are operating in single-call mode. */
bool single_call;
/*
* Absolute position relative to the beginning of the uncompressed
* data (in a single .xz Block). We care only about the lowest 32
* bits so this doesn't need to be uint64_t even with big files.
*/
uint32_t pos;
/* x86 filter state */
uint32_t x86_prev_mask;
/* Temporary space to hold the variables from struct xz_buf */
uint8_t *out;
size_t out_pos;
size_t out_size;
struct {
/* Amount of already filtered data in the beginning of buf */
size_t filtered;
/* Total amount of data currently stored in buf */
size_t size;
/*
* Buffer to hold a mix of filtered and unfiltered data. This
* needs to be big enough to hold Alignment + 2 * Look-ahead:
*
* Type Alignment Look-ahead
* x86 1 4
* PowerPC 4 0
* IA-64 16 0
* ARM 4 0
* ARM-Thumb 2 2
* SPARC 4 0
*/
uint8_t buf[16];
} temp;
};
#ifdef XZ_DEC_X86
/*
* This is used to test the most significant byte of a memory address
* in an x86 instruction.
*/
static inline int bcj_x86_test_msbyte(uint8_t b)
{
return b == 0x00 || b == 0xFF;
}
static noinline_for_stack size_t XZ_FUNC bcj_x86(
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
static const bool mask_to_allowed_status[8]
= { true, true, true, false, true, false, false, false };
static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
size_t i;
size_t prev_pos = (size_t)-1;
uint32_t prev_mask = s->x86_prev_mask;
uint32_t src;
uint32_t dest;
uint32_t j;
uint8_t b;
if (size <= 4)
return 0;
size -= 4;
for (i = 0; i < size; ++i) {
if ((buf[i] & 0xFE) != 0xE8)
continue;
prev_pos = i - prev_pos;
if (prev_pos > 3) {
prev_mask = 0;
} else {
prev_mask = (prev_mask << (prev_pos - 1)) & 7;
if (prev_mask != 0) {
b = buf[i + 4 - mask_to_bit_num[prev_mask]];
if (!mask_to_allowed_status[prev_mask]
|| bcj_x86_test_msbyte(b)) {
prev_pos = i;
prev_mask = (prev_mask << 1) | 1;
continue;
}
}
}
prev_pos = i;
if (bcj_x86_test_msbyte(buf[i + 4])) {
src = get_unaligned_le32(buf + i + 1);
while (true) {
dest = src - (s->pos + (uint32_t)i + 5);
if (prev_mask == 0)
break;
j = mask_to_bit_num[prev_mask] * 8;
b = (uint8_t)(dest >> (24 - j));
if (!bcj_x86_test_msbyte(b))
break;
src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
}
dest &= 0x01FFFFFF;
dest |= (uint32_t)0 - (dest & 0x01000000);
put_unaligned_le32(dest, buf + i + 1);
i += 4;
} else {
prev_mask = (prev_mask << 1) | 1;
}
}
prev_pos = i - prev_pos;
s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
return i;
}
#endif
#ifdef XZ_DEC_POWERPC
static noinline_for_stack size_t XZ_FUNC bcj_powerpc(
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
size_t i;
uint32_t instr;
for (i = 0; i + 4 <= size; i += 4) {
instr = get_unaligned_be32(buf + i);
if ((instr & 0xFC000003) == 0x48000001) {
instr &= 0x03FFFFFC;
instr -= s->pos + (uint32_t)i;
instr &= 0x03FFFFFC;
instr |= 0x48000001;
put_unaligned_be32(instr, buf + i);
}
}
return i;
}
#endif
#ifdef XZ_DEC_IA64
static noinline_for_stack size_t XZ_FUNC bcj_ia64(
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
static const uint8_t branch_table[32] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 6, 6, 0, 0, 7, 7,
4, 4, 0, 0, 4, 4, 0, 0
};
/*
* The local variables take a little bit stack space, but it's less
* than what LZMA2 decoder takes, so it doesn't make sense to reduce
* stack usage here without doing that for the LZMA2 decoder too.
*/
/* Loop counters */
size_t i;
size_t j;
/* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
uint32_t slot;
/* Bitwise offset of the instruction indicated by slot */
uint32_t bit_pos;
/* bit_pos split into byte and bit parts */
uint32_t byte_pos;
uint32_t bit_res;
/* Address part of an instruction */
uint32_t addr;
/* Mask used to detect which instructions to convert */
uint32_t mask;
/* 41-bit instruction stored somewhere in the lowest 48 bits */
uint64_t instr;
/* Instruction normalized with bit_res for easier manipulation */
uint64_t norm;
for (i = 0; i + 16 <= size; i += 16) {
mask = branch_table[buf[i] & 0x1F];
for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
if (((mask >> slot) & 1) == 0)
continue;
byte_pos = bit_pos >> 3;
bit_res = bit_pos & 7;
instr = 0;
for (j = 0; j < 6; ++j)
instr |= (uint64_t)(buf[i + j + byte_pos])
<< (8 * j);
norm = instr >> bit_res;
if (((norm >> 37) & 0x0F) == 0x05
&& ((norm >> 9) & 0x07) == 0) {
addr = (norm >> 13) & 0x0FFFFF;
addr |= ((uint32_t)(norm >> 36) & 1) << 20;
addr <<= 4;
addr -= s->pos + (uint32_t)i;
addr >>= 4;
norm &= ~((uint64_t)0x8FFFFF << 13);
norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
norm |= (uint64_t)(addr & 0x100000)
<< (36 - 20);
instr &= (1 << bit_res) - 1;
instr |= norm << bit_res;
for (j = 0; j < 6; j++)
buf[i + j + byte_pos]
= (uint8_t)(instr >> (8 * j));
}
}
}
return i;
}
#endif
#ifdef XZ_DEC_ARM
static noinline_for_stack size_t XZ_FUNC bcj_arm(
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
size_t i;
uint32_t addr;
for (i = 0; i + 4 <= size; i += 4) {
if (buf[i + 3] == 0xEB) {
addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
| ((uint32_t)buf[i + 2] << 16);
addr <<= 2;
addr -= s->pos + (uint32_t)i + 8;
addr >>= 2;
buf[i] = (uint8_t)addr;
buf[i + 1] = (uint8_t)(addr >> 8);
buf[i + 2] = (uint8_t)(addr >> 16);
}
}
return i;
}
#endif
#ifdef XZ_DEC_ARMTHUMB
static noinline_for_stack size_t XZ_FUNC bcj_armthumb(
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
size_t i;
uint32_t addr;
for (i = 0; i + 4 <= size; i += 2) {
if ((buf[i + 1] & 0xF8) == 0xF0
&& (buf[i + 3] & 0xF8) == 0xF8) {
addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
| ((uint32_t)buf[i] << 11)
| (((uint32_t)buf[i + 3] & 0x07) << 8)
| (uint32_t)buf[i + 2];
addr <<= 1;
addr -= s->pos + (uint32_t)i + 4;
addr >>= 1;
buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
buf[i] = (uint8_t)(addr >> 11);
buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
buf[i + 2] = (uint8_t)addr;
i += 2;
}
}
return i;
}
#endif
#ifdef XZ_DEC_SPARC
static noinline_for_stack size_t XZ_FUNC bcj_sparc(
struct xz_dec_bcj *s, uint8_t *buf, size_t size)
{
size_t i;
uint32_t instr;
for (i = 0; i + 4 <= size; i += 4) {
instr = get_unaligned_be32(buf + i);
if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
instr <<= 2;
instr -= s->pos + (uint32_t)i;
instr >>= 2;
instr = ((uint32_t)0x40000000 - (instr & 0x400000))
| 0x40000000 | (instr & 0x3FFFFF);
put_unaligned_be32(instr, buf + i);
}
}
return i;
}
#endif
/*
* Apply the selected BCJ filter. Update *pos and s->pos to match the amount
* of data that got filtered.
*
* NOTE: This is implemented as a switch statement to avoid using function
* pointers, which could be problematic in the kernel boot code, which must
* avoid pointers to static data (at least on x86).
*/
static void XZ_FUNC bcj_apply(struct xz_dec_bcj *s,
uint8_t *buf, size_t *pos, size_t size)
{
size_t filtered;
buf += *pos;
size -= *pos;
switch (s->type) {
#ifdef XZ_DEC_X86
case BCJ_X86:
filtered = bcj_x86(s, buf, size);
break;
#endif
#ifdef XZ_DEC_POWERPC
case BCJ_POWERPC:
filtered = bcj_powerpc(s, buf, size);
break;
#endif
#ifdef XZ_DEC_IA64
case BCJ_IA64:
filtered = bcj_ia64(s, buf, size);
break;
#endif
#ifdef XZ_DEC_ARM
case BCJ_ARM:
filtered = bcj_arm(s, buf, size);
break;
#endif
#ifdef XZ_DEC_ARMTHUMB
case BCJ_ARMTHUMB:
filtered = bcj_armthumb(s, buf, size);
break;
#endif
#ifdef XZ_DEC_SPARC
case BCJ_SPARC:
filtered = bcj_sparc(s, buf, size);
break;
#endif
default:
/* Never reached but silence compiler warnings. */
filtered = 0;
break;
}
*pos += filtered;
s->pos += filtered;
}
/*
* Flush pending filtered data from temp to the output buffer.
* Move the remaining mixture of possibly filtered and unfiltered
* data to the beginning of temp.
*/
static void XZ_FUNC bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
{
size_t copy_size;
copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
b->out_pos += copy_size;
s->temp.filtered -= copy_size;
s->temp.size -= copy_size;
memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
}
/*
* The BCJ filter functions are primitive in sense that they process the
* data in chunks of 1-16 bytes. To hide this issue, this function does
* some buffering.
*/
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
struct xz_dec_lzma2 *lzma2, struct xz_buf *b)
{
size_t out_start;
/*
* Flush pending already filtered data to the output buffer. Return
* immediatelly if we couldn't flush everything, or if the next
* filter in the chain had already returned XZ_STREAM_END.
*/
if (s->temp.filtered > 0) {
bcj_flush(s, b);
if (s->temp.filtered > 0)
return XZ_OK;
if (s->ret == XZ_STREAM_END)
return XZ_STREAM_END;
}
/*
* If we have more output space than what is currently pending in
* temp, copy the unfiltered data from temp to the output buffer
* and try to fill the output buffer by decoding more data from the
* next filter in the chain. Apply the BCJ filter on the new data
* in the output buffer. If everything cannot be filtered, copy it
* to temp and rewind the output buffer position accordingly.
*
* This needs to be always run when temp.size == 0 to handle a special
* case where the output buffer is full and the next filter has no
* more output coming but hasn't returned XZ_STREAM_END yet.
*/
if (s->temp.size < b->out_size - b->out_pos || s->temp.size == 0) {
out_start = b->out_pos;
memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
b->out_pos += s->temp.size;
s->ret = xz_dec_lzma2_run(lzma2, b);
if (s->ret != XZ_STREAM_END
&& (s->ret != XZ_OK || s->single_call))
return s->ret;
bcj_apply(s, b->out, &out_start, b->out_pos);
/*
* As an exception, if the next filter returned XZ_STREAM_END,
* we can do that too, since the last few bytes that remain
* unfiltered are meant to remain unfiltered.
*/
if (s->ret == XZ_STREAM_END)
return XZ_STREAM_END;
s->temp.size = b->out_pos - out_start;
b->out_pos -= s->temp.size;
memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
/*
* If there wasn't enough input to the next filter to fill
* the output buffer with unfiltered data, there's no point
* to try decoding more data to temp.
*/
if (b->out_pos + s->temp.size < b->out_size)
return XZ_OK;
}
/*
* We have unfiltered data in temp. If the output buffer isn't full
* yet, try to fill the temp buffer by decoding more data from the
* next filter. Apply the BCJ filter on temp. Then we hopefully can
* fill the actual output buffer by copying filtered data from temp.
* A mix of filtered and unfiltered data may be left in temp; it will
* be taken care on the next call to this function.
*/
if (b->out_pos < b->out_size) {
/* Make b->out{,_pos,_size} temporarily point to s->temp. */
s->out = b->out;
s->out_pos = b->out_pos;
s->out_size = b->out_size;
b->out = s->temp.buf;
b->out_pos = s->temp.size;
b->out_size = sizeof(s->temp.buf);
s->ret = xz_dec_lzma2_run(lzma2, b);
s->temp.size = b->out_pos;
b->out = s->out;
b->out_pos = s->out_pos;
b->out_size = s->out_size;
if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
return s->ret;
bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
/*
* If the next filter returned XZ_STREAM_END, we mark that
* everything is filtered, since the last unfiltered bytes
* of the stream are meant to be left as is.
*/
if (s->ret == XZ_STREAM_END)
s->temp.filtered = s->temp.size;
bcj_flush(s, b);
if (s->temp.filtered > 0)
return XZ_OK;
}
return s->ret;
}
XZ_EXTERN struct xz_dec_bcj * XZ_FUNC xz_dec_bcj_create(bool single_call)
{
struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (s != NULL)
s->single_call = single_call;
return s;
}
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_reset(
struct xz_dec_bcj *s, uint8_t id)
{
switch (id) {
#ifdef XZ_DEC_X86
case BCJ_X86:
#endif
#ifdef XZ_DEC_POWERPC
case BCJ_POWERPC:
#endif
#ifdef XZ_DEC_IA64
case BCJ_IA64:
#endif
#ifdef XZ_DEC_ARM
case BCJ_ARM:
#endif
#ifdef XZ_DEC_ARMTHUMB
case BCJ_ARMTHUMB:
#endif
#ifdef XZ_DEC_SPARC
case BCJ_SPARC:
#endif
break;
default:
/* Unsupported Filter ID */
return XZ_OPTIONS_ERROR;
}
s->type = id;
s->ret = XZ_OK;
s->pos = 0;
s->x86_prev_mask = 0;
s->temp.filtered = 0;
s->temp.size = 0;
return XZ_OK;
}
#endif

1174
src/bled/xz_dec_lzma2.c Normal file

File diff suppressed because it is too large Load diff

822
src/bled/xz_dec_stream.c Normal file
View file

@ -0,0 +1,822 @@
/*
* .xz Stream decoder
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#include "xz_private.h"
#include "xz_stream.h"
/* Hash used to validate the Index field */
struct xz_dec_hash {
vli_type unpadded;
vli_type uncompressed;
uint32_t crc32;
};
struct xz_dec {
/* Position in dec_main() */
enum {
SEQ_STREAM_HEADER,
SEQ_BLOCK_START,
SEQ_BLOCK_HEADER,
SEQ_BLOCK_UNCOMPRESS,
SEQ_BLOCK_PADDING,
SEQ_BLOCK_CHECK,
SEQ_INDEX,
SEQ_INDEX_PADDING,
SEQ_INDEX_CRC32,
SEQ_STREAM_FOOTER
} sequence;
/* Position in variable-length integers and Check fields */
uint32_t pos;
/* Variable-length integer decoded by dec_vli() */
vli_type vli;
/* Saved in_pos and out_pos */
size_t in_start;
size_t out_start;
/* CRC32 value in Block or Index */
uint32_t crc32;
/* Type of the integrity check calculated from uncompressed data */
enum xz_check check_type;
/* Operation mode */
enum xz_mode mode;
/*
* True if the next call to xz_dec_run() is allowed to return
* XZ_BUF_ERROR.
*/
bool allow_buf_error;
/* Information stored in Block Header */
struct {
/*
* Value stored in the Compressed Size field, or
* VLI_UNKNOWN if Compressed Size is not present.
*/
vli_type compressed;
/*
* Value stored in the Uncompressed Size field, or
* VLI_UNKNOWN if Uncompressed Size is not present.
*/
vli_type uncompressed;
/* Size of the Block Header field */
uint32_t size;
} block_header;
/* Information collected when decoding Blocks */
struct {
/* Observed compressed size of the current Block */
vli_type compressed;
/* Observed uncompressed size of the current Block */
vli_type uncompressed;
/* Number of Blocks decoded so far */
vli_type count;
/*
* Hash calculated from the Block sizes. This is used to
* validate the Index field.
*/
struct xz_dec_hash hash;
} block;
/* Variables needed when verifying the Index field */
struct {
/* Position in dec_index() */
enum {
SEQ_INDEX_COUNT,
SEQ_INDEX_UNPADDED,
SEQ_INDEX_UNCOMPRESSED
} sequence;
/* Size of the Index in bytes */
vli_type size;
/* Number of Records (matches block.count in valid files) */
vli_type count;
/*
* Hash calculated from the Records (matches block.hash in
* valid files).
*/
struct xz_dec_hash hash;
} index;
/*
* Temporary buffer needed to hold Stream Header, Block Header,
* and Stream Footer. The Block Header is the biggest (1 KiB)
* so we reserve space according to that. buf[] has to be aligned
* to a multiple of four bytes; the size_t variables before it
* should guarantee this.
*/
struct {
size_t pos;
size_t size;
uint8_t buf[1024];
} temp;
struct xz_dec_lzma2 *lzma2;
#ifdef XZ_DEC_BCJ
struct xz_dec_bcj *bcj;
bool bcj_active;
#endif
};
#ifdef XZ_DEC_ANY_CHECK
/* Sizes of the Check field with different Check IDs */
static const uint8_t check_sizes[16] = {
0,
4, 4, 4,
8, 8, 8,
16, 16, 16,
32, 32, 32,
64, 64, 64
};
#endif
/*
* Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
* must have set s->temp.pos to indicate how much data we are supposed
* to copy into s->temp.buf. Return true once s->temp.pos has reached
* s->temp.size.
*/
static bool XZ_FUNC fill_temp(struct xz_dec *s, struct xz_buf *b)
{
size_t copy_size = min_t(size_t,
b->in_size - b->in_pos, s->temp.size - s->temp.pos);
memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
b->in_pos += copy_size;
s->temp.pos += copy_size;
if (s->temp.pos == s->temp.size) {
s->temp.pos = 0;
return true;
}
return false;
}
/* Decode a variable-length integer (little-endian base-128 encoding) */
static enum xz_ret XZ_FUNC dec_vli(struct xz_dec *s,
const uint8_t *in, size_t *in_pos, size_t in_size)
{
uint8_t byte;
if (s->pos == 0)
s->vli = 0;
while (*in_pos < in_size) {
byte = in[*in_pos];
++*in_pos;
s->vli |= (vli_type)(byte & 0x7F) << s->pos;
if ((byte & 0x80) == 0) {
/* Don't allow non-minimal encodings. */
if (byte == 0 && s->pos != 0)
return XZ_DATA_ERROR;
s->pos = 0;
return XZ_STREAM_END;
}
s->pos += 7;
if (s->pos == 7 * VLI_BYTES_MAX)
return XZ_DATA_ERROR;
}
return XZ_OK;
}
/*
* Decode the Compressed Data field from a Block. Update and validate
* the observed compressed and uncompressed sizes of the Block so that
* they don't exceed the values possibly stored in the Block Header
* (validation assumes that no integer overflow occurs, since vli_type
* is normally uint64_t). Update the CRC32 if presence of the CRC32
* field was indicated in Stream Header.
*
* Once the decoding is finished, validate that the observed sizes match
* the sizes possibly stored in the Block Header. Update the hash and
* Block count, which are later used to validate the Index field.
*/
static enum xz_ret XZ_FUNC dec_block(struct xz_dec *s, struct xz_buf *b)
{
enum xz_ret ret;
s->in_start = b->in_pos;
s->out_start = b->out_pos;
#ifdef XZ_DEC_BCJ
if (s->bcj_active)
ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
else
#endif
ret = xz_dec_lzma2_run(s->lzma2, b);
s->block.compressed += b->in_pos - s->in_start;
s->block.uncompressed += b->out_pos - s->out_start;
/*
* There is no need to separately check for VLI_UNKNOWN, since
* the observed sizes are always smaller than VLI_UNKNOWN.
*/
if (s->block.compressed > s->block_header.compressed
|| s->block.uncompressed
> s->block_header.uncompressed)
return XZ_DATA_ERROR;
if (s->check_type == XZ_CHECK_CRC32)
s->crc32 = xz_crc32(b->out + s->out_start,
b->out_pos - s->out_start, s->crc32);
if (ret == XZ_STREAM_END) {
if (s->block_header.compressed != VLI_UNKNOWN
&& s->block_header.compressed
!= s->block.compressed)
return XZ_DATA_ERROR;
if (s->block_header.uncompressed != VLI_UNKNOWN
&& s->block_header.uncompressed
!= s->block.uncompressed)
return XZ_DATA_ERROR;
s->block.hash.unpadded += s->block_header.size
+ s->block.compressed;
#ifdef XZ_DEC_ANY_CHECK
s->block.hash.unpadded += check_sizes[s->check_type];
#else
if (s->check_type == XZ_CHECK_CRC32)
s->block.hash.unpadded += 4;
#endif
s->block.hash.uncompressed += s->block.uncompressed;
s->block.hash.crc32 = xz_crc32(
(const uint8_t *)&s->block.hash,
sizeof(s->block.hash), s->block.hash.crc32);
++s->block.count;
}
return ret;
}
/* Update the Index size and the CRC32 value. */
static void XZ_FUNC index_update(struct xz_dec *s, const struct xz_buf *b)
{
size_t in_used = b->in_pos - s->in_start;
s->index.size += in_used;
s->crc32 = xz_crc32(b->in + s->in_start, in_used, s->crc32);
}
/*
* Decode the Number of Records, Unpadded Size, and Uncompressed Size
* fields from the Index field. That is, Index Padding and CRC32 are not
* decoded by this function.
*
* This can return XZ_OK (more input needed), XZ_STREAM_END (everything
* successfully decoded), or XZ_DATA_ERROR (input is corrupt).
*/
static enum xz_ret XZ_FUNC dec_index(struct xz_dec *s, struct xz_buf *b)
{
enum xz_ret ret;
do {
ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
if (ret != XZ_STREAM_END) {
index_update(s, b);
return ret;
}
switch (s->index.sequence) {
case SEQ_INDEX_COUNT:
s->index.count = s->vli;
/*
* Validate that the Number of Records field
* indicates the same number of Records as
* there were Blocks in the Stream.
*/
if (s->index.count != s->block.count)
return XZ_DATA_ERROR;
s->index.sequence = SEQ_INDEX_UNPADDED;
break;
case SEQ_INDEX_UNPADDED:
s->index.hash.unpadded += s->vli;
s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
break;
case SEQ_INDEX_UNCOMPRESSED:
s->index.hash.uncompressed += s->vli;
s->index.hash.crc32 = xz_crc32(
(const uint8_t *)&s->index.hash,
sizeof(s->index.hash),
s->index.hash.crc32);
--s->index.count;
s->index.sequence = SEQ_INDEX_UNPADDED;
break;
}
} while (s->index.count > 0);
return XZ_STREAM_END;
}
/*
* Validate that the next four input bytes match the value of s->crc32.
* s->pos must be zero when starting to validate the first byte.
*/
static enum xz_ret XZ_FUNC crc32_validate(struct xz_dec *s, struct xz_buf *b)
{
do {
if (b->in_pos == b->in_size)
return XZ_OK;
if (((s->crc32 >> s->pos) & 0xFF) != b->in[b->in_pos++])
return XZ_DATA_ERROR;
s->pos += 8;
} while (s->pos < 32);
s->crc32 = 0;
s->pos = 0;
return XZ_STREAM_END;
}
#ifdef XZ_DEC_ANY_CHECK
/*
* Skip over the Check field when the Check ID is not supported.
* Returns true once the whole Check field has been skipped over.
*/
static bool XZ_FUNC check_skip(struct xz_dec *s, struct xz_buf *b)
{
while (s->pos < check_sizes[s->check_type]) {
if (b->in_pos == b->in_size)
return false;
++b->in_pos;
++s->pos;
}
s->pos = 0;
return true;
}
#endif
/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
static enum xz_ret XZ_FUNC dec_stream_header(struct xz_dec *s)
{
if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
return XZ_FORMAT_ERROR;
if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0)
!= get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
return XZ_DATA_ERROR;
if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
return XZ_OPTIONS_ERROR;
/*
* Of integrity checks, we support only none (Check ID = 0) and
* CRC32 (Check ID = 1). However, if XZ_DEC_ANY_CHECK is defined,
* we will accept other check types too, but then the check won't
* be verified and a warning (XZ_UNSUPPORTED_CHECK) will be given.
*/
s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
#ifdef XZ_DEC_ANY_CHECK
if (s->check_type > XZ_CHECK_MAX)
return XZ_OPTIONS_ERROR;
if (s->check_type > XZ_CHECK_CRC32)
return XZ_UNSUPPORTED_CHECK;
#else
if (s->check_type > XZ_CHECK_CRC32)
return XZ_OPTIONS_ERROR;
#endif
return XZ_OK;
}
/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
static enum xz_ret XZ_FUNC dec_stream_footer(struct xz_dec *s)
{
if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
return XZ_DATA_ERROR;
if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
return XZ_DATA_ERROR;
/*
* Validate Backward Size. Note that we never added the size of the
* Index CRC32 field to s->index.size, thus we use s->index.size / 4
* instead of s->index.size / 4 - 1.
*/
if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
return XZ_DATA_ERROR;
if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
return XZ_DATA_ERROR;
/*
* Use XZ_STREAM_END instead of XZ_OK to be more convenient
* for the caller.
*/
return XZ_STREAM_END;
}
/* Decode the Block Header and initialize the filter chain. */
static enum xz_ret XZ_FUNC dec_block_header(struct xz_dec *s)
{
enum xz_ret ret;
/*
* Validate the CRC32. We know that the temp buffer is at least
* eight bytes so this is safe.
*/
s->temp.size -= 4;
if (xz_crc32(s->temp.buf, s->temp.size, 0)
!= get_le32(s->temp.buf + s->temp.size))
return XZ_DATA_ERROR;
s->temp.pos = 2;
/*
* Catch unsupported Block Flags. We support only one or two filters
* in the chain, so we catch that with the same test.
*/
#ifdef XZ_DEC_BCJ
if (s->temp.buf[1] & 0x3E)
#else
if (s->temp.buf[1] & 0x3F)
#endif
return XZ_OPTIONS_ERROR;
/* Compressed Size */
if (s->temp.buf[1] & 0x40) {
if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
!= XZ_STREAM_END)
return XZ_DATA_ERROR;
s->block_header.compressed = s->vli;
} else {
s->block_header.compressed = VLI_UNKNOWN;
}
/* Uncompressed Size */
if (s->temp.buf[1] & 0x80) {
if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
!= XZ_STREAM_END)
return XZ_DATA_ERROR;
s->block_header.uncompressed = s->vli;
} else {
s->block_header.uncompressed = VLI_UNKNOWN;
}
#ifdef XZ_DEC_BCJ
/* If there are two filters, the first one must be a BCJ filter. */
s->bcj_active = s->temp.buf[1] & 0x01;
if (s->bcj_active) {
if (s->temp.size - s->temp.pos < 2)
return XZ_OPTIONS_ERROR;
ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
if (ret != XZ_OK)
return ret;
/*
* We don't support custom start offset,
* so Size of Properties must be zero.
*/
if (s->temp.buf[s->temp.pos++] != 0x00)
return XZ_OPTIONS_ERROR;
}
#endif
/* Valid Filter Flags always take at least two bytes. */
if (s->temp.size - s->temp.pos < 2)
return XZ_DATA_ERROR;
/* Filter ID = LZMA2 */
if (s->temp.buf[s->temp.pos++] != 0x21)
return XZ_OPTIONS_ERROR;
/* Size of Properties = 1-byte Filter Properties */
if (s->temp.buf[s->temp.pos++] != 0x01)
return XZ_OPTIONS_ERROR;
/* Filter Properties contains LZMA2 dictionary size. */
if (s->temp.size - s->temp.pos < 1)
return XZ_DATA_ERROR;
ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
if (ret != XZ_OK)
return ret;
/* The rest must be Header Padding. */
while (s->temp.pos < s->temp.size)
if (s->temp.buf[s->temp.pos++] != 0x00)
return XZ_OPTIONS_ERROR;
s->temp.pos = 0;
s->block.compressed = 0;
s->block.uncompressed = 0;
return XZ_OK;
}
static enum xz_ret XZ_FUNC dec_main(struct xz_dec *s, struct xz_buf *b)
{
enum xz_ret ret;
/*
* Store the start position for the case when we are in the middle
* of the Index field.
*/
s->in_start = b->in_pos;
while (true) {
switch (s->sequence) {
case SEQ_STREAM_HEADER:
/*
* Stream Header is copied to s->temp, and then
* decoded from there. This way if the caller
* gives us only little input at a time, we can
* still keep the Stream Header decoding code
* simple. Similar approach is used in many places
* in this file.
*/
if (!fill_temp(s, b))
return XZ_OK;
/*
* If dec_stream_header() returns
* XZ_UNSUPPORTED_CHECK, it is still possible
* to continue decoding if working in multi-call
* mode. Thus, update s->sequence before calling
* dec_stream_header().
*/
s->sequence = SEQ_BLOCK_START;
ret = dec_stream_header(s);
if (ret != XZ_OK)
return ret;
case SEQ_BLOCK_START:
/* We need one byte of input to continue. */
if (b->in_pos == b->in_size)
return XZ_OK;
/* See if this is the beginning of the Index field. */
if (b->in[b->in_pos] == 0) {
s->in_start = b->in_pos++;
s->sequence = SEQ_INDEX;
break;
}
/*
* Calculate the size of the Block Header and
* prepare to decode it.
*/
s->block_header.size
= ((uint32_t)b->in[b->in_pos] + 1) * 4;
s->temp.size = s->block_header.size;
s->temp.pos = 0;
s->sequence = SEQ_BLOCK_HEADER;
case SEQ_BLOCK_HEADER:
if (!fill_temp(s, b))
return XZ_OK;
ret = dec_block_header(s);
if (ret != XZ_OK)
return ret;
s->sequence = SEQ_BLOCK_UNCOMPRESS;
case SEQ_BLOCK_UNCOMPRESS:
ret = dec_block(s, b);
if (ret != XZ_STREAM_END)
return ret;
s->sequence = SEQ_BLOCK_PADDING;
case SEQ_BLOCK_PADDING:
/*
* Size of Compressed Data + Block Padding
* must be a multiple of four. We don't need
* s->block.compressed for anything else
* anymore, so we use it here to test the size
* of the Block Padding field.
*/
while (s->block.compressed & 3) {
if (b->in_pos == b->in_size)
return XZ_OK;
if (b->in[b->in_pos++] != 0)
return XZ_DATA_ERROR;
++s->block.compressed;
}
s->sequence = SEQ_BLOCK_CHECK;
case SEQ_BLOCK_CHECK:
if (s->check_type == XZ_CHECK_CRC32) {
ret = crc32_validate(s, b);
if (ret != XZ_STREAM_END)
return ret;
}
#ifdef XZ_DEC_ANY_CHECK
else if (!check_skip(s, b)) {
return XZ_OK;
}
#endif
s->sequence = SEQ_BLOCK_START;
break;
case SEQ_INDEX:
ret = dec_index(s, b);
if (ret != XZ_STREAM_END)
return ret;
s->sequence = SEQ_INDEX_PADDING;
case SEQ_INDEX_PADDING:
while ((s->index.size + (b->in_pos - s->in_start))
& 3) {
if (b->in_pos == b->in_size) {
index_update(s, b);
return XZ_OK;
}
if (b->in[b->in_pos++] != 0)
return XZ_DATA_ERROR;
}
/* Finish the CRC32 value and Index size. */
index_update(s, b);
/* Compare the hashes to validate the Index field. */
if (!memeq(&s->block.hash, &s->index.hash,
sizeof(s->block.hash)))
return XZ_DATA_ERROR;
s->sequence = SEQ_INDEX_CRC32;
case SEQ_INDEX_CRC32:
ret = crc32_validate(s, b);
if (ret != XZ_STREAM_END)
return ret;
s->temp.size = STREAM_HEADER_SIZE;
s->sequence = SEQ_STREAM_FOOTER;
case SEQ_STREAM_FOOTER:
if (!fill_temp(s, b))
return XZ_OK;
return dec_stream_footer(s);
}
}
/* Never reached */
}
/*
* xz_dec_run() is a wrapper for dec_main() to handle some special cases in
* multi-call and single-call decoding.
*
* In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we
* are not going to make any progress anymore. This is to prevent the caller
* from calling us infinitely when the input file is truncated or otherwise
* corrupt. Since zlib-style API allows that the caller fills the input buffer
* only when the decoder doesn't produce any new output, we have to be careful
* to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only
* after the second consecutive call to xz_dec_run() that makes no progress.
*
* In single-call mode, if we couldn't decode everything and no error
* occurred, either the input is truncated or the output buffer is too small.
* Since we know that the last input byte never produces any output, we know
* that if all the input was consumed and decoding wasn't finished, the file
* must be corrupt. Otherwise the output buffer has to be too small or the
* file is corrupt in a way that decoding it produces too big output.
*
* If single-call decoding fails, we reset b->in_pos and b->out_pos back to
* their original values. This is because with some filter chains there won't
* be any valid uncompressed data in the output buffer unless the decoding
* actually succeeds (that's the price to pay of using the output buffer as
* the workspace).
*/
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b)
{
size_t in_start;
size_t out_start;
enum xz_ret ret;
if (DEC_IS_SINGLE(s->mode))
xz_dec_reset(s);
in_start = b->in_pos;
out_start = b->out_pos;
ret = dec_main(s, b);
if (DEC_IS_SINGLE(s->mode)) {
if (ret == XZ_OK)
ret = b->in_pos == b->in_size
? XZ_DATA_ERROR : XZ_BUF_ERROR;
if (ret != XZ_STREAM_END) {
b->in_pos = in_start;
b->out_pos = out_start;
}
} else if (ret == XZ_OK && in_start == b->in_pos
&& out_start == b->out_pos) {
if (s->allow_buf_error)
ret = XZ_BUF_ERROR;
s->allow_buf_error = true;
} else {
s->allow_buf_error = false;
}
return ret;
}
XZ_EXTERN struct xz_dec * XZ_FUNC xz_dec_init(
enum xz_mode mode, uint32_t dict_max)
{
struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
if (s == NULL)
return NULL;
s->mode = mode;
#ifdef XZ_DEC_BCJ
s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
if (s->bcj == NULL)
goto error_bcj;
#endif
s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
if (s->lzma2 == NULL)
goto error_lzma2;
xz_dec_reset(s);
return s;
error_lzma2:
#ifdef XZ_DEC_BCJ
xz_dec_bcj_end(s->bcj);
error_bcj:
#endif
kfree(s);
return NULL;
}
XZ_EXTERN void XZ_FUNC xz_dec_reset(struct xz_dec *s)
{
s->sequence = SEQ_STREAM_HEADER;
s->allow_buf_error = false;
s->pos = 0;
s->crc32 = 0;
memzero(&s->block, sizeof(s->block));
memzero(&s->index, sizeof(s->index));
s->temp.pos = 0;
s->temp.size = STREAM_HEADER_SIZE;
}
XZ_EXTERN void XZ_FUNC xz_dec_end(struct xz_dec *s)
{
if (s != NULL) {
xz_dec_lzma2_end(s->lzma2);
#ifdef XZ_DEC_BCJ
xz_dec_bcj_end(s->bcj);
#endif
kfree(s);
}
}

204
src/bled/xz_lzma2.h Normal file
View file

@ -0,0 +1,204 @@
/*
* LZMA2 definitions
*
* Authors: Lasse Collin <lasse.collin@tukaani.org>
* Igor Pavlov <http://7-zip.org/>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_LZMA2_H
#define XZ_LZMA2_H
/* Range coder constants */
#define RC_SHIFT_BITS 8
#define RC_TOP_BITS 24
#define RC_TOP_VALUE (1 << RC_TOP_BITS)
#define RC_BIT_MODEL_TOTAL_BITS 11
#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS)
#define RC_MOVE_BITS 5
/*
* Maximum number of position states. A position state is the lowest pb
* number of bits of the current uncompressed offset. In some places there
* are different sets of probabilities for different position states.
*/
#define POS_STATES_MAX (1 << 4)
/*
* This enum is used to track which LZMA symbols have occurred most recently
* and in which order. This information is used to predict the next symbol.
*
* Symbols:
* - Literal: One 8-bit byte
* - Match: Repeat a chunk of data at some distance
* - Long repeat: Multi-byte match at a recently seen distance
* - Short repeat: One-byte repeat at a recently seen distance
*
* The symbol names are in from STATE_oldest_older_previous. REP means
* either short or long repeated match, and NONLIT means any non-literal.
*/
enum lzma_state {
STATE_LIT_LIT,
STATE_MATCH_LIT_LIT,
STATE_REP_LIT_LIT,
STATE_SHORTREP_LIT_LIT,
STATE_MATCH_LIT,
STATE_REP_LIT,
STATE_SHORTREP_LIT,
STATE_LIT_MATCH,
STATE_LIT_LONGREP,
STATE_LIT_SHORTREP,
STATE_NONLIT_MATCH,
STATE_NONLIT_REP
};
/* Total number of states */
#define STATES 12
/* The lowest 7 states indicate that the previous state was a literal. */
#define LIT_STATES 7
/* Indicate that the latest symbol was a literal. */
static inline void XZ_FUNC lzma_state_literal(enum lzma_state *state)
{
if (*state <= STATE_SHORTREP_LIT_LIT)
*state = STATE_LIT_LIT;
else if (*state <= STATE_LIT_SHORTREP)
*state -= 3;
else
*state -= 6;
}
/* Indicate that the latest symbol was a match. */
static inline void XZ_FUNC lzma_state_match(enum lzma_state *state)
{
*state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
}
/* Indicate that the latest state was a long repeated match. */
static inline void XZ_FUNC lzma_state_long_rep(enum lzma_state *state)
{
*state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
}
/* Indicate that the latest symbol was a short match. */
static inline void XZ_FUNC lzma_state_short_rep(enum lzma_state *state)
{
*state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
}
/* Test if the previous symbol was a literal. */
static inline bool XZ_FUNC lzma_state_is_literal(enum lzma_state state)
{
return state < LIT_STATES;
}
/* Each literal coder is divided in three sections:
* - 0x001-0x0FF: Without match byte
* - 0x101-0x1FF: With match byte; match bit is 0
* - 0x201-0x2FF: With match byte; match bit is 1
*
* Match byte is used when the previous LZMA symbol was something else than
* a literal (that is, it was some kind of match).
*/
#define LITERAL_CODER_SIZE 0x300
/* Maximum number of literal coders */
#define LITERAL_CODERS_MAX (1 << 4)
/* Minimum length of a match is two bytes. */
#define MATCH_LEN_MIN 2
/* Match length is encoded with 4, 5, or 10 bits.
*
* Length Bits
* 2-9 4 = Choice=0 + 3 bits
* 10-17 5 = Choice=1 + Choice2=0 + 3 bits
* 18-273 10 = Choice=1 + Choice2=1 + 8 bits
*/
#define LEN_LOW_BITS 3
#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
#define LEN_MID_BITS 3
#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
#define LEN_HIGH_BITS 8
#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
/*
* Maximum length of a match is 273 which is a result of the encoding
* described above.
*/
#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
/*
* Different sets of probabilities are used for match distances that have
* very short match length: Lengths of 2, 3, and 4 bytes have a separate
* set of probabilities for each length. The matches with longer length
* use a shared set of probabilities.
*/
#define DIST_STATES 4
/*
* Get the index of the appropriate probability array for decoding
* the distance slot.
*/
static inline uint32_t XZ_FUNC lzma_get_dist_state(uint32_t len)
{
return len < DIST_STATES + MATCH_LEN_MIN
? len - MATCH_LEN_MIN : DIST_STATES - 1;
}
/*
* The highest two bits of a 32-bit match distance are encoded using six bits.
* This six-bit value is called a distance slot. This way encoding a 32-bit
* value takes 6-36 bits, larger values taking more bits.
*/
#define DIST_SLOT_BITS 6
#define DIST_SLOTS (1 << DIST_SLOT_BITS)
/* Match distances up to 127 are fully encoded using probabilities. Since
* the highest two bits (distance slot) are always encoded using six bits,
* the distances 0-3 don't need any additional bits to encode, since the
* distance slot itself is the same as the actual distance. DIST_MODEL_START
* indicates the first distance slot where at least one additional bit is
* needed.
*/
#define DIST_MODEL_START 4
/*
* Match distances greater than 127 are encoded in three pieces:
* - distance slot: the highest two bits
* - direct bits: 2-26 bits below the highest two bits
* - alignment bits: four lowest bits
*
* Direct bits don't use any probabilities.
*
* The distance slot value of 14 is for distances 128-191.
*/
#define DIST_MODEL_END 14
/* Distance slots that indicate a distance <= 127. */
#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
/*
* For match distances greater than 127, only the highest two bits and the
* lowest four bits (alignment) is encoded using probabilities.
*/
#define ALIGN_BITS 4
#define ALIGN_SIZE (1 << ALIGN_BITS)
#define ALIGN_MASK (ALIGN_SIZE - 1)
/* Total number of all probability variables */
#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE)
/*
* LZMA remembers the four most recent match distances. Reusing these
* distances tends to take less space than re-encoding the actual
* distance value.
*/
#define REPS 4
#endif

159
src/bled/xz_private.h Normal file
View file

@ -0,0 +1,159 @@
/*
* Private includes and definitions
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_PRIVATE_H
#define XZ_PRIVATE_H
#ifdef __KERNEL__
/* XZ_PREBOOT may be defined only via decompress_unxz.c. */
# ifndef XZ_PREBOOT
# include <linux/slab.h>
# include <linux/vmalloc.h>
# include <linux/string.h>
# define memeq(a, b, size) (memcmp(a, b, size) == 0)
# define memzero(buf, size) memset(buf, 0, size)
# endif
# include <asm/byteorder.h>
# include <asm/unaligned.h>
# define get_le32(p) le32_to_cpup((const uint32_t *)(p))
/* XZ_IGNORE_KCONFIG may be defined only via decompress_unxz.c. */
# ifndef XZ_IGNORE_KCONFIG
# ifdef CONFIG_XZ_DEC_X86
# define XZ_DEC_X86
# endif
# ifdef CONFIG_XZ_DEC_POWERPC
# define XZ_DEC_POWERPC
# endif
# ifdef CONFIG_XZ_DEC_IA64
# define XZ_DEC_IA64
# endif
# ifdef CONFIG_XZ_DEC_ARM
# define XZ_DEC_ARM
# endif
# ifdef CONFIG_XZ_DEC_ARMTHUMB
# define XZ_DEC_ARMTHUMB
# endif
# ifdef CONFIG_XZ_DEC_SPARC
# define XZ_DEC_SPARC
# endif
# endif
# include <linux/xz.h>
#else
/*
* For userspace builds, use a separate header to define the required
* macros and functions. This makes it easier to adapt the code into
* different environments and avoids clutter in the Linux kernel tree.
*/
# include "xz_config.h"
#endif
/* If no specific decoding mode is requested, enable support for all modes. */
#if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \
&& !defined(XZ_DEC_DYNALLOC)
# define XZ_DEC_SINGLE
# define XZ_DEC_PREALLOC
# define XZ_DEC_DYNALLOC
#endif
/*
* The DEC_IS_foo(mode) macros are used in "if" statements. If only some
* of the supported modes are enabled, these macros will evaluate to true or
* false at compile time and thus allow the compiler to omit unneeded code.
*/
#ifdef XZ_DEC_SINGLE
# define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE)
#else
# define DEC_IS_SINGLE(mode) (false)
#endif
#ifdef XZ_DEC_PREALLOC
# define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC)
#else
# define DEC_IS_PREALLOC(mode) (false)
#endif
#ifdef XZ_DEC_DYNALLOC
# define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC)
#else
# define DEC_IS_DYNALLOC(mode) (false)
#endif
#if !defined(XZ_DEC_SINGLE)
# define DEC_IS_MULTI(mode) (true)
#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC)
# define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE)
#else
# define DEC_IS_MULTI(mode) (false)
#endif
/*
* If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
* XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
*/
#ifndef XZ_DEC_BCJ
# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \
|| defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \
|| defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \
|| defined(XZ_DEC_SPARC)
# define XZ_DEC_BCJ
# endif
#endif
/*
* Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used
* before calling xz_dec_lzma2_run().
*/
XZ_EXTERN struct xz_dec_lzma2 * XZ_FUNC xz_dec_lzma2_create(
enum xz_mode mode, uint32_t dict_max);
/*
* Decode the LZMA2 properties (one byte) and reset the decoder. Return
* XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not
* big enough, and XZ_OPTIONS_ERROR if props indicates something that this
* decoder doesn't support.
*/
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_reset(
struct xz_dec_lzma2 *s, uint8_t props);
/* Decode raw LZMA2 stream from b->in to b->out. */
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_lzma2_run(
struct xz_dec_lzma2 *s, struct xz_buf *b);
/* Free the memory allocated for the LZMA2 decoder. */
XZ_EXTERN void XZ_FUNC xz_dec_lzma2_end(struct xz_dec_lzma2 *s);
#ifdef XZ_DEC_BCJ
/*
* Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before
* calling xz_dec_bcj_run().
*/
XZ_EXTERN struct xz_dec_bcj * XZ_FUNC xz_dec_bcj_create(bool single_call);
/*
* Decode the Filter ID of a BCJ filter. This implementation doesn't
* support custom start offsets, so no decoding of Filter Properties
* is needed. Returns XZ_OK if the given Filter ID is supported.
* Otherwise XZ_OPTIONS_ERROR is returned.
*/
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_reset(
struct xz_dec_bcj *s, uint8_t id);
/*
* Decode raw BCJ + LZMA2 stream. This must be used only if there actually is
* a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run()
* must be called directly.
*/
XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_bcj_run(struct xz_dec_bcj *s,
struct xz_dec_lzma2 *lzma2, struct xz_buf *b);
/* Free the memory allocated for the BCJ filters. */
#define xz_dec_bcj_end(s) kfree(s)
#endif
#endif

62
src/bled/xz_stream.h Normal file
View file

@ -0,0 +1,62 @@
/*
* Definitions for handling the .xz file format
*
* Author: Lasse Collin <lasse.collin@tukaani.org>
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef XZ_STREAM_H
#define XZ_STREAM_H
#if defined(__KERNEL__) && !XZ_INTERNAL_CRC32
# include <linux/crc32.h>
# undef crc32
# define xz_crc32(buf, size, crc) \
(~crc32_le(~(uint32_t)(crc), buf, size))
#endif
/*
* See the .xz file format specification at
* http://tukaani.org/xz/xz-file-format.txt
* to understand the container format.
*/
#define STREAM_HEADER_SIZE 12
#define HEADER_MAGIC "\xFD" "7zXZ"
#define HEADER_MAGIC_SIZE 6
#define FOOTER_MAGIC "YZ"
#define FOOTER_MAGIC_SIZE 2
/*
* Variable-length integer can hold a 63-bit unsigned integer or a special
* value indicating that the value is unknown.
*
* Experimental: vli_type can be defined to uint32_t to save a few bytes
* in code size (no effect on speed). Doing so limits the uncompressed and
* compressed size of the file to less than 256 MiB and may also weaken
* error detection slightly.
*/
typedef uint64_t vli_type;
#define VLI_MAX ((vli_type)-1 / 2)
#define VLI_UNKNOWN ((vli_type)-1)
/* Maximum encoded size of a VLI */
#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
/* Integrity Check types */
enum xz_check {
XZ_CHECK_NONE = 0,
XZ_CHECK_CRC32 = 1,
XZ_CHECK_CRC64 = 4,
XZ_CHECK_SHA256 = 10
};
/* Maximum possible Check ID */
#define XZ_CHECK_MAX 15
#endif

View file

@ -45,11 +45,12 @@
#include "format.h"
#include "badblocks.h"
#include "localization.h"
#include "bled/bled.h"
/*
* Globals
*/
DWORD FormatStatus;
DWORD FormatStatus, LastRefresh;
badblocks_report report;
static float format_percent = 0.0f;
static int task_number = 0;
@ -374,7 +375,7 @@ static DWORD GetFATSizeSectors(DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPer
static BOOL FormatFAT32(DWORD DriveIndex)
{
BOOL r = FALSE;
DWORD i, LastRefresh = 0;
DWORD i;
HANDLE hLogicalVolume;
DWORD cbRet;
DISK_GEOMETRY dgDrive;
@ -412,6 +413,7 @@ static BOOL FormatFAT32(DWORD DriveIndex)
ULONGLONG FatNeeded, ClusterCount;
PrintStatus(0, TRUE, MSG_222, "Large FAT32");
LastRefresh = 0;
VolumeId = GetVolumeID();
// Open the drive and lock it
@ -1256,6 +1258,16 @@ DWORD WINAPI CloseFormatPromptThread(LPVOID param) {
ExitThread(0);
}
void update_progress(const uint64_t processed_bytes)
{
if (GetTickCount() > LastRefresh + 25) {
LastRefresh = GetTickCount();
format_percent = (100.0f*processed_bytes)/(1.0f*iso_report.projected_size);
PrintStatus(0, FALSE, MSG_261, format_percent);
UpdateProgress(OP_FORMAT, format_percent);
}
}
/*
* Standalone thread for the formatting operation
* According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562.aspx
@ -1273,7 +1285,7 @@ DWORD WINAPI FormatThread(void* param)
int i, r, pt, bt, fs, dt;
BOOL s, ret, use_large_fat32, add_uefi_togo;
const DWORD SectorSize = SelectedDrive.Geometry.BytesPerSector;
DWORD rSize, wSize, BufSize, LastRefresh = 0, DriveIndex = (DWORD)(uintptr_t)param;
DWORD rSize, wSize, BufSize, DriveIndex = (DWORD)(uintptr_t)param;
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
HANDLE hSourceImage = INVALID_HANDLE_VALUE;
@ -1454,63 +1466,71 @@ DWORD WINAPI FormatThread(void* param)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
goto out;
}
LastRefresh = 0;
uprintf("Writing Image...");
// Our buffer size must be a multiple of the sector size
BufSize = ((DD_BUFFER_SIZE + SectorSize - 1) / SectorSize) * SectorSize;
buffer = (uint8_t*)malloc(BufSize + SectorSize); // +1 sector for align
if (buffer == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
uprintf("could not allocate DD buffer");
goto out;
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx does buffer sector alignment
aligned_buffer = ((void *) ((((uintptr_t)(buffer)) + (SectorSize) - 1) & (~(((uintptr_t)(SectorSize)) - 1))));
// Don't bother trying for something clever, using double buffering overlapped and whatnot:
// With Windows' default optimizations, sync read + sync write for sequential operations
// will be as fast, if not faster, than whatever async scheme you can come up with.
for (wb = 0, wSize = 0; ; wb += wSize) {
s = ReadFile(hSourceImage, aligned_buffer, BufSize, &rSize, NULL);
if (!s) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
uprintf("read error: %s", WindowsErrorString());
if (iso_report.compression_type != BLED_COMPRESSION_NONE) {
uprintf("Writing Compressed Image...");
bled_init(_uprintf, update_progress);
bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, iso_report.compression_type);
bled_exit();
} else {
uprintf("Writing Image...");
// Our buffer size must be a multiple of the sector size
BufSize = ((DD_BUFFER_SIZE + SectorSize - 1) / SectorSize) * SectorSize;
buffer = (uint8_t*)malloc(BufSize + SectorSize); // +1 sector for align
if (buffer == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
uprintf("could not allocate DD buffer");
goto out;
}
if (rSize == 0)
break;
if (GetTickCount() > LastRefresh + 25) {
LastRefresh = GetTickCount();
format_percent = (100.0f*wb)/(1.0f*iso_report.projected_size);
PrintStatus(0, FALSE, MSG_261, format_percent);
UpdateProgress(OP_FORMAT, format_percent);
}
// Don't overflow our projected size (mostly for VHDs)
if (wb + rSize > iso_report.projected_size) {
rSize = (DWORD)(iso_report.projected_size - wb);
}
// WriteFile fails unless the size is a multiple of sector size
if (rSize % SectorSize != 0)
rSize = ((rSize + SectorSize -1) / SectorSize) * SectorSize;
for (i=0; i<WRITE_RETRIES; i++) {
CHECK_FOR_USER_CANCEL;
s = WriteFile(hPhysicalDrive, aligned_buffer, rSize, &wSize, NULL);
if ((s) && (wSize == rSize))
break;
if (s)
uprintf("write error: Wrote %d bytes, expected %d bytes\n", wSize, rSize);
else
uprintf("write error: %s", WindowsErrorString());
if (i < WRITE_RETRIES-1) {
li.QuadPart = wb;
SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN);
uprintf(" RETRYING...\n");
} else {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx does buffer sector alignment
aligned_buffer = ((void *) ((((uintptr_t)(buffer)) + (SectorSize) - 1) & (~(((uintptr_t)(SectorSize)) - 1))));
// Don't bother trying for something clever, using double buffering overlapped and whatnot:
// With Windows' default optimizations, sync read + sync write for sequential operations
// will be as fast, if not faster, than whatever async scheme you can come up with.
for (wb = 0, wSize = 0; ; wb += wSize) {
s = ReadFile(hSourceImage, aligned_buffer, BufSize, &rSize, NULL);
if (!s) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
uprintf("read error: %s", WindowsErrorString());
goto out;
}
if (rSize == 0)
break;
if (GetTickCount() > LastRefresh + 25) {
LastRefresh = GetTickCount();
format_percent = (100.0f*wb)/(1.0f*iso_report.projected_size);
PrintStatus(0, FALSE, MSG_261, format_percent);
UpdateProgress(OP_FORMAT, format_percent);
}
// Don't overflow our projected size (mostly for VHDs)
if (wb + rSize > iso_report.projected_size) {
rSize = (DWORD)(iso_report.projected_size - wb);
}
// WriteFile fails unless the size is a multiple of sector size
if (rSize % SectorSize != 0)
rSize = ((rSize + SectorSize -1) / SectorSize) * SectorSize;
for (i=0; i<WRITE_RETRIES; i++) {
CHECK_FOR_USER_CANCEL;
s = WriteFile(hPhysicalDrive, aligned_buffer, rSize, &wSize, NULL);
if ((s) && (wSize == rSize))
break;
if (s)
uprintf("write error: Wrote %d bytes, expected %d bytes\n", wSize, rSize);
else
uprintf("write error: %s", WindowsErrorString());
if (i < WRITE_RETRIES-1) {
li.QuadPart = wb;
SetFilePointerEx(hPhysicalDrive, li, NULL, FILE_BEGIN);
uprintf(" RETRYING...\n");
} else {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out;
}
}
if (i >= WRITE_RETRIES) goto out;
}
if (i >= WRITE_RETRIES) goto out;
}
// If the image contains a partition we might be able to access, try to re-mount it
@ -1739,7 +1759,7 @@ out:
DWORD WINAPI SaveImageThread(void* param)
{
BOOL s;
DWORD rSize, wSize, LastRefresh = 0, DriveIndex = (DWORD)(uintptr_t)param;
DWORD rSize, wSize, DriveIndex = (DWORD)(uintptr_t)param;
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
HANDLE hDestImage = INVALID_HANDLE_VALUE;
LARGE_INTEGER li;
@ -1748,6 +1768,7 @@ DWORD WINAPI SaveImageThread(void* param)
int i;
PrintStatus(0, TRUE, MSG_225);
LastRefresh = 0;
hPhysicalDrive = GetPhysicalHandle(DriveIndex, FALSE, TRUE);
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;

View file

@ -3,7 +3,7 @@
* Compensating for what Microsoft should have done a long long time ago.
* Also see http://utf8everywhere.org/
*
* Copyright © 2010-2013 Pete Batard <pete@akeo.ie>
* Copyright © 2010-2014 Pete Batard <pete@akeo.ie>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,6 +28,7 @@
#include <shlwapi.h>
#include <setupapi.h>
#include <direct.h>
#include <io.h>
#pragma once
#if defined(_MSC_VER)
@ -721,6 +722,15 @@ static __inline FILE* fopenU(const char* filename, const char* mode)
return ret;
}
static __inline int _openU(const char *filename, int oflag , int pmode)
{
int ret = -1;
wconvert(filename);
ret = _wopen(wfilename, oflag, pmode);
wfree(filename);
return ret;
}
// returned UTF-8 string must be freed
static __inline char* getenvU(const char* varname)
{

View file

@ -0,0 +1,16 @@
/* Workaround stdbool.h for WDK compilers - Public Domain */
#include <windows.h>
#ifndef _STDBOOL
#define _STDBOOL
#ifndef __cplusplus
#define bool BOOL
#define false FALSE
#define true TRUE
#endif
#endif

View file

@ -41,6 +41,7 @@
#include "drive.h"
#include "registry.h"
#include "localization.h"
#include "bled/bled.h"
/* Redefinitions for WDK and MinGW */
// TODO: these would be better in a 'missing.h' file
@ -1637,6 +1638,7 @@ void SetBoot(int fs, int bt)
/*
* Main dialog callback
*/
extern int uncompress(const char* src, const char* dst, int type);
static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
DRAWITEMSTRUCT* pDI;

View file

@ -240,6 +240,7 @@ typedef struct {
char cfg_path[128]; /* path to the ISO's isolinux.cfg */
char reactos_path[128]; /* path to the ISO's freeldr.sys or setupldr.sys */
uint64_t projected_size;
uint64_t src_size;
// TODO: use a bitmask and #define tests for the following
uint8_t winpe;
BOOL has_4GB_file;
@ -257,6 +258,7 @@ typedef struct {
BOOL has_kolibrios;
BOOL uses_minint;
BOOL is_bootable_img;
BOOL compression_type;
BOOL is_vhd;
uint16_t sl_version; // Syslinux/Isolinux version
char sl_version_str[12];

View file

@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 1.5.0.562"
CAPTION "Rufus 1.5.0.563"
FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,291,50,14
@ -164,7 +164,7 @@ END
IDD_DIALOG_XP DIALOGEX 12, 12, 242, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 1.5.0.562"
CAPTION "Rufus 1.5.0.563"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,291,50,14
@ -297,7 +297,7 @@ END
IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 1.5.0.562"
CAPTION "Rufus 1.5.0.563"
FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,291,50,14
@ -437,7 +437,7 @@ END
IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 1.5.0.562"
CAPTION "Rufus 1.5.0.563"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,291,50,14
@ -703,8 +703,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,5,0,562
PRODUCTVERSION 1,5,0,562
FILEVERSION 1,5,0,563
PRODUCTVERSION 1,5,0,563
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -721,13 +721,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.5.0.562"
VALUE "FileVersion", "1.5.0.563"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "1.5.0.562"
VALUE "ProductVersion", "1.5.0.563"
END
END
BLOCK "VarFileInfo"

View file

@ -27,6 +27,7 @@
#include "msapi_utf8.h"
#include "drive.h"
#include "registry.h"
#include "bled/bled.h"
#if defined(_MSC_VER)
#define bswap_uint64 _byteswap_uint64
@ -211,6 +212,43 @@ out:
return r;
}
typedef struct {
const char* ext;
bled_compression_type type;
} comp_assoc;
static comp_assoc blah[] = {
{ ".xz", BLED_COMPRESSION_XZ },
{ ".gz", BLED_COMPRESSION_GZIP },
{ ".lzma", BLED_COMPRESSION_LZMA },
{ ".bz2", BLED_COMPRESSION_BZIP2 },
{ ".Z", BLED_COMPRESSION_LZW },
};
// For now we consider that an image that matches a known extension is bootable
// TODO: uncompress header and check for bootable flag
BOOL IsCompressedBootableImage(const char* path)
{
char* p;
int i;
iso_report.compression_type = BLED_COMPRESSION_NONE;
for (p = (char*)&path[strlen(path)-1]; (*p != '.') && (p != path); p--);
if (p == path)
return FALSE;
for (i = 0; i<ARRAYSIZE(blah); i++) {
if (strcmp(p, blah[i].ext) == 0) {
iso_report.compression_type = blah[i].type;
return TRUE;
}
}
return FALSE;
}
BOOL IsHDImage(const char* path)
{
HANDLE handle = INVALID_HANDLE_VALUE;
@ -227,7 +265,10 @@ BOOL IsHDImage(const char* path)
uprintf("Could not open image '%s'", path);
goto out;
}
iso_report.is_bootable_img = AnalyzeMBR(handle, "Image");
iso_report.is_bootable_img = IsCompressedBootableImage(path);
if (iso_report.compression_type == BLED_COMPRESSION_NONE)
iso_report.is_bootable_img = AnalyzeMBR(handle, "Image");
if (!GetFileSizeEx(handle, &liImageSize)) {
uprintf("Could not get image size: %s", WindowsErrorString());
@ -236,7 +277,7 @@ BOOL IsHDImage(const char* path)
iso_report.projected_size = (uint64_t)liImageSize.QuadPart;
size = sizeof(vhd_footer);
if (iso_report.projected_size >= (512 + size)) {
if ((iso_report.compression_type == BLED_COMPRESSION_NONE) && (iso_report.projected_size >= (512 + size))) {
footer = (vhd_footer*)malloc(size);
ptr.QuadPart = iso_report.projected_size - size;
if ( (footer == NULL) || (!SetFilePointerEx(handle, ptr, NULL, FILE_BEGIN)) ||

View file

@ -10,8 +10,23 @@ set PWD=%~dp0
set ARCH_DIR=%_BUILDARCH%
if /I Test%_BUILDARCH%==Testx86 set ARCH_DIR=i386
::# Bled Library
cd src\bled
if EXIST Makefile ren Makefile Makefile.hide
copy .msvc\bled_sources sources >NUL 2>&1
@echo on
%BUILD_CMD%
@echo off
if errorlevel 1 goto builderror
copy obj%BUILD_ALT_DIR%\%ARCH_DIR%\bled.lib . >NUL 2>&1
if EXIST Makefile.hide ren Makefile.hide Makefile
if EXIST sources del sources >NUL 2>&1
::# MS-SYS Library
cd src\ms-sys
cd ..\ms-sys
if EXIST Makefile ren Makefile Makefile.hide
copy .msvc\ms-sys_sources sources >NUL 2>&1