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 | *.txt           eol=crlf | ||||||
| *.loc           eol=crlf | *.loc           eol=crlf | ||||||
| *.sh            export-ignore | *.sh            export-ignore | ||||||
|  | *.cmd           export-ignore | ||||||
| .gitattributes  export-ignore | .gitattributes  export-ignore | ||||||
| .gitignore      export-ignore | .gitignore      export-ignore | ||||||
| *.creole        export-ignore | *.creole        export-ignore | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,4 @@ | ||||||
|  | *.a | ||||||
| *.aps | *.aps | ||||||
| *.dep | *.dep | ||||||
| *.exe | *.exe | ||||||
|  | @ -16,11 +17,16 @@ | ||||||
| *.pdb | *.pdb | ||||||
| *.plg | *.plg | ||||||
| *.res | *.res | ||||||
|  | *.sdf | ||||||
| *.suo | *.suo | ||||||
| *.swp | *.swp | ||||||
|  | *.tlog | ||||||
| *.user | *.user | ||||||
|  | *.opensdf | ||||||
|  | *.o_manifest | ||||||
| .deps | .deps | ||||||
| .libs | .libs | ||||||
|  | Makefile | ||||||
| x86_32 | x86_32 | ||||||
| x86_64 | x86_64 | ||||||
| autom4te.cache | 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/Makefile" | ||||||
| 
 | 
 | ||||||
| ac_config_files="$ac_config_files src/ms-sys/Makefile" | ac_config_files="$ac_config_files src/bled/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/libcdio/iso9660/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 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 | cat >confcache <<\_ACEOF | ||||||
| # This file is a shell script that caches the results of configure | # This file is a shell script that caches the results of configure | ||||||
| # tests run on this system so they can be shared between configure | # tests run on this system so they can be shared between configure | ||||||
|  | @ -4538,13 +4540,14 @@ do | ||||||
|   case $ac_config_target in |   case $ac_config_target in | ||||||
|     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; |     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; | ||||||
|     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; |     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; | ||||||
|     "src/ms-sys/Makefile") CONFIG_FILES="$CONFIG_FILES src/ms-sys/Makefile" ;; |     "src/bled/Makefile") CONFIG_FILES="$CONFIG_FILES src/bled/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/libcdio/iso9660/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/iso9660/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/udf/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/udf/Makefile" ;; | ||||||
|     "src/libcdio/driver/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/driver/Makefile" ;; |     "src/libcdio/driver/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcdio/driver/Makefile" ;; | ||||||
|     "res/localization/Makefile") CONFIG_FILES="$CONFIG_FILES res/localization/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;; |   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; | ||||||
|   esac |   esac | ||||||
|  |  | ||||||
|  | @ -63,11 +63,12 @@ AC_SUBST([SUFFIX]) | ||||||
| 
 | 
 | ||||||
| AC_CONFIG_FILES([Makefile]) | AC_CONFIG_FILES([Makefile]) | ||||||
| AC_CONFIG_FILES([src/Makefile]) | AC_CONFIG_FILES([src/Makefile]) | ||||||
| AC_CONFIG_FILES([src/ms-sys/Makefile]) | AC_CONFIG_FILES([src/bled/Makefile]) | ||||||
| AC_CONFIG_FILES([src/syslinux/libfat/Makefile]) |  | ||||||
| AC_CONFIG_FILES([src/syslinux/libinstaller/Makefile]) |  | ||||||
| AC_CONFIG_FILES([src/libcdio/iso9660/Makefile]) | AC_CONFIG_FILES([src/libcdio/iso9660/Makefile]) | ||||||
| AC_CONFIG_FILES([src/libcdio/udf/Makefile]) | AC_CONFIG_FILES([src/libcdio/udf/Makefile]) | ||||||
| AC_CONFIG_FILES([src/libcdio/driver/Makefile]) | AC_CONFIG_FILES([src/libcdio/driver/Makefile]) | ||||||
| AC_CONFIG_FILES([res/localization/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 | AC_OUTPUT | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								rufus.sln
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								rufus.sln
									
										
									
									
									
								
							|  | @ -1,4 +1,3 @@ | ||||||
| 
 |  | ||||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||||
| # Visual Studio 2013 | # Visual Studio 2013 | ||||||
| VisualStudioVersion = 12.0.31101.0 | VisualStudioVersion = 12.0.31101.0 | ||||||
|  | @ -19,6 +18,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcdio-driver", "src\libcd | ||||||
| EndProject | EndProject | ||||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "src\getopt\.msvc\getopt.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "src\getopt\.msvc\getopt.vcxproj", "{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}" | ||||||
| EndProject | EndProject | ||||||
|  | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bled", "src\bled\.msvc\bled.vcxproj", "{FB6D52D4-A2F8-C358-DB85-BBCAECFDDD7D}" | ||||||
|  | EndProject | ||||||
| Global | Global | ||||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||||
| 		Debug|Win32 = Debug|Win32 | 		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|Win32.Build.0 = Release|Win32 | ||||||
| 		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 | 		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.ActiveCfg = Release|x64 | ||||||
| 		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|x64.Build.0 = Release|x64 | 		{AE83E1B4-CE06-47EE-B7A3-C3A1D7C2D71E}.Release|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 | 	EndGlobalSection | ||||||
| 	GlobalSection(SolutionProperties) = preSolution | 	GlobalSection(SolutionProperties) = preSolution | ||||||
| 		HideSolutionNode = FALSE | 		HideSolutionNode = FALSE | ||||||
|  |  | ||||||
|  | @ -199,12 +199,12 @@ | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\badblocks.h" /> |     <ClInclude Include="..\badblocks.h" /> | ||||||
|  |     <ClInclude Include="..\bled\bled.h" /> | ||||||
|     <ClInclude Include="..\drive.h" /> |     <ClInclude Include="..\drive.h" /> | ||||||
|     <ClInclude Include="..\format.h" /> |     <ClInclude Include="..\format.h" /> | ||||||
|     <ClInclude Include="..\hdd_vs_ufd.h" /> |     <ClInclude Include="..\hdd_vs_ufd.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\cdio.h" /> |     <ClInclude Include="..\libcdio\cdio\cdio.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> |     <ClInclude Include="..\libcdio\cdio\iso9660.h" /> | ||||||
|     <ClInclude Include="..\libcdio\cdio\logging.h" /> |  | ||||||
|     <ClInclude Include="..\libcdio\cdio\udf.h" /> |     <ClInclude Include="..\libcdio\cdio\udf.h" /> | ||||||
|     <ClInclude Include="..\localization.h" /> |     <ClInclude Include="..\localization.h" /> | ||||||
|     <ClInclude Include="..\localization_data.h" /> |     <ClInclude Include="..\localization_data.h" /> | ||||||
|  | @ -231,6 +231,9 @@ | ||||||
|     <ResourceCompile Include="..\rufus.rc" /> |     <ResourceCompile Include="..\rufus.rc" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <ProjectReference Include="..\bled\.msvc\bled.vcxproj"> | ||||||
|  |       <Project>{fb6d52d4-a2f8-c358-db85-bbcaecfddd7d}</Project> | ||||||
|  |     </ProjectReference> | ||||||
|     <ProjectReference Include="..\getopt\.msvc\getopt.vcxproj"> |     <ProjectReference Include="..\getopt\.msvc\getopt.vcxproj"> | ||||||
|       <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project> |       <Project>{ae83e1b4-ce06-47ee-b7a3-c3a1d7c2d71e}</Project> | ||||||
|     </ProjectReference> |     </ProjectReference> | ||||||
|  |  | ||||||
|  | @ -98,9 +98,6 @@ | ||||||
|     <ClInclude Include="..\libcdio\cdio\cdio.h"> |     <ClInclude Include="..\libcdio\cdio\cdio.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="..\libcdio\cdio\logging.h"> |  | ||||||
|       <Filter>Header Files</Filter> |  | ||||||
|     </ClInclude> |  | ||||||
|     <ClInclude Include="..\libcdio\cdio\iso9660.h"> |     <ClInclude Include="..\libcdio\cdio\iso9660.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  | @ -128,6 +125,9 @@ | ||||||
|     <ClInclude Include="..\usb.h"> |     <ClInclude Include="..\usb.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\bled\bled.h"> | ||||||
|  |       <Filter>Header Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="..\..\res\rufus.ico"> |     <None Include="..\..\res\rufus.ico"> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ TARGETTYPE=PROGRAM | ||||||
| UMTYPE=windows | UMTYPE=windows | ||||||
| UMENTRY=winmain | 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 | C_DEFINES = $(C_DEFINES) /DDDKBUILD /DUNICODE /D_UNICODE /DRUFUS_LOC /DISOLATION_AWARE_ENABLED | ||||||
| 
 | 
 | ||||||
| !IFNDEF MSC_WARNING_LEVEL | !IFNDEF MSC_WARNING_LEVEL | ||||||
|  | @ -19,6 +19,7 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ | ||||||
|            $(SDK_LIB_PATH)\shell32.lib \ |            $(SDK_LIB_PATH)\shell32.lib \ | ||||||
|            $(SDK_LIB_PATH)\wininet.lib \ |            $(SDK_LIB_PATH)\wininet.lib \ | ||||||
|            $(SDK_LIB_PATH)\shlwapi.lib \ |            $(SDK_LIB_PATH)\shlwapi.lib \ | ||||||
|  |            .\bled\bled.lib \ | ||||||
|            .\ms-sys\ms-sys.lib \ |            .\ms-sys\ms-sys.lib \ | ||||||
|            .\syslinux\libfat\libfat.lib \ |            .\syslinux\libfat\libfat.lib \ | ||||||
|            .\syslinux\libinstaller\libinstaller.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 | 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_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_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) | ||||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | 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 | 	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-stdfn.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
 | ||||||
| 	rufus-rufus.$(OBJEXT) | 	rufus-rufus.$(OBJEXT) | ||||||
| rufus_OBJECTS = $(am_rufus_OBJECTS) | 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 \
 | 	syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
 | ||||||
| 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a \
 | 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a \
 | ||||||
| 	libcdio/driver/libdriver.a | 	libcdio/driver/libdriver.a | ||||||
|  | @ -263,7 +263,7 @@ target_alias = @target_alias@ | ||||||
| top_build_prefix = @top_build_prefix@ | top_build_prefix = @top_build_prefix@ | ||||||
| top_builddir = @top_builddir@ | top_builddir = @top_builddir@ | ||||||
| top_srcdir = @top_srcdir@ | 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_0 = @echo "  RC     $@";$(WINDRES) | ||||||
| AM_V_WINDRES_1 = $(WINDRES) | AM_V_WINDRES_1 = $(WINDRES) | ||||||
| AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY)) | 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_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_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) | ||||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | 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 | 	libcdio/iso9660/libiso9660.a libcdio/udf/libudf.a libcdio/driver/libdriver.a -lsetupapi -lole32 -lgdi32 -lwininet -lshlwapi | ||||||
| 
 | 
 | ||||||
| all: all-recursive | 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 "format.h" | ||||||
| #include "badblocks.h" | #include "badblocks.h" | ||||||
| #include "localization.h" | #include "localization.h" | ||||||
|  | #include "bled/bled.h" | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Globals |  * Globals | ||||||
|  */ |  */ | ||||||
| DWORD FormatStatus; | DWORD FormatStatus, LastRefresh; | ||||||
| badblocks_report report; | badblocks_report report; | ||||||
| static float format_percent = 0.0f; | static float format_percent = 0.0f; | ||||||
| static int task_number = 0; | static int task_number = 0; | ||||||
|  | @ -374,7 +375,7 @@ static DWORD GetFATSizeSectors(DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPer | ||||||
| static BOOL FormatFAT32(DWORD DriveIndex) | static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	DWORD i, LastRefresh = 0; | 	DWORD i; | ||||||
| 	HANDLE hLogicalVolume; | 	HANDLE hLogicalVolume; | ||||||
| 	DWORD cbRet; | 	DWORD cbRet; | ||||||
| 	DISK_GEOMETRY dgDrive; | 	DISK_GEOMETRY dgDrive; | ||||||
|  | @ -412,6 +413,7 @@ static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| 	ULONGLONG FatNeeded, ClusterCount; | 	ULONGLONG FatNeeded, ClusterCount; | ||||||
| 
 | 
 | ||||||
| 	PrintStatus(0, TRUE, MSG_222, "Large FAT32"); | 	PrintStatus(0, TRUE, MSG_222, "Large FAT32"); | ||||||
|  | 	LastRefresh = 0; | ||||||
| 	VolumeId = GetVolumeID(); | 	VolumeId = GetVolumeID(); | ||||||
| 
 | 
 | ||||||
| 	// Open the drive and lock it
 | 	// Open the drive and lock it
 | ||||||
|  | @ -1256,6 +1258,16 @@ DWORD WINAPI CloseFormatPromptThread(LPVOID param) { | ||||||
| 	ExitThread(0); | 	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 |  * Standalone thread for the formatting operation | ||||||
|  * According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562.aspx
 |  * 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; | 	int i, r, pt, bt, fs, dt; | ||||||
| 	BOOL s, ret, use_large_fat32, add_uefi_togo; | 	BOOL s, ret, use_large_fat32, add_uefi_togo; | ||||||
| 	const DWORD SectorSize = SelectedDrive.Geometry.BytesPerSector; | 	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 hPhysicalDrive = INVALID_HANDLE_VALUE; | ||||||
| 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; | 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; | ||||||
| 	HANDLE hSourceImage = 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; | 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | 		LastRefresh = 0; | ||||||
| 
 | 
 | ||||||
| 		uprintf("Writing Image..."); | 		if (iso_report.compression_type != BLED_COMPRESSION_NONE) { | ||||||
| 		// Our buffer size must be a multiple of the sector size
 | 			uprintf("Writing Compressed Image..."); | ||||||
| 		BufSize = ((DD_BUFFER_SIZE + SectorSize - 1) / SectorSize) * SectorSize; | 			bled_init(_uprintf, update_progress); | ||||||
| 		buffer = (uint8_t*)malloc(BufSize + SectorSize);	// +1 sector for align
 | 			bled_uncompress_with_handles(hSourceImage, hPhysicalDrive, iso_report.compression_type); | ||||||
| 		if (buffer == NULL) { | 			bled_exit(); | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; | 		} else { | ||||||
| 			uprintf("could not allocate DD buffer"); | 			uprintf("Writing Image..."); | ||||||
| 			goto out; | 			// Our buffer size must be a multiple of the sector size
 | ||||||
| 		} | 			BufSize = ((DD_BUFFER_SIZE + SectorSize - 1) / SectorSize) * SectorSize; | ||||||
| 		// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx does buffer sector alignment
 | 			buffer = (uint8_t*)malloc(BufSize + SectorSize);	// +1 sector for align
 | ||||||
| 		aligned_buffer = ((void *) ((((uintptr_t)(buffer)) + (SectorSize) - 1) & (~(((uintptr_t)(SectorSize)) - 1)))); | 			if (buffer == NULL) { | ||||||
| 
 | 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY; | ||||||
| 		// Don't bother trying for something clever, using double buffering overlapped and whatnot:
 | 				uprintf("could not allocate DD buffer"); | ||||||
| 		// 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; | 				goto out; | ||||||
| 			} | 			} | ||||||
| 			if (rSize == 0) | 			// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx does buffer sector alignment
 | ||||||
| 				break; | 			aligned_buffer = ((void *) ((((uintptr_t)(buffer)) + (SectorSize) - 1) & (~(((uintptr_t)(SectorSize)) - 1)))); | ||||||
| 			if (GetTickCount() > LastRefresh + 25) { | 
 | ||||||
| 				LastRefresh = GetTickCount(); | 			// Don't bother trying for something clever, using double buffering overlapped and whatnot:
 | ||||||
| 				format_percent = (100.0f*wb)/(1.0f*iso_report.projected_size); | 			// With Windows' default optimizations, sync read + sync write for sequential operations
 | ||||||
| 				PrintStatus(0, FALSE, MSG_261, format_percent); | 			// will be as fast, if not faster, than whatever async scheme you can come up with.
 | ||||||
| 				UpdateProgress(OP_FORMAT, format_percent); | 			for (wb = 0, wSize = 0; ; wb += wSize) { | ||||||
| 			} | 				s = ReadFile(hSourceImage, aligned_buffer, BufSize, &rSize, NULL); | ||||||
| 			// Don't overflow our projected size (mostly for VHDs)
 | 				if (!s) { | ||||||
| 			if (wb + rSize > iso_report.projected_size) { | 					FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; | ||||||
| 				rSize = (DWORD)(iso_report.projected_size - wb); | 					uprintf("read error: %s", WindowsErrorString()); | ||||||
| 			} |  | ||||||
| 			// 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; | 					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
 | 		// 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) | DWORD WINAPI SaveImageThread(void* param) | ||||||
| { | { | ||||||
| 	BOOL s; | 	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 hPhysicalDrive = INVALID_HANDLE_VALUE; | ||||||
| 	HANDLE hDestImage = INVALID_HANDLE_VALUE; | 	HANDLE hDestImage = INVALID_HANDLE_VALUE; | ||||||
| 	LARGE_INTEGER li; | 	LARGE_INTEGER li; | ||||||
|  | @ -1748,6 +1768,7 @@ DWORD WINAPI SaveImageThread(void* param) | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	PrintStatus(0, TRUE, MSG_225); | 	PrintStatus(0, TRUE, MSG_225); | ||||||
|  | 	LastRefresh = 0; | ||||||
| 	hPhysicalDrive = GetPhysicalHandle(DriveIndex, FALSE, TRUE); | 	hPhysicalDrive = GetPhysicalHandle(DriveIndex, FALSE, TRUE); | ||||||
| 	if (hPhysicalDrive == INVALID_HANDLE_VALUE) { | 	if (hPhysicalDrive == INVALID_HANDLE_VALUE) { | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | 		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. |  * Compensating for what Microsoft should have done a long long time ago. | ||||||
|  * Also see http://utf8everywhere.org/
 |  * 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 |  * This library is free software; you can redistribute it and/or | ||||||
|  * modify it under the terms of the GNU Lesser General Public |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  | @ -28,6 +28,7 @@ | ||||||
| #include <shlwapi.h> | #include <shlwapi.h> | ||||||
| #include <setupapi.h> | #include <setupapi.h> | ||||||
| #include <direct.h> | #include <direct.h> | ||||||
|  | #include <io.h> | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
|  | @ -721,6 +722,15 @@ static __inline FILE* fopenU(const char* filename, const char* mode) | ||||||
| 	return ret; | 	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
 | // returned UTF-8 string must be freed
 | ||||||
| static __inline char* getenvU(const char* varname) | 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 "drive.h" | ||||||
| #include "registry.h" | #include "registry.h" | ||||||
| #include "localization.h" | #include "localization.h" | ||||||
|  | #include "bled/bled.h" | ||||||
| 
 | 
 | ||||||
| /* Redefinitions for WDK and MinGW */ | /* Redefinitions for WDK and MinGW */ | ||||||
| // TODO: these would be better in a 'missing.h' file
 | // TODO: these would be better in a 'missing.h' file
 | ||||||
|  | @ -1637,6 +1638,7 @@ void SetBoot(int fs, int bt) | ||||||
| /*
 | /*
 | ||||||
|  * Main dialog callback |  * 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) | static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) | ||||||
| { | { | ||||||
| 	DRAWITEMSTRUCT* pDI; | 	DRAWITEMSTRUCT* pDI; | ||||||
|  |  | ||||||
|  | @ -240,6 +240,7 @@ typedef struct { | ||||||
| 	char cfg_path[128];		/* path to the ISO's isolinux.cfg */ | 	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 */ | 	char reactos_path[128];	/* path to the ISO's freeldr.sys or setupldr.sys */ | ||||||
| 	uint64_t projected_size; | 	uint64_t projected_size; | ||||||
|  | 	uint64_t src_size; | ||||||
| 	// TODO: use a bitmask and #define tests for the following
 | 	// TODO: use a bitmask and #define tests for the following
 | ||||||
| 	uint8_t winpe; | 	uint8_t winpe; | ||||||
| 	BOOL has_4GB_file; | 	BOOL has_4GB_file; | ||||||
|  | @ -257,6 +258,7 @@ typedef struct { | ||||||
| 	BOOL has_kolibrios; | 	BOOL has_kolibrios; | ||||||
| 	BOOL uses_minint; | 	BOOL uses_minint; | ||||||
| 	BOOL is_bootable_img; | 	BOOL is_bootable_img; | ||||||
|  | 	BOOL compression_type; | ||||||
| 	BOOL is_vhd; | 	BOOL is_vhd; | ||||||
| 	uint16_t sl_version;	// Syslinux/Isolinux version
 | 	uint16_t sl_version;	// Syslinux/Isolinux version
 | ||||||
| 	char sl_version_str[12]; | 	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 | IDD_DIALOG DIALOGEX 12, 12, 242, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | 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 | FONT 8, "Segoe UI", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 | ||||||
|  | @ -164,7 +164,7 @@ END | ||||||
| 
 | 
 | ||||||
| IDD_DIALOG_XP DIALOGEX 12, 12, 242, 329 | IDD_DIALOG_XP DIALOGEX 12, 12, 242, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | 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 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 | ||||||
|  | @ -297,7 +297,7 @@ END | ||||||
| IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 329 | IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | 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 | 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 | FONT 8, "Segoe UI", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 | ||||||
|  | @ -437,7 +437,7 @@ END | ||||||
| IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 329 | IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | 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 | 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 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,127,291,50,14 | ||||||
|  | @ -703,8 +703,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,5,0,562 |  FILEVERSION 1,5,0,563 | ||||||
|  PRODUCTVERSION 1,5,0,562 |  PRODUCTVERSION 1,5,0,563 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -721,13 +721,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" |             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "1.5.0.562" |             VALUE "FileVersion", "1.5.0.563" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "1.5.0.562" |             VALUE "ProductVersion", "1.5.0.563" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								src/vhd.c
									
										
									
									
									
								
							
							
						
						
									
										45
									
								
								src/vhd.c
									
										
									
									
									
								
							|  | @ -27,6 +27,7 @@ | ||||||
| #include "msapi_utf8.h" | #include "msapi_utf8.h" | ||||||
| #include "drive.h" | #include "drive.h" | ||||||
| #include "registry.h" | #include "registry.h" | ||||||
|  | #include "bled/bled.h" | ||||||
| 
 | 
 | ||||||
| #if defined(_MSC_VER) | #if defined(_MSC_VER) | ||||||
| #define bswap_uint64 _byteswap_uint64 | #define bswap_uint64 _byteswap_uint64 | ||||||
|  | @ -211,6 +212,43 @@ out: | ||||||
| 	return r; | 	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) | BOOL IsHDImage(const char* path) | ||||||
| { | { | ||||||
| 	HANDLE handle = INVALID_HANDLE_VALUE; | 	HANDLE handle = INVALID_HANDLE_VALUE; | ||||||
|  | @ -227,7 +265,10 @@ BOOL IsHDImage(const char* path) | ||||||
| 		uprintf("Could not open image '%s'", path); | 		uprintf("Could not open image '%s'", path); | ||||||
| 		goto out; | 		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)) { | 	if (!GetFileSizeEx(handle, &liImageSize)) { | ||||||
| 		uprintf("Could not get image size: %s", WindowsErrorString()); | 		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; | 	iso_report.projected_size = (uint64_t)liImageSize.QuadPart; | ||||||
| 
 | 
 | ||||||
| 	size = sizeof(vhd_footer); | 	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); | 		footer = (vhd_footer*)malloc(size); | ||||||
| 		ptr.QuadPart = iso_report.projected_size - size; | 		ptr.QuadPart = iso_report.projected_size - size; | ||||||
| 		if ( (footer == NULL) || (!SetFilePointerEx(handle, ptr, NULL, FILE_BEGIN)) || | 		if ( (footer == NULL) || (!SetFilePointerEx(handle, ptr, NULL, FILE_BEGIN)) || | ||||||
|  |  | ||||||
|  | @ -10,8 +10,23 @@ set PWD=%~dp0 | ||||||
| set ARCH_DIR=%_BUILDARCH% | set ARCH_DIR=%_BUILDARCH% | ||||||
| if /I Test%_BUILDARCH%==Testx86 set ARCH_DIR=i386 | 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 | ::# MS-SYS Library | ||||||
| cd src\ms-sys | cd ..\ms-sys | ||||||
| if EXIST Makefile ren Makefile Makefile.hide | if EXIST Makefile ren Makefile Makefile.hide | ||||||
| 
 | 
 | ||||||
| copy .msvc\ms-sys_sources sources >NUL 2>&1 | copy .msvc\ms-sys_sources sources >NUL 2>&1 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue