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:
parent
3f0e71f3ba
commit
7599715ae6
56 changed files with 10020 additions and 89 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -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
6
.gitignore
vendored
|
@ -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
19
configure
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
11
rufus.sln
11
rufus.sln
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
176
src/bled/.msvc/bled.vcxproj
Normal 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>
|
114
src/bled/.msvc/bled.vcxproj.filters
Normal file
114
src/bled/.msvc/bled.vcxproj.filters
Normal 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>
|
20
src/bled/.msvc/bled_sources
Normal file
20
src/bled/.msvc/bled_sources
Normal 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
8
src/bled/Makefile.am
Normal 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
642
src/bled/Makefile.in
Normal 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
262
src/bled/bb_archive.h
Normal 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
139
src/bled/bled.c
Normal 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
41
src/bled/bled.h
Normal 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
257
src/bled/crc32.c
Normal 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
15
src/bled/data_align.c
Normal 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
213
src/bled/data_extract_all.c
Normal 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
12
src/bled/data_skip.c
Normal 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);
|
||||
}
|
829
src/bled/decompress_bunzip2.c
Normal file
829
src/bled/decompress_bunzip2.c
Normal 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
1271
src/bled/decompress_gunzip.c
Normal file
File diff suppressed because it is too large
Load diff
315
src/bled/decompress_uncompress.c
Normal file
315
src/bled/decompress_uncompress.c
Normal 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;
|
||||
}
|
468
src/bled/decompress_unlzma.c
Normal file
468
src/bled/decompress_unlzma.c
Normal 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
131
src/bled/decompress_unxz.c
Normal 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;
|
||||
}
|
17
src/bled/filter_accept_all.c
Normal file
17
src/bled/filter_accept_all.c
Normal 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;
|
||||
}
|
19
src/bled/filter_accept_list.c
Normal file
19
src/bled/filter_accept_list.c
Normal 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;
|
||||
}
|
38
src/bled/filter_accept_reject_list.c
Normal file
38
src/bled/filter_accept_reject_list.c
Normal 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;
|
||||
}
|
54
src/bled/find_list_entry.c
Normal file
54
src/bled/find_list_entry.c
Normal 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
12
src/bled/header_list.c
Normal 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
10
src/bled/header_skip.c
Normal 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)
|
||||
{
|
||||
}
|
69
src/bled/header_verbose_list.c
Normal file
69
src/bled/header_verbose_list.c
Normal 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
22
src/bled/init_handle.c
Normal 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
233
src/bled/libbb.h
Normal 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
351
src/bled/open_transformer.c
Normal 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
621
src/bled/platform.h
Normal 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
19
src/bled/seek_by_jump.c
Normal 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
16
src/bled/seek_by_read.c
Normal 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
282
src/bled/xz.h
Normal 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
123
src/bled/xz_config.h
Normal 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
580
src/bled/xz_dec_bcj.c
Normal 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
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
822
src/bled/xz_dec_stream.c
Normal 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
204
src/bled/xz_lzma2.h
Normal 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
159
src/bled/xz_private.h
Normal 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
62
src/bled/xz_stream.h
Normal 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
|
131
src/format.c
131
src/format.c
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
16
src/msvc-missing/stdbool.h
Normal file
16
src/msvc-missing/stdbool.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
16
src/rufus.rc
16
src/rufus.rc
|
@ -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"
|
||||
|
|
45
src/vhd.c
45
src/vhd.c
|
@ -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)) ||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue