Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30e859be0b | ||
|
|
5b204622cc | ||
|
|
b07ab3e9b9 | ||
|
|
3dc4334d38 | ||
|
|
ca30682447 | ||
|
|
0e5c9dcdf4 | ||
|
|
ea99a46b6d | ||
|
|
23bc9fd943 | ||
|
|
cfcb729f79 | ||
|
|
51521bddc8 | ||
|
|
41331dd3ec | ||
|
|
9c155991d7 | ||
|
|
43e787bd88 | ||
|
|
3909c23817 | ||
|
|
c0d3dbf537 | ||
|
|
0388124aad | ||
|
|
e1aad8c445 | ||
|
|
b5fb12503d | ||
|
|
bd2f162009 | ||
|
|
408940f16c | ||
|
|
a710bd714a | ||
|
|
7a3b698578 | ||
|
|
e275fcf017 | ||
|
|
0e2e1a0b05 | ||
|
|
3431a6635b | ||
|
|
521a42a4c3 | ||
|
|
a4b83e8e95 | ||
|
|
121e088a7d | ||
|
|
46f714348e | ||
|
|
a56a08cf79 | ||
|
|
8a50b4b5df | ||
|
|
37ceb026db | ||
|
|
586300a787 | ||
|
|
92c8d77cfb | ||
|
|
c546a57f90 | ||
|
|
5244fc00c4 | ||
|
|
4c76400cce | ||
|
|
240b3b6709 | ||
|
|
e54582384a | ||
|
|
3ad1a92279 | ||
|
|
447dd06750 | ||
|
|
4827f71a08 | ||
|
|
bb3b75bc09 | ||
|
|
b7bd0421c5 | ||
|
|
9a3ae75a48 | ||
|
|
120bea1a6f | ||
|
|
4a41245099 | ||
|
|
0f0535fcaa | ||
|
|
8d8deb4e5d | ||
|
|
83bce6e82a | ||
|
|
739f03f951 | ||
|
|
7583be518c | ||
|
|
0619c3e6c4 | ||
|
|
e33916b608 | ||
|
|
596f19f79e | ||
|
|
2884e67a1a | ||
|
|
ae5740b19c | ||
|
|
b14ded7d01 | ||
|
|
914049d19c | ||
|
|
915b82e95b | ||
|
|
0f09a00810 | ||
|
|
f5f23217b3 | ||
|
|
5d362f43eb | ||
|
|
ce26dba5ba | ||
|
|
ad8e3dd4b1 | ||
|
|
53e1d650e5 | ||
|
|
bcd64ca3b8 | ||
|
|
078f20290f | ||
|
|
9c98a6b180 | ||
|
|
a30ff41e9d | ||
|
|
a43eb98099 | ||
|
|
8d8a987eea | ||
|
|
c5f0063c75 | ||
|
|
d57eb5de40 | ||
|
|
672dc834f1 | ||
|
|
5e8f4d7d88 | ||
|
|
68a48aa20e | ||
|
|
b5ac94fd24 | ||
|
|
b4020169b7 | ||
|
|
b8f38540c2 | ||
|
|
d65cd2ea9d | ||
|
|
6cd3054608 | ||
|
|
f44494aad2 | ||
|
|
7c5ccae39c | ||
|
|
82df346497 | ||
|
|
225c627f7d | ||
|
|
db8158a5cc | ||
|
|
62090966b1 | ||
|
|
dec6a65a64 | ||
|
|
7d7b1c9554 | ||
|
|
a4a4a1c665 | ||
|
|
b8887e9179 | ||
|
|
c0cc7df743 | ||
|
|
c5e2d27028 | ||
|
|
bb7b62fcb4 | ||
|
|
e56962c624 | ||
|
|
d9e159a395 | ||
|
|
4578b9dd33 | ||
|
|
b44f9c07b8 | ||
|
|
55bcdaf3c4 | ||
|
|
8f6f2ad5fb | ||
|
|
7063b0e2e9 | ||
|
|
3679a3dcdc | ||
|
|
4ae7992c2e | ||
|
|
566b978768 | ||
|
|
7a3820c539 | ||
|
|
bca5f2761d | ||
|
|
f7d49e2d7c | ||
|
|
f8b3d67c67 | ||
|
|
2043f834b0 | ||
|
|
c65486db27 | ||
|
|
30589b5419 | ||
|
|
3f59ffc209 | ||
|
|
d487d78b30 | ||
|
|
1d5b57bd9b | ||
|
|
9e89bb1ee0 | ||
|
|
6c717b6558 | ||
|
|
5c3dd5c27e | ||
|
|
ceca477ed4 | ||
|
|
34eff624c4 | ||
|
|
930f9188a5 | ||
|
|
397d2d5ab3 | ||
|
|
3064a0e551 | ||
|
|
d22a27a9c3 | ||
|
|
98cd93d3a7 | ||
|
|
d52e453488 | ||
|
|
61a4b59216 | ||
|
|
7443318057 | ||
|
|
e474a61e86 | ||
|
|
5e67eb720a | ||
|
|
d18e09d5b0 | ||
|
|
7855c3efd0 | ||
|
|
c689d51f79 | ||
|
|
fee885a931 | ||
|
|
a1e78c5fc4 | ||
|
|
3c52d21ba9 | ||
|
|
a6e3b69a3b | ||
|
|
0fbdb2298e | ||
|
|
7df69ea96e | ||
|
|
fc746532d8 | ||
|
|
d60c6d20af | ||
|
|
55e4fe414e | ||
|
|
5bb372d495 | ||
|
|
a86a4355da | ||
|
|
c9fd8d4df0 | ||
|
|
02123b82d5 | ||
|
|
7140c588c6 | ||
|
|
f60a99bd90 | ||
|
|
50fd547660 | ||
|
|
2fa05a7264 | ||
|
|
1a20b75c46 | ||
|
|
dab094fc31 | ||
|
|
13a12e32ab | ||
|
|
73418b7e05 | ||
|
|
3f7de8e289 | ||
|
|
18a30653b1 | ||
|
|
b73887478a | ||
|
|
51fb0afc82 | ||
|
|
a45fa6b8a0 | ||
|
|
6c6700d2f4 | ||
|
|
0574424b05 | ||
|
|
919d837abf | ||
|
|
12db0fc415 | ||
|
|
e4bd6d3191 | ||
|
|
f9749af452 | ||
|
|
02a516944d | ||
|
|
0d4ae83bd2 | ||
|
|
d15b013734 | ||
|
|
7e49256146 | ||
|
|
97a759a14b | ||
|
|
a3dc63a17f | ||
|
|
be85b3b4cd | ||
|
|
3da621e118 | ||
|
|
211f14074a | ||
|
|
819d0d56f0 | ||
|
|
fa7fadebfa | ||
|
|
a6e7d468e3 | ||
|
|
b8f7cf0fa7 | ||
|
|
886df95632 | ||
|
|
80c2d56436 | ||
|
|
4f6a0e3fc1 | ||
|
|
91a76f61c9 | ||
|
|
0cdc6af8cd | ||
|
|
6186dd6dc6 | ||
|
|
bf26d0e7f7 | ||
|
|
2aa8ed38a2 | ||
|
|
b1b25804fc | ||
|
|
053d00c451 | ||
|
|
b579191d9f | ||
|
|
db8df5bd96 | ||
|
|
507074781d | ||
|
|
62e7e2b0b9 | ||
|
|
f2b096a82e | ||
|
|
ec6d4535ab | ||
|
|
83a886f154 | ||
|
|
8d2ce022c1 | ||
|
|
d42bff7e8f | ||
|
|
80fa033e18 | ||
|
|
bd247ee400 | ||
|
|
76c44d530d | ||
|
|
1d82e28fd6 | ||
|
|
1250e1ea6a |
@@ -1,5 +0,0 @@
|
||||
# Xcode
|
||||
xcuserdata/
|
||||
|
||||
# JetBrains
|
||||
.idea/
|
||||
+1
-1
@@ -23,4 +23,4 @@ before_script:
|
||||
script:
|
||||
- make
|
||||
- cd ../test
|
||||
- python test.py --exe_dir=../build
|
||||
- travis_wait 30 python test.py --exe_dir=../build
|
||||
|
||||
+118
-142
@@ -5,11 +5,12 @@
|
||||
#***************************************************************************
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
option(USE_CRYPT "Enables building with PKWARE traditional encryption" ON)
|
||||
option(USE_AES "Enables building with AES library" ON)
|
||||
option(USE_BZIP2 "Enables building with BZIP2 library" ON)
|
||||
option(USE_LZMA "Enables building with LZMA library" ON)
|
||||
option(BUILD_TEST "Enables building of executables. Requires ZLIB!" OFF)
|
||||
option(USE_ZLIB "Enables ZLIB compression" ON)
|
||||
option(USE_BZIP2 "Enables BZIP2 compression" ON)
|
||||
option(USE_LZMA "Enables LZMA compression" ON)
|
||||
option(USE_PKCRYPT "Enables PKWARE traditional encryption" ON)
|
||||
option(USE_AES "Enables AES encryption" ON)
|
||||
option(BUILD_TEST "Builds minizip test executable" OFF)
|
||||
|
||||
# Set a consistent MACOSX_RPATH default across all CMake versions.
|
||||
# When CMake 2.8.12 is required, change this default to 1.
|
||||
@@ -18,24 +19,30 @@ if(NOT DEFINED CMAKE_MACOSX_RPATH)
|
||||
set(CMAKE_MACOSX_RPATH 0)
|
||||
endif()
|
||||
|
||||
set(INSTALL_BIN_DIR "bin" CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_LIB_DIR "lib" CACHE PATH "Installation directory for libraries")
|
||||
set(INSTALL_INC_DIR "include" CACHE PATH "Installation directory for headers")
|
||||
set(INSTALL_MAN_DIR "share/man" CACHE PATH "Installation directory for manual pages")
|
||||
set(INSTALL_PKGCONFIG_DIR "share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
|
||||
project("minizip")
|
||||
|
||||
set(VERSION "2.2.2")
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(INSTALL_BIN_DIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_LIB_DIR ${CMAKE_INSTALL_LIBDIR} CACHE PATH "Installation directory for libraries")
|
||||
set(INSTALL_INC_DIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "Installation directory for headers")
|
||||
set(INSTALL_MAN_DIR ${CMAKE_INSTALL_MANDIR} CACHE PATH "Installation directory for manual pages")
|
||||
set(INSTALL_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
set(INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/minizip CACHE PATH "Installation directory for cmake files.")
|
||||
|
||||
set(VERSION "2.3.2")
|
||||
|
||||
# Set cmake debug postfix to d
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
# Ensure correct version of zlib is referenced
|
||||
set(ZLIB_ROOT ${DEF_ZLIB_ROOT} CACHE PATH "Parent directory of zlib installation")
|
||||
find_package(ZLIB REQUIRED)
|
||||
if(ZLIB_FOUND)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
if(USE_ZLIB)
|
||||
set(ZLIB_ROOT ${DEF_ZLIB_ROOT} CACHE PATH "Parent directory of zlib installation")
|
||||
find_package(ZLIB REQUIRED)
|
||||
if(ZLIB_FOUND)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
endif()
|
||||
add_definitions(-DHAVE_ZLIB)
|
||||
endif()
|
||||
|
||||
set(MINIZIP_PC ${CMAKE_CURRENT_BINARY_DIR}/minizip.pc)
|
||||
@@ -44,31 +51,29 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/minizip.pc.cmakein ${MINIZIP_PC} @ONL
|
||||
set(PROJECT_NAME libminizip)
|
||||
|
||||
set(MINIZIP_SRC
|
||||
src/mz_os.c
|
||||
src/mz_compat.c
|
||||
src/mz_strm.c
|
||||
src/mz_strm_buf.c
|
||||
src/mz_strm_mem.c
|
||||
src/mz_strm_posix.c
|
||||
src/mz_strm_split.c
|
||||
src/mz_strm_zlib.c
|
||||
src/mz_zip.c)
|
||||
mz_os.c
|
||||
mz_compat.c
|
||||
mz_strm.c
|
||||
mz_strm_buf.c
|
||||
mz_strm_mem.c
|
||||
mz_strm_posix.c
|
||||
mz_strm_split.c
|
||||
mz_zip.c)
|
||||
|
||||
set(MINIZIP_PUBLIC_HEADERS
|
||||
src/mz.h
|
||||
src/mz_os.h
|
||||
src/mz_compat.h
|
||||
src/mz_strm.h
|
||||
src/mz_strm_buf.h
|
||||
src/mz_strm_mem.h
|
||||
src/mz_strm_posix.h
|
||||
src/mz_strm_split.h
|
||||
src/mz_strm_zlib.h
|
||||
src/mz_zip.h)
|
||||
mz.h
|
||||
mz_os.h
|
||||
mz_compat.h
|
||||
mz_strm.h
|
||||
mz_strm_buf.h
|
||||
mz_strm_mem.h
|
||||
mz_strm_posix.h
|
||||
mz_strm_split.h
|
||||
mz_zip.h)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND MINIZIP_SRC "src/mz_os_win32.c" "src/mz_strm_win32.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "src/mz_os_win32.h" "src/mz_strm_win32.h")
|
||||
list(APPEND MINIZIP_SRC "mz_os_win32.c" "mz_strm_win32.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_os_win32.h" "mz_strm_win32.h")
|
||||
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
endif()
|
||||
@@ -78,55 +83,65 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -O3")
|
||||
add_compile_options(-O3)
|
||||
|
||||
list(APPEND MINIZIP_SRC "src/mz_os_posix.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "src/mz_os_posix.h")
|
||||
list(APPEND MINIZIP_SRC "mz_os_posix.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_os_posix.h")
|
||||
|
||||
add_definitions(-D__USE_FILE_OFFSET64)
|
||||
add_definitions(-D__USE_LARGEFILE64)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE)
|
||||
add_definitions(-D_FILE_OFFSET_BIT=64)
|
||||
set(define_lfs_macros TRUE)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
if(ANDROID)
|
||||
string(REGEX REPLACE "android-([0-9+])" "\\1"
|
||||
android_api "${ANDROID_PLATFORM}")
|
||||
if(${android_api} LESS 24)
|
||||
set(define_lfs_macros FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
pkg_check_modules(LIBBSD libbsd)
|
||||
if(define_lfs_macros)
|
||||
add_definitions(-D__USE_FILE_OFFSET64)
|
||||
add_definitions(-D__USE_LARGEFILE64)
|
||||
add_definitions(-D_LARGEFILE64_SOURCE)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
endif()
|
||||
|
||||
include_directories(${LIBBSD_INCLUDE_DIRS})
|
||||
link_directories(${LIBBSD_LIBRARY_DIRS})
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(LIBBSD libbsd REQUIRED)
|
||||
|
||||
include_directories(${LIBBSD_INCLUDE_DIRS})
|
||||
link_directories(${LIBBSD_LIBRARY_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_CRYPT)
|
||||
add_definitions(-DHAVE_CRYPT)
|
||||
if(USE_PKCRYPT)
|
||||
add_definitions(-DHAVE_PKCRYPT)
|
||||
|
||||
list(APPEND MINIZIP_SRC "src/mz_strm_crypt.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "src/mz_strm_crypt.h")
|
||||
list(APPEND MINIZIP_SRC "mz_strm_pkcrypt.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_strm_pkcrypt.h")
|
||||
endif()
|
||||
|
||||
if(USE_AES)
|
||||
add_definitions(-DHAVE_AES)
|
||||
|
||||
list(APPEND MINIZIP_SRC "src/mz_strm_aes.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "src/mz_strm_aes.h")
|
||||
list(APPEND MINIZIP_SRC "mz_strm_aes.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_strm_aes.h")
|
||||
|
||||
set(AES_SRC
|
||||
lib/aes/aescrypt.c
|
||||
lib/aes/aeskey.c
|
||||
lib/aes/aestab.c
|
||||
lib/aes/aes_ni.c
|
||||
lib/aes/fileenc.c
|
||||
lib/aes/hmac.c
|
||||
lib/aes/pwd2key.c
|
||||
lib/aes/sha1.c)
|
||||
|
||||
set(AES_PUBLIC_HEADERS
|
||||
lib/aes/aes.h
|
||||
lib/aes/aes_ni.h
|
||||
lib/aes/aesopt.h
|
||||
lib/aes/aestab.h
|
||||
lib/aes/brg_endian.h
|
||||
lib/aes/brg_types.h
|
||||
lib/aes/fileenc.h
|
||||
lib/aes/hmac.h
|
||||
lib/aes/pwd2key.h
|
||||
lib/aes/sha1.h)
|
||||
@@ -136,12 +151,28 @@ if(USE_AES)
|
||||
source_group("AES" FILES ${AES_SRC} ${AES_PUBLIC_HEADERS})
|
||||
endif()
|
||||
|
||||
if(USE_ZLIB)
|
||||
add_definitions(-DHAVE_ZLIB)
|
||||
|
||||
list(APPEND MINIZIP_SRC "mz_strm_zlib.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_strm_zlib.h")
|
||||
|
||||
include(CheckFunctionExists)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB)
|
||||
CHECK_FUNCTION_EXISTS(z_get_crc_table
|
||||
NEEDS_Z_PREFIX)
|
||||
|
||||
if(NEEDS_Z_PREFIX)
|
||||
add_definitions(-DZ_PREFIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_BZIP2)
|
||||
add_definitions(-DHAVE_BZIP2)
|
||||
add_definitions(-DBZ_NO_STDIO)
|
||||
|
||||
list(APPEND MINIZIP_SRC "src/mz_strm_bzip.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "src/mz_strm_bzip.h")
|
||||
list(APPEND MINIZIP_SRC "mz_strm_bzip.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_strm_bzip.h")
|
||||
|
||||
set(BZIP2_SRC
|
||||
lib/bzip2/blocksort.c
|
||||
@@ -166,12 +197,8 @@ if(USE_LZMA)
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
add_definitions(-DLZMA_API_STATIC)
|
||||
|
||||
if(UNIX)
|
||||
add_definitions(-DMYTHREAD_POSIX)
|
||||
endif()
|
||||
|
||||
list(APPEND MINIZIP_SRC "src/mz_strm_lzma.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "src/mz_strm_lzma.h")
|
||||
list(APPEND MINIZIP_SRC "mz_strm_lzma.c")
|
||||
list(APPEND MINIZIP_PUBLIC_HEADERS "mz_strm_lzma.h")
|
||||
|
||||
set(LZMA_CHECK_SRC
|
||||
lib/liblzma/check/check.c
|
||||
@@ -180,53 +207,8 @@ if(USE_LZMA)
|
||||
set(LZMA_COMMON_SRC
|
||||
lib/liblzma/common/alone_decoder.c
|
||||
lib/liblzma/common/alone_encoder.c
|
||||
lib/liblzma/common/auto_decoder.c
|
||||
lib/liblzma/common/block_buffer_decoder.c
|
||||
lib/liblzma/common/block_buffer_encoder.c
|
||||
lib/liblzma/common/block_decoder.c
|
||||
lib/liblzma/common/block_encoder.c
|
||||
lib/liblzma/common/block_header_decoder.c
|
||||
lib/liblzma/common/block_header_encoder.c
|
||||
lib/liblzma/common/block_util.c
|
||||
lib/liblzma/common/common.c
|
||||
lib/liblzma/common/easy_buffer_encoder.c
|
||||
lib/liblzma/common/easy_decoder_memusage.c
|
||||
lib/liblzma/common/easy_encoder.c
|
||||
lib/liblzma/common/easy_encoder_memusage.c
|
||||
lib/liblzma/common/easy_preset.c
|
||||
lib/liblzma/common/filter_buffer_decoder.c
|
||||
lib/liblzma/common/filter_buffer_encoder.c
|
||||
lib/liblzma/common/filter_common.c
|
||||
lib/liblzma/common/filter_decoder.c
|
||||
lib/liblzma/common/filter_encoder.c
|
||||
lib/liblzma/common/filter_flags_decoder.c
|
||||
lib/liblzma/common/filter_flags_encoder.c
|
||||
lib/liblzma/common/hardware_cputhreads.c
|
||||
lib/liblzma/common/hardware_physmem.c
|
||||
lib/liblzma/common/index.c
|
||||
lib/liblzma/common/index_decoder.c
|
||||
lib/liblzma/common/index_encoder.c
|
||||
lib/liblzma/common/index_hash.c
|
||||
lib/liblzma/common/outqueue.c
|
||||
lib/liblzma/common/stream_buffer_decoder.c
|
||||
lib/liblzma/common/stream_buffer_encoder.c
|
||||
lib/liblzma/common/stream_decoder.c
|
||||
lib/liblzma/common/stream_encoder.c
|
||||
lib/liblzma/common/stream_encoder_mt.c
|
||||
lib/liblzma/common/stream_flags_common.c
|
||||
lib/liblzma/common/stream_flags_decoder.c
|
||||
lib/liblzma/common/stream_flags_encoder.c
|
||||
lib/liblzma/common/tuklib_cpucores.c
|
||||
lib/liblzma/common/tuklib_exit.c
|
||||
lib/liblzma/common/tuklib_mbstr_fw.c
|
||||
lib/liblzma/common/tuklib_mbstr_width.c
|
||||
lib/liblzma/common/tuklib_open_stdxxx.c
|
||||
lib/liblzma/common/tuklib_physmem.c
|
||||
lib/liblzma/common/tuklib_progname.c
|
||||
lib/liblzma/common/tuklib_progname.h
|
||||
lib/liblzma/common/vli_decoder.c
|
||||
lib/liblzma/common/vli_encoder.c
|
||||
lib/liblzma/common/vli_size.c)
|
||||
lib/liblzma/common/filter_encoder.c)
|
||||
set(LZMA_LZ_SRC
|
||||
lib/liblzma/lz/lz_decoder.c
|
||||
lib/liblzma/lz/lz_encoder.c
|
||||
@@ -247,17 +229,10 @@ if(USE_LZMA)
|
||||
set(LZMA_API_HEADERS
|
||||
lib/liblzma/api/lzma.h
|
||||
lib/liblzma/api/lzma/base.h
|
||||
lib/liblzma/api/lzma/bcj.h
|
||||
lib/liblzma/api/lzma/block.h
|
||||
lib/liblzma/api/lzma/check.h
|
||||
lib/liblzma/api/lzma/container.h
|
||||
lib/liblzma/api/lzma/delta.h
|
||||
lib/liblzma/api/lzma/filter.h
|
||||
lib/liblzma/api/lzma/hardware.h
|
||||
lib/liblzma/api/lzma/index.h
|
||||
lib/liblzma/api/lzma/index_hash.h
|
||||
lib/liblzma/api/lzma/lzma12.h
|
||||
lib/liblzma/api/lzma/stream_flags.h
|
||||
lib/liblzma/api/lzma/version.h
|
||||
lib/liblzma/api/lzma/vli.h)
|
||||
set(LZMA_CHECK_HEADERS
|
||||
@@ -267,31 +242,14 @@ if(USE_LZMA)
|
||||
lib/liblzma/check/crc_macros.h)
|
||||
set(LZMA_COMMON_HEADERS
|
||||
lib/liblzma/common/alone_decoder.h
|
||||
lib/liblzma/common/block_buffer_encoder.h
|
||||
lib/liblzma/common/block_decoder.h
|
||||
lib/liblzma/common/block_encoder.h
|
||||
lib/liblzma/common/common.h
|
||||
lib/liblzma/common/easy_preset.h
|
||||
lib/liblzma/common/filter_common.h
|
||||
lib/liblzma/common/filter_decoder.h
|
||||
lib/liblzma/common/filter_encoder.h
|
||||
lib/liblzma/common/index.h
|
||||
lib/liblzma/common/index_encoder.h
|
||||
lib/liblzma/common/memcmplen.h
|
||||
lib/liblzma/common/mythread.h
|
||||
lib/liblzma/common/outqueue.h
|
||||
lib/liblzma/common/stream_decoder.h
|
||||
lib/liblzma/common/stream_flags_common.h
|
||||
lib/liblzma/common/sysdefs.h
|
||||
lib/liblzma/common/tuklib_common.h
|
||||
lib/liblzma/common/tuklib_config.h
|
||||
lib/liblzma/common/tuklib_cpucores.h
|
||||
lib/liblzma/common/tuklib_exit.h
|
||||
lib/liblzma/common/tuklib_gettext.h
|
||||
lib/liblzma/common/tuklib_integer.h
|
||||
lib/liblzma/common/tuklib_mbstr.h
|
||||
lib/liblzma/common/tuklib_open_stdxxx.h
|
||||
lib/liblzma/common/tuklib_physmem.h)
|
||||
lib/liblzma/common/tuklib_integer.h)
|
||||
set(LZMA_LZ_HEADERS
|
||||
lib/liblzma/lz/lz_decoder.h
|
||||
lib/liblzma/lz/lz_encoder.h
|
||||
@@ -342,8 +300,19 @@ if(USE_LZMA)
|
||||
source_group("LZMA\\RangeCoder" FILES ${LZMA_RANGECODER_SRC} ${LZMA_RANGECODER_HEADERS})
|
||||
endif()
|
||||
|
||||
# Enable x86 optimizations if supported
|
||||
if(CMAKE_C_COMPILER MATCHES ".*clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -msse4.1 -maes")
|
||||
include(CheckCCompilerFlag)
|
||||
macro(enable_option_if_supported option variable)
|
||||
check_c_compiler_flag("-Werror=unused-command-line-argument ${option}" ${variable})
|
||||
if(${variable})
|
||||
add_compile_options(${option})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
enable_option_if_supported(-msse3 check_opt_sse3)
|
||||
enable_option_if_supported(-msse4.1 check_opt_sse41)
|
||||
enable_option_if_supported(-maes check_opt_aes)
|
||||
endif()
|
||||
|
||||
# Create minizip library
|
||||
@@ -355,11 +324,18 @@ add_library(${PROJECT_NAME}
|
||||
${BZIP2_SRC} ${BZIP2_PUBLIC_HEADERS}
|
||||
${LZMA_SRC} ${LZMA_PUBLIC_HEADERS})
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C PREFIX "")
|
||||
if (MINGW AND BUILD_SHARED_LIBS)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES ARCHIVE_OUTPUT_NAME "minizip")
|
||||
endif ()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C PREFIX ""
|
||||
POSITION_INDEPENDENT_CODE 1)
|
||||
if(USE_ZLIB)
|
||||
target_link_libraries(${PROJECT_NAME} ZLIB::ZLIB)
|
||||
endif()
|
||||
if(USE_LZMA)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES C_STANDARD 99)
|
||||
endif()
|
||||
target_link_libraries(${PROJECT_NAME} ZLIB::ZLIB)
|
||||
if(UNIX)
|
||||
target_link_libraries(${PROJECT_NAME} ${LIBBSD_LIBRARIES})
|
||||
endif()
|
||||
@@ -373,14 +349,14 @@ install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}
|
||||
LIBRARY DESTINATION "${INSTALL_LIB_DIR}")
|
||||
|
||||
install(EXPORT ${PROJECT_NAME}
|
||||
DESTINATION "cmake"
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}"
|
||||
NAMESPACE "MINIZIP::")
|
||||
|
||||
install(FILES ${MINIZIP_PUBLIC_HEADERS} DESTINATION "${INSTALL_INC_DIR}")
|
||||
install(FILES ${MINIZIP_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
|
||||
if(BUILD_TEST)
|
||||
add_executable(minizip "src/minizip.c")
|
||||
add_executable(minizip "minizip.c")
|
||||
target_link_libraries(minizip ${PROJECT_NAME})
|
||||
|
||||
install(TARGETS minizip
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'Minizip'
|
||||
s.version = '2.2.2'
|
||||
s.version = '2.3.2'
|
||||
s.license = 'zlib'
|
||||
s.summary = 'Minizip contrib in zlib with the latest bug fixes and advanced features'
|
||||
s.description = <<-DESC
|
||||
@@ -17,7 +17,7 @@ DESC
|
||||
s.libraries = 'z'
|
||||
|
||||
s.subspec 'Core' do |sp|
|
||||
sp.source_files = 'src/{mz_os,mz_compat,mz_strm,mz_strm_mem,mz_strm_buf,mz_zip,mz_strm_crypt,mz_strm_posix,mz_strm_zlib}.{c,h}'
|
||||
sp.source_files = '{mz_os,mz_compat,mz_strm,mz_strm_mem,mz_strm_buf,mz_zip,mz_strm_crypt,mz_strm_posix,mz_strm_zlib}.{c,h}'
|
||||
end
|
||||
|
||||
s.subspec 'AES' do |sp|
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Minizip 2.2.2
|
||||
# Minizip 2.3.2
|
||||
|
||||
This library is a refactoring of the minizip contribution found in the zlib distribution that is supported on Windows, macOS, and Linux. The motivation for this work has been the inclusion of advanced features, improvements in code maintainability and readability, and the reduction of duplicate code. It is based on the original work of [Gilles Vollant](http://www.winimage.com/zLibDll/minizip.html) that has been contributed to by many people over the years.
|
||||
This library is a refactoring of the minizip contribution found in the zlib distribution and is supported on Windows, macOS, and Linux. The motivation for this work has been the inclusion of advanced features, improvements in code maintainability and readability, and the reduction of duplicate code. It is based on the original work of [Gilles Vollant](http://www.winimage.com/zLibDll/minizip.html) that has been contributed to by many people over the years.
|
||||
|
||||
Dev: 
|
||||
Master: 
|
||||
@@ -14,9 +14,21 @@ To generate the project files for your platform and IDE download and run cmake i
|
||||
|
||||
```
|
||||
cmake .
|
||||
cmake . -DBUILD_TEST=ON
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
## Build Options
|
||||
|
||||
| Name | Description | Default Value |
|
||||
|:- |:-|:-:|
|
||||
| USE_ZLIB | Enables ZLIB compression | ON |
|
||||
| USE_BZIP2 | Enables BZIP2 compression | ON |
|
||||
| USE_LZMA | Enables LZMA compression | ON |
|
||||
| USE_PKCRYPT | Enables PKWARE traditional encryption | ON |
|
||||
| USE_AES | Enables AES encryption | ON |
|
||||
| BUILD_TEST | Builds minizip test executable | OFF |
|
||||
|
||||
## Contents
|
||||
|
||||
| File(s) | Description | Required |
|
||||
@@ -24,18 +36,18 @@ cmake --build .
|
||||
| minizip.c | Sample application | No |
|
||||
| mz_compat.\* | Minizip 1.0 compatibility layer | No |
|
||||
| mz.h | Error codes and flags | Yes |
|
||||
| mz_os\* | OS specific helper functions | Encryption |
|
||||
| mz_os\* | OS specific helper functions | Encryption, Disk Splitting |
|
||||
| mz_strm.\* | Stream interface | Yes |
|
||||
| mz_strm_aes.\* | WinZIP AES stream | No |
|
||||
| mz_strm_buf.\* | Buffered stream | No |
|
||||
| mz_strm_bzip.\* | BZIP2 stream using libbzip2 | No |
|
||||
| mz_strm_crypt.\* | PKWARE traditional encryption stream | No |
|
||||
| mz_strm_lzma.\* | LZMA stream using liblzma | No |
|
||||
| mz_strm_lzma.\* | LZMA stream using liblzma | zlib or liblzma |
|
||||
| mz_strm_mem.\* | Memory stream | Yes |
|
||||
| mz_strm_split.\* | Disk splitting stream | No |
|
||||
| mz_strm_pkcrypt.\* | PKWARE traditional encryption stream | No |
|
||||
| mz_strm_posix.\* | File stream using Posix functions | Non-windows systems |
|
||||
| mz_strm_win32.\* | File stream using Win32 API functions | Windows systems |
|
||||
| mz_strm_zlib.\* | Deflate stream using zlib | Yes |
|
||||
| mz_strm_zlib.\* | Deflate stream using zlib | zlib or liblzma |
|
||||
| mz_zip.\* | Zip functionality | Yes |
|
||||
|
||||
## Features
|
||||
@@ -54,10 +66,10 @@ cmake --build .
|
||||
|
||||
### Encryption
|
||||
|
||||
#### [WinZIP AES Encryption](http://www.winzip.com/aes_info.htm)
|
||||
#### [WinZIP AES Encryption](https://www.winzip.com/aes_info.htm)
|
||||
|
||||
+ Requires ``cmake . -DUSE_AES=ON`` or ``#define HAVE_AES``
|
||||
+ Requires [Brian Gladman's](https://github.com/BrianGladman/aes) AES library
|
||||
+ Requires Brian Gladman's [AES](https://github.com/BrianGladman/aes) and [SHA](https://github.com/BrianGladman/sha) libraries
|
||||
|
||||
When zipping with a password it will always use AES 256-bit encryption.
|
||||
When unzipping it will use AES decryption only if necessary.
|
||||
@@ -68,7 +80,7 @@ To disable encryption use the following cmake commands:
|
||||
|
||||
```
|
||||
cmake . -DUSE_AES=OFF
|
||||
cmake . -DUSE_CRYPT=OFF
|
||||
cmake . -DUSE_PKCRYPT=OFF
|
||||
```
|
||||
|
||||
### NTFS Timestamps
|
||||
@@ -81,7 +93,7 @@ This library has been refactored around streams.
|
||||
|
||||
#### Memory Streaming
|
||||
|
||||
To unzip from a zip file in memory create a memory stream and pass it to the unzip open functions.
|
||||
To unzip from a zip file in memory pass the memory stream to the open function.
|
||||
```
|
||||
uint8_t *zip_buffer = NULL;
|
||||
int32_t zip_buffer_size = 0;
|
||||
@@ -90,15 +102,15 @@ void *mem_stream = NULL;
|
||||
// fill zip_buffer with zip contents
|
||||
mz_stream_mem_create(&mem_stream);
|
||||
mz_stream_mem_set_buffer(mem_stream, zip_buffer, zip_buffer_size);
|
||||
mz_stream_open(mem_stream, NULL, MZ_STREAM_MODE_READ);
|
||||
mz_stream_open(mem_stream, NULL, MZ_OPEN_MODE_READ);
|
||||
|
||||
void *zip_handle = mz_zip_open(mem_stream, MZ_STREAM_MODE_READ);
|
||||
void *zip_handle = mz_zip_open(mem_stream, MZ_OPEN_MODE_READ);
|
||||
// do unzip operations
|
||||
|
||||
mz_stream_mem_delete(&mem_stream);
|
||||
```
|
||||
|
||||
To create a zip file in memory first create a growable memory stream and pass it to the zip open functions.
|
||||
To create a zip file in memory first create a growable memory stream and pass it to the open function.
|
||||
|
||||
```
|
||||
void *mem_stream = NULL;
|
||||
@@ -112,6 +124,9 @@ void *zip_handle = mz_zip_open(mem_stream, MZ_OPEN_MODE_WRITE);
|
||||
|
||||
mz_stream_mem_delete(&mem_stream);
|
||||
```
|
||||
|
||||
For a complete example, see test_zip_mem() in [test.c](https://github.com/nmoinvaz/minizip/blob/master/test/test.c).
|
||||
|
||||
#### Buffered Streaming
|
||||
|
||||
By default the library will read bytes typically one at a time. The buffered stream allows for buffered read and write operations to improve I/O performance.
|
||||
@@ -132,7 +147,7 @@ void *zip_handle = mz_zip_open(buf_stream, MZ_OPEN_MODE_READ);
|
||||
|
||||
#### Disk Splitting Stream
|
||||
|
||||
To create an archive with multiple disks use the disk splitting stream and for zipping supply a disk size value in bytes.
|
||||
To create an archive with multiple disks use the disk splitting stream and supply a disk size value in bytes.
|
||||
|
||||
```
|
||||
void *stream = NULL;
|
||||
@@ -147,13 +162,9 @@ mz_stream_set_base(split_stream, stream);
|
||||
|
||||
mz_stream_open(split_stream, path..
|
||||
|
||||
handle = mz_zip_open(split_stream, MZ_OPEN_MODE_WRITE);
|
||||
void *zip_handle = mz_zip_open(split_stream, MZ_OPEN_MODE_WRITE);
|
||||
```
|
||||
|
||||
The central directory is the only data stored in the .zip and doesn't follow disk size restrictions.
|
||||
|
||||
When unzipping it will automatically determine when in needs to cross disk boundaries.
|
||||
|
||||
### Windows RT
|
||||
|
||||
+ Requires ``#define MZ_USE_WINRT_API``
|
||||
@@ -163,3 +174,4 @@ When unzipping it will automatically determine when in needs to cross disk bound
|
||||
+ Archives are required to have a central directory.
|
||||
+ Central directory header values should be correct and it is necessary for the compressed size to be accurate for AES encryption.
|
||||
+ Central directory encryption is not supported due to licensing restrictions mentioned by PKWARE in their zip appnote.
|
||||
+ Central directory is the only data stored on the last disk of a split-disk archive and doesn't follow disk size restrictions.
|
||||
|
||||
@@ -1,687 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 09/09/2014
|
||||
*/
|
||||
|
||||
#include "aes_ni.h"
|
||||
|
||||
#if defined( USE_INTEL_AES_IF_PRESENT )
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(__cpuid)
|
||||
#define INLINE __inline
|
||||
|
||||
INLINE int has_aes_ni(void)
|
||||
{
|
||||
static int test = -1;
|
||||
if(test < 0)
|
||||
{
|
||||
int cpu_info[4];
|
||||
__cpuid(cpu_info, 1);
|
||||
test = cpu_info[2] & 0x02000000;
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
#elif defined( __GNUC__ )
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
#if !defined(__clang__)
|
||||
#pragma GCC target ("ssse3")
|
||||
#pragma GCC target ("sse4.1")
|
||||
#pragma GCC target ("aes")
|
||||
#endif
|
||||
|
||||
#include <x86intrin.h>
|
||||
#define INLINE static __inline
|
||||
|
||||
INLINE int has_aes_ni()
|
||||
{
|
||||
static int test = -1;
|
||||
if(test < 0)
|
||||
{
|
||||
unsigned int a, b, c, d;
|
||||
if(!__get_cpuid(1, &a, &b, &c, &d))
|
||||
test = 0;
|
||||
else
|
||||
test = (c & 0x2000000);
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
#else
|
||||
#error AES New Instructions require Microsoft, Intel, GNU C, or CLANG
|
||||
#endif
|
||||
|
||||
INLINE __m128i aes_128_assist(__m128i t1, __m128i t2)
|
||||
{
|
||||
__m128i t3;
|
||||
t2 = _mm_shuffle_epi32(t2, 0xff);
|
||||
t3 = _mm_slli_si128(t1, 0x4);
|
||||
t1 = _mm_xor_si128(t1, t3);
|
||||
t3 = _mm_slli_si128(t3, 0x4);
|
||||
t1 = _mm_xor_si128(t1, t3);
|
||||
t3 = _mm_slli_si128(t3, 0x4);
|
||||
t1 = _mm_xor_si128(t1, t3);
|
||||
t1 = _mm_xor_si128(t1, t2);
|
||||
return t1;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1])
|
||||
{
|
||||
__m128i t1, t2;
|
||||
__m128i *ks = (__m128i*)cx->ks;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(encrypt_key128)(key, cx);
|
||||
}
|
||||
|
||||
t1 = _mm_loadu_si128((__m128i*)key);
|
||||
|
||||
ks[0] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x1);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[1] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x2);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[2] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x4);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[3] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x8);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[4] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x10);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[5] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x20);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[6] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x40);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[7] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x80);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[8] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x1b);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[9] = t1;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t1, 0x36);
|
||||
t1 = aes_128_assist(t1, t2);
|
||||
ks[10] = t1;
|
||||
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 10 * 16;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
INLINE void aes_192_assist(__m128i* t1, __m128i * t2, __m128i * t3)
|
||||
{
|
||||
__m128i t4;
|
||||
*t2 = _mm_shuffle_epi32(*t2, 0x55);
|
||||
t4 = _mm_slli_si128(*t1, 0x4);
|
||||
*t1 = _mm_xor_si128(*t1, t4);
|
||||
t4 = _mm_slli_si128(t4, 0x4);
|
||||
*t1 = _mm_xor_si128(*t1, t4);
|
||||
t4 = _mm_slli_si128(t4, 0x4);
|
||||
*t1 = _mm_xor_si128(*t1, t4);
|
||||
*t1 = _mm_xor_si128(*t1, *t2);
|
||||
*t2 = _mm_shuffle_epi32(*t1, 0xff);
|
||||
t4 = _mm_slli_si128(*t3, 0x4);
|
||||
*t3 = _mm_xor_si128(*t3, t4);
|
||||
*t3 = _mm_xor_si128(*t3, *t2);
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1])
|
||||
{
|
||||
__m128i t1, t2, t3;
|
||||
__m128i *ks = (__m128i*)cx->ks;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(encrypt_key192)(key, cx);
|
||||
}
|
||||
|
||||
t1 = _mm_loadu_si128((__m128i*)key);
|
||||
t3 = _mm_loadu_si128((__m128i*)(key + 16));
|
||||
|
||||
ks[0] = t1;
|
||||
ks[1] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x1);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
|
||||
ks[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[1]), _mm_castsi128_pd(t1), 0));
|
||||
ks[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x2);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[3] = t1;
|
||||
ks[4] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x4);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[4]), _mm_castsi128_pd(t1), 0));
|
||||
ks[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x8);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[6] = t1;
|
||||
ks[7] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x10);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[7]), _mm_castsi128_pd(t1), 0));
|
||||
ks[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x20);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[9] = t1;
|
||||
ks[10] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x40);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(ks[10]), _mm_castsi128_pd(t1), 0));
|
||||
ks[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(t1), _mm_castsi128_pd(t3), 1));
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x80);
|
||||
aes_192_assist(&t1, &t2, &t3);
|
||||
ks[12] = t1;
|
||||
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 12 * 16;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
INLINE void aes_256_assist1(__m128i* t1, __m128i * t2)
|
||||
{
|
||||
__m128i t4;
|
||||
*t2 = _mm_shuffle_epi32(*t2, 0xff);
|
||||
t4 = _mm_slli_si128(*t1, 0x4);
|
||||
*t1 = _mm_xor_si128(*t1, t4);
|
||||
t4 = _mm_slli_si128(t4, 0x4);
|
||||
*t1 = _mm_xor_si128(*t1, t4);
|
||||
t4 = _mm_slli_si128(t4, 0x4);
|
||||
*t1 = _mm_xor_si128(*t1, t4);
|
||||
*t1 = _mm_xor_si128(*t1, *t2);
|
||||
}
|
||||
|
||||
INLINE void aes_256_assist2(__m128i* t1, __m128i * t3)
|
||||
{
|
||||
__m128i t2, t4;
|
||||
t4 = _mm_aeskeygenassist_si128(*t1, 0x0);
|
||||
t2 = _mm_shuffle_epi32(t4, 0xaa);
|
||||
t4 = _mm_slli_si128(*t3, 0x4);
|
||||
*t3 = _mm_xor_si128(*t3, t4);
|
||||
t4 = _mm_slli_si128(t4, 0x4);
|
||||
*t3 = _mm_xor_si128(*t3, t4);
|
||||
t4 = _mm_slli_si128(t4, 0x4);
|
||||
*t3 = _mm_xor_si128(*t3, t4);
|
||||
*t3 = _mm_xor_si128(*t3, t2);
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1])
|
||||
{
|
||||
__m128i t1, t2, t3;
|
||||
__m128i *ks = (__m128i*)cx->ks;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(encrypt_key256)(key, cx);
|
||||
}
|
||||
|
||||
t1 = _mm_loadu_si128((__m128i*)key);
|
||||
t3 = _mm_loadu_si128((__m128i*)(key + 16));
|
||||
|
||||
ks[0] = t1;
|
||||
ks[1] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x01);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[2] = t1;
|
||||
aes_256_assist2(&t1, &t3);
|
||||
ks[3] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x02);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[4] = t1;
|
||||
aes_256_assist2(&t1, &t3);
|
||||
ks[5] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x04);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[6] = t1;
|
||||
aes_256_assist2(&t1, &t3);
|
||||
ks[7] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x08);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[8] = t1;
|
||||
aes_256_assist2(&t1, &t3);
|
||||
ks[9] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x10);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[10] = t1;
|
||||
aes_256_assist2(&t1, &t3);
|
||||
ks[11] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x20);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[12] = t1;
|
||||
aes_256_assist2(&t1, &t3);
|
||||
ks[13] = t3;
|
||||
|
||||
t2 = _mm_aeskeygenassist_si128(t3, 0x40);
|
||||
aes_256_assist1(&t1, &t2);
|
||||
ks[14] = t1;
|
||||
|
||||
cx->inf.l = 0;
|
||||
cx->inf.b[0] = 14 * 16;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
INLINE void enc_to_dec(aes_decrypt_ctx cx[1])
|
||||
{
|
||||
__m128i *ks = (__m128i*)cx->ks;
|
||||
int j;
|
||||
|
||||
for( j = 1 ; j < (cx->inf.b[0] >> 4) ; ++j )
|
||||
ks[j] = _mm_aesimc_si128(ks[j]);
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1])
|
||||
{
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(decrypt_key128)(key, cx);
|
||||
}
|
||||
|
||||
if(aes_ni(encrypt_key128)(key, (aes_encrypt_ctx*)cx) == EXIT_SUCCESS)
|
||||
{
|
||||
enc_to_dec(cx);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1])
|
||||
{
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(decrypt_key192)(key, cx);
|
||||
}
|
||||
|
||||
if(aes_ni(encrypt_key192)(key, (aes_encrypt_ctx*)cx) == EXIT_SUCCESS)
|
||||
{
|
||||
enc_to_dec(cx);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1])
|
||||
{
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(decrypt_key256)(key, cx);
|
||||
}
|
||||
|
||||
if(aes_ni(encrypt_key256)(key, (aes_encrypt_ctx*)cx) == EXIT_SUCCESS)
|
||||
{
|
||||
enc_to_dec(cx);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1])
|
||||
{
|
||||
__m128i *key = (__m128i*)cx->ks, t;
|
||||
|
||||
if(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(encrypt)(in, out, cx);
|
||||
}
|
||||
|
||||
t = _mm_xor_si128(_mm_loadu_si128((__m128i*)in), *(__m128i*)key);
|
||||
|
||||
switch(cx->inf.b[0])
|
||||
{
|
||||
case 14 * 16:
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
case 12 * 16:
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
case 10 * 16:
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenc_si128(t, *(__m128i*)++key);
|
||||
t = _mm_aesenclast_si128(t, *(__m128i*)++key);
|
||||
}
|
||||
|
||||
_mm_storeu_si128(&((__m128i*)out)[0], t);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_ni(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1])
|
||||
{
|
||||
__m128i *key = (__m128i*)cx->ks + (cx->inf.b[0] >> 4), t;
|
||||
|
||||
if(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_xi(decrypt)(in, out, cx);
|
||||
}
|
||||
|
||||
t = _mm_xor_si128(_mm_loadu_si128((__m128i*)in), *(__m128i*)key);
|
||||
|
||||
switch(cx->inf.b[0])
|
||||
{
|
||||
case 14 * 16:
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
case 12 * 16:
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
case 10 * 16:
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdec_si128(t, *(__m128i*)--key);
|
||||
t = _mm_aesdeclast_si128(t, *(__m128i*)--key);
|
||||
}
|
||||
|
||||
_mm_storeu_si128((__m128i*)out, t);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ADD_AESNI_MODE_CALLS
|
||||
#ifdef USE_AES_CONTEXT
|
||||
|
||||
AES_RETURN aes_CBC_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
unsigned char ivec[16],
|
||||
unsigned long length,
|
||||
const aes_encrypt_ctx cx[1])
|
||||
{
|
||||
__m128i feedback, data, *key = (__m128i*)cx->ks;
|
||||
int number_of_rounds = cx->inf.b[0] >> 4, j;
|
||||
unsigned long i;
|
||||
|
||||
if(number_of_rounds != 10 && number_of_rounds != 12 && number_of_rounds != 14)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_cbc_encrypt(in, out, length, ivec, cx);
|
||||
}
|
||||
|
||||
if(length % 16)
|
||||
length = length / 16 + 1;
|
||||
else length /= 16;
|
||||
feedback = _mm_loadu_si128((__m128i*)ivec);
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
data = _mm_loadu_si128(&((__m128i*)in)[i]);
|
||||
feedback = _mm_xor_si128(data, feedback);
|
||||
feedback = _mm_xor_si128(feedback, ((__m128i*)key)[0]);
|
||||
for(j = 1; j <number_of_rounds; j++)
|
||||
feedback = _mm_aesenc_si128(feedback, ((__m128i*)key)[j]);
|
||||
feedback = _mm_aesenclast_si128(feedback, ((__m128i*)key)[j]);
|
||||
_mm_storeu_si128(&((__m128i*)out)[i], feedback);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
AES_RETURN aes_CBC_decrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
unsigned char ivec[16],
|
||||
unsigned long length,
|
||||
const aes_decrypt_ctx cx[1])
|
||||
{
|
||||
__m128i data, feedback, last_in, *key = (__m128i*)cx->ks;
|
||||
int number_of_rounds = cx->inf.b[0] >> 4, j;
|
||||
unsigned long i;
|
||||
|
||||
if(number_of_rounds != 10 && number_of_rounds != 12 && number_of_rounds != 14)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
return aes_cbc_decrypt(in, out, length, ivec, cx);
|
||||
}
|
||||
|
||||
if(length % 16)
|
||||
length = length / 16 + 1;
|
||||
else length /= 16;
|
||||
feedback = _mm_loadu_si128((__m128i*)ivec);
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
last_in = _mm_loadu_si128(&((__m128i*)in)[i]);
|
||||
data = _mm_xor_si128(last_in, ((__m128i*)key)[number_of_rounds]);
|
||||
for(j = number_of_rounds - 1; j > 0; j--)
|
||||
{
|
||||
data = _mm_aesdec_si128(data, ((__m128i*)key)[j]);
|
||||
}
|
||||
data = _mm_aesdeclast_si128(data, ((__m128i*)key)[0]);
|
||||
data = _mm_xor_si128(data, feedback);
|
||||
_mm_storeu_si128(&((__m128i*)out)[i], data);
|
||||
feedback = last_in;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void ctr_inc(unsigned char *ctr_blk)
|
||||
{
|
||||
uint32_t c;
|
||||
|
||||
c = *(uint32_t*)(ctr_blk + 8);
|
||||
c++;
|
||||
*(uint32_t*)(ctr_blk + 8) = c;
|
||||
|
||||
if(!c)
|
||||
*(uint32_t*)(ctr_blk + 12) = *(uint32_t*)(ctr_blk + 12) + 1;
|
||||
}
|
||||
|
||||
AES_RETURN AES_CTR_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
const unsigned char ivec[8],
|
||||
const unsigned char nonce[4],
|
||||
unsigned long length,
|
||||
const aes_encrypt_ctx cx[1])
|
||||
{
|
||||
__m128i ctr_block = { 0 }, *key = (__m128i*)cx->ks, tmp, ONE, BSWAP_EPI64;
|
||||
int number_of_rounds = cx->inf.b[0] >> 4, j;
|
||||
unsigned long i;
|
||||
|
||||
if(number_of_rounds != 10 && number_of_rounds != 12 && number_of_rounds != 14)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if(!has_aes_ni())
|
||||
{
|
||||
unsigned char ctr_blk[16];
|
||||
*(uint64_t*)ctr_blk = *(uint64_t*)ivec;
|
||||
*(uint32_t*)(ctr_blk + 8) = *(uint32_t*)nonce;
|
||||
return aes_ctr_crypt(in, out, length, (unsigned char*)ctr_blk, ctr_inc, cx);
|
||||
}
|
||||
|
||||
if(length % 16)
|
||||
length = length / 16 + 1;
|
||||
else length /= 16;
|
||||
ONE = _mm_set_epi32(0, 1, 0, 0);
|
||||
BSWAP_EPI64 = _mm_setr_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);
|
||||
#ifdef _MSC_VER
|
||||
ctr_block = _mm_insert_epi64(ctr_block, *(long long*)ivec, 1);
|
||||
#else
|
||||
ctr_block = _mm_set_epi64(*(__m64*)ivec, *(__m64*)&ctr_block);
|
||||
#endif
|
||||
ctr_block = _mm_insert_epi32(ctr_block, *(long*)nonce, 1);
|
||||
ctr_block = _mm_srli_si128(ctr_block, 4);
|
||||
ctr_block = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);
|
||||
ctr_block = _mm_add_epi64(ctr_block, ONE);
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
tmp = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);
|
||||
ctr_block = _mm_add_epi64(ctr_block, ONE);
|
||||
tmp = _mm_xor_si128(tmp, ((__m128i*)key)[0]);
|
||||
for(j = 1; j <number_of_rounds; j++)
|
||||
{
|
||||
tmp = _mm_aesenc_si128(tmp, ((__m128i*)key)[j]);
|
||||
};
|
||||
tmp = _mm_aesenclast_si128(tmp, ((__m128i*)key)[j]);
|
||||
tmp = _mm_xor_si128(tmp, _mm_loadu_si128(&((__m128i*)in)[i]));
|
||||
_mm_storeu_si128(&((__m128i*)out)[i], tmp);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void aes_CBC_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
unsigned char ivec[16],
|
||||
unsigned long length,
|
||||
unsigned char *key,
|
||||
int number_of_rounds)
|
||||
{
|
||||
__m128i feedback, data;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if(length % 16)
|
||||
length = length / 16 + 1;
|
||||
else length /= 16;
|
||||
feedback = _mm_loadu_si128((__m128i*)ivec);
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
data = _mm_loadu_si128(&((__m128i*)in)[i]);
|
||||
feedback = _mm_xor_si128(data, feedback);
|
||||
feedback = _mm_xor_si128(feedback, ((__m128i*)key)[0]);
|
||||
for(j = 1; j <number_of_rounds; j++)
|
||||
feedback = _mm_aesenc_si128(feedback, ((__m128i*)key)[j]);
|
||||
feedback = _mm_aesenclast_si128(feedback, ((__m128i*)key)[j]);
|
||||
_mm_storeu_si128(&((__m128i*)out)[i], feedback);
|
||||
}
|
||||
}
|
||||
|
||||
void aes_CBC_decrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
unsigned char ivec[16],
|
||||
unsigned long length,
|
||||
unsigned char *key,
|
||||
int number_of_rounds)
|
||||
{
|
||||
__m128i data, feedback, last_in;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if(length % 16)
|
||||
length = length / 16 + 1;
|
||||
else length /= 16;
|
||||
feedback = _mm_loadu_si128((__m128i*)ivec);
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
last_in = _mm_loadu_si128(&((__m128i*)in)[i]);
|
||||
data = _mm_xor_si128(last_in, ((__m128i*)key)[0]);
|
||||
for(j = 1; j <number_of_rounds; j++)
|
||||
{
|
||||
data = _mm_aesdec_si128(data, ((__m128i*)key)[j]);
|
||||
}
|
||||
data = _mm_aesdeclast_si128(data, ((__m128i*)key)[j]);
|
||||
data = _mm_xor_si128(data, feedback);
|
||||
_mm_storeu_si128(&((__m128i*)out)[i], data);
|
||||
feedback = last_in;
|
||||
}
|
||||
}
|
||||
|
||||
void AES_CTR_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
const unsigned char ivec[8],
|
||||
const unsigned char nonce[4],
|
||||
unsigned long length,
|
||||
const unsigned char *key,
|
||||
int number_of_rounds)
|
||||
{
|
||||
__m128i ctr_block = { 0 }, tmp, ONE, BSWAP_EPI64;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if(length % 16)
|
||||
length = length / 16 + 1;
|
||||
else length /= 16;
|
||||
ONE = _mm_set_epi32(0, 1, 0, 0);
|
||||
BSWAP_EPI64 = _mm_setr_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);
|
||||
#ifdef _MSC_VER
|
||||
ctr_block = _mm_insert_epi64(ctr_block, *(long long*)ivec, 1);
|
||||
#else
|
||||
ctr_block = _mm_set_epi64(*(__m64*)ivec, *(__m64*)&ctr_block);
|
||||
#endif
|
||||
ctr_block = _mm_insert_epi32(ctr_block, *(long*)nonce, 1);
|
||||
ctr_block = _mm_srli_si128(ctr_block, 4);
|
||||
ctr_block = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);
|
||||
ctr_block = _mm_add_epi64(ctr_block, ONE);
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
tmp = _mm_shuffle_epi8(ctr_block, BSWAP_EPI64);
|
||||
ctr_block = _mm_add_epi64(ctr_block, ONE);
|
||||
tmp = _mm_xor_si128(tmp, ((__m128i*)key)[0]);
|
||||
for(j = 1; j <number_of_rounds; j++)
|
||||
{
|
||||
tmp = _mm_aesenc_si128(tmp, ((__m128i*)key)[j]);
|
||||
};
|
||||
tmp = _mm_aesenclast_si128(tmp, ((__m128i*)key)[j]);
|
||||
tmp = _mm_xor_si128(tmp, _mm_loadu_si128(&((__m128i*)in)[i]));
|
||||
_mm_storeu_si128(&((__m128i*)out)[i], tmp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
The redistribution and use of this software (with or without changes)
|
||||
is allowed without the payment of fees or royalties provided that:
|
||||
|
||||
source code distributions include the above copyright notice, this
|
||||
list of conditions and the following disclaimer;
|
||||
|
||||
binary distributions include the above copyright notice, this list
|
||||
of conditions and the following disclaimer in their documentation.
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its operation, including, but not limited to, correctness
|
||||
and fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 13/11/2013
|
||||
*/
|
||||
|
||||
#ifndef AES_NI_H
|
||||
#define AES_NI_H
|
||||
|
||||
#define USE_AES_CONTEXT
|
||||
|
||||
#include "aesopt.h"
|
||||
|
||||
#if defined( USE_INTEL_AES_IF_PRESENT )
|
||||
|
||||
/* map names in C code to make them internal ('name' -> 'aes_name_i') */
|
||||
#define aes_xi(x) aes_ ## x ## _i
|
||||
|
||||
/* map names here to provide the external API ('name' -> 'aes_name') */
|
||||
#define aes_ni(x) aes_ ## x
|
||||
|
||||
AES_RETURN aes_ni(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_ni(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_ni(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_ni(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_ni(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_ni(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_ni(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_ni(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_xi(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_xi(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_xi(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_xi(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
AES_RETURN aes_xi(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1]);
|
||||
|
||||
AES_RETURN aes_xi(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]);
|
||||
AES_RETURN aes_xi(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -188,7 +188,7 @@ Issue Date: 20/12/2007
|
||||
built
|
||||
*/
|
||||
|
||||
#if 1 && defined( INTEL_AES_POSSIBLE ) && !defined( USE_INTEL_AES_IF_PRESENT )
|
||||
#if 0 && defined( INTEL_AES_POSSIBLE ) && !defined( USE_INTEL_AES_IF_PRESENT )
|
||||
# define USE_INTEL_AES_IF_PRESENT
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
-------------------------------------------------------------------------
|
||||
Issue Date: 24/01/2003
|
||||
|
||||
This file implements password based file encryption and authentication
|
||||
using AES in CTR mode, HMAC-SHA1 authentication and RFC2898 password
|
||||
based key derivation.
|
||||
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "fileenc.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* subroutine for data encryption/decryption */
|
||||
/* this could be speeded up a lot by aligning */
|
||||
/* buffers and using 32 bit operations */
|
||||
|
||||
static void encr_data(unsigned char data[], unsigned long d_len, fcrypt_ctx cx[1])
|
||||
{
|
||||
unsigned int i = 0, pos = cx->encr_pos;
|
||||
|
||||
while (i < d_len)
|
||||
{
|
||||
if (pos == AES_BLOCK_SIZE)
|
||||
{
|
||||
unsigned int j = 0;
|
||||
/* increment encryption nonce */
|
||||
while (j < 8 && !++cx->nonce[j])
|
||||
++j;
|
||||
/* encrypt the nonce to form next xor buffer */
|
||||
aes_encrypt(cx->nonce, cx->encr_bfr, cx->encr_ctx);
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
data[i++] ^= cx->encr_bfr[pos++];
|
||||
}
|
||||
|
||||
cx->encr_pos = pos;
|
||||
}
|
||||
|
||||
int fcrypt_init(
|
||||
int mode, /* the mode to be used (input) */
|
||||
const unsigned char pwd[], /* the user specified password (input) */
|
||||
unsigned int pwd_len, /* the length of the password (input) */
|
||||
const unsigned char salt[], /* the salt (input) */
|
||||
#ifdef PASSWORD_VERIFIER
|
||||
unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */
|
||||
#endif
|
||||
fcrypt_ctx cx[1]) /* the file encryption context (output) */
|
||||
{ unsigned char kbuf[2 * MAX_KEY_LENGTH + PWD_VER_LENGTH];
|
||||
|
||||
if (pwd_len > MAX_PWD_LENGTH)
|
||||
return PASSWORD_TOO_LONG;
|
||||
|
||||
if (mode < 1 || mode > 3)
|
||||
return BAD_MODE;
|
||||
|
||||
cx->mode = mode;
|
||||
cx->pwd_len = pwd_len;
|
||||
|
||||
/* derive the encryption and authentication keys and the password verifier */
|
||||
derive_key(pwd, pwd_len, salt, SALT_LENGTH(mode), KEYING_ITERATIONS,
|
||||
kbuf, 2 * KEY_LENGTH(mode) + PWD_VER_LENGTH);
|
||||
|
||||
/* initialise the encryption nonce and buffer pos */
|
||||
cx->encr_pos = AES_BLOCK_SIZE;
|
||||
/* if we need a random component in the encryption */
|
||||
/* nonce, this is where it would have to be set */
|
||||
memset(cx->nonce, 0, AES_BLOCK_SIZE * sizeof(unsigned char));
|
||||
|
||||
/* initialise for encryption using key 1 */
|
||||
aes_encrypt_key(kbuf, KEY_LENGTH(mode), cx->encr_ctx);
|
||||
|
||||
/* initialise for authentication using key 2 */
|
||||
hmac_sha_begin(HMAC_SHA1, cx->auth_ctx);
|
||||
hmac_sha_key(kbuf + KEY_LENGTH(mode), KEY_LENGTH(mode), cx->auth_ctx);
|
||||
|
||||
#ifdef PASSWORD_VERIFIER
|
||||
memcpy(pwd_ver, kbuf + 2 * KEY_LENGTH(mode), PWD_VER_LENGTH);
|
||||
#endif
|
||||
|
||||
return GOOD_RETURN;
|
||||
}
|
||||
|
||||
/* perform 'in place' encryption and authentication */
|
||||
|
||||
void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1])
|
||||
{
|
||||
encr_data(data, data_len, cx);
|
||||
hmac_sha_data(data, data_len, cx->auth_ctx);
|
||||
}
|
||||
|
||||
/* perform 'in place' authentication and decryption */
|
||||
|
||||
void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1])
|
||||
{
|
||||
hmac_sha_data(data, data_len, cx->auth_ctx);
|
||||
encr_data(data, data_len, cx);
|
||||
}
|
||||
|
||||
/* close encryption/decryption and return the MAC value */
|
||||
|
||||
int fcrypt_end(unsigned char mac[], fcrypt_ctx cx[1])
|
||||
{
|
||||
hmac_sha_end(mac, MAC_LENGTH(cx->mode), cx->auth_ctx);
|
||||
return MAC_LENGTH(cx->mode); /* return MAC length in bytes */
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 24/01/2003
|
||||
|
||||
This file contains the header file for fileenc.c, which implements password
|
||||
based file encryption and authentication using AES in CTR mode, HMAC-SHA1
|
||||
authentication and RFC2898 password based key derivation.
|
||||
*/
|
||||
|
||||
#ifndef _FENC_H
|
||||
#define _FENC_H
|
||||
|
||||
#include "aes.h"
|
||||
#include "hmac.h"
|
||||
#include "pwd2key.h"
|
||||
|
||||
#define PASSWORD_VERIFIER
|
||||
|
||||
#define MAX_KEY_LENGTH 32
|
||||
#define MAX_PWD_LENGTH 128
|
||||
#define MAX_SALT_LENGTH 16
|
||||
#define KEYING_ITERATIONS 1000
|
||||
|
||||
#ifdef PASSWORD_VERIFIER
|
||||
#define PWD_VER_LENGTH 2
|
||||
#else
|
||||
#define PWD_VER_LENGTH 0
|
||||
#endif
|
||||
|
||||
#define GOOD_RETURN 0
|
||||
#define PASSWORD_TOO_LONG -100
|
||||
#define BAD_MODE -101
|
||||
|
||||
/*
|
||||
Field lengths (in bytes) versus File Encryption Mode (0 < mode < 4)
|
||||
|
||||
Mode Key Salt MAC Overhead
|
||||
1 16 8 10 18
|
||||
2 24 12 10 22
|
||||
3 32 16 10 26
|
||||
|
||||
The following macros assume that the mode value is correct.
|
||||
*/
|
||||
|
||||
#define KEY_LENGTH(mode) (8 * (mode & 3) + 8)
|
||||
#define SALT_LENGTH(mode) (4 * (mode & 3) + 4)
|
||||
#define MAC_LENGTH(mode) (10)
|
||||
|
||||
/* the context for file encryption */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{ unsigned char nonce[AES_BLOCK_SIZE]; /* the CTR nonce */
|
||||
unsigned char encr_bfr[AES_BLOCK_SIZE]; /* encrypt buffer */
|
||||
aes_encrypt_ctx encr_ctx[1]; /* encryption context */
|
||||
hmac_ctx auth_ctx[1]; /* authentication context */
|
||||
unsigned int encr_pos; /* block position (enc) */
|
||||
unsigned int pwd_len; /* password length */
|
||||
unsigned int mode; /* File encryption mode */
|
||||
} fcrypt_ctx;
|
||||
|
||||
/* initialise file encryption or decryption */
|
||||
|
||||
int fcrypt_init(
|
||||
int mode, /* the mode to be used (input) */
|
||||
const unsigned char pwd[], /* the user specified password (input) */
|
||||
unsigned int pwd_len, /* the length of the password (input) */
|
||||
const unsigned char salt[], /* the salt (input) */
|
||||
#ifdef PASSWORD_VERIFIER
|
||||
unsigned char pwd_ver[PWD_VER_LENGTH], /* 2 byte password verifier (output) */
|
||||
#endif
|
||||
fcrypt_ctx cx[1]); /* the file encryption context (output) */
|
||||
|
||||
/* perform 'in place' encryption or decryption and authentication */
|
||||
|
||||
void fcrypt_encrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]);
|
||||
void fcrypt_decrypt(unsigned char data[], unsigned int data_len, fcrypt_ctx cx[1]);
|
||||
|
||||
/* close encryption/decryption and return the MAC value */
|
||||
/* the return value is the length of the MAC */
|
||||
|
||||
int fcrypt_end(unsigned char mac[], /* the MAC value (output) */
|
||||
fcrypt_ctx cx[1]); /* the context (input) */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -23,6 +23,7 @@ a password and a salt value.
|
||||
|
||||
#include <string.h>
|
||||
#include "hmac.h"
|
||||
#include "pwd2key.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
|
||||
@@ -292,21 +292,21 @@ extern "C" {
|
||||
|
||||
/* Filters */
|
||||
#include "lzma/filter.h"
|
||||
#include "lzma/bcj.h"
|
||||
#include "lzma/delta.h"
|
||||
//#include "lzma/bcj.h"
|
||||
//#include "lzma/delta.h"
|
||||
#include "lzma/lzma12.h"
|
||||
|
||||
/* Container formats */
|
||||
#include "lzma/container.h"
|
||||
|
||||
/* Advanced features */
|
||||
#include "lzma/stream_flags.h"
|
||||
#include "lzma/block.h"
|
||||
#include "lzma/index.h"
|
||||
#include "lzma/index_hash.h"
|
||||
//#include "lzma/stream_flags.h"
|
||||
//#include "lzma/block.h"
|
||||
//#include "lzma/index.h"
|
||||
//#include "lzma/index_hash.h"
|
||||
|
||||
/* Hardware information */
|
||||
#include "lzma/hardware.h"
|
||||
//#include "lzma/hardware.h"
|
||||
|
||||
/*
|
||||
* All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* \file lzma/bcj.h
|
||||
* \brief Branch/Call/Jump conversion filters
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/* Filter IDs for lzma_filter.id */
|
||||
|
||||
#define LZMA_FILTER_X86 LZMA_VLI_C(0x04)
|
||||
/**<
|
||||
* Filter for x86 binaries
|
||||
*/
|
||||
|
||||
#define LZMA_FILTER_POWERPC LZMA_VLI_C(0x05)
|
||||
/**<
|
||||
* Filter for Big endian PowerPC binaries
|
||||
*/
|
||||
|
||||
#define LZMA_FILTER_IA64 LZMA_VLI_C(0x06)
|
||||
/**<
|
||||
* Filter for IA-64 (Itanium) binaries.
|
||||
*/
|
||||
|
||||
#define LZMA_FILTER_ARM LZMA_VLI_C(0x07)
|
||||
/**<
|
||||
* Filter for ARM binaries.
|
||||
*/
|
||||
|
||||
#define LZMA_FILTER_ARMTHUMB LZMA_VLI_C(0x08)
|
||||
/**<
|
||||
* Filter for ARM-Thumb binaries.
|
||||
*/
|
||||
|
||||
#define LZMA_FILTER_SPARC LZMA_VLI_C(0x09)
|
||||
/**<
|
||||
* Filter for SPARC binaries.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options for BCJ filters
|
||||
*
|
||||
* The BCJ filters never change the size of the data. Specifying options
|
||||
* for them is optional: if pointer to options is NULL, default value is
|
||||
* used. You probably never need to specify options to BCJ filters, so just
|
||||
* set the options pointer to NULL and be happy.
|
||||
*
|
||||
* If options with non-default values have been specified when encoding,
|
||||
* the same options must also be specified when decoding.
|
||||
*
|
||||
* \note At the moment, none of the BCJ filters support
|
||||
* LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified,
|
||||
* LZMA_OPTIONS_ERROR will be returned. If there is need,
|
||||
* partial support for LZMA_SYNC_FLUSH can be added in future.
|
||||
* Partial means that flushing would be possible only at
|
||||
* offsets that are multiple of 2, 4, or 16 depending on
|
||||
* the filter, except x86 which cannot be made to support
|
||||
* LZMA_SYNC_FLUSH predictably.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Start offset for conversions
|
||||
*
|
||||
* This setting is useful only when the same filter is used
|
||||
* _separately_ for multiple sections of the same executable file,
|
||||
* and the sections contain cross-section branch/call/jump
|
||||
* instructions. In that case it is beneficial to set the start
|
||||
* offset of the non-first sections so that the relative addresses
|
||||
* of the cross-section branch/call/jump instructions will use the
|
||||
* same absolute addresses as in the first section.
|
||||
*
|
||||
* When the pointer to options is NULL, the default value (zero)
|
||||
* is used.
|
||||
*/
|
||||
uint32_t start_offset;
|
||||
|
||||
} lzma_options_bcj;
|
||||
@@ -1,581 +0,0 @@
|
||||
/**
|
||||
* \file lzma/block.h
|
||||
* \brief .xz Block handling
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options for the Block and Block Header encoders and decoders
|
||||
*
|
||||
* Different Block handling functions use different parts of this structure.
|
||||
* Some read some members, other functions write, and some do both. Only the
|
||||
* members listed for reading need to be initialized when the specified
|
||||
* functions are called. The members marked for writing will be assigned
|
||||
* new values at some point either by calling the given function or by
|
||||
* later calls to lzma_code().
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Block format version
|
||||
*
|
||||
* To prevent API and ABI breakages when new features are needed,
|
||||
* a version number is used to indicate which fields in this
|
||||
* structure are in use:
|
||||
* - liblzma >= 5.0.0: version = 0 is supported.
|
||||
* - liblzma >= 5.1.4beta: Support for version = 1 was added,
|
||||
* which adds the ignore_check field.
|
||||
*
|
||||
* If version is greater than one, most Block related functions
|
||||
* will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
|
||||
* with any version value).
|
||||
*
|
||||
* Read by:
|
||||
* - All functions that take pointer to lzma_block as argument,
|
||||
* including lzma_block_header_decode().
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decode()
|
||||
*/
|
||||
uint32_t version;
|
||||
|
||||
/**
|
||||
* \brief Size of the Block Header field
|
||||
*
|
||||
* This is always a multiple of four.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_compressed_size()
|
||||
* - lzma_block_unpadded_size()
|
||||
* - lzma_block_total_size()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_decode()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_buffer_encode()
|
||||
*/
|
||||
uint32_t header_size;
|
||||
# define LZMA_BLOCK_HEADER_SIZE_MIN 8
|
||||
# define LZMA_BLOCK_HEADER_SIZE_MAX 1024
|
||||
|
||||
/**
|
||||
* \brief Type of integrity Check
|
||||
*
|
||||
* The Check ID is not stored into the Block Header, thus its value
|
||||
* must be provided also when decoding.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_compressed_size()
|
||||
* - lzma_block_unpadded_size()
|
||||
* - lzma_block_total_size()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_encode()
|
||||
* - lzma_block_buffer_decode()
|
||||
*/
|
||||
lzma_check check;
|
||||
|
||||
/**
|
||||
* \brief Size of the Compressed Data in bytes
|
||||
*
|
||||
* Encoding: If this is not LZMA_VLI_UNKNOWN, Block Header encoder
|
||||
* will store this value to the Block Header. Block encoder doesn't
|
||||
* care about this value, but will set it once the encoding has been
|
||||
* finished.
|
||||
*
|
||||
* Decoding: If this is not LZMA_VLI_UNKNOWN, Block decoder will
|
||||
* verify that the size of the Compressed Data field matches
|
||||
* compressed_size.
|
||||
*
|
||||
* Usually you don't know this value when encoding in streamed mode,
|
||||
* and thus cannot write this field into the Block Header.
|
||||
*
|
||||
* In non-streamed mode you can reserve space for this field before
|
||||
* encoding the actual Block. After encoding the data, finish the
|
||||
* Block by encoding the Block Header. Steps in detail:
|
||||
*
|
||||
* - Set compressed_size to some big enough value. If you don't know
|
||||
* better, use LZMA_VLI_MAX, but remember that bigger values take
|
||||
* more space in Block Header.
|
||||
*
|
||||
* - Call lzma_block_header_size() to see how much space you need to
|
||||
* reserve for the Block Header.
|
||||
*
|
||||
* - Encode the Block using lzma_block_encoder() and lzma_code().
|
||||
* It sets compressed_size to the correct value.
|
||||
*
|
||||
* - Use lzma_block_header_encode() to encode the Block Header.
|
||||
* Because space was reserved in the first step, you don't need
|
||||
* to call lzma_block_header_size() anymore, because due to
|
||||
* reserving, header_size has to be big enough. If it is "too big",
|
||||
* lzma_block_header_encode() will add enough Header Padding to
|
||||
* make Block Header to match the size specified by header_size.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_compressed_size()
|
||||
* - lzma_block_unpadded_size()
|
||||
* - lzma_block_total_size()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_decode()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_compressed_size()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_encode()
|
||||
* - lzma_block_buffer_decode()
|
||||
*/
|
||||
lzma_vli compressed_size;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed Size in bytes
|
||||
*
|
||||
* This is handled very similarly to compressed_size above.
|
||||
*
|
||||
* uncompressed_size is needed by fewer functions than
|
||||
* compressed_size. This is because uncompressed_size isn't
|
||||
* needed to validate that Block stays within proper limits.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_decode()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decode()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_encode()
|
||||
* - lzma_block_buffer_decode()
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Array of filters
|
||||
*
|
||||
* There can be 1-4 filters. The end of the array is marked with
|
||||
* .id = LZMA_VLI_UNKNOWN.
|
||||
*
|
||||
* Read by:
|
||||
* - lzma_block_header_size()
|
||||
* - lzma_block_header_encode()
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_encode()
|
||||
* - lzma_block_buffer_decode()
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_header_decode(): Note that this does NOT free()
|
||||
* the old filter options structures. All unused filters[] will
|
||||
* have .id == LZMA_VLI_UNKNOWN and .options == NULL. If
|
||||
* decoding fails, all filters[] are guaranteed to be
|
||||
* LZMA_VLI_UNKNOWN and NULL.
|
||||
*
|
||||
* \note Because of the array is terminated with
|
||||
* .id = LZMA_VLI_UNKNOWN, the actual array must
|
||||
* have LZMA_FILTERS_MAX + 1 members or the Block
|
||||
* Header decoder will overflow the buffer.
|
||||
*/
|
||||
lzma_filter *filters;
|
||||
|
||||
/**
|
||||
* \brief Raw value stored in the Check field
|
||||
*
|
||||
* After successful coding, the first lzma_check_size(check) bytes
|
||||
* of this array contain the raw value stored in the Check field.
|
||||
*
|
||||
* Note that CRC32 and CRC64 are stored in little endian byte order.
|
||||
* Take it into account if you display the Check values to the user.
|
||||
*
|
||||
* Written by:
|
||||
* - lzma_block_encoder()
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_encode()
|
||||
* - lzma_block_buffer_decode()
|
||||
*/
|
||||
uint8_t raw_check[LZMA_CHECK_SIZE_MAX];
|
||||
|
||||
/*
|
||||
* Reserved space to allow possible future extensions without
|
||||
* breaking the ABI. You should not touch these, because the names
|
||||
* of these variables may change. These are and will never be used
|
||||
* with the currently supported options, so it is safe to leave these
|
||||
* uninitialized.
|
||||
*/
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
void *reserved_ptr3;
|
||||
uint32_t reserved_int1;
|
||||
uint32_t reserved_int2;
|
||||
lzma_vli reserved_int3;
|
||||
lzma_vli reserved_int4;
|
||||
lzma_vli reserved_int5;
|
||||
lzma_vli reserved_int6;
|
||||
lzma_vli reserved_int7;
|
||||
lzma_vli reserved_int8;
|
||||
lzma_reserved_enum reserved_enum1;
|
||||
lzma_reserved_enum reserved_enum2;
|
||||
lzma_reserved_enum reserved_enum3;
|
||||
lzma_reserved_enum reserved_enum4;
|
||||
|
||||
/**
|
||||
* \brief A flag to Block decoder to not verify the Check field
|
||||
*
|
||||
* This field is supported by liblzma >= 5.1.4beta if .version >= 1.
|
||||
*
|
||||
* If this is set to true, the integrity check won't be calculated
|
||||
* and verified. Unless you know what you are doing, you should
|
||||
* leave this to false. (A reason to set this to true is when the
|
||||
* file integrity is verified externally anyway and you want to
|
||||
* speed up the decompression, which matters mostly when using
|
||||
* SHA-256 as the integrity check.)
|
||||
*
|
||||
* If .version >= 1, read by:
|
||||
* - lzma_block_decoder()
|
||||
* - lzma_block_buffer_decode()
|
||||
*
|
||||
* Written by (.version is ignored):
|
||||
* - lzma_block_header_decode() always sets this to false
|
||||
*/
|
||||
lzma_bool ignore_check;
|
||||
|
||||
lzma_bool reserved_bool2;
|
||||
lzma_bool reserved_bool3;
|
||||
lzma_bool reserved_bool4;
|
||||
lzma_bool reserved_bool5;
|
||||
lzma_bool reserved_bool6;
|
||||
lzma_bool reserved_bool7;
|
||||
lzma_bool reserved_bool8;
|
||||
|
||||
} lzma_block;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode the Block Header Size field
|
||||
*
|
||||
* To decode Block Header using lzma_block_header_decode(), the size of the
|
||||
* Block Header has to be known and stored into lzma_block.header_size.
|
||||
* The size can be calculated from the first byte of a Block using this macro.
|
||||
* Note that if the first byte is 0x00, it indicates beginning of Index; use
|
||||
* this macro only when the byte is not 0x00.
|
||||
*
|
||||
* There is no encoding macro, because Block Header encoder is enough for that.
|
||||
*/
|
||||
#define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate Block Header Size
|
||||
*
|
||||
* Calculate the minimum size needed for the Block Header field using the
|
||||
* settings specified in the lzma_block structure. Note that it is OK to
|
||||
* increase the calculated header_size value as long as it is a multiple of
|
||||
* four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
|
||||
* just means that lzma_block_header_encode() will add Header Padding.
|
||||
*
|
||||
* \return - LZMA_OK: Size calculated successfully and stored to
|
||||
* block->header_size.
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported version, filters or
|
||||
* filter options.
|
||||
* - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
|
||||
*
|
||||
* \note This doesn't check that all the options are valid i.e. this
|
||||
* may return LZMA_OK even if lzma_block_header_encode() or
|
||||
* lzma_block_encoder() would fail. If you want to validate the
|
||||
* filter chain, consider using lzma_memlimit_encoder() which as
|
||||
* a side-effect validates the filter chain.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode Block Header
|
||||
*
|
||||
* The caller must have calculated the size of the Block Header already with
|
||||
* lzma_block_header_size(). If a value larger than the one calculated by
|
||||
* lzma_block_header_size() is used, the Block Header will be padded to the
|
||||
* specified size.
|
||||
*
|
||||
* \param out Beginning of the output buffer. This must be
|
||||
* at least block->header_size bytes.
|
||||
* \param block Block options to be encoded.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful. block->header_size
|
||||
* bytes were written to output buffer.
|
||||
* - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
|
||||
* - LZMA_PROG_ERROR: Invalid arguments, for example
|
||||
* block->header_size is invalid or block->filters is NULL.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_header_encode(
|
||||
const lzma_block *block, uint8_t *out)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode Block Header
|
||||
*
|
||||
* block->version should (usually) be set to the highest value supported
|
||||
* by the application. If the application sets block->version to a value
|
||||
* higher than supported by the current liblzma version, this function will
|
||||
* downgrade block->version to the highest value supported by it. Thus one
|
||||
* should check the value of block->version after calling this function if
|
||||
* block->version was set to a non-zero value and the application doesn't
|
||||
* otherwise know that the liblzma version being used is new enough to
|
||||
* support the specified block->version.
|
||||
*
|
||||
* The size of the Block Header must have already been decoded with
|
||||
* lzma_block_header_size_decode() macro and stored to block->header_size.
|
||||
*
|
||||
* The integrity check type from Stream Header must have been stored
|
||||
* to block->check.
|
||||
*
|
||||
* block->filters must have been allocated, but they don't need to be
|
||||
* initialized (possible existing filter options are not freed).
|
||||
*
|
||||
* \param block Destination for Block options.
|
||||
* \param allocator lzma_allocator for custom allocator functions.
|
||||
* Set to NULL to use malloc() (and also free()
|
||||
* if an error occurs).
|
||||
* \param in Beginning of the input buffer. This must be
|
||||
* at least block->header_size bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Decoding was successful. block->header_size
|
||||
* bytes were read from the input buffer.
|
||||
* - LZMA_OPTIONS_ERROR: The Block Header specifies some
|
||||
* unsupported options such as unsupported filters. This can
|
||||
* happen also if block->version was set to a too low value
|
||||
* compared to what would be required to properly represent
|
||||
* the information stored in the Block Header.
|
||||
* - LZMA_DATA_ERROR: Block Header is corrupt, for example,
|
||||
* the CRC32 doesn't match.
|
||||
* - LZMA_PROG_ERROR: Invalid arguments, for example
|
||||
* block->header_size is invalid or block->filters is NULL.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
|
||||
const lzma_allocator *allocator, const uint8_t *in)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Validate and set Compressed Size according to Unpadded Size
|
||||
*
|
||||
* Block Header stores Compressed Size, but Index has Unpadded Size. If the
|
||||
* application has already parsed the Index and is now decoding Blocks,
|
||||
* it can calculate Compressed Size from Unpadded Size. This function does
|
||||
* exactly that with error checking:
|
||||
*
|
||||
* - Compressed Size calculated from Unpadded Size must be positive integer,
|
||||
* that is, Unpadded Size must be big enough that after Block Header and
|
||||
* Check fields there's still at least one byte for Compressed Size.
|
||||
*
|
||||
* - If Compressed Size was present in Block Header, the new value
|
||||
* calculated from Unpadded Size is compared against the value
|
||||
* from Block Header.
|
||||
*
|
||||
* \note This function must be called _after_ decoding the Block Header
|
||||
* field so that it can properly validate Compressed Size if it
|
||||
* was present in Block Header.
|
||||
*
|
||||
* \return - LZMA_OK: block->compressed_size was set successfully.
|
||||
* - LZMA_DATA_ERROR: unpadded_size is too small compared to
|
||||
* block->header_size and lzma_check_size(block->check).
|
||||
* - LZMA_PROG_ERROR: Some values are invalid. For example,
|
||||
* block->header_size must be a multiple of four and
|
||||
* between 8 and 1024 inclusive.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_compressed_size(
|
||||
lzma_block *block, lzma_vli unpadded_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate Unpadded Size
|
||||
*
|
||||
* The Index field stores Unpadded Size and Uncompressed Size. The latter
|
||||
* can be taken directly from the lzma_block structure after coding a Block,
|
||||
* but Unpadded Size needs to be calculated from Block Header Size,
|
||||
* Compressed Size, and size of the Check field. This is where this function
|
||||
* is needed.
|
||||
*
|
||||
* \return Unpadded Size on success, or zero on error.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate the total encoded size of a Block
|
||||
*
|
||||
* This is equivalent to lzma_block_unpadded_size() except that the returned
|
||||
* value includes the size of the Block Padding field.
|
||||
*
|
||||
* \return On success, total encoded size of the Block. On error,
|
||||
* zero is returned.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Block encoder
|
||||
*
|
||||
* Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
|
||||
* filter chain supports it), and LZMA_FINISH.
|
||||
*
|
||||
* \return - LZMA_OK: All good, continue with lzma_code().
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
|
||||
* that is not supported by this buid of liblzma. Initializing
|
||||
* the encoder failed.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_encoder(
|
||||
lzma_stream *strm, lzma_block *block)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Block decoder
|
||||
*
|
||||
* Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
|
||||
* LZMA_FINISH is not required. It is supported only for convenience.
|
||||
*
|
||||
* \return - LZMA_OK: All good, continue with lzma_code().
|
||||
* - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but
|
||||
* the given Check ID is not supported, thus Check will be
|
||||
* ignored.
|
||||
* - LZMA_PROG_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_decoder(
|
||||
lzma_stream *strm, lzma_block *block)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate maximum output size for single-call Block encoding
|
||||
*
|
||||
* This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks.
|
||||
* See the documentation of lzma_stream_buffer_bound().
|
||||
*/
|
||||
extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Block encoder
|
||||
*
|
||||
* In contrast to the multi-call encoder initialized with
|
||||
* lzma_block_encoder(), this function encodes also the Block Header. This
|
||||
* is required to make it possible to write appropriate Block Header also
|
||||
* in case the data isn't compressible, and different filter chain has to be
|
||||
* used to encode the data in uncompressed form using uncompressed chunks
|
||||
* of the LZMA2 filter.
|
||||
*
|
||||
* When the data isn't compressible, header_size, compressed_size, and
|
||||
* uncompressed_size are set just like when the data was compressible, but
|
||||
* it is possible that header_size is too small to hold the filter chain
|
||||
* specified in block->filters, because that isn't necessarily the filter
|
||||
* chain that was actually used to encode the data. lzma_block_unpadded_size()
|
||||
* still works normally, because it doesn't read the filters array.
|
||||
*
|
||||
* \param block Block options: block->version, block->check,
|
||||
* and block->filters must have been initialized.
|
||||
* \param allocator lzma_allocator for custom allocator functions.
|
||||
* Set to NULL to use malloc() and free().
|
||||
* \param in Beginning of the input buffer
|
||||
* \param in_size Size of the input buffer
|
||||
* \param out Beginning of the output buffer
|
||||
* \param out_pos The next byte will be written to out[*out_pos].
|
||||
* *out_pos is updated only if encoding succeeds.
|
||||
* \param out_size Size of the out buffer; the first byte into
|
||||
* which no data is written to is out[out_size].
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_BUF_ERROR: Not enough output buffer space.
|
||||
* - LZMA_UNSUPPORTED_CHECK
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_DATA_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
|
||||
lzma_block *block, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call uncompressed .xz Block encoder
|
||||
*
|
||||
* This is like lzma_block_buffer_encode() except this doesn't try to
|
||||
* compress the data and instead encodes the data using LZMA2 uncompressed
|
||||
* chunks. The required output buffer size can be determined with
|
||||
* lzma_block_buffer_bound().
|
||||
*
|
||||
* Since the data won't be compressed, this function ignores block->filters.
|
||||
* This function doesn't take lzma_allocator because this function doesn't
|
||||
* allocate any memory from the heap.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Block decoder
|
||||
*
|
||||
* This is single-call equivalent of lzma_block_decoder(), and requires that
|
||||
* the caller has already decoded Block Header and checked its memory usage.
|
||||
*
|
||||
* \param block Block options just like with lzma_block_decoder().
|
||||
* \param allocator lzma_allocator for custom allocator functions.
|
||||
* Set to NULL to use malloc() and free().
|
||||
* \param in Beginning of the input buffer
|
||||
* \param in_pos The next byte will be read from in[*in_pos].
|
||||
* *in_pos is updated only if decoding succeeds.
|
||||
* \param in_size Size of the input buffer; the first byte that
|
||||
* won't be read is in[in_size].
|
||||
* \param out Beginning of the output buffer
|
||||
* \param out_pos The next byte will be written to out[*out_pos].
|
||||
* *out_pos is updated only if encoding succeeds.
|
||||
* \param out_size Size of the out buffer; the first byte into
|
||||
* which no data is written to is out[out_size].
|
||||
*
|
||||
* \return - LZMA_OK: Decoding was successful.
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_DATA_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_BUF_ERROR: Output buffer was too small.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
|
||||
lzma_block *block, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
lzma_nothrow;
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* \file lzma/delta.h
|
||||
* \brief Delta filter
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Filter ID
|
||||
*
|
||||
* Filter ID of the Delta filter. This is used as lzma_filter.id.
|
||||
*/
|
||||
#define LZMA_FILTER_DELTA LZMA_VLI_C(0x03)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Type of the delta calculation
|
||||
*
|
||||
* Currently only byte-wise delta is supported. Other possible types could
|
||||
* be, for example, delta of 16/32/64-bit little/big endian integers, but
|
||||
* these are not currently planned since byte-wise delta is almost as good.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_DELTA_TYPE_BYTE
|
||||
} lzma_delta_type;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options for the Delta filter
|
||||
*
|
||||
* These options are needed by both encoder and decoder.
|
||||
*/
|
||||
typedef struct {
|
||||
/** For now, this must always be LZMA_DELTA_TYPE_BYTE. */
|
||||
lzma_delta_type type;
|
||||
|
||||
/**
|
||||
* \brief Delta distance
|
||||
*
|
||||
* With the only currently supported type, LZMA_DELTA_TYPE_BYTE,
|
||||
* the distance is as bytes.
|
||||
*
|
||||
* Examples:
|
||||
* - 16-bit stereo audio: distance = 4 bytes
|
||||
* - 24-bit RGB image data: distance = 3 bytes
|
||||
*/
|
||||
uint32_t dist;
|
||||
# define LZMA_DELTA_DIST_MIN 1
|
||||
# define LZMA_DELTA_DIST_MAX 256
|
||||
|
||||
/*
|
||||
* Reserved space to allow possible future extensions without
|
||||
* breaking the ABI. You should not touch these, because the names
|
||||
* of these variables may change. These are and will never be used
|
||||
* when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these
|
||||
* uninitialized.
|
||||
*/
|
||||
uint32_t reserved_int1;
|
||||
uint32_t reserved_int2;
|
||||
uint32_t reserved_int3;
|
||||
uint32_t reserved_int4;
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
|
||||
} lzma_options_delta;
|
||||
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* \file lzma/hardware.h
|
||||
* \brief Hardware information
|
||||
*
|
||||
* Since liblzma can consume a lot of system resources, it also provides
|
||||
* ways to limit the resource usage. Applications linking against liblzma
|
||||
* need to do the actual decisions how much resources to let liblzma to use.
|
||||
* To ease making these decisions, liblzma provides functions to find out
|
||||
* the relevant capabilities of the underlaying hardware. Currently there
|
||||
* is only a function to find out the amount of RAM, but in the future there
|
||||
* will be also a function to detect how many concurrent threads the system
|
||||
* can run.
|
||||
*
|
||||
* \note On some operating systems, these function may temporarily
|
||||
* load a shared library or open file descriptor(s) to find out
|
||||
* the requested hardware information. Unless the application
|
||||
* assumes that specific file descriptors are not touched by
|
||||
* other threads, this should have no effect on thread safety.
|
||||
* Possible operations involving file descriptors will restart
|
||||
* the syscalls if they return EINTR.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total amount of physical memory (RAM) in bytes
|
||||
*
|
||||
* This function may be useful when determining a reasonable memory
|
||||
* usage limit for decompressing or how much memory it is OK to use
|
||||
* for compressing.
|
||||
*
|
||||
* \return On success, the total amount of physical memory in bytes
|
||||
* is returned. If the amount of RAM cannot be determined,
|
||||
* zero is returned. This can happen if an error occurs
|
||||
* or if there is no code in liblzma to detect the amount
|
||||
* of RAM on the specific operating system.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the number of processor cores or threads
|
||||
*
|
||||
* This function may be useful when determining how many threads to use.
|
||||
* If the hardware supports more than one thread per CPU core, the number
|
||||
* of hardware threads is returned if that information is available.
|
||||
*
|
||||
* \return On success, the number of available CPU threads or cores is
|
||||
* returned. If this information isn't available or an error
|
||||
* occurs, zero is returned.
|
||||
*/
|
||||
extern LZMA_API(uint32_t) lzma_cputhreads(void) lzma_nothrow;
|
||||
@@ -1,682 +0,0 @@
|
||||
/**
|
||||
* \file lzma/index.h
|
||||
* \brief Handling of .xz Index and related information
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Opaque data type to hold the Index(es) and other information
|
||||
*
|
||||
* lzma_index often holds just one .xz Index and possibly the Stream Flags
|
||||
* of the same Stream and size of the Stream Padding field. However,
|
||||
* multiple lzma_indexes can be concatenated with lzma_index_cat() and then
|
||||
* there may be information about multiple Streams in the same lzma_index.
|
||||
*
|
||||
* Notes about thread safety: Only one thread may modify lzma_index at
|
||||
* a time. All functions that take non-const pointer to lzma_index
|
||||
* modify it. As long as no thread is modifying the lzma_index, getting
|
||||
* information from the same lzma_index can be done from multiple threads
|
||||
* at the same time with functions that take a const pointer to
|
||||
* lzma_index or use lzma_index_iter. The same iterator must be used
|
||||
* only by one thread at a time, of course, but there can be as many
|
||||
* iterators for the same lzma_index as needed.
|
||||
*/
|
||||
typedef struct lzma_index_s lzma_index;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Iterator to get information about Blocks and Streams
|
||||
*/
|
||||
typedef struct {
|
||||
struct {
|
||||
/**
|
||||
* \brief Pointer to Stream Flags
|
||||
*
|
||||
* This is NULL if Stream Flags have not been set for
|
||||
* this Stream with lzma_index_stream_flags().
|
||||
*/
|
||||
const lzma_stream_flags *flags;
|
||||
|
||||
const void *reserved_ptr1;
|
||||
const void *reserved_ptr2;
|
||||
const void *reserved_ptr3;
|
||||
|
||||
/**
|
||||
* \brief Stream number in the lzma_index
|
||||
*
|
||||
* The first Stream is 1.
|
||||
*/
|
||||
lzma_vli number;
|
||||
|
||||
/**
|
||||
* \brief Number of Blocks in the Stream
|
||||
*
|
||||
* If this is zero, the block structure below has
|
||||
* undefined values.
|
||||
*/
|
||||
lzma_vli block_count;
|
||||
|
||||
/**
|
||||
* \brief Compressed start offset of this Stream
|
||||
*
|
||||
* The offset is relative to the beginning of the lzma_index
|
||||
* (i.e. usually the beginning of the .xz file).
|
||||
*/
|
||||
lzma_vli compressed_offset;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed start offset of this Stream
|
||||
*
|
||||
* The offset is relative to the beginning of the lzma_index
|
||||
* (i.e. usually the beginning of the .xz file).
|
||||
*/
|
||||
lzma_vli uncompressed_offset;
|
||||
|
||||
/**
|
||||
* \brief Compressed size of this Stream
|
||||
*
|
||||
* This includes all headers except the possible
|
||||
* Stream Padding after this Stream.
|
||||
*/
|
||||
lzma_vli compressed_size;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed size of this Stream
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Size of Stream Padding after this Stream
|
||||
*
|
||||
* If it hasn't been set with lzma_index_stream_padding(),
|
||||
* this defaults to zero. Stream Padding is always
|
||||
* a multiple of four bytes.
|
||||
*/
|
||||
lzma_vli padding;
|
||||
|
||||
lzma_vli reserved_vli1;
|
||||
lzma_vli reserved_vli2;
|
||||
lzma_vli reserved_vli3;
|
||||
lzma_vli reserved_vli4;
|
||||
} stream;
|
||||
|
||||
struct {
|
||||
/**
|
||||
* \brief Block number in the file
|
||||
*
|
||||
* The first Block is 1.
|
||||
*/
|
||||
lzma_vli number_in_file;
|
||||
|
||||
/**
|
||||
* \brief Compressed start offset of this Block
|
||||
*
|
||||
* This offset is relative to the beginning of the
|
||||
* lzma_index (i.e. usually the beginning of the .xz file).
|
||||
* Normally this is where you should seek in the .xz file
|
||||
* to start decompressing this Block.
|
||||
*/
|
||||
lzma_vli compressed_file_offset;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed start offset of this Block
|
||||
*
|
||||
* This offset is relative to the beginning of the lzma_index
|
||||
* (i.e. usually the beginning of the .xz file).
|
||||
*
|
||||
* When doing random-access reading, it is possible that
|
||||
* the target offset is not exactly at Block boundary. One
|
||||
* will need to compare the target offset against
|
||||
* uncompressed_file_offset or uncompressed_stream_offset,
|
||||
* and possibly decode and throw away some amount of data
|
||||
* before reaching the target offset.
|
||||
*/
|
||||
lzma_vli uncompressed_file_offset;
|
||||
|
||||
/**
|
||||
* \brief Block number in this Stream
|
||||
*
|
||||
* The first Block is 1.
|
||||
*/
|
||||
lzma_vli number_in_stream;
|
||||
|
||||
/**
|
||||
* \brief Compressed start offset of this Block
|
||||
*
|
||||
* This offset is relative to the beginning of the Stream
|
||||
* containing this Block.
|
||||
*/
|
||||
lzma_vli compressed_stream_offset;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed start offset of this Block
|
||||
*
|
||||
* This offset is relative to the beginning of the Stream
|
||||
* containing this Block.
|
||||
*/
|
||||
lzma_vli uncompressed_stream_offset;
|
||||
|
||||
/**
|
||||
* \brief Uncompressed size of this Block
|
||||
*
|
||||
* You should pass this to the Block decoder if you will
|
||||
* decode this Block. It will allow the Block decoder to
|
||||
* validate the uncompressed size.
|
||||
*/
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/**
|
||||
* \brief Unpadded size of this Block
|
||||
*
|
||||
* You should pass this to the Block decoder if you will
|
||||
* decode this Block. It will allow the Block decoder to
|
||||
* validate the unpadded size.
|
||||
*/
|
||||
lzma_vli unpadded_size;
|
||||
|
||||
/**
|
||||
* \brief Total compressed size
|
||||
*
|
||||
* This includes all headers and padding in this Block.
|
||||
* This is useful if you need to know how many bytes
|
||||
* the Block decoder will actually read.
|
||||
*/
|
||||
lzma_vli total_size;
|
||||
|
||||
lzma_vli reserved_vli1;
|
||||
lzma_vli reserved_vli2;
|
||||
lzma_vli reserved_vli3;
|
||||
lzma_vli reserved_vli4;
|
||||
|
||||
const void *reserved_ptr1;
|
||||
const void *reserved_ptr2;
|
||||
const void *reserved_ptr3;
|
||||
const void *reserved_ptr4;
|
||||
} block;
|
||||
|
||||
/*
|
||||
* Internal data which is used to store the state of the iterator.
|
||||
* The exact format may vary between liblzma versions, so don't
|
||||
* touch these in any way.
|
||||
*/
|
||||
union {
|
||||
const void *p;
|
||||
size_t s;
|
||||
lzma_vli v;
|
||||
} internal[6];
|
||||
} lzma_index_iter;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Operation mode for lzma_index_iter_next()
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_INDEX_ITER_ANY = 0,
|
||||
/**<
|
||||
* \brief Get the next Block or Stream
|
||||
*
|
||||
* Go to the next Block if the current Stream has at least
|
||||
* one Block left. Otherwise go to the next Stream even if
|
||||
* it has no Blocks. If the Stream has no Blocks
|
||||
* (lzma_index_iter.stream.block_count == 0),
|
||||
* lzma_index_iter.block will have undefined values.
|
||||
*/
|
||||
|
||||
LZMA_INDEX_ITER_STREAM = 1,
|
||||
/**<
|
||||
* \brief Get the next Stream
|
||||
*
|
||||
* Go to the next Stream even if the current Stream has
|
||||
* unread Blocks left. If the next Stream has at least one
|
||||
* Block, the iterator will point to the first Block.
|
||||
* If there are no Blocks, lzma_index_iter.block will have
|
||||
* undefined values.
|
||||
*/
|
||||
|
||||
LZMA_INDEX_ITER_BLOCK = 2,
|
||||
/**<
|
||||
* \brief Get the next Block
|
||||
*
|
||||
* Go to the next Block if the current Stream has at least
|
||||
* one Block left. If the current Stream has no Blocks left,
|
||||
* the next Stream with at least one Block is located and
|
||||
* the iterator will be made to point to the first Block of
|
||||
* that Stream.
|
||||
*/
|
||||
|
||||
LZMA_INDEX_ITER_NONEMPTY_BLOCK = 3
|
||||
/**<
|
||||
* \brief Get the next non-empty Block
|
||||
*
|
||||
* This is like LZMA_INDEX_ITER_BLOCK except that it will
|
||||
* skip Blocks whose Uncompressed Size is zero.
|
||||
*/
|
||||
|
||||
} lzma_index_iter_mode;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate memory usage of lzma_index
|
||||
*
|
||||
* On disk, the size of the Index field depends on both the number of Records
|
||||
* stored and how big values the Records store (due to variable-length integer
|
||||
* encoding). When the Index is kept in lzma_index structure, the memory usage
|
||||
* depends only on the number of Records/Blocks stored in the Index(es), and
|
||||
* in case of concatenated lzma_indexes, the number of Streams. The size in
|
||||
* RAM is almost always significantly bigger than in the encoded form on disk.
|
||||
*
|
||||
* This function calculates an approximate amount of memory needed hold
|
||||
* the given number of Streams and Blocks in lzma_index structure. This
|
||||
* value may vary between CPU architectures and also between liblzma versions
|
||||
* if the internal implementation is modified.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_index_memusage(
|
||||
lzma_vli streams, lzma_vli blocks) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate the memory usage of an existing lzma_index
|
||||
*
|
||||
* This is a shorthand for lzma_index_memusage(lzma_index_stream_count(i),
|
||||
* lzma_index_block_count(i)).
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Allocate and initialize a new lzma_index structure
|
||||
*
|
||||
* \return On success, a pointer to an empty initialized lzma_index is
|
||||
* returned. If allocation fails, NULL is returned.
|
||||
*/
|
||||
extern LZMA_API(lzma_index *) lzma_index_init(const lzma_allocator *allocator)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Deallocate lzma_index
|
||||
*
|
||||
* If i is NULL, this does nothing.
|
||||
*/
|
||||
extern LZMA_API(void) lzma_index_end(
|
||||
lzma_index *i, const lzma_allocator *allocator) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add a new Block to lzma_index
|
||||
*
|
||||
* \param i Pointer to a lzma_index structure
|
||||
* \param allocator Pointer to lzma_allocator, or NULL to
|
||||
* use malloc()
|
||||
* \param unpadded_size Unpadded Size of a Block. This can be
|
||||
* calculated with lzma_block_unpadded_size()
|
||||
* after encoding or decoding the Block.
|
||||
* \param uncompressed_size Uncompressed Size of a Block. This can be
|
||||
* taken directly from lzma_block structure
|
||||
* after encoding or decoding the Block.
|
||||
*
|
||||
* Appending a new Block does not invalidate iterators. For example,
|
||||
* if an iterator was pointing to the end of the lzma_index, after
|
||||
* lzma_index_append() it is possible to read the next Block with
|
||||
* an existing iterator.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_DATA_ERROR: Compressed or uncompressed size of the
|
||||
* Stream or size of the Index field would grow too big.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_append(
|
||||
lzma_index *i, const lzma_allocator *allocator,
|
||||
lzma_vli unpadded_size, lzma_vli uncompressed_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set the Stream Flags
|
||||
*
|
||||
* Set the Stream Flags of the last (and typically the only) Stream
|
||||
* in lzma_index. This can be useful when reading information from the
|
||||
* lzma_index, because to decode Blocks, knowing the integrity check type
|
||||
* is needed.
|
||||
*
|
||||
* The given Stream Flags are copied into internal preallocated structure
|
||||
* in the lzma_index, thus the caller doesn't need to keep the *stream_flags
|
||||
* available after calling this function.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported stream_flags->version.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_stream_flags(
|
||||
lzma_index *i, const lzma_stream_flags *stream_flags)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the types of integrity Checks
|
||||
*
|
||||
* If lzma_index_stream_flags() is used to set the Stream Flags for
|
||||
* every Stream, lzma_index_checks() can be used to get a bitmask to
|
||||
* indicate which Check types have been used. It can be useful e.g. if
|
||||
* showing the Check types to the user.
|
||||
*
|
||||
* The bitmask is 1 << check_id, e.g. CRC32 is 1 << 1 and SHA-256 is 1 << 10.
|
||||
*/
|
||||
extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set the amount of Stream Padding
|
||||
*
|
||||
* Set the amount of Stream Padding of the last (and typically the only)
|
||||
* Stream in the lzma_index. This is needed when planning to do random-access
|
||||
* reading within multiple concatenated Streams.
|
||||
*
|
||||
* By default, the amount of Stream Padding is assumed to be zero bytes.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_DATA_ERROR: The file size would grow too big.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_stream_padding(
|
||||
lzma_index *i, lzma_vli stream_padding)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the number of Streams
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the number of Blocks
|
||||
*
|
||||
* This returns the total number of Blocks in lzma_index. To get number
|
||||
* of Blocks in individual Streams, use lzma_index_iter.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Index field as bytes
|
||||
*
|
||||
* This is needed to verify the Backward Size field in the Stream Footer.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total size of the Stream
|
||||
*
|
||||
* If multiple lzma_indexes have been combined, this works as if the Blocks
|
||||
* were in a single Stream. This is useful if you are going to combine
|
||||
* Blocks from multiple Streams into a single new Stream.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total size of the Blocks
|
||||
*
|
||||
* This doesn't include the Stream Header, Stream Footer, Stream Padding,
|
||||
* or Index fields.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the total size of the file
|
||||
*
|
||||
* When no lzma_indexes have been combined with lzma_index_cat() and there is
|
||||
* no Stream Padding, this function is identical to lzma_index_stream_size().
|
||||
* If multiple lzma_indexes have been combined, this includes also the headers
|
||||
* of each separate Stream and the possible Stream Padding fields.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the uncompressed size of the file
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize an iterator
|
||||
*
|
||||
* \param iter Pointer to a lzma_index_iter structure
|
||||
* \param i lzma_index to which the iterator will be associated
|
||||
*
|
||||
* This function associates the iterator with the given lzma_index, and calls
|
||||
* lzma_index_iter_rewind() on the iterator.
|
||||
*
|
||||
* This function doesn't allocate any memory, thus there is no
|
||||
* lzma_index_iter_end(). The iterator is valid as long as the
|
||||
* associated lzma_index is valid, that is, until lzma_index_end() or
|
||||
* using it as source in lzma_index_cat(). Specifically, lzma_index doesn't
|
||||
* become invalid if new Blocks are added to it with lzma_index_append() or
|
||||
* if it is used as the destination in lzma_index_cat().
|
||||
*
|
||||
* It is safe to make copies of an initialized lzma_index_iter, for example,
|
||||
* to easily restart reading at some particular position.
|
||||
*/
|
||||
extern LZMA_API(void) lzma_index_iter_init(
|
||||
lzma_index_iter *iter, const lzma_index *i) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Rewind the iterator
|
||||
*
|
||||
* Rewind the iterator so that next call to lzma_index_iter_next() will
|
||||
* return the first Block or Stream.
|
||||
*/
|
||||
extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the next Block or Stream
|
||||
*
|
||||
* \param iter Iterator initialized with lzma_index_iter_init()
|
||||
* \param mode Specify what kind of information the caller wants
|
||||
* to get. See lzma_index_iter_mode for details.
|
||||
*
|
||||
* \return If next Block or Stream matching the mode was found, *iter
|
||||
* is updated and this function returns false. If no Block or
|
||||
* Stream matching the mode is found, *iter is not modified
|
||||
* and this function returns true. If mode is set to an unknown
|
||||
* value, *iter is not modified and this function returns true.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_index_iter_next(
|
||||
lzma_index_iter *iter, lzma_index_iter_mode mode)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Locate a Block
|
||||
*
|
||||
* If it is possible to seek in the .xz file, it is possible to parse
|
||||
* the Index field(s) and use lzma_index_iter_locate() to do random-access
|
||||
* reading with granularity of Block size.
|
||||
*
|
||||
* \param iter Iterator that was earlier initialized with
|
||||
* lzma_index_iter_init().
|
||||
* \param target Uncompressed target offset which the caller would
|
||||
* like to locate from the Stream
|
||||
*
|
||||
* If the target is smaller than the uncompressed size of the Stream (can be
|
||||
* checked with lzma_index_uncompressed_size()):
|
||||
* - Information about the Stream and Block containing the requested
|
||||
* uncompressed offset is stored into *iter.
|
||||
* - Internal state of the iterator is adjusted so that
|
||||
* lzma_index_iter_next() can be used to read subsequent Blocks or Streams.
|
||||
* - This function returns false.
|
||||
*
|
||||
* If target is greater than the uncompressed size of the Stream, *iter
|
||||
* is not modified, and this function returns true.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_index_iter_locate(
|
||||
lzma_index_iter *iter, lzma_vli target) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Concatenate lzma_indexes
|
||||
*
|
||||
* Concatenating lzma_indexes is useful when doing random-access reading in
|
||||
* multi-Stream .xz file, or when combining multiple Streams into single
|
||||
* Stream.
|
||||
*
|
||||
* \param dest lzma_index after which src is appended
|
||||
* \param src lzma_index to be appended after dest. If this
|
||||
* function succeeds, the memory allocated for src
|
||||
* is freed or moved to be part of dest, and all
|
||||
* iterators pointing to src will become invalid.
|
||||
* \param allocator Custom memory allocator; can be NULL to use
|
||||
* malloc() and free().
|
||||
*
|
||||
* \return - LZMA_OK: lzma_indexes were concatenated successfully.
|
||||
* src is now a dangling pointer.
|
||||
* - LZMA_DATA_ERROR: *dest would grow too big.
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *dest, lzma_index *src,
|
||||
const lzma_allocator *allocator)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Duplicate lzma_index
|
||||
*
|
||||
* \return A copy of the lzma_index, or NULL if memory allocation failed.
|
||||
*/
|
||||
extern LZMA_API(lzma_index *) lzma_index_dup(
|
||||
const lzma_index *i, const lzma_allocator *allocator)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Index encoder
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param i Pointer to lzma_index which should be encoded.
|
||||
*
|
||||
* The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
|
||||
* It is enough to use only one of them (you can choose freely; use LZMA_RUN
|
||||
* to support liblzma versions older than 5.0.0).
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_encoder(
|
||||
lzma_stream *strm, const lzma_index *i)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Index decoder
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param i The decoded Index will be made available via
|
||||
* this pointer. Initially this function will
|
||||
* set *i to NULL (the old value is ignored). If
|
||||
* decoding succeeds (lzma_code() returns
|
||||
* LZMA_STREAM_END), *i will be set to point
|
||||
* to a new lzma_index, which the application
|
||||
* has to later free with lzma_index_end().
|
||||
* \param memlimit How much memory the resulting lzma_index is
|
||||
* allowed to require.
|
||||
*
|
||||
* The valid `action' values for lzma_code() are LZMA_RUN and LZMA_FINISH.
|
||||
* It is enough to use only one of them (you can choose freely; use LZMA_RUN
|
||||
* to support liblzma versions older than 5.0.0).
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded, continue with lzma_code().
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_MEMLIMIT_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_decoder(
|
||||
lzma_stream *strm, lzma_index **i, uint64_t memlimit)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Index encoder
|
||||
*
|
||||
* \param i lzma_index to be encoded
|
||||
* \param out Beginning of the output buffer
|
||||
* \param out_pos The next byte will be written to out[*out_pos].
|
||||
* *out_pos is updated only if encoding succeeds.
|
||||
* \param out_size Size of the out buffer; the first byte into
|
||||
* which no data is written to is out[out_size].
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_BUF_ERROR: Output buffer is too small. Use
|
||||
* lzma_index_size() to find out how much output
|
||||
* space is needed.
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note This function doesn't take allocator argument since all
|
||||
* the internal data is allocated on stack.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Index decoder
|
||||
*
|
||||
* \param i If decoding succeeds, *i will point to a new
|
||||
* lzma_index, which the application has to
|
||||
* later free with lzma_index_end(). If an error
|
||||
* occurs, *i will be NULL. The old value of *i
|
||||
* is always ignored and thus doesn't need to be
|
||||
* initialized by the caller.
|
||||
* \param memlimit Pointer to how much memory the resulting
|
||||
* lzma_index is allowed to require. The value
|
||||
* pointed by this pointer is modified if and only
|
||||
* if LZMA_MEMLIMIT_ERROR is returned.
|
||||
* \param allocator Pointer to lzma_allocator, or NULL to use malloc()
|
||||
* \param in Beginning of the input buffer
|
||||
* \param in_pos The next byte will be read from in[*in_pos].
|
||||
* *in_pos is updated only if decoding succeeds.
|
||||
* \param in_size Size of the input buffer; the first byte that
|
||||
* won't be read is in[in_size].
|
||||
*
|
||||
* \return - LZMA_OK: Decoding was successful.
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
|
||||
* The minimum required memlimit value was stored to *memlimit.
|
||||
* - LZMA_DATA_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
|
||||
uint64_t *memlimit, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_nothrow;
|
||||
@@ -1,107 +0,0 @@
|
||||
/**
|
||||
* \file lzma/index_hash.h
|
||||
* \brief Validate Index by using a hash function
|
||||
*
|
||||
* Hashing makes it possible to use constant amount of memory to validate
|
||||
* Index of arbitrary size.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Opaque data type to hold the Index hash
|
||||
*/
|
||||
typedef struct lzma_index_hash_s lzma_index_hash;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Allocate and initialize a new lzma_index_hash structure
|
||||
*
|
||||
* If index_hash is NULL, a new lzma_index_hash structure is allocated,
|
||||
* initialized, and a pointer to it returned. If allocation fails, NULL
|
||||
* is returned.
|
||||
*
|
||||
* If index_hash is non-NULL, it is reinitialized and the same pointer
|
||||
* returned. In this case, return value cannot be NULL or a different
|
||||
* pointer than the index_hash that was given as an argument.
|
||||
*/
|
||||
extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
|
||||
lzma_index_hash *index_hash, const lzma_allocator *allocator)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Deallocate lzma_index_hash structure
|
||||
*/
|
||||
extern LZMA_API(void) lzma_index_hash_end(
|
||||
lzma_index_hash *index_hash, const lzma_allocator *allocator)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add a new Record to an Index hash
|
||||
*
|
||||
* \param index_hash Pointer to a lzma_index_hash structure
|
||||
* \param unpadded_size Unpadded Size of a Block
|
||||
* \param uncompressed_size Uncompressed Size of a Block
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_DATA_ERROR: Compressed or uncompressed size of the
|
||||
* Stream or size of the Index field would grow too big.
|
||||
* - LZMA_PROG_ERROR: Invalid arguments or this function is being
|
||||
* used when lzma_index_hash_decode() has already been used.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_hash_append(lzma_index_hash *index_hash,
|
||||
lzma_vli unpadded_size, lzma_vli uncompressed_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode and validate the Index field
|
||||
*
|
||||
* After telling the sizes of all Blocks with lzma_index_hash_append(),
|
||||
* the actual Index field is decoded with this function. Specifically,
|
||||
* once decoding of the Index field has been started, no more Records
|
||||
* can be added using lzma_index_hash_append().
|
||||
*
|
||||
* This function doesn't use lzma_stream structure to pass the input data.
|
||||
* Instead, the input buffer is specified using three arguments. This is
|
||||
* because it matches better the internal APIs of liblzma.
|
||||
*
|
||||
* \param index_hash Pointer to a lzma_index_hash structure
|
||||
* \param in Pointer to the beginning of the input buffer
|
||||
* \param in_pos in[*in_pos] is the next byte to process
|
||||
* \param in_size in[in_size] is the first byte not to process
|
||||
*
|
||||
* \return - LZMA_OK: So far good, but more input is needed.
|
||||
* - LZMA_STREAM_END: Index decoded successfully and it matches
|
||||
* the Records given with lzma_index_hash_append().
|
||||
* - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
|
||||
* information given with lzma_index_hash_append().
|
||||
* - LZMA_BUF_ERROR: Cannot progress because *in_pos >= in_size.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_index_hash_decode(lzma_index_hash *index_hash,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Index field as bytes
|
||||
*
|
||||
* This is needed to verify the Backward Size field in the Stream Footer.
|
||||
*/
|
||||
extern LZMA_API(lzma_vli) lzma_index_hash_size(
|
||||
const lzma_index_hash *index_hash)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
@@ -1,223 +0,0 @@
|
||||
/**
|
||||
* \file lzma/stream_flags.h
|
||||
* \brief .xz Stream Header and Stream Footer encoder and decoder
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*
|
||||
* See ../lzma.h for information about liblzma as a whole.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H_INTERNAL
|
||||
# error Never include this file directly. Use <lzma.h> instead.
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* \brief Size of Stream Header and Stream Footer
|
||||
*
|
||||
* Stream Header and Stream Footer have the same size and they are not
|
||||
* going to change even if a newer version of the .xz file format is
|
||||
* developed in future.
|
||||
*/
|
||||
#define LZMA_STREAM_HEADER_SIZE 12
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options for encoding/decoding Stream Header and Stream Footer
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Stream Flags format version
|
||||
*
|
||||
* To prevent API and ABI breakages if new features are needed in
|
||||
* Stream Header or Stream Footer, a version number is used to
|
||||
* indicate which fields in this structure are in use. For now,
|
||||
* version must always be zero. With non-zero version, the
|
||||
* lzma_stream_header_encode() and lzma_stream_footer_encode()
|
||||
* will return LZMA_OPTIONS_ERROR.
|
||||
*
|
||||
* lzma_stream_header_decode() and lzma_stream_footer_decode()
|
||||
* will always set this to the lowest value that supports all the
|
||||
* features indicated by the Stream Flags field. The application
|
||||
* must check that the version number set by the decoding functions
|
||||
* is supported by the application. Otherwise it is possible that
|
||||
* the application will decode the Stream incorrectly.
|
||||
*/
|
||||
uint32_t version;
|
||||
|
||||
/**
|
||||
* \brief Backward Size
|
||||
*
|
||||
* Backward Size must be a multiple of four bytes. In this Stream
|
||||
* format version, Backward Size is the size of the Index field.
|
||||
*
|
||||
* Backward Size isn't actually part of the Stream Flags field, but
|
||||
* it is convenient to include in this structure anyway. Backward
|
||||
* Size is present only in the Stream Footer. There is no need to
|
||||
* initialize backward_size when encoding Stream Header.
|
||||
*
|
||||
* lzma_stream_header_decode() always sets backward_size to
|
||||
* LZMA_VLI_UNKNOWN so that it is convenient to use
|
||||
* lzma_stream_flags_compare() when both Stream Header and Stream
|
||||
* Footer have been decoded.
|
||||
*/
|
||||
lzma_vli backward_size;
|
||||
# define LZMA_BACKWARD_SIZE_MIN 4
|
||||
# define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
|
||||
|
||||
/**
|
||||
* \brief Check ID
|
||||
*
|
||||
* This indicates the type of the integrity check calculated from
|
||||
* uncompressed data.
|
||||
*/
|
||||
lzma_check check;
|
||||
|
||||
/*
|
||||
* Reserved space to allow possible future extensions without
|
||||
* breaking the ABI. You should not touch these, because the
|
||||
* names of these variables may change.
|
||||
*
|
||||
* (We will never be able to use all of these since Stream Flags
|
||||
* is just two bytes plus Backward Size of four bytes. But it's
|
||||
* nice to have the proper types when they are needed.)
|
||||
*/
|
||||
lzma_reserved_enum reserved_enum1;
|
||||
lzma_reserved_enum reserved_enum2;
|
||||
lzma_reserved_enum reserved_enum3;
|
||||
lzma_reserved_enum reserved_enum4;
|
||||
lzma_bool reserved_bool1;
|
||||
lzma_bool reserved_bool2;
|
||||
lzma_bool reserved_bool3;
|
||||
lzma_bool reserved_bool4;
|
||||
lzma_bool reserved_bool5;
|
||||
lzma_bool reserved_bool6;
|
||||
lzma_bool reserved_bool7;
|
||||
lzma_bool reserved_bool8;
|
||||
uint32_t reserved_int1;
|
||||
uint32_t reserved_int2;
|
||||
|
||||
} lzma_stream_flags;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode Stream Header
|
||||
*
|
||||
* \param options Stream Header options to be encoded.
|
||||
* options->backward_size is ignored and doesn't
|
||||
* need to be initialized.
|
||||
* \param out Beginning of the output buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_OPTIONS_ERROR: options->version is not supported by
|
||||
* this liblzma version.
|
||||
* - LZMA_PROG_ERROR: Invalid options.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_header_encode(
|
||||
const lzma_stream_flags *options, uint8_t *out)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode Stream Footer
|
||||
*
|
||||
* \param options Stream Footer options to be encoded.
|
||||
* \param out Beginning of the output buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_OPTIONS_ERROR: options->version is not supported by
|
||||
* this liblzma version.
|
||||
* - LZMA_PROG_ERROR: Invalid options.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_footer_encode(
|
||||
const lzma_stream_flags *options, uint8_t *out)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode Stream Header
|
||||
*
|
||||
* \param options Target for the decoded Stream Header options.
|
||||
* \param in Beginning of the input buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
*
|
||||
* options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to
|
||||
* help comparing Stream Flags from Stream Header and Stream Footer with
|
||||
* lzma_stream_flags_compare().
|
||||
*
|
||||
* \return - LZMA_OK: Decoding was successful.
|
||||
* - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
|
||||
* buffer cannot be Stream Header.
|
||||
* - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header
|
||||
* is corrupt.
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported options are present
|
||||
* in the header.
|
||||
*
|
||||
* \note When decoding .xz files that contain multiple Streams, it may
|
||||
* make sense to print "file format not recognized" only if
|
||||
* decoding of the Stream Header of the _first_ Stream gives
|
||||
* LZMA_FORMAT_ERROR. If non-first Stream Header gives
|
||||
* LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is
|
||||
* probably more appropriate.
|
||||
*
|
||||
* For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if
|
||||
* LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode()
|
||||
* when decoding non-first Stream.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_header_decode(
|
||||
lzma_stream_flags *options, const uint8_t *in)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode Stream Footer
|
||||
*
|
||||
* \param options Target for the decoded Stream Header options.
|
||||
* \param in Beginning of the input buffer of
|
||||
* LZMA_STREAM_HEADER_SIZE bytes.
|
||||
*
|
||||
* \return - LZMA_OK: Decoding was successful.
|
||||
* - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
|
||||
* buffer cannot be Stream Footer.
|
||||
* - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer
|
||||
* is corrupt.
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported options are present
|
||||
* in Stream Footer.
|
||||
*
|
||||
* \note If Stream Header was already decoded successfully, but
|
||||
* decoding Stream Footer returns LZMA_FORMAT_ERROR, the
|
||||
* application should probably report some other error message
|
||||
* than "file format not recognized", since the file more likely
|
||||
* is corrupt (possibly truncated). Stream decoder in liblzma
|
||||
* uses LZMA_DATA_ERROR in this situation.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_footer_decode(
|
||||
lzma_stream_flags *options, const uint8_t *in)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compare two lzma_stream_flags structures
|
||||
*
|
||||
* backward_size values are compared only if both are not
|
||||
* LZMA_VLI_UNKNOWN.
|
||||
*
|
||||
* \return - LZMA_OK: Both are equal. If either had backward_size set
|
||||
* to LZMA_VLI_UNKNOWN, backward_size values were not
|
||||
* compared or validated.
|
||||
* - LZMA_DATA_ERROR: The structures differ.
|
||||
* - LZMA_OPTIONS_ERROR: version in either structure is greater
|
||||
* than the maximum supported version (currently zero).
|
||||
* - LZMA_PROG_ERROR: Invalid value, e.g. invalid check or
|
||||
* backward_size.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_flags_compare(
|
||||
const lzma_stream_flags *a, const lzma_stream_flags *b)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
@@ -22,7 +22,7 @@
|
||||
*/
|
||||
#define LZMA_VERSION_MAJOR 5
|
||||
#define LZMA_VERSION_MINOR 2
|
||||
#define LZMA_VERSION_PATCH 2
|
||||
#define LZMA_VERSION_PATCH 3
|
||||
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
|
||||
|
||||
#ifndef LZMA_VERSION_COMMIT
|
||||
|
||||
+22
-12
@@ -15,7 +15,18 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
|
||||
// If the function for external SHA-256 is missing, use the internal SHA-256
|
||||
// code. Due to how configure works, these defines can only get defined when
|
||||
// both a usable header and a type have already been found.
|
||||
#if !(defined(HAVE_CC_SHA256_INIT) \
|
||||
|| defined(HAVE_SHA256_INIT) \
|
||||
|| defined(HAVE_SHA256INIT))
|
||||
# define HAVE_INTERNAL_SHA256 1
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INTERNAL_SHA256)
|
||||
// Nothing
|
||||
#elif defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
|
||||
# include <CommonCrypto/CommonDigest.h>
|
||||
#elif defined(HAVE_SHA256_H)
|
||||
# include <sys/types.h>
|
||||
@@ -23,18 +34,9 @@
|
||||
#elif defined(HAVE_SHA2_H)
|
||||
# include <sys/types.h>
|
||||
# include <sha2.h>
|
||||
#elif defined(HAVE_MINIX_SHA2_H)
|
||||
# include <sys/types.h>
|
||||
# include <minix/sha2.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CC_SHA256_CTX)
|
||||
typedef CC_SHA256_CTX lzma_sha256_state;
|
||||
#elif defined(HAVE_SHA256_CTX)
|
||||
typedef SHA256_CTX lzma_sha256_state;
|
||||
#elif defined(HAVE_SHA2_CTX)
|
||||
typedef SHA2_CTX lzma_sha256_state;
|
||||
#else
|
||||
#if defined(HAVE_INTERNAL_SHA256)
|
||||
/// State for the internal SHA-256 implementation
|
||||
typedef struct {
|
||||
/// Internal state
|
||||
@@ -43,9 +45,17 @@ typedef struct {
|
||||
/// Size of the message excluding padding
|
||||
uint64_t size;
|
||||
} lzma_sha256_state;
|
||||
#elif defined(HAVE_CC_SHA256_CTX)
|
||||
typedef CC_SHA256_CTX lzma_sha256_state;
|
||||
#elif defined(HAVE_SHA256_CTX)
|
||||
typedef SHA256_CTX lzma_sha256_state;
|
||||
#elif defined(HAVE_SHA2_CTX)
|
||||
typedef SHA2_CTX lzma_sha256_state;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CC_SHA256_INIT)
|
||||
#if defined(HAVE_INTERNAL_SHA256)
|
||||
// Nothing
|
||||
#elif defined(HAVE_CC_SHA256_INIT)
|
||||
# define LZMA_SHA256FUNC(x) CC_SHA256_ ## x
|
||||
#elif defined(HAVE_SHA256_INIT)
|
||||
# define LZMA_SHA256FUNC(x) SHA256_ ## x
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "crc_macros.h"
|
||||
|
||||
|
||||
// If you make any changes, do some benchmarking! Seemingly unrelated
|
||||
// If you make any changes, do some bench marking! Seemingly unrelated
|
||||
// changes can very easily ruin the performance (and very probably is
|
||||
// very compiler dependent).
|
||||
extern LZMA_API(uint32_t)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file crc32_small.c
|
||||
/// \brief CRC32 calculation (size-optimized)
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "check.h"
|
||||
|
||||
|
||||
uint32_t lzma_crc32_table[1][256];
|
||||
|
||||
|
||||
static void
|
||||
crc32_init(void)
|
||||
{
|
||||
static const uint32_t poly32 = UINT32_C(0xEDB88320);
|
||||
|
||||
for (size_t b = 0; b < 256; ++b) {
|
||||
uint32_t r = b;
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
if (r & 1)
|
||||
r = (r >> 1) ^ poly32;
|
||||
else
|
||||
r >>= 1;
|
||||
}
|
||||
|
||||
lzma_crc32_table[0][b] = r;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_crc32_init(void)
|
||||
{
|
||||
mythread_once(crc32_init);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
|
||||
{
|
||||
lzma_crc32_init();
|
||||
|
||||
crc = ~crc;
|
||||
|
||||
while (size != 0) {
|
||||
crc = lzma_crc32_table[0][*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
|
||||
--size;
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "lz_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
lzma_next_coder next;
|
||||
|
||||
enum {
|
||||
@@ -46,17 +46,19 @@ struct lzma_coder_s {
|
||||
/// Options decoded from the header needed to initialize
|
||||
/// the LZMA decoder
|
||||
lzma_options_lzma options;
|
||||
};
|
||||
} lzma_alone_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_decode(lzma_coder *coder,
|
||||
alone_decode(void *coder_ptr,
|
||||
const lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
lzma_action action)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size
|
||||
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
|
||||
switch (coder->sequence) {
|
||||
@@ -96,13 +98,13 @@ alone_decode(lzma_coder *coder,
|
||||
|
||||
coder->uncompressed_size = LZMA_VLI_UNKNOWN;
|
||||
|
||||
// Calculate the memory usage so that it is ready
|
||||
// for SEQ_CODER_INIT.
|
||||
coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
|
||||
+ LZMA_MEMUSAGE_BASE;
|
||||
// Calculate the memory usage so that it is ready
|
||||
// for SEQ_CODER_INIT.
|
||||
coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
|
||||
+ LZMA_MEMUSAGE_BASE;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_CODER_INIT;
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_CODER_INIT;
|
||||
|
||||
// Fall through
|
||||
|
||||
@@ -147,8 +149,9 @@ alone_decode(lzma_coder *coder,
|
||||
|
||||
|
||||
static void
|
||||
alone_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
alone_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -156,9 +159,11 @@ alone_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
alone_decoder_memconfig(void *coder_ptr, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
|
||||
*memusage = coder->memusage;
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
@@ -182,26 +187,29 @@ lzma_alone_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
if (memlimit == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_alone_coder *coder = next->coder;
|
||||
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &alone_decode;
|
||||
next->end = &alone_decoder_end;
|
||||
next->memconfig = &alone_decoder_memconfig;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
next->coder->sequence = SEQ_PROPERTIES;
|
||||
next->coder->picky = picky;
|
||||
next->coder->pos = 0;
|
||||
next->coder->options.dict_size = 0;
|
||||
next->coder->options.preset_dict = NULL;
|
||||
next->coder->options.preset_dict_size = 0;
|
||||
next->coder->uncompressed_size = 0;
|
||||
next->coder->memlimit = memlimit;
|
||||
next->coder->memusage = LZMA_MEMUSAGE_BASE;
|
||||
coder->sequence = SEQ_PROPERTIES;
|
||||
coder->picky = picky;
|
||||
coder->pos = 0;
|
||||
coder->options.dict_size = 0;
|
||||
coder->options.preset_dict = NULL;
|
||||
coder->options.preset_dict_size = 0;
|
||||
coder->uncompressed_size = 0;
|
||||
coder->memlimit = memlimit;
|
||||
coder->memusage = LZMA_MEMUSAGE_BASE;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define ALONE_HEADER_SIZE (1 + 4)
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
lzma_next_coder next;
|
||||
|
||||
enum {
|
||||
@@ -27,17 +27,19 @@ struct lzma_coder_s {
|
||||
|
||||
size_t header_pos;
|
||||
uint8_t header[ALONE_HEADER_SIZE];
|
||||
};
|
||||
} lzma_alone_coder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_encode(lzma_coder *coder,
|
||||
alone_encode(void *coder_ptr,
|
||||
const lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
lzma_action action)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_HEADER:
|
||||
@@ -65,8 +67,9 @@ alone_encode(lzma_coder *coder,
|
||||
|
||||
|
||||
static void
|
||||
alone_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_alone_coder *coder = coder_ptr;
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
@@ -80,23 +83,26 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
{
|
||||
lzma_next_coder_init(&alone_encoder_init, next, allocator);
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_alone_coder *coder = next->coder;
|
||||
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &alone_encode;
|
||||
next->end = &alone_encoder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_HEADER;
|
||||
next->coder->header_pos = 0;
|
||||
coder->sequence = SEQ_HEADER;
|
||||
coder->header_pos = 0;
|
||||
|
||||
// Encode the header:
|
||||
// - Properties (1 byte)
|
||||
if (lzma_lzma_lclppb_encode(options, next->coder->header))
|
||||
if (lzma_lzma_lclppb_encode(options, coder->header))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// - Dictionary size (4 bytes)
|
||||
@@ -116,7 +122,7 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
if (d != UINT32_MAX)
|
||||
++d;
|
||||
|
||||
unaligned_write32le(next->coder->header + 1, d);
|
||||
unaligned_write32le(coder->header + 1, d);
|
||||
|
||||
// Initialize the LZMA encoder.
|
||||
const lzma_filter_info filters[2] = {
|
||||
@@ -128,7 +134,7 @@ alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
}
|
||||
};
|
||||
|
||||
return lzma_next_filter_init(&next->coder->next, allocator, filters);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file auto_decoder.c
|
||||
/// \brief Autodetect between .xz Stream and .lzma (LZMA_Alone) formats
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_decoder.h"
|
||||
#include "alone_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
/// Stream decoder or LZMA_Alone decoder
|
||||
lzma_next_coder next;
|
||||
|
||||
uint64_t memlimit;
|
||||
uint32_t flags;
|
||||
|
||||
enum {
|
||||
SEQ_INIT,
|
||||
SEQ_CODE,
|
||||
SEQ_FINISH,
|
||||
} sequence;
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
switch (coder->sequence) {
|
||||
case SEQ_INIT:
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
// Update the sequence now, because we want to continue from
|
||||
// SEQ_CODE even if we return some LZMA_*_CHECK.
|
||||
coder->sequence = SEQ_CODE;
|
||||
|
||||
// Detect the file format. For now this is simple, since if
|
||||
// it doesn't start with 0xFD (the first magic byte of the
|
||||
// new format), it has to be LZMA_Alone, or something that
|
||||
// we don't support at all.
|
||||
if (in[*in_pos] == 0xFD) {
|
||||
return_if_error(lzma_stream_decoder_init(
|
||||
&coder->next, allocator,
|
||||
coder->memlimit, coder->flags));
|
||||
} else {
|
||||
return_if_error(lzma_alone_decoder_init(&coder->next,
|
||||
allocator, coder->memlimit, true));
|
||||
|
||||
// If the application wants to know about missing
|
||||
// integrity check or about the check in general, we
|
||||
// need to handle it here, because LZMA_Alone decoder
|
||||
// doesn't accept any flags.
|
||||
if (coder->flags & LZMA_TELL_NO_CHECK)
|
||||
return LZMA_NO_CHECK;
|
||||
|
||||
if (coder->flags & LZMA_TELL_ANY_CHECK)
|
||||
return LZMA_GET_CHECK;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CODE: {
|
||||
const lzma_ret ret = coder->next.code(
|
||||
coder->next.coder, allocator,
|
||||
in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
if (ret != LZMA_STREAM_END
|
||||
|| (coder->flags & LZMA_CONCATENATED) == 0)
|
||||
return ret;
|
||||
|
||||
coder->sequence = SEQ_FINISH;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_FINISH:
|
||||
// When LZMA_DECODE_CONCATENATED was used and we were decoding
|
||||
// LZMA_Alone file, we need to check check that there is no
|
||||
// trailing garbage and wait for LZMA_FINISH.
|
||||
if (*in_pos < in_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
return action == LZMA_FINISH ? LZMA_STREAM_END : LZMA_OK;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
auto_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_check
|
||||
auto_decoder_get_check(const lzma_coder *coder)
|
||||
{
|
||||
// It is LZMA_Alone if get_check is NULL.
|
||||
return coder->next.get_check == NULL ? LZMA_CHECK_NONE
|
||||
: coder->next.get_check(coder->next.coder);
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
lzma_ret ret;
|
||||
|
||||
if (coder->next.memconfig != NULL) {
|
||||
ret = coder->next.memconfig(coder->next.coder,
|
||||
memusage, old_memlimit, new_memlimit);
|
||||
assert(*old_memlimit == coder->memlimit);
|
||||
} else {
|
||||
// No coder is configured yet. Use the base value as
|
||||
// the current memory usage.
|
||||
*memusage = LZMA_MEMUSAGE_BASE;
|
||||
*old_memlimit = coder->memlimit;
|
||||
ret = LZMA_OK;
|
||||
}
|
||||
|
||||
if (ret == LZMA_OK && new_memlimit != 0)
|
||||
coder->memlimit = new_memlimit;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
auto_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
uint64_t memlimit, uint32_t flags)
|
||||
{
|
||||
lzma_next_coder_init(&auto_decoder_init, next, allocator);
|
||||
|
||||
if (memlimit == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (flags & ~LZMA_SUPPORTED_FLAGS)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &auto_decode;
|
||||
next->end = &auto_decoder_end;
|
||||
next->get_check = &auto_decoder_get_check;
|
||||
next->memconfig = &auto_decoder_memconfig;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
next->coder->memlimit = memlimit;
|
||||
next->coder->flags = flags;
|
||||
next->coder->sequence = SEQ_INIT;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
{
|
||||
lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_buffer_decoder.c
|
||||
/// \brief Single-call .xz Block decoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_decoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|
||||
|| *in_pos > in_size || out_pos == NULL
|
||||
|| (out == NULL && *out_pos != out_size)
|
||||
|| *out_pos > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Initialize the Block decoder.
|
||||
lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT;
|
||||
lzma_ret ret = lzma_block_decoder_init(
|
||||
&block_decoder, allocator, block);
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
// Save the positions so that we can restore them in case
|
||||
// an error occurs.
|
||||
const size_t in_start = *in_pos;
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
// Do the actual decoding.
|
||||
ret = block_decoder.code(block_decoder.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size,
|
||||
LZMA_FINISH);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
if (ret == LZMA_OK) {
|
||||
// Either the input was truncated or the
|
||||
// output buffer was too small.
|
||||
assert(*in_pos == in_size
|
||||
|| *out_pos == out_size);
|
||||
|
||||
// If all the input was consumed, then the
|
||||
// input is truncated, even if the output
|
||||
// buffer is also full. This is because
|
||||
// processing the last byte of the Block
|
||||
// never produces output.
|
||||
//
|
||||
// NOTE: This assumption may break when new
|
||||
// filters are added, if the end marker of
|
||||
// the filter doesn't consume at least one
|
||||
// complete byte.
|
||||
if (*in_pos == in_size)
|
||||
ret = LZMA_DATA_ERROR;
|
||||
else
|
||||
ret = LZMA_BUF_ERROR;
|
||||
}
|
||||
|
||||
// Restore the positions.
|
||||
*in_pos = in_start;
|
||||
*out_pos = out_start;
|
||||
}
|
||||
}
|
||||
|
||||
// Free the decoder memory. This needs to be done even if
|
||||
// initialization fails, because the internal API doesn't
|
||||
// require the initialization function to free its memory on error.
|
||||
lzma_next_end(&block_decoder, allocator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_buffer_encoder.c
|
||||
/// \brief Single-call .xz Block encoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_buffer_encoder.h"
|
||||
#include "block_encoder.h"
|
||||
#include "filter_encoder.h"
|
||||
#include "lzma2_encoder.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
/// Estimate the maximum size of the Block Header and Check fields for
|
||||
/// a Block that uses LZMA2 uncompressed chunks. We could use
|
||||
/// lzma_block_header_size() but this is simpler.
|
||||
///
|
||||
/// Block Header Size + Block Flags + Compressed Size
|
||||
/// + Uncompressed Size + Filter Flags for LZMA2 + CRC32 + Check
|
||||
/// and round up to the next multiple of four to take Header Padding
|
||||
/// into account.
|
||||
#define HEADERS_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 3 + 4 \
|
||||
+ LZMA_CHECK_SIZE_MAX + 3) & ~3)
|
||||
|
||||
|
||||
static uint64_t
|
||||
lzma2_bound(uint64_t uncompressed_size)
|
||||
{
|
||||
// Prevent integer overflow in overhead calculation.
|
||||
if (uncompressed_size > COMPRESSED_SIZE_MAX)
|
||||
return 0;
|
||||
|
||||
// Calculate the exact overhead of the LZMA2 headers: Round
|
||||
// uncompressed_size up to the next multiple of LZMA2_CHUNK_MAX,
|
||||
// multiply by the size of per-chunk header, and add one byte for
|
||||
// the end marker.
|
||||
const uint64_t overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
|
||||
/ LZMA2_CHUNK_MAX)
|
||||
* LZMA2_HEADER_UNCOMPRESSED + 1;
|
||||
|
||||
// Catch the possible integer overflow.
|
||||
if (COMPRESSED_SIZE_MAX - overhead < uncompressed_size)
|
||||
return 0;
|
||||
|
||||
return uncompressed_size + overhead;
|
||||
}
|
||||
|
||||
|
||||
extern uint64_t
|
||||
lzma_block_buffer_bound64(uint64_t uncompressed_size)
|
||||
{
|
||||
// If the data doesn't compress, we always use uncompressed
|
||||
// LZMA2 chunks.
|
||||
uint64_t lzma2_size = lzma2_bound(uncompressed_size);
|
||||
if (lzma2_size == 0)
|
||||
return 0;
|
||||
|
||||
// Take Block Padding into account.
|
||||
lzma2_size = (lzma2_size + 3) & ~UINT64_C(3);
|
||||
|
||||
// No risk of integer overflow because lzma2_bound() already takes
|
||||
// into account the size of the headers in the Block.
|
||||
return HEADERS_BOUND + lzma2_size;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(size_t)
|
||||
lzma_block_buffer_bound(size_t uncompressed_size)
|
||||
{
|
||||
uint64_t ret = lzma_block_buffer_bound64(uncompressed_size);
|
||||
|
||||
#if SIZE_MAX < UINT64_MAX
|
||||
// Catch the possible integer overflow on 32-bit systems.
|
||||
if (ret > SIZE_MAX)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Use LZMA2 uncompressed chunks. We wouldn't need a dictionary at
|
||||
// all, but LZMA2 always requires a dictionary, so use the minimum
|
||||
// value to minimize memory usage of the decoder.
|
||||
lzma_options_lzma lzma2 = {
|
||||
.dict_size = LZMA_DICT_SIZE_MIN,
|
||||
};
|
||||
|
||||
lzma_filter filters[2];
|
||||
filters[0].id = LZMA_FILTER_LZMA2;
|
||||
filters[0].options = &lzma2;
|
||||
filters[1].id = LZMA_VLI_UNKNOWN;
|
||||
|
||||
// Set the above filter options to *block temporarily so that we can
|
||||
// encode the Block Header.
|
||||
lzma_filter *filters_orig = block->filters;
|
||||
block->filters = filters;
|
||||
|
||||
if (lzma_block_header_size(block) != LZMA_OK) {
|
||||
block->filters = filters_orig;
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
// Check that there's enough output space. The caller has already
|
||||
// set block->compressed_size to what lzma2_bound() has returned,
|
||||
// so we can reuse that value. We know that compressed_size is a
|
||||
// known valid VLI and header_size is a small value so their sum
|
||||
// will never overflow.
|
||||
assert(block->compressed_size == lzma2_bound(in_size));
|
||||
if (out_size - *out_pos
|
||||
< block->header_size + block->compressed_size) {
|
||||
block->filters = filters_orig;
|
||||
return LZMA_BUF_ERROR;
|
||||
}
|
||||
|
||||
if (lzma_block_header_encode(block, out + *out_pos) != LZMA_OK) {
|
||||
block->filters = filters_orig;
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
block->filters = filters_orig;
|
||||
*out_pos += block->header_size;
|
||||
|
||||
// Encode the data using LZMA2 uncompressed chunks.
|
||||
size_t in_pos = 0;
|
||||
uint8_t control = 0x01; // Dictionary reset
|
||||
|
||||
while (in_pos < in_size) {
|
||||
// Control byte: Indicate uncompressed chunk, of which
|
||||
// the first resets the dictionary.
|
||||
out[(*out_pos)++] = control;
|
||||
control = 0x02; // No dictionary reset
|
||||
|
||||
// Size of the uncompressed chunk
|
||||
const size_t copy_size
|
||||
= my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
|
||||
out[(*out_pos)++] = (copy_size - 1) >> 8;
|
||||
out[(*out_pos)++] = (copy_size - 1) & 0xFF;
|
||||
|
||||
// The actual data
|
||||
assert(*out_pos + copy_size <= out_size);
|
||||
memcpy(out + *out_pos, in + in_pos, copy_size);
|
||||
|
||||
in_pos += copy_size;
|
||||
*out_pos += copy_size;
|
||||
}
|
||||
|
||||
// End marker
|
||||
out[(*out_pos)++] = 0x00;
|
||||
assert(*out_pos <= out_size);
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encode_normal(lzma_block *block, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Find out the size of the Block Header.
|
||||
return_if_error(lzma_block_header_size(block));
|
||||
|
||||
// Reserve space for the Block Header and skip it for now.
|
||||
if (out_size - *out_pos <= block->header_size)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
const size_t out_start = *out_pos;
|
||||
*out_pos += block->header_size;
|
||||
|
||||
// Limit out_size so that we stop encoding if the output would grow
|
||||
// bigger than what uncompressed Block would be.
|
||||
if (out_size - *out_pos > block->compressed_size)
|
||||
out_size = *out_pos + block->compressed_size;
|
||||
|
||||
// TODO: In many common cases this could be optimized to use
|
||||
// significantly less memory.
|
||||
lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
|
||||
lzma_ret ret = lzma_raw_encoder_init(
|
||||
&raw_encoder, allocator, block->filters);
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
size_t in_pos = 0;
|
||||
ret = raw_encoder.code(raw_encoder.coder, allocator,
|
||||
in, &in_pos, in_size, out, out_pos, out_size,
|
||||
LZMA_FINISH);
|
||||
}
|
||||
|
||||
// NOTE: This needs to be run even if lzma_raw_encoder_init() failed.
|
||||
lzma_next_end(&raw_encoder, allocator);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
// Compression was successful. Write the Block Header.
|
||||
block->compressed_size
|
||||
= *out_pos - (out_start + block->header_size);
|
||||
ret = lzma_block_header_encode(block, out + out_start);
|
||||
if (ret != LZMA_OK)
|
||||
ret = LZMA_PROG_ERROR;
|
||||
|
||||
} else if (ret == LZMA_OK) {
|
||||
// Output buffer became full.
|
||||
ret = LZMA_BUF_ERROR;
|
||||
}
|
||||
|
||||
// Reset *out_pos if something went wrong.
|
||||
if (ret != LZMA_OK)
|
||||
*out_pos = out_start;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size,
|
||||
bool try_to_compress)
|
||||
{
|
||||
// Validate the arguments.
|
||||
if (block == NULL || (in == NULL && in_size != 0) || out == NULL
|
||||
|| out_pos == NULL || *out_pos > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// The contents of the structure may depend on the version so
|
||||
// check the version before validating the contents of *block.
|
||||
if (block->version > 1)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX
|
||||
|| (try_to_compress && block->filters == NULL))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (!lzma_check_is_supported(block->check))
|
||||
return LZMA_UNSUPPORTED_CHECK;
|
||||
|
||||
// Size of a Block has to be a multiple of four, so limit the size
|
||||
// here already. This way we don't need to check it again when adding
|
||||
// Block Padding.
|
||||
out_size -= (out_size - *out_pos) & 3;
|
||||
|
||||
// Get the size of the Check field.
|
||||
const size_t check_size = lzma_check_size(block->check);
|
||||
assert(check_size != UINT32_MAX);
|
||||
|
||||
// Reserve space for the Check field.
|
||||
if (out_size - *out_pos <= check_size)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
out_size -= check_size;
|
||||
|
||||
// Initialize block->uncompressed_size and calculate the worst-case
|
||||
// value for block->compressed_size.
|
||||
block->uncompressed_size = in_size;
|
||||
block->compressed_size = lzma2_bound(in_size);
|
||||
if (block->compressed_size == 0)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Do the actual compression.
|
||||
lzma_ret ret = LZMA_BUF_ERROR;
|
||||
if (try_to_compress)
|
||||
ret = block_encode_normal(block, allocator,
|
||||
in, in_size, out, out_pos, out_size);
|
||||
|
||||
if (ret != LZMA_OK) {
|
||||
// If the error was something else than output buffer
|
||||
// becoming full, return the error now.
|
||||
if (ret != LZMA_BUF_ERROR)
|
||||
return ret;
|
||||
|
||||
// The data was uncompressible (at least with the options
|
||||
// given to us) or the output buffer was too small. Use the
|
||||
// uncompressed chunks of LZMA2 to wrap the data into a valid
|
||||
// Block. If we haven't been given enough output space, even
|
||||
// this may fail.
|
||||
return_if_error(block_encode_uncompressed(block, in, in_size,
|
||||
out, out_pos, out_size));
|
||||
}
|
||||
|
||||
assert(*out_pos <= out_size);
|
||||
|
||||
// Block Padding. No buffer overflow here, because we already adjusted
|
||||
// out_size so that (out_size - out_start) is a multiple of four.
|
||||
// Thus, if the buffer is full, the loop body can never run.
|
||||
for (size_t i = (size_t)(block->compressed_size); i & 3; ++i) {
|
||||
assert(*out_pos < out_size);
|
||||
out[(*out_pos)++] = 0x00;
|
||||
}
|
||||
|
||||
// If there's no Check field, we are done now.
|
||||
if (check_size > 0) {
|
||||
// Calculate the integrity check. We reserved space for
|
||||
// the Check field earlier so we don't need to check for
|
||||
// available output space here.
|
||||
lzma_check_state check;
|
||||
lzma_check_init(&check, block->check);
|
||||
lzma_check_update(&check, block->check, in, in_size);
|
||||
lzma_check_finish(&check, block->check);
|
||||
|
||||
memcpy(block->raw_check, check.buffer.u8, check_size);
|
||||
memcpy(out + *out_pos, check.buffer.u8, check_size);
|
||||
*out_pos += check_size;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_buffer_encode(lzma_block *block, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
return block_buffer_encode(block, allocator,
|
||||
in, in_size, out, out_pos, out_size, true);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_uncomp_encode(lzma_block *block,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// It won't allocate any memory from heap so no need
|
||||
// for lzma_allocator.
|
||||
return block_buffer_encode(block, NULL,
|
||||
in, in_size, out, out_pos, out_size, false);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_buffer_encoder.h
|
||||
/// \brief Single-call .xz Block encoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_BLOCK_BUFFER_ENCODER_H
|
||||
#define LZMA_BLOCK_BUFFER_ENCODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/// uint64_t version of lzma_block_buffer_bound(). It is used by
|
||||
/// stream_encoder_mt.c. Probably the original lzma_block_buffer_bound()
|
||||
/// should have been 64-bit, but fixing it would break the ABI.
|
||||
extern uint64_t lzma_block_buffer_bound64(uint64_t uncompressed_size);
|
||||
|
||||
#endif
|
||||
@@ -1,252 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_decoder.c
|
||||
/// \brief Decodes .xz Blocks
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_decoder.h"
|
||||
#include "filter_decoder.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
enum {
|
||||
SEQ_CODE,
|
||||
SEQ_PADDING,
|
||||
SEQ_CHECK,
|
||||
} sequence;
|
||||
|
||||
/// The filters in the chain; initialized with lzma_raw_decoder_init().
|
||||
lzma_next_coder next;
|
||||
|
||||
/// Decoding options; we also write Compressed Size and Uncompressed
|
||||
/// Size back to this structure when the decoding has been finished.
|
||||
lzma_block *block;
|
||||
|
||||
/// Compressed Size calculated while decoding
|
||||
lzma_vli compressed_size;
|
||||
|
||||
/// Uncompressed Size calculated while decoding
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Maximum allowed Compressed Size; this takes into account the
|
||||
/// size of the Block Header and Check fields when Compressed Size
|
||||
/// is unknown.
|
||||
lzma_vli compressed_limit;
|
||||
|
||||
/// Position when reading the Check field
|
||||
size_t check_pos;
|
||||
|
||||
/// Check of the uncompressed data
|
||||
lzma_check_state check;
|
||||
|
||||
/// True if the integrity check won't be calculated and verified.
|
||||
bool ignore_check;
|
||||
};
|
||||
|
||||
|
||||
static inline bool
|
||||
update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
|
||||
{
|
||||
if (limit > LZMA_VLI_MAX)
|
||||
limit = LZMA_VLI_MAX;
|
||||
|
||||
if (limit < *size || limit - *size < add)
|
||||
return true;
|
||||
|
||||
*size += add;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
is_size_valid(lzma_vli size, lzma_vli reference)
|
||||
{
|
||||
return reference == LZMA_VLI_UNKNOWN || reference == size;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_decode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
switch (coder->sequence) {
|
||||
case SEQ_CODE: {
|
||||
const size_t in_start = *in_pos;
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
const lzma_ret ret = coder->next.code(coder->next.coder,
|
||||
allocator, in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
const size_t out_used = *out_pos - out_start;
|
||||
|
||||
// NOTE: We compare to compressed_limit here, which prevents
|
||||
// the total size of the Block growing past LZMA_VLI_MAX.
|
||||
if (update_size(&coder->compressed_size, in_used,
|
||||
coder->compressed_limit)
|
||||
|| update_size(&coder->uncompressed_size,
|
||||
out_used,
|
||||
coder->block->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
if (!coder->ignore_check)
|
||||
lzma_check_update(&coder->check, coder->block->check,
|
||||
out + out_start, out_used);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
// Compressed and Uncompressed Sizes are now at their final
|
||||
// values. Verify that they match the values given to us.
|
||||
if (!is_size_valid(coder->compressed_size,
|
||||
coder->block->compressed_size)
|
||||
|| !is_size_valid(coder->uncompressed_size,
|
||||
coder->block->uncompressed_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Copy the values into coder->block. The caller
|
||||
// may use this information to construct Index.
|
||||
coder->block->compressed_size = coder->compressed_size;
|
||||
coder->block->uncompressed_size = coder->uncompressed_size;
|
||||
|
||||
coder->sequence = SEQ_PADDING;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_PADDING:
|
||||
// Compressed Data is padded to a multiple of four bytes.
|
||||
while (coder->compressed_size & 3) {
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
// We use compressed_size here just get the Padding
|
||||
// right. The actual Compressed Size was stored to
|
||||
// coder->block already, and won't be modified by
|
||||
// us anymore.
|
||||
++coder->compressed_size;
|
||||
|
||||
if (in[(*in_pos)++] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
if (coder->block->check == LZMA_CHECK_NONE)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
if (!coder->ignore_check)
|
||||
lzma_check_finish(&coder->check, coder->block->check);
|
||||
|
||||
coder->sequence = SEQ_CHECK;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CHECK: {
|
||||
const size_t check_size = lzma_check_size(coder->block->check);
|
||||
lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check,
|
||||
&coder->check_pos, check_size);
|
||||
if (coder->check_pos < check_size)
|
||||
return LZMA_OK;
|
||||
|
||||
// Validate the Check only if we support it.
|
||||
// coder->check.buffer may be uninitialized
|
||||
// when the Check ID is not supported.
|
||||
if (!coder->ignore_check
|
||||
&& lzma_check_is_supported(coder->block->check)
|
||||
&& memcmp(coder->block->raw_check,
|
||||
coder->check.buffer.u8,
|
||||
check_size) != 0)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
}
|
||||
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
block_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lzma_block *block)
|
||||
{
|
||||
lzma_next_coder_init(&lzma_block_decoder_init, next, allocator);
|
||||
|
||||
// Validate the options. lzma_block_unpadded_size() does that for us
|
||||
// except for Uncompressed Size and filters. Filters are validated
|
||||
// by the raw decoder.
|
||||
if (lzma_block_unpadded_size(block) == 0
|
||||
|| !lzma_vli_is_valid(block->uncompressed_size))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Allocate and initialize *next->coder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &block_decode;
|
||||
next->end = &block_decoder_end;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_CODE;
|
||||
next->coder->block = block;
|
||||
next->coder->compressed_size = 0;
|
||||
next->coder->uncompressed_size = 0;
|
||||
|
||||
// If Compressed Size is not known, we calculate the maximum allowed
|
||||
// value so that encoded size of the Block (including Block Padding)
|
||||
// is still a valid VLI and a multiple of four.
|
||||
next->coder->compressed_limit
|
||||
= block->compressed_size == LZMA_VLI_UNKNOWN
|
||||
? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
|
||||
- block->header_size
|
||||
- lzma_check_size(block->check)
|
||||
: block->compressed_size;
|
||||
|
||||
// Initialize the check. It's caller's problem if the Check ID is not
|
||||
// supported, and the Block decoder cannot verify the Check field.
|
||||
// Caller can test lzma_check_is_supported(block->check).
|
||||
next->coder->check_pos = 0;
|
||||
lzma_check_init(&next->coder->check, block->check);
|
||||
|
||||
next->coder->ignore_check = block->version >= 1
|
||||
? block->ignore_check : false;
|
||||
|
||||
// Initialize the filter chain.
|
||||
return lzma_raw_decoder_init(&next->coder->next, allocator,
|
||||
block->filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_decoder(lzma_stream *strm, lzma_block *block)
|
||||
{
|
||||
lzma_next_strm_init(lzma_block_decoder_init, strm, block);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_decoder.h
|
||||
/// \brief Decodes .xz Blocks
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_BLOCK_DECODER_H
|
||||
#define LZMA_BLOCK_DECODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator, lzma_block *block);
|
||||
|
||||
#endif
|
||||
@@ -1,217 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_encoder.c
|
||||
/// \brief Encodes .xz Blocks
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_encoder.h"
|
||||
#include "filter_encoder.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
/// The filters in the chain; initialized with lzma_raw_decoder_init().
|
||||
lzma_next_coder next;
|
||||
|
||||
/// Encoding options; we also write Unpadded Size, Compressed Size,
|
||||
/// and Uncompressed Size back to this structure when the encoding
|
||||
/// has been finished.
|
||||
lzma_block *block;
|
||||
|
||||
enum {
|
||||
SEQ_CODE,
|
||||
SEQ_PADDING,
|
||||
SEQ_CHECK,
|
||||
} sequence;
|
||||
|
||||
/// Compressed Size calculated while encoding
|
||||
lzma_vli compressed_size;
|
||||
|
||||
/// Uncompressed Size calculated while encoding
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Position in the Check field
|
||||
size_t pos;
|
||||
|
||||
/// Check of the uncompressed data
|
||||
lzma_check_state check;
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
// Check that our amount of input stays in proper limits.
|
||||
if (LZMA_VLI_MAX - coder->uncompressed_size < in_size - *in_pos)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
switch (coder->sequence) {
|
||||
case SEQ_CODE: {
|
||||
const size_t in_start = *in_pos;
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
const lzma_ret ret = coder->next.code(coder->next.coder,
|
||||
allocator, in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
|
||||
const size_t in_used = *in_pos - in_start;
|
||||
const size_t out_used = *out_pos - out_start;
|
||||
|
||||
if (COMPRESSED_SIZE_MAX - coder->compressed_size < out_used)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->compressed_size += out_used;
|
||||
|
||||
// No need to check for overflow because we have already
|
||||
// checked it at the beginning of this function.
|
||||
coder->uncompressed_size += in_used;
|
||||
|
||||
lzma_check_update(&coder->check, coder->block->check,
|
||||
in + in_start, in_used);
|
||||
|
||||
if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
|
||||
return ret;
|
||||
|
||||
assert(*in_pos == in_size);
|
||||
assert(action == LZMA_FINISH);
|
||||
|
||||
// Copy the values into coder->block. The caller
|
||||
// may use this information to construct Index.
|
||||
coder->block->compressed_size = coder->compressed_size;
|
||||
coder->block->uncompressed_size = coder->uncompressed_size;
|
||||
|
||||
coder->sequence = SEQ_PADDING;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_PADDING:
|
||||
// Pad Compressed Data to a multiple of four bytes. We can
|
||||
// use coder->compressed_size for this since we don't need
|
||||
// it for anything else anymore.
|
||||
while (coder->compressed_size & 3) {
|
||||
if (*out_pos >= out_size)
|
||||
return LZMA_OK;
|
||||
|
||||
out[*out_pos] = 0x00;
|
||||
++*out_pos;
|
||||
++coder->compressed_size;
|
||||
}
|
||||
|
||||
if (coder->block->check == LZMA_CHECK_NONE)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
lzma_check_finish(&coder->check, coder->block->check);
|
||||
|
||||
coder->sequence = SEQ_CHECK;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CHECK: {
|
||||
const size_t check_size = lzma_check_size(coder->block->check);
|
||||
lzma_bufcpy(coder->check.buffer.u8, &coder->pos, check_size,
|
||||
out, out_pos, out_size);
|
||||
if (coder->pos < check_size)
|
||||
return LZMA_OK;
|
||||
|
||||
memcpy(coder->block->raw_check, coder->check.buffer.u8,
|
||||
check_size);
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
}
|
||||
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
block_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encoder_update(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters lzma_attribute((__unused__)),
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
if (coder->sequence != SEQ_CODE)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return lzma_next_filter_update(
|
||||
&coder->next, allocator, reversed_filters);
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lzma_block *block)
|
||||
{
|
||||
lzma_next_coder_init(&lzma_block_encoder_init, next, allocator);
|
||||
|
||||
if (block == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// The contents of the structure may depend on the version so
|
||||
// check the version first.
|
||||
if (block->version > 1)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// If the Check ID is not supported, we cannot calculate the check and
|
||||
// thus not create a proper Block.
|
||||
if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (!lzma_check_is_supported(block->check))
|
||||
return LZMA_UNSUPPORTED_CHECK;
|
||||
|
||||
// Allocate and initialize *next->coder if needed.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &block_encode;
|
||||
next->end = &block_encoder_end;
|
||||
next->update = &block_encoder_update;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_CODE;
|
||||
next->coder->block = block;
|
||||
next->coder->compressed_size = 0;
|
||||
next->coder->uncompressed_size = 0;
|
||||
next->coder->pos = 0;
|
||||
|
||||
// Initialize the check
|
||||
lzma_check_init(&next->coder->check, block->check);
|
||||
|
||||
// Initialize the requested filters.
|
||||
return lzma_raw_encoder_init(&next->coder->next, allocator,
|
||||
block->filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_encoder(lzma_stream *strm, lzma_block *block)
|
||||
{
|
||||
lzma_next_strm_init(lzma_block_encoder_init, strm, block);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_encoder.h
|
||||
/// \brief Encodes .xz Blocks
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_BLOCK_ENCODER_H
|
||||
#define LZMA_BLOCK_ENCODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/// \brief Biggest Compressed Size value that the Block encoder supports
|
||||
///
|
||||
/// The maximum size of a single Block is limited by the maximum size of
|
||||
/// a Stream, which in theory is 2^63 - 3 bytes (i.e. LZMA_VLI_MAX - 3).
|
||||
/// While the size is really big and no one should hit it in practice, we
|
||||
/// take it into account in some places anyway to catch some errors e.g. if
|
||||
/// application passes insanely big value to some function.
|
||||
///
|
||||
/// We could take into account the headers etc. to determine the exact
|
||||
/// maximum size of the Compressed Data field, but the complexity would give
|
||||
/// us nothing useful. Instead, limit the size of Compressed Data so that
|
||||
/// even with biggest possible Block Header and Check fields the total
|
||||
/// encoded size of the Block stays as a valid VLI. This doesn't guarantee
|
||||
/// that the size of the Stream doesn't grow too big, but that problem is
|
||||
/// taken care outside the Block handling code.
|
||||
///
|
||||
/// ~LZMA_VLI_C(3) is to guarantee that if we need padding at the end of
|
||||
/// the Compressed Data field, it will still stay in the proper limit.
|
||||
///
|
||||
/// This constant is in this file because it is needed in both
|
||||
/// block_encoder.c and block_buffer_encoder.c.
|
||||
#define COMPRESSED_SIZE_MAX ((LZMA_VLI_MAX - LZMA_BLOCK_HEADER_SIZE_MAX \
|
||||
- LZMA_CHECK_SIZE_MAX) & ~LZMA_VLI_C(3))
|
||||
|
||||
|
||||
extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator, lzma_block *block);
|
||||
|
||||
#endif
|
||||
@@ -1,124 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_header_decoder.c
|
||||
/// \brief Decodes Block Header from .xz files
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
static void
|
||||
free_properties(lzma_block *block, const lzma_allocator *allocator)
|
||||
{
|
||||
// Free allocated filter options. The last array member is not
|
||||
// touched after the initialization in the beginning of
|
||||
// lzma_block_header_decode(), so we don't need to touch that here.
|
||||
for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
|
||||
lzma_free(block->filters[i].options, allocator);
|
||||
block->filters[i].id = LZMA_VLI_UNKNOWN;
|
||||
block->filters[i].options = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_header_decode(lzma_block *block,
|
||||
const lzma_allocator *allocator, const uint8_t *in)
|
||||
{
|
||||
// NOTE: We consider the header to be corrupt not only when the
|
||||
// CRC32 doesn't match, but also when variable-length integers
|
||||
// are invalid or over 63 bits, or if the header is too small
|
||||
// to contain the claimed information.
|
||||
|
||||
// Initialize the filter options array. This way the caller can
|
||||
// safely free() the options even if an error occurs in this function.
|
||||
for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
|
||||
block->filters[i].id = LZMA_VLI_UNKNOWN;
|
||||
block->filters[i].options = NULL;
|
||||
}
|
||||
|
||||
// Versions 0 and 1 are supported. If a newer version was specified,
|
||||
// we need to downgrade it.
|
||||
if (block->version > 1)
|
||||
block->version = 1;
|
||||
|
||||
// This isn't a Block Header option, but since the decompressor will
|
||||
// read it if version >= 1, it's better to initialize it here than
|
||||
// to expect the caller to do it since in almost all cases this
|
||||
// should be false.
|
||||
block->ignore_check = false;
|
||||
|
||||
// Validate Block Header Size and Check type. The caller must have
|
||||
// already set these, so it is a programming error if this test fails.
|
||||
if (lzma_block_header_size_decode(in[0]) != block->header_size
|
||||
|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Exclude the CRC32 field.
|
||||
const size_t in_size = block->header_size - 4;
|
||||
|
||||
// Verify CRC32
|
||||
if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size))
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Check for unsupported flags.
|
||||
if (in[1] & 0x3C)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Start after the Block Header Size and Block Flags fields.
|
||||
size_t in_pos = 2;
|
||||
|
||||
// Compressed Size
|
||||
if (in[1] & 0x40) {
|
||||
return_if_error(lzma_vli_decode(&block->compressed_size,
|
||||
NULL, in, &in_pos, in_size));
|
||||
|
||||
// Validate Compressed Size. This checks that it isn't zero
|
||||
// and that the total size of the Block is a valid VLI.
|
||||
if (lzma_block_unpadded_size(block) == 0)
|
||||
return LZMA_DATA_ERROR;
|
||||
} else {
|
||||
block->compressed_size = LZMA_VLI_UNKNOWN;
|
||||
}
|
||||
|
||||
// Uncompressed Size
|
||||
if (in[1] & 0x80)
|
||||
return_if_error(lzma_vli_decode(&block->uncompressed_size,
|
||||
NULL, in, &in_pos, in_size));
|
||||
else
|
||||
block->uncompressed_size = LZMA_VLI_UNKNOWN;
|
||||
|
||||
// Filter Flags
|
||||
const size_t filter_count = (in[1] & 3) + 1;
|
||||
for (size_t i = 0; i < filter_count; ++i) {
|
||||
const lzma_ret ret = lzma_filter_flags_decode(
|
||||
&block->filters[i], allocator,
|
||||
in, &in_pos, in_size);
|
||||
if (ret != LZMA_OK) {
|
||||
free_properties(block, allocator);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Padding
|
||||
while (in_pos < in_size) {
|
||||
if (in[in_pos++] != 0x00) {
|
||||
free_properties(block, allocator);
|
||||
|
||||
// Possibly some new field present so use
|
||||
// LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_header_encoder.c
|
||||
/// \brief Encodes Block Header for .xz files
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_header_size(lzma_block *block)
|
||||
{
|
||||
if (block->version > 1)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Block Header Size + Block Flags + CRC32.
|
||||
uint32_t size = 1 + 1 + 4;
|
||||
|
||||
// Compressed Size
|
||||
if (block->compressed_size != LZMA_VLI_UNKNOWN) {
|
||||
const uint32_t add = lzma_vli_size(block->compressed_size);
|
||||
if (add == 0 || block->compressed_size == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
size += add;
|
||||
}
|
||||
|
||||
// Uncompressed Size
|
||||
if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {
|
||||
const uint32_t add = lzma_vli_size(block->uncompressed_size);
|
||||
if (add == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
size += add;
|
||||
}
|
||||
|
||||
// List of Filter Flags
|
||||
if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
|
||||
// Don't allow too many filters.
|
||||
if (i == LZMA_FILTERS_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
uint32_t add;
|
||||
return_if_error(lzma_filter_flags_size(&add,
|
||||
block->filters + i));
|
||||
|
||||
size += add;
|
||||
}
|
||||
|
||||
// Pad to a multiple of four bytes.
|
||||
block->header_size = (size + 3) & ~UINT32_C(3);
|
||||
|
||||
// NOTE: We don't verify that the encoded size of the Block stays
|
||||
// within limits. This is because it is possible that we are called
|
||||
// with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve
|
||||
// space for Block Header, and later called again with lower,
|
||||
// real values.
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_header_encode(const lzma_block *block, uint8_t *out)
|
||||
{
|
||||
// Validate everything but filters.
|
||||
if (lzma_block_unpadded_size(block) == 0
|
||||
|| !lzma_vli_is_valid(block->uncompressed_size))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Indicate the size of the buffer _excluding_ the CRC32 field.
|
||||
const size_t out_size = block->header_size - 4;
|
||||
|
||||
// Store the Block Header Size.
|
||||
out[0] = out_size / 4;
|
||||
|
||||
// We write Block Flags in pieces.
|
||||
out[1] = 0x00;
|
||||
size_t out_pos = 2;
|
||||
|
||||
// Compressed Size
|
||||
if (block->compressed_size != LZMA_VLI_UNKNOWN) {
|
||||
return_if_error(lzma_vli_encode(block->compressed_size, NULL,
|
||||
out, &out_pos, out_size));
|
||||
|
||||
out[1] |= 0x40;
|
||||
}
|
||||
|
||||
// Uncompressed Size
|
||||
if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {
|
||||
return_if_error(lzma_vli_encode(block->uncompressed_size, NULL,
|
||||
out, &out_pos, out_size));
|
||||
|
||||
out[1] |= 0x80;
|
||||
}
|
||||
|
||||
// Filter Flags
|
||||
if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
size_t filter_count = 0;
|
||||
do {
|
||||
// There can be a maximum of four filters.
|
||||
if (filter_count == LZMA_FILTERS_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return_if_error(lzma_filter_flags_encode(
|
||||
block->filters + filter_count,
|
||||
out, &out_pos, out_size));
|
||||
|
||||
} while (block->filters[++filter_count].id != LZMA_VLI_UNKNOWN);
|
||||
|
||||
out[1] |= filter_count - 1;
|
||||
|
||||
// Padding
|
||||
memzero(out + out_pos, out_size - out_pos);
|
||||
|
||||
// CRC32
|
||||
unaligned_write32le(out + out_size, lzma_crc32(out, out_size, 0));
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_header.c
|
||||
/// \brief Utility functions to handle lzma_block
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "index.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
|
||||
{
|
||||
// Validate everything but Uncompressed Size and filters.
|
||||
if (lzma_block_unpadded_size(block) == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
const uint32_t container_size = block->header_size
|
||||
+ lzma_check_size(block->check);
|
||||
|
||||
// Validate that Compressed Size will be greater than zero.
|
||||
if (unpadded_size <= container_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Calculate what Compressed Size is supposed to be.
|
||||
// If Compressed Size was present in Block Header,
|
||||
// compare that the new value matches it.
|
||||
const lzma_vli compressed_size = unpadded_size - container_size;
|
||||
if (block->compressed_size != LZMA_VLI_UNKNOWN
|
||||
&& block->compressed_size != compressed_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
block->compressed_size = compressed_size;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_vli)
|
||||
lzma_block_unpadded_size(const lzma_block *block)
|
||||
{
|
||||
// Validate the values that we are interested in i.e. all but
|
||||
// Uncompressed Size and the filters.
|
||||
//
|
||||
// NOTE: This function is used for validation too, so it is
|
||||
// essential that these checks are always done even if
|
||||
// Compressed Size is unknown.
|
||||
if (block == NULL || block->version > 1
|
||||
|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
|
||||
|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
|
||||
|| (block->header_size & 3)
|
||||
|| !lzma_vli_is_valid(block->compressed_size)
|
||||
|| block->compressed_size == 0
|
||||
|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
|
||||
return 0;
|
||||
|
||||
// If Compressed Size is unknown, return that we cannot know
|
||||
// size of the Block either.
|
||||
if (block->compressed_size == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_VLI_UNKNOWN;
|
||||
|
||||
// Calculate Unpadded Size and validate it.
|
||||
const lzma_vli unpadded_size = block->compressed_size
|
||||
+ block->header_size
|
||||
+ lzma_check_size(block->check);
|
||||
|
||||
assert(unpadded_size >= UNPADDED_SIZE_MIN);
|
||||
if (unpadded_size > UNPADDED_SIZE_MAX)
|
||||
return 0;
|
||||
|
||||
return unpadded_size;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_vli)
|
||||
lzma_block_total_size(const lzma_block *block)
|
||||
{
|
||||
lzma_vli unpadded_size = lzma_block_unpadded_size(block);
|
||||
|
||||
if (unpadded_size != LZMA_VLI_UNKNOWN)
|
||||
unpadded_size = vli_ceil4(unpadded_size);
|
||||
|
||||
return unpadded_size;
|
||||
}
|
||||
@@ -14,7 +14,6 @@
|
||||
#define LZMA_COMMON_H
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include "mythread.h"
|
||||
#include "tuklib_integer.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
@@ -88,10 +87,6 @@
|
||||
#define LZMA_TIMED_OUT 32
|
||||
|
||||
|
||||
/// Type of encoder/decoder specific data; the actual structure is defined
|
||||
/// differently in different coders.
|
||||
typedef struct lzma_coder_s lzma_coder;
|
||||
|
||||
typedef struct lzma_next_coder_s lzma_next_coder;
|
||||
|
||||
typedef struct lzma_filter_info_s lzma_filter_info;
|
||||
@@ -107,7 +102,7 @@ typedef lzma_ret (*lzma_init_function)(
|
||||
/// input and output buffers, but for simplicity they still use this same
|
||||
/// function prototype.
|
||||
typedef lzma_ret (*lzma_code_function)(
|
||||
lzma_coder *coder, const lzma_allocator *allocator,
|
||||
void *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
@@ -115,7 +110,7 @@ typedef lzma_ret (*lzma_code_function)(
|
||||
|
||||
/// Type of a function to free the memory allocated for the coder
|
||||
typedef void (*lzma_end_function)(
|
||||
lzma_coder *coder, const lzma_allocator *allocator);
|
||||
void *coder, const lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Raw coder validates and converts an array of lzma_filter structures to
|
||||
@@ -138,7 +133,7 @@ struct lzma_filter_info_s {
|
||||
/// Hold data and function pointers of the next filter in the chain.
|
||||
struct lzma_next_coder_s {
|
||||
/// Pointer to coder-specific data
|
||||
lzma_coder *coder;
|
||||
void *coder;
|
||||
|
||||
/// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
|
||||
/// point to a filter coder.
|
||||
@@ -160,21 +155,21 @@ struct lzma_next_coder_s {
|
||||
|
||||
/// Pointer to a function to get progress information. If this is NULL,
|
||||
/// lzma_stream.total_in and .total_out are used instead.
|
||||
void (*get_progress)(lzma_coder *coder,
|
||||
void (*get_progress)(void *coder,
|
||||
uint64_t *progress_in, uint64_t *progress_out);
|
||||
|
||||
/// Pointer to function to return the type of the integrity check.
|
||||
/// Most coders won't support this.
|
||||
lzma_check (*get_check)(const lzma_coder *coder);
|
||||
lzma_check (*get_check)(const void *coder);
|
||||
|
||||
/// Pointer to function to get and/or change the memory usage limit.
|
||||
/// If new_memlimit == 0, the limit is not changed.
|
||||
lzma_ret (*memconfig)(lzma_coder *coder, uint64_t *memusage,
|
||||
lzma_ret (*memconfig)(void *coder, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit);
|
||||
|
||||
/// Update the filter-specific options or the whole filter chain
|
||||
/// in the encoder.
|
||||
lzma_ret (*update)(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
lzma_ret (*update)(void *coder, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
const lzma_filter *reversed_filters);
|
||||
};
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_buffer_encoder.c
|
||||
/// \brief Easy single-call .xz Stream encoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "easy_preset.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_easy_buffer_encode(uint32_t preset, lzma_check check,
|
||||
const lzma_allocator *allocator, const uint8_t *in,
|
||||
size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
lzma_options_easy opt_easy;
|
||||
if (lzma_easy_preset(&opt_easy, preset))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
return lzma_stream_buffer_encode(opt_easy.filters, check,
|
||||
allocator, in, in_size, out, out_pos, out_size);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_decoder_memusage.c
|
||||
/// \brief Decoder memory usage calculation to match easy encoder presets
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "easy_preset.h"
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_easy_decoder_memusage(uint32_t preset)
|
||||
{
|
||||
lzma_options_easy opt_easy;
|
||||
if (lzma_easy_preset(&opt_easy, preset))
|
||||
return UINT32_MAX;
|
||||
|
||||
return lzma_raw_decoder_memusage(opt_easy.filters);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_encoder.c
|
||||
/// \brief Easy .xz Stream encoder initialization
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "easy_preset.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_easy_encoder(lzma_stream *strm, uint32_t preset, lzma_check check)
|
||||
{
|
||||
lzma_options_easy opt_easy;
|
||||
if (lzma_easy_preset(&opt_easy, preset))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
return lzma_stream_encoder(strm, opt_easy.filters, check);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_encoder_memusage.c
|
||||
/// \brief Easy .xz Stream encoder memory usage calculation
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "easy_preset.h"
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_easy_encoder_memusage(uint32_t preset)
|
||||
{
|
||||
lzma_options_easy opt_easy;
|
||||
if (lzma_easy_preset(&opt_easy, preset))
|
||||
return UINT32_MAX;
|
||||
|
||||
return lzma_raw_encoder_memusage(opt_easy.filters);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_preset.c
|
||||
/// \brief Preset handling for easy encoder and decoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "easy_preset.h"
|
||||
|
||||
|
||||
extern bool
|
||||
lzma_easy_preset(lzma_options_easy *opt_easy, uint32_t preset)
|
||||
{
|
||||
if (lzma_lzma_preset(&opt_easy->opt_lzma, preset))
|
||||
return true;
|
||||
|
||||
opt_easy->filters[0].id = LZMA_FILTER_LZMA2;
|
||||
opt_easy->filters[0].options = &opt_easy->opt_lzma;
|
||||
opt_easy->filters[1].id = LZMA_VLI_UNKNOWN;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_preset.h
|
||||
/// \brief Preset handling for easy encoder and decoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// We need to keep the filters array available in case
|
||||
/// LZMA_FULL_FLUSH is used.
|
||||
lzma_filter filters[LZMA_FILTERS_MAX + 1];
|
||||
|
||||
/// Options for LZMA2
|
||||
lzma_options_lzma opt_lzma;
|
||||
|
||||
// Options for more filters can be added later, so this struct
|
||||
// is not ready to be put into the public API.
|
||||
|
||||
} lzma_options_easy;
|
||||
|
||||
|
||||
/// Set *easy to the settings given by the preset. Returns true on error,
|
||||
/// false on success.
|
||||
extern bool lzma_easy_preset(lzma_options_easy *easy, uint32_t preset);
|
||||
@@ -1,88 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_buffer_decoder.c
|
||||
/// \brief Single-call raw decoding
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_decoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_raw_buffer_decode(
|
||||
const lzma_filter *filters, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Validate what isn't validated later in filter_common.c.
|
||||
if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL
|
||||
|| out_pos == NULL || *out_pos > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Initialize the decoer.
|
||||
lzma_next_coder next = LZMA_NEXT_CODER_INIT;
|
||||
return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
|
||||
|
||||
// Store the positions so that we can restore them if something
|
||||
// goes wrong.
|
||||
const size_t in_start = *in_pos;
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
// Do the actual decoding and free decoder's memory.
|
||||
lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size,
|
||||
out, out_pos, out_size, LZMA_FINISH);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
if (ret == LZMA_OK) {
|
||||
// Either the input was truncated or the
|
||||
// output buffer was too small.
|
||||
assert(*in_pos == in_size || *out_pos == out_size);
|
||||
|
||||
if (*in_pos != in_size) {
|
||||
// Since input wasn't consumed completely,
|
||||
// the output buffer became full and is
|
||||
// too small.
|
||||
ret = LZMA_BUF_ERROR;
|
||||
|
||||
} else if (*out_pos != out_size) {
|
||||
// Since output didn't became full, the input
|
||||
// has to be truncated.
|
||||
ret = LZMA_DATA_ERROR;
|
||||
|
||||
} else {
|
||||
// All the input was consumed and output
|
||||
// buffer is full. Now we don't immediately
|
||||
// know the reason for the error. Try
|
||||
// decoding one more byte. If it succeeds,
|
||||
// then the output buffer was too small. If
|
||||
// we cannot get a new output byte, the input
|
||||
// is truncated.
|
||||
uint8_t tmp[1];
|
||||
size_t tmp_pos = 0;
|
||||
(void)next.code(next.coder, allocator,
|
||||
in, in_pos, in_size,
|
||||
tmp, &tmp_pos, 1, LZMA_FINISH);
|
||||
|
||||
if (tmp_pos == 1)
|
||||
ret = LZMA_BUF_ERROR;
|
||||
else
|
||||
ret = LZMA_DATA_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the positions.
|
||||
*in_pos = in_start;
|
||||
*out_pos = out_start;
|
||||
}
|
||||
|
||||
lzma_next_end(&next, allocator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_buffer_encoder.c
|
||||
/// \brief Single-call raw encoding
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_encoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_raw_buffer_encode(
|
||||
const lzma_filter *filters, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Validate what isn't validated later in filter_common.c.
|
||||
if ((in == NULL && in_size != 0) || out == NULL
|
||||
|| out_pos == NULL || *out_pos > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Initialize the encoder
|
||||
lzma_next_coder next = LZMA_NEXT_CODER_INIT;
|
||||
return_if_error(lzma_raw_encoder_init(&next, allocator, filters));
|
||||
|
||||
// Store the output position so that we can restore it if
|
||||
// something goes wrong.
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
// Do the actual encoding and free coder's memory.
|
||||
size_t in_pos = 0;
|
||||
lzma_ret ret = next.code(next.coder, allocator, in, &in_pos, in_size,
|
||||
out, out_pos, out_size, LZMA_FINISH);
|
||||
lzma_next_end(&next, allocator);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
if (ret == LZMA_OK) {
|
||||
// Output buffer was too small.
|
||||
assert(*out_pos == out_size);
|
||||
ret = LZMA_BUF_ERROR;
|
||||
}
|
||||
|
||||
// Restore the output position.
|
||||
*out_pos = out_start;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,337 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_common.c
|
||||
/// \brief Filter-specific stuff common for both encoder and decoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_common.h"
|
||||
|
||||
|
||||
static const struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// Size of the filter-specific options structure
|
||||
size_t options_size;
|
||||
|
||||
/// True if it is OK to use this filter as non-last filter in
|
||||
/// the chain.
|
||||
bool non_last_ok;
|
||||
|
||||
/// True if it is OK to use this filter as the last filter in
|
||||
/// the chain.
|
||||
bool last_ok;
|
||||
|
||||
/// True if the filter may change the size of the data (that is, the
|
||||
/// amount of encoded output can be different than the amount of
|
||||
/// uncompressed input).
|
||||
bool changes_size;
|
||||
|
||||
} features[] = {
|
||||
#if defined (HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1)
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA1,
|
||||
.options_size = sizeof(lzma_options_lzma),
|
||||
.non_last_ok = false,
|
||||
.last_ok = true,
|
||||
.changes_size = true,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.options_size = sizeof(lzma_options_lzma),
|
||||
.non_last_ok = false,
|
||||
.last_ok = true,
|
||||
.changes_size = true,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_X86) || defined(HAVE_DECODER_X86)
|
||||
{
|
||||
.id = LZMA_FILTER_X86,
|
||||
.options_size = sizeof(lzma_options_bcj),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
|
||||
{
|
||||
.id = LZMA_FILTER_POWERPC,
|
||||
.options_size = sizeof(lzma_options_bcj),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_IA64) || defined(HAVE_DECODER_IA64)
|
||||
{
|
||||
.id = LZMA_FILTER_IA64,
|
||||
.options_size = sizeof(lzma_options_bcj),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
|
||||
{
|
||||
.id = LZMA_FILTER_ARM,
|
||||
.options_size = sizeof(lzma_options_bcj),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
|
||||
{
|
||||
.id = LZMA_FILTER_ARMTHUMB,
|
||||
.options_size = sizeof(lzma_options_bcj),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
|
||||
{
|
||||
.id = LZMA_FILTER_SPARC,
|
||||
.options_size = sizeof(lzma_options_bcj),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
|
||||
{
|
||||
.id = LZMA_FILTER_DELTA,
|
||||
.options_size = sizeof(lzma_options_delta),
|
||||
.non_last_ok = true,
|
||||
.last_ok = false,
|
||||
.changes_size = false,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.id = LZMA_VLI_UNKNOWN
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
|
||||
const lzma_allocator *allocator)
|
||||
{
|
||||
if (src == NULL || dest == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
lzma_ret ret;
|
||||
size_t i;
|
||||
for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
|
||||
// There must be a maximum of four filters plus
|
||||
// the array terminator.
|
||||
if (i == LZMA_FILTERS_MAX) {
|
||||
ret = LZMA_OPTIONS_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dest[i].id = src[i].id;
|
||||
|
||||
if (src[i].options == NULL) {
|
||||
dest[i].options = NULL;
|
||||
} else {
|
||||
// See if the filter is supported only when the
|
||||
// options is not NULL. This might be convenient
|
||||
// sometimes if the app is actually copying only
|
||||
// a partial filter chain with a place holder ID.
|
||||
//
|
||||
// When options is not NULL, the Filter ID must be
|
||||
// supported by us, because otherwise we don't know
|
||||
// how big the options are.
|
||||
size_t j;
|
||||
for (j = 0; src[i].id != features[j].id; ++j) {
|
||||
if (features[j].id == LZMA_VLI_UNKNOWN) {
|
||||
ret = LZMA_OPTIONS_ERROR;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate and copy the options.
|
||||
dest[i].options = lzma_alloc(features[j].options_size,
|
||||
allocator);
|
||||
if (dest[i].options == NULL) {
|
||||
ret = LZMA_MEM_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(dest[i].options, src[i].options,
|
||||
features[j].options_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the filter array.
|
||||
assert(i <= LZMA_FILTERS_MAX + 1);
|
||||
dest[i].id = LZMA_VLI_UNKNOWN;
|
||||
dest[i].options = NULL;
|
||||
|
||||
return LZMA_OK;
|
||||
|
||||
error:
|
||||
// Free the options which we have already allocated.
|
||||
while (i-- > 0) {
|
||||
lzma_free(dest[i].options, allocator);
|
||||
dest[i].options = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
validate_chain(const lzma_filter *filters, size_t *count)
|
||||
{
|
||||
// There must be at least one filter.
|
||||
if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Number of non-last filters that may change the size of the data
|
||||
// significantly (that is, more than 1-2 % or so).
|
||||
size_t changes_size_count = 0;
|
||||
|
||||
// True if it is OK to add a new filter after the current filter.
|
||||
bool non_last_ok = true;
|
||||
|
||||
// True if the last filter in the given chain is actually usable as
|
||||
// the last filter. Only filters that support embedding End of Payload
|
||||
// Marker can be used as the last filter in the chain.
|
||||
bool last_ok = false;
|
||||
|
||||
size_t i = 0;
|
||||
do {
|
||||
size_t j;
|
||||
for (j = 0; filters[i].id != features[j].id; ++j)
|
||||
if (features[j].id == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// If the previous filter in the chain cannot be a non-last
|
||||
// filter, the chain is invalid.
|
||||
if (!non_last_ok)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
non_last_ok = features[j].non_last_ok;
|
||||
last_ok = features[j].last_ok;
|
||||
changes_size_count += features[j].changes_size;
|
||||
|
||||
} while (filters[++i].id != LZMA_VLI_UNKNOWN);
|
||||
|
||||
// There must be 1-4 filters. The last filter must be usable as
|
||||
// the last filter in the chain. A maximum of three filters are
|
||||
// allowed to change the size of the data.
|
||||
if (i > LZMA_FILTERS_MAX || !last_ok || changes_size_count > 3)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
*count = i;
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options,
|
||||
lzma_filter_find coder_find, bool is_encoder)
|
||||
{
|
||||
// Do some basic validation and get the number of filters.
|
||||
size_t count;
|
||||
return_if_error(validate_chain(options, &count));
|
||||
|
||||
// Set the filter functions and copy the options pointer.
|
||||
lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
|
||||
if (is_encoder) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
// The order of the filters is reversed in the
|
||||
// encoder. It allows more efficient handling
|
||||
// of the uncompressed data.
|
||||
const size_t j = count - i - 1;
|
||||
|
||||
const lzma_filter_coder *const fc
|
||||
= coder_find(options[i].id);
|
||||
if (fc == NULL || fc->init == NULL)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
filters[j].id = options[i].id;
|
||||
filters[j].init = fc->init;
|
||||
filters[j].options = options[i].options;
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
const lzma_filter_coder *const fc
|
||||
= coder_find(options[i].id);
|
||||
if (fc == NULL || fc->init == NULL)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
filters[i].id = options[i].id;
|
||||
filters[i].init = fc->init;
|
||||
filters[i].options = options[i].options;
|
||||
}
|
||||
}
|
||||
|
||||
// Terminate the array.
|
||||
filters[count].id = LZMA_VLI_UNKNOWN;
|
||||
filters[count].init = NULL;
|
||||
|
||||
// Initialize the filters.
|
||||
const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
|
||||
if (ret != LZMA_OK)
|
||||
lzma_next_end(next, allocator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern uint64_t
|
||||
lzma_raw_coder_memusage(lzma_filter_find coder_find,
|
||||
const lzma_filter *filters)
|
||||
{
|
||||
// The chain has to have at least one filter.
|
||||
{
|
||||
size_t tmp;
|
||||
if (validate_chain(filters, &tmp) != LZMA_OK)
|
||||
return UINT64_MAX;
|
||||
}
|
||||
|
||||
uint64_t total = 0;
|
||||
size_t i = 0;
|
||||
|
||||
do {
|
||||
const lzma_filter_coder *const fc
|
||||
= coder_find(filters[i].id);
|
||||
if (fc == NULL)
|
||||
return UINT64_MAX; // Unsupported Filter ID
|
||||
|
||||
if (fc->memusage == NULL) {
|
||||
// This filter doesn't have a function to calculate
|
||||
// the memory usage and validate the options. Such
|
||||
// filters need only little memory, so we use 1 KiB
|
||||
// as a good estimate. They also accept all possible
|
||||
// options, so there's no need to worry about lack
|
||||
// of validation.
|
||||
total += 1024;
|
||||
} else {
|
||||
// Call the filter-specific memory usage calculation
|
||||
// function.
|
||||
const uint64_t usage
|
||||
= fc->memusage(filters[i].options);
|
||||
if (usage == UINT64_MAX)
|
||||
return UINT64_MAX; // Invalid options
|
||||
|
||||
total += usage;
|
||||
}
|
||||
} while (filters[++i].id != LZMA_VLI_UNKNOWN);
|
||||
|
||||
// Add some fixed amount of extra. It's to compensate memory usage
|
||||
// of Stream, Block etc. coders, malloc() overhead, stack etc.
|
||||
return total + LZMA_MEMUSAGE_BASE;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_common.c
|
||||
/// \brief Filter-specific stuff common for both encoder and decoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_FILTER_COMMON_H
|
||||
#define LZMA_FILTER_COMMON_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
|
||||
typedef struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// Initializes the filter encoder and calls lzma_next_filter_init()
|
||||
/// for filters + 1.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Calculates memory usage of the encoder. If the options are
|
||||
/// invalid, UINT64_MAX is returned.
|
||||
uint64_t (*memusage)(const void *options);
|
||||
|
||||
} lzma_filter_coder;
|
||||
|
||||
|
||||
typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_coder_init(
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
lzma_filter_find coder_find, bool is_encoder);
|
||||
|
||||
|
||||
extern uint64_t lzma_raw_coder_memusage(lzma_filter_find coder_find,
|
||||
const lzma_filter *filters);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,195 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_decoder.h"
|
||||
#include "filter_common.h"
|
||||
#include "lzma_decoder.h"
|
||||
#ifdef HAVE_DECODER_LZMA2
|
||||
#include "lzma2_decoder.h"
|
||||
#endif
|
||||
#if defined(HAVE_DECODER_X86) || \
|
||||
defined(HAVE_DECODER_POWERPC) || \
|
||||
defined(HAVE_DECODER_IA64) || \
|
||||
defined(HAVE_DECODER_ARM) || \
|
||||
defined(HAVE_DECODER_ARMTHUMB) || \
|
||||
defined(HAVE_DECODER_SPARC)
|
||||
#include "simple_decoder.h"
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_DELTA
|
||||
#include "delta_decoder.h"
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// Filter ID
|
||||
lzma_vli id;
|
||||
|
||||
/// Initializes the filter encoder and calls lzma_next_filter_init()
|
||||
/// for filters + 1.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Calculates memory usage of the encoder. If the options are
|
||||
/// invalid, UINT64_MAX is returned.
|
||||
uint64_t (*memusage)(const void *options);
|
||||
|
||||
/// Decodes Filter Properties.
|
||||
///
|
||||
/// \return - LZMA_OK: Properties decoded successfully.
|
||||
/// - LZMA_OPTIONS_ERROR: Unsupported properties
|
||||
/// - LZMA_MEM_ERROR: Memory allocation failed.
|
||||
lzma_ret (*props_decode)(
|
||||
void **options, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size);
|
||||
|
||||
} lzma_filter_decoder;
|
||||
|
||||
|
||||
static const lzma_filter_decoder decoders[] = {
|
||||
#ifdef HAVE_DECODER_LZMA1
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA1,
|
||||
.init = &lzma_lzma_decoder_init,
|
||||
.memusage = &lzma_lzma_decoder_memusage,
|
||||
.props_decode = &lzma_lzma_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_LZMA2
|
||||
{
|
||||
.id = LZMA_FILTER_LZMA2,
|
||||
.init = &lzma_lzma2_decoder_init,
|
||||
.memusage = &lzma_lzma2_decoder_memusage,
|
||||
.props_decode = &lzma_lzma2_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_X86
|
||||
{
|
||||
.id = LZMA_FILTER_X86,
|
||||
.init = &lzma_simple_x86_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_POWERPC
|
||||
{
|
||||
.id = LZMA_FILTER_POWERPC,
|
||||
.init = &lzma_simple_powerpc_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_IA64
|
||||
{
|
||||
.id = LZMA_FILTER_IA64,
|
||||
.init = &lzma_simple_ia64_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_ARM
|
||||
{
|
||||
.id = LZMA_FILTER_ARM,
|
||||
.init = &lzma_simple_arm_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_ARMTHUMB
|
||||
{
|
||||
.id = LZMA_FILTER_ARMTHUMB,
|
||||
.init = &lzma_simple_armthumb_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_SPARC
|
||||
{
|
||||
.id = LZMA_FILTER_SPARC,
|
||||
.init = &lzma_simple_sparc_decoder_init,
|
||||
.memusage = NULL,
|
||||
.props_decode = &lzma_simple_props_decode,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_DECODER_DELTA
|
||||
{
|
||||
.id = LZMA_FILTER_DELTA,
|
||||
.init = &lzma_delta_decoder_init,
|
||||
.memusage = &lzma_delta_coder_memusage,
|
||||
.props_decode = &lzma_delta_props_decode,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static const lzma_filter_decoder *
|
||||
decoder_find(lzma_vli id)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
|
||||
if (decoders[i].id == id)
|
||||
return decoders + i;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_bool)
|
||||
lzma_filter_decoder_is_supported(lzma_vli id)
|
||||
{
|
||||
return decoder_find(id) != NULL;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options)
|
||||
{
|
||||
return lzma_raw_coder_init(next, allocator,
|
||||
options, (lzma_filter_find)(&decoder_find), false);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
|
||||
{
|
||||
lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_raw_decoder_memusage(const lzma_filter *filters)
|
||||
{
|
||||
return lzma_raw_coder_memusage(
|
||||
(lzma_filter_find)(&decoder_find), filters);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_properties_decode(lzma_filter *filter, const lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size)
|
||||
{
|
||||
// Make it always NULL so that the caller can always safely free() it.
|
||||
filter->options = NULL;
|
||||
|
||||
const lzma_filter_decoder *const fd = decoder_find(filter->id);
|
||||
if (fd == NULL)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
if (fd->props_decode == NULL)
|
||||
return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR;
|
||||
|
||||
return fd->props_decode(
|
||||
&filter->options, allocator, props, props_size);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_FILTER_DECODER_H
|
||||
#define LZMA_FILTER_DECODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern lzma_ret lzma_raw_decoder_init(
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options);
|
||||
|
||||
#endif
|
||||
@@ -11,7 +11,6 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_encoder.h"
|
||||
#include "filter_common.h"
|
||||
#include "lzma_encoder.h"
|
||||
#ifdef HAVE_DECODER_LZMA2
|
||||
#include "lzma2_encoder.h"
|
||||
@@ -179,64 +178,6 @@ lzma_filter_encoder_is_supported(lzma_vli id)
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
|
||||
{
|
||||
if (strm->internal->next.update == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Validate the filter chain.
|
||||
if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// The actual filter chain in the encoder is reversed. Some things
|
||||
// still want the normal order chain, so we provide both.
|
||||
size_t count = 1;
|
||||
while (filters[count].id != LZMA_VLI_UNKNOWN)
|
||||
++count;
|
||||
|
||||
lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
reversed_filters[count - i - 1] = filters[i];
|
||||
|
||||
reversed_filters[count].id = LZMA_VLI_UNKNOWN;
|
||||
|
||||
return strm->internal->next.update(strm->internal->next.coder,
|
||||
strm->allocator, filters, reversed_filters);
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *options)
|
||||
{
|
||||
return lzma_raw_coder_init(next, allocator,
|
||||
options, (lzma_filter_find)(&encoder_find), true);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
|
||||
{
|
||||
lzma_next_strm_init(lzma_raw_coder_init, strm, options,
|
||||
(lzma_filter_find)(&encoder_find), true);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_raw_encoder_memusage(const lzma_filter *filters)
|
||||
{
|
||||
return lzma_raw_coder_memusage(
|
||||
(lzma_filter_find)(&encoder_find), filters);
|
||||
}
|
||||
|
||||
|
||||
extern uint64_t
|
||||
lzma_mt_block_size(const lzma_filter *filters)
|
||||
{
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_flags_decoder.c
|
||||
/// \brief Decodes a Filter Flags field
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_decoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filter_flags_decode(
|
||||
lzma_filter *filter, const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
// Set the pointer to NULL so the caller can always safely free it.
|
||||
filter->options = NULL;
|
||||
|
||||
// Filter ID
|
||||
return_if_error(lzma_vli_decode(&filter->id, NULL,
|
||||
in, in_pos, in_size));
|
||||
|
||||
if (filter->id >= LZMA_FILTER_RESERVED_START)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Size of Properties
|
||||
lzma_vli props_size;
|
||||
return_if_error(lzma_vli_decode(&props_size, NULL,
|
||||
in, in_pos, in_size));
|
||||
|
||||
// Filter Properties
|
||||
if (in_size - *in_pos < props_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
const lzma_ret ret = lzma_properties_decode(
|
||||
filter, allocator, in + *in_pos, props_size);
|
||||
|
||||
*in_pos += props_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_flags_encoder.c
|
||||
/// \brief Decodes a Filter Flags field
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "filter_encoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter)
|
||||
{
|
||||
if (filter->id >= LZMA_FILTER_RESERVED_START)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return_if_error(lzma_properties_size(size, filter));
|
||||
|
||||
*size += lzma_vli_size(filter->id) + lzma_vli_size(*size);
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_filter_flags_encode(const lzma_filter *filter,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Filter ID
|
||||
if (filter->id >= LZMA_FILTER_RESERVED_START)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return_if_error(lzma_vli_encode(filter->id, NULL,
|
||||
out, out_pos, out_size));
|
||||
|
||||
// Size of Properties
|
||||
uint32_t props_size;
|
||||
return_if_error(lzma_properties_size(&props_size, filter));
|
||||
return_if_error(lzma_vli_encode(props_size, NULL,
|
||||
out, out_pos, out_size));
|
||||
|
||||
// Filter Properties
|
||||
if (out_size - *out_pos < props_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
return_if_error(lzma_properties_encode(filter, out + *out_pos));
|
||||
|
||||
*out_pos += props_size;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file hardware_cputhreads.c
|
||||
/// \brief Get the number of CPU threads or cores
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "tuklib_cpucores.h"
|
||||
|
||||
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_cputhreads(void)
|
||||
{
|
||||
return tuklib_cpucores();
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file hardware_physmem.c
|
||||
/// \brief Get the total amount of physical memory (RAM)
|
||||
//
|
||||
// Author: Jonathan Nieder
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "tuklib_physmem.h"
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_physmem(void)
|
||||
{
|
||||
// It is simpler to make lzma_physmem() a wrapper for
|
||||
// tuklib_physmem() than to hack appropriate symbol visiblity
|
||||
// support for the tuklib modules.
|
||||
return tuklib_physmem();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,345 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index_decoder.c
|
||||
/// \brief Decodes the Index field
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "index.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
enum {
|
||||
SEQ_INDICATOR,
|
||||
SEQ_COUNT,
|
||||
SEQ_MEMUSAGE,
|
||||
SEQ_UNPADDED,
|
||||
SEQ_UNCOMPRESSED,
|
||||
SEQ_PADDING_INIT,
|
||||
SEQ_PADDING,
|
||||
SEQ_CRC32,
|
||||
} sequence;
|
||||
|
||||
/// Memory usage limit
|
||||
uint64_t memlimit;
|
||||
|
||||
/// Target Index
|
||||
lzma_index *index;
|
||||
|
||||
/// Pointer give by the application, which is set after
|
||||
/// successful decoding.
|
||||
lzma_index **index_ptr;
|
||||
|
||||
/// Number of Records left to decode.
|
||||
lzma_vli count;
|
||||
|
||||
/// The most recent Unpadded Size field
|
||||
lzma_vli unpadded_size;
|
||||
|
||||
/// The most recent Uncompressed Size field
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Position in integers
|
||||
size_t pos;
|
||||
|
||||
/// CRC32 of the List of Records field
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size,
|
||||
uint8_t *restrict out lzma_attribute((__unused__)),
|
||||
size_t *restrict out_pos lzma_attribute((__unused__)),
|
||||
size_t out_size lzma_attribute((__unused__)),
|
||||
lzma_action action lzma_attribute((__unused__)))
|
||||
{
|
||||
// Similar optimization as in index_encoder.c
|
||||
const size_t in_start = *in_pos;
|
||||
lzma_ret ret = LZMA_OK;
|
||||
|
||||
while (*in_pos < in_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_INDICATOR:
|
||||
// Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or
|
||||
// LZMA_FORMAT_ERROR, because a typical usage case for Index
|
||||
// decoder is when parsing the Stream backwards. If seeking
|
||||
// backward from the Stream Footer gives us something that
|
||||
// doesn't begin with Index Indicator, the file is considered
|
||||
// corrupt, not "programming error" or "unrecognized file
|
||||
// format". One could argue that the application should
|
||||
// verify the Index Indicator before trying to decode the
|
||||
// Index, but well, I suppose it is simpler this way.
|
||||
if (in[(*in_pos)++] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->sequence = SEQ_COUNT;
|
||||
break;
|
||||
|
||||
case SEQ_COUNT:
|
||||
ret = lzma_vli_decode(&coder->count, &coder->pos,
|
||||
in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_MEMUSAGE;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_MEMUSAGE:
|
||||
if (lzma_index_memusage(1, coder->count) > coder->memlimit) {
|
||||
ret = LZMA_MEMLIMIT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Tell the Index handling code how many Records this
|
||||
// Index has to allow it to allocate memory more efficiently.
|
||||
lzma_index_prealloc(coder->index, coder->count);
|
||||
|
||||
ret = LZMA_OK;
|
||||
coder->sequence = coder->count == 0
|
||||
? SEQ_PADDING_INIT : SEQ_UNPADDED;
|
||||
break;
|
||||
|
||||
case SEQ_UNPADDED:
|
||||
case SEQ_UNCOMPRESSED: {
|
||||
lzma_vli *size = coder->sequence == SEQ_UNPADDED
|
||||
? &coder->unpadded_size
|
||||
: &coder->uncompressed_size;
|
||||
|
||||
ret = lzma_vli_decode(size, &coder->pos,
|
||||
in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
ret = LZMA_OK;
|
||||
coder->pos = 0;
|
||||
|
||||
if (coder->sequence == SEQ_UNPADDED) {
|
||||
// Validate that encoded Unpadded Size isn't too small
|
||||
// or too big.
|
||||
if (coder->unpadded_size < UNPADDED_SIZE_MIN
|
||||
|| coder->unpadded_size
|
||||
> UNPADDED_SIZE_MAX)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
coder->sequence = SEQ_UNCOMPRESSED;
|
||||
} else {
|
||||
// Add the decoded Record to the Index.
|
||||
return_if_error(lzma_index_append(
|
||||
coder->index, allocator,
|
||||
coder->unpadded_size,
|
||||
coder->uncompressed_size));
|
||||
|
||||
// Check if this was the last Record.
|
||||
coder->sequence = --coder->count == 0
|
||||
? SEQ_PADDING_INIT
|
||||
: SEQ_UNPADDED;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_PADDING_INIT:
|
||||
coder->pos = lzma_index_padding_size(coder->index);
|
||||
coder->sequence = SEQ_PADDING;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (coder->pos > 0) {
|
||||
--coder->pos;
|
||||
if (in[(*in_pos)++] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Finish the CRC32 calculation.
|
||||
coder->crc32 = lzma_crc32(in + in_start,
|
||||
*in_pos - in_start, coder->crc32);
|
||||
|
||||
coder->sequence = SEQ_CRC32;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CRC32:
|
||||
do {
|
||||
if (*in_pos == in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
|
||||
!= in[(*in_pos)++])
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
} while (++coder->pos < 4);
|
||||
|
||||
// Decoding was successful, now we can let the application
|
||||
// see the decoded Index.
|
||||
*coder->index_ptr = coder->index;
|
||||
|
||||
// Make index NULL so we don't free it unintentionally.
|
||||
coder->index = NULL;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
out:
|
||||
// Update the CRC32,
|
||||
coder->crc32 = lzma_crc32(in + in_start,
|
||||
*in_pos - in_start, coder->crc32);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
index_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_index_end(coder->index, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
*memusage = lzma_index_memusage(1, coder->count);
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
if (new_memlimit != 0) {
|
||||
if (new_memlimit < *memusage)
|
||||
return LZMA_MEMLIMIT_ERROR;
|
||||
|
||||
coder->memlimit = new_memlimit;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_reset(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
lzma_index **i, uint64_t memlimit)
|
||||
{
|
||||
// Remember the pointer given by the application. We will set it
|
||||
// to point to the decoded Index only if decoding is successful.
|
||||
// Before that, keep it NULL so that applications can always safely
|
||||
// pass it to lzma_index_end() no matter did decoding succeed or not.
|
||||
coder->index_ptr = i;
|
||||
*i = NULL;
|
||||
|
||||
// We always allocate a new lzma_index.
|
||||
coder->index = lzma_index_init(allocator);
|
||||
if (coder->index == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Initialize the rest.
|
||||
coder->sequence = SEQ_INDICATOR;
|
||||
coder->memlimit = memlimit;
|
||||
coder->count = 0; // Needs to be initialized due to _memconfig().
|
||||
coder->pos = 0;
|
||||
coder->crc32 = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lzma_index **i, uint64_t memlimit)
|
||||
{
|
||||
lzma_next_coder_init(&index_decoder_init, next, allocator);
|
||||
|
||||
if (i == NULL || memlimit == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &index_decode;
|
||||
next->end = &index_decoder_end;
|
||||
next->memconfig = &index_decoder_memconfig;
|
||||
next->coder->index = NULL;
|
||||
} else {
|
||||
lzma_index_end(next->coder->index, allocator);
|
||||
}
|
||||
|
||||
return index_decoder_reset(next->coder, allocator, i, memlimit);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
|
||||
{
|
||||
lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_buffer_decode(lzma_index **i, uint64_t *memlimit,
|
||||
const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
{
|
||||
// Sanity checks
|
||||
if (i == NULL || memlimit == NULL
|
||||
|| in == NULL || in_pos == NULL || *in_pos > in_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Initialize the decoder.
|
||||
lzma_coder coder;
|
||||
return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
|
||||
|
||||
// Store the input start position so that we can restore it in case
|
||||
// of an error.
|
||||
const size_t in_start = *in_pos;
|
||||
|
||||
// Do the actual decoding.
|
||||
lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
|
||||
NULL, NULL, 0, LZMA_RUN);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
// Something went wrong, free the Index structure and restore
|
||||
// the input position.
|
||||
lzma_index_end(coder.index, allocator);
|
||||
*in_pos = in_start;
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
// The input is truncated or otherwise corrupt.
|
||||
// Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR
|
||||
// like lzma_vli_decode() does in single-call mode.
|
||||
ret = LZMA_DATA_ERROR;
|
||||
|
||||
} else if (ret == LZMA_MEMLIMIT_ERROR) {
|
||||
// Tell the caller how much memory would have
|
||||
// been needed.
|
||||
*memlimit = lzma_index_memusage(1, coder.count);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index_encoder.c
|
||||
/// \brief Encodes the Index field
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "index_encoder.h"
|
||||
#include "index.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
enum {
|
||||
SEQ_INDICATOR,
|
||||
SEQ_COUNT,
|
||||
SEQ_UNPADDED,
|
||||
SEQ_UNCOMPRESSED,
|
||||
SEQ_NEXT,
|
||||
SEQ_PADDING,
|
||||
SEQ_CRC32,
|
||||
} sequence;
|
||||
|
||||
/// Index being encoded
|
||||
const lzma_index *index;
|
||||
|
||||
/// Iterator for the Index being encoded
|
||||
lzma_index_iter iter;
|
||||
|
||||
/// Position in integers
|
||||
size_t pos;
|
||||
|
||||
/// CRC32 of the List of Records field
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
index_encode(lzma_coder *coder,
|
||||
const lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
const uint8_t *restrict in lzma_attribute((__unused__)),
|
||||
size_t *restrict in_pos lzma_attribute((__unused__)),
|
||||
size_t in_size lzma_attribute((__unused__)),
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size,
|
||||
lzma_action action lzma_attribute((__unused__)))
|
||||
{
|
||||
// Position where to start calculating CRC32. The idea is that we
|
||||
// need to call lzma_crc32() only once per call to index_encode().
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
// Return value to use if we return at the end of this function.
|
||||
// We use "goto out" to jump out of the while-switch construct
|
||||
// instead of returning directly, because that way we don't need
|
||||
// to copypaste the lzma_crc32() call to many places.
|
||||
lzma_ret ret = LZMA_OK;
|
||||
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_INDICATOR:
|
||||
out[*out_pos] = 0x00;
|
||||
++*out_pos;
|
||||
coder->sequence = SEQ_COUNT;
|
||||
break;
|
||||
|
||||
case SEQ_COUNT: {
|
||||
const lzma_vli count = lzma_index_block_count(coder->index);
|
||||
ret = lzma_vli_encode(count, &coder->pos,
|
||||
out, out_pos, out_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
ret = LZMA_OK;
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_NEXT;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_NEXT:
|
||||
if (lzma_index_iter_next(
|
||||
&coder->iter, LZMA_INDEX_ITER_BLOCK)) {
|
||||
// Get the size of the Index Padding field.
|
||||
coder->pos = lzma_index_padding_size(coder->index);
|
||||
assert(coder->pos <= 3);
|
||||
coder->sequence = SEQ_PADDING;
|
||||
break;
|
||||
}
|
||||
|
||||
coder->sequence = SEQ_UNPADDED;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_UNPADDED:
|
||||
case SEQ_UNCOMPRESSED: {
|
||||
const lzma_vli size = coder->sequence == SEQ_UNPADDED
|
||||
? coder->iter.block.unpadded_size
|
||||
: coder->iter.block.uncompressed_size;
|
||||
|
||||
ret = lzma_vli_encode(size, &coder->pos,
|
||||
out, out_pos, out_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
ret = LZMA_OK;
|
||||
coder->pos = 0;
|
||||
|
||||
// Advance to SEQ_UNCOMPRESSED or SEQ_NEXT.
|
||||
++coder->sequence;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (coder->pos > 0) {
|
||||
--coder->pos;
|
||||
out[(*out_pos)++] = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
// Finish the CRC32 calculation.
|
||||
coder->crc32 = lzma_crc32(out + out_start,
|
||||
*out_pos - out_start, coder->crc32);
|
||||
|
||||
coder->sequence = SEQ_CRC32;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CRC32:
|
||||
// We don't use the main loop, because we don't want
|
||||
// coder->crc32 to be touched anymore.
|
||||
do {
|
||||
if (*out_pos == out_size)
|
||||
return LZMA_OK;
|
||||
|
||||
out[*out_pos] = (coder->crc32 >> (coder->pos * 8))
|
||||
& 0xFF;
|
||||
++*out_pos;
|
||||
|
||||
} while (++coder->pos < 4);
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
out:
|
||||
// Update the CRC32.
|
||||
coder->crc32 = lzma_crc32(out + out_start,
|
||||
*out_pos - out_start, coder->crc32);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
index_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
index_encoder_reset(lzma_coder *coder, const lzma_index *i)
|
||||
{
|
||||
lzma_index_iter_init(&coder->iter, i);
|
||||
|
||||
coder->sequence = SEQ_INDICATOR;
|
||||
coder->index = i;
|
||||
coder->pos = 0;
|
||||
coder->crc32 = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_index *i)
|
||||
{
|
||||
lzma_next_coder_init(&lzma_index_encoder_init, next, allocator);
|
||||
|
||||
if (i == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &index_encode;
|
||||
next->end = &index_encoder_end;
|
||||
}
|
||||
|
||||
index_encoder_reset(next->coder, i);
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_encoder(lzma_stream *strm, const lzma_index *i)
|
||||
{
|
||||
lzma_next_strm_init(lzma_index_encoder_init, strm, i);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_buffer_encode(const lzma_index *i,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Validate the arguments.
|
||||
if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Don't try to encode if there's not enough output space.
|
||||
if (out_size - *out_pos < lzma_index_size(i))
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
// The Index encoder needs just one small data structure so we can
|
||||
// allocate it on stack.
|
||||
lzma_coder coder;
|
||||
index_encoder_reset(&coder, i);
|
||||
|
||||
// Do the actual encoding. This should never fail, but store
|
||||
// the original *out_pos just in case.
|
||||
const size_t out_start = *out_pos;
|
||||
lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
|
||||
out, out_pos, out_size, LZMA_RUN);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
// We should never get here, but just in case, restore the
|
||||
// output position and set the error accordingly if something
|
||||
// goes wrong and debugging isn't enabled.
|
||||
assert(0);
|
||||
*out_pos = out_start;
|
||||
ret = LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index_encoder.h
|
||||
/// \brief Encodes the Index field
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_INDEX_ENCODER_H
|
||||
#define LZMA_INDEX_ENCODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator, const lzma_index *i);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,334 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index_hash.c
|
||||
/// \brief Validates Index by using a hash function
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
#include "index.h"
|
||||
#include "check.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// Sum of the Block sizes (including Block Padding)
|
||||
lzma_vli blocks_size;
|
||||
|
||||
/// Sum of the Uncompressed Size fields
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Number of Records
|
||||
lzma_vli count;
|
||||
|
||||
/// Size of the List of Index Records as bytes
|
||||
lzma_vli index_list_size;
|
||||
|
||||
/// Check calculated from Unpadded Sizes and Uncompressed Sizes.
|
||||
lzma_check_state check;
|
||||
|
||||
} lzma_index_hash_info;
|
||||
|
||||
|
||||
struct lzma_index_hash_s {
|
||||
enum {
|
||||
SEQ_BLOCK,
|
||||
SEQ_COUNT,
|
||||
SEQ_UNPADDED,
|
||||
SEQ_UNCOMPRESSED,
|
||||
SEQ_PADDING_INIT,
|
||||
SEQ_PADDING,
|
||||
SEQ_CRC32,
|
||||
} sequence;
|
||||
|
||||
/// Information collected while decoding the actual Blocks.
|
||||
lzma_index_hash_info blocks;
|
||||
|
||||
/// Information collected from the Index field.
|
||||
lzma_index_hash_info records;
|
||||
|
||||
/// Number of Records not fully decoded
|
||||
lzma_vli remaining;
|
||||
|
||||
/// Unpadded Size currently being read from an Index Record.
|
||||
lzma_vli unpadded_size;
|
||||
|
||||
/// Uncompressed Size currently being read from an Index Record.
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Position in variable-length integers when decoding them from
|
||||
/// the List of Records.
|
||||
size_t pos;
|
||||
|
||||
/// CRC32 of the Index
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
|
||||
extern LZMA_API(lzma_index_hash *)
|
||||
lzma_index_hash_init(lzma_index_hash *index_hash,
|
||||
const lzma_allocator *allocator)
|
||||
{
|
||||
if (index_hash == NULL) {
|
||||
index_hash = lzma_alloc(sizeof(lzma_index_hash), allocator);
|
||||
if (index_hash == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
index_hash->sequence = SEQ_BLOCK;
|
||||
index_hash->blocks.blocks_size = 0;
|
||||
index_hash->blocks.uncompressed_size = 0;
|
||||
index_hash->blocks.count = 0;
|
||||
index_hash->blocks.index_list_size = 0;
|
||||
index_hash->records.blocks_size = 0;
|
||||
index_hash->records.uncompressed_size = 0;
|
||||
index_hash->records.count = 0;
|
||||
index_hash->records.index_list_size = 0;
|
||||
index_hash->unpadded_size = 0;
|
||||
index_hash->uncompressed_size = 0;
|
||||
index_hash->pos = 0;
|
||||
index_hash->crc32 = 0;
|
||||
|
||||
// These cannot fail because LZMA_CHECK_BEST is known to be supported.
|
||||
(void)lzma_check_init(&index_hash->blocks.check, LZMA_CHECK_BEST);
|
||||
(void)lzma_check_init(&index_hash->records.check, LZMA_CHECK_BEST);
|
||||
|
||||
return index_hash;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(void)
|
||||
lzma_index_hash_end(lzma_index_hash *index_hash,
|
||||
const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_free(index_hash, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_vli)
|
||||
lzma_index_hash_size(const lzma_index_hash *index_hash)
|
||||
{
|
||||
// Get the size of the Index from ->blocks instead of ->records for
|
||||
// cases where application wants to know the Index Size before
|
||||
// decoding the Index.
|
||||
return index_size(index_hash->blocks.count,
|
||||
index_hash->blocks.index_list_size);
|
||||
}
|
||||
|
||||
|
||||
/// Updates the sizes and the hash without any validation.
|
||||
static lzma_ret
|
||||
hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
|
||||
lzma_vli uncompressed_size)
|
||||
{
|
||||
info->blocks_size += vli_ceil4(unpadded_size);
|
||||
info->uncompressed_size += uncompressed_size;
|
||||
info->index_list_size += lzma_vli_size(unpadded_size)
|
||||
+ lzma_vli_size(uncompressed_size);
|
||||
++info->count;
|
||||
|
||||
const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
|
||||
lzma_check_update(&info->check, LZMA_CHECK_BEST,
|
||||
(const uint8_t *)(sizes), sizeof(sizes));
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_hash_append(lzma_index_hash *index_hash, lzma_vli unpadded_size,
|
||||
lzma_vli uncompressed_size)
|
||||
{
|
||||
// Validate the arguments.
|
||||
if (index_hash->sequence != SEQ_BLOCK
|
||||
|| unpadded_size < UNPADDED_SIZE_MIN
|
||||
|| unpadded_size > UNPADDED_SIZE_MAX
|
||||
|| uncompressed_size > LZMA_VLI_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Update the hash.
|
||||
return_if_error(hash_append(&index_hash->blocks,
|
||||
unpadded_size, uncompressed_size));
|
||||
|
||||
// Validate the properties of *info are still in allowed limits.
|
||||
if (index_hash->blocks.blocks_size > LZMA_VLI_MAX
|
||||
|| index_hash->blocks.uncompressed_size > LZMA_VLI_MAX
|
||||
|| index_size(index_hash->blocks.count,
|
||||
index_hash->blocks.index_list_size)
|
||||
> LZMA_BACKWARD_SIZE_MAX
|
||||
|| index_stream_size(index_hash->blocks.blocks_size,
|
||||
index_hash->blocks.count,
|
||||
index_hash->blocks.index_list_size)
|
||||
> LZMA_VLI_MAX)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
|
||||
size_t *in_pos, size_t in_size)
|
||||
{
|
||||
// Catch zero input buffer here, because in contrast to Index encoder
|
||||
// and decoder functions, applications call this function directly
|
||||
// instead of via lzma_code(), which does the buffer checking.
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
// NOTE: This function has many similarities to index_encode() and
|
||||
// index_decode() functions found from index_encoder.c and
|
||||
// index_decoder.c. See the comments especially in index_encoder.c.
|
||||
const size_t in_start = *in_pos;
|
||||
lzma_ret ret = LZMA_OK;
|
||||
|
||||
while (*in_pos < in_size)
|
||||
switch (index_hash->sequence) {
|
||||
case SEQ_BLOCK:
|
||||
// Check the Index Indicator is present.
|
||||
if (in[(*in_pos)++] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
index_hash->sequence = SEQ_COUNT;
|
||||
break;
|
||||
|
||||
case SEQ_COUNT: {
|
||||
ret = lzma_vli_decode(&index_hash->remaining,
|
||||
&index_hash->pos, in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
// The count must match the count of the Blocks decoded.
|
||||
if (index_hash->remaining != index_hash->blocks.count)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
ret = LZMA_OK;
|
||||
index_hash->pos = 0;
|
||||
|
||||
// Handle the special case when there are no Blocks.
|
||||
index_hash->sequence = index_hash->remaining == 0
|
||||
? SEQ_PADDING_INIT : SEQ_UNPADDED;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_UNPADDED:
|
||||
case SEQ_UNCOMPRESSED: {
|
||||
lzma_vli *size = index_hash->sequence == SEQ_UNPADDED
|
||||
? &index_hash->unpadded_size
|
||||
: &index_hash->uncompressed_size;
|
||||
|
||||
ret = lzma_vli_decode(size, &index_hash->pos,
|
||||
in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
goto out;
|
||||
|
||||
ret = LZMA_OK;
|
||||
index_hash->pos = 0;
|
||||
|
||||
if (index_hash->sequence == SEQ_UNPADDED) {
|
||||
if (index_hash->unpadded_size < UNPADDED_SIZE_MIN
|
||||
|| index_hash->unpadded_size
|
||||
> UNPADDED_SIZE_MAX)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
index_hash->sequence = SEQ_UNCOMPRESSED;
|
||||
} else {
|
||||
// Update the hash.
|
||||
return_if_error(hash_append(&index_hash->records,
|
||||
index_hash->unpadded_size,
|
||||
index_hash->uncompressed_size));
|
||||
|
||||
// Verify that we don't go over the known sizes. Note
|
||||
// that this validation is simpler than the one used
|
||||
// in lzma_index_hash_append(), because here we know
|
||||
// that values in index_hash->blocks are already
|
||||
// validated and we are fine as long as we don't
|
||||
// exceed them in index_hash->records.
|
||||
if (index_hash->blocks.blocks_size
|
||||
< index_hash->records.blocks_size
|
||||
|| index_hash->blocks.uncompressed_size
|
||||
< index_hash->records.uncompressed_size
|
||||
|| index_hash->blocks.index_list_size
|
||||
< index_hash->records.index_list_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Check if this was the last Record.
|
||||
index_hash->sequence = --index_hash->remaining == 0
|
||||
? SEQ_PADDING_INIT : SEQ_UNPADDED;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_PADDING_INIT:
|
||||
index_hash->pos = (LZMA_VLI_C(4) - index_size_unpadded(
|
||||
index_hash->records.count,
|
||||
index_hash->records.index_list_size)) & 3;
|
||||
index_hash->sequence = SEQ_PADDING;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_PADDING:
|
||||
if (index_hash->pos > 0) {
|
||||
--index_hash->pos;
|
||||
if (in[(*in_pos)++] != 0x00)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Compare the sizes.
|
||||
if (index_hash->blocks.blocks_size
|
||||
!= index_hash->records.blocks_size
|
||||
|| index_hash->blocks.uncompressed_size
|
||||
!= index_hash->records.uncompressed_size
|
||||
|| index_hash->blocks.index_list_size
|
||||
!= index_hash->records.index_list_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Finish the hashes and compare them.
|
||||
lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST);
|
||||
lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST);
|
||||
if (memcmp(index_hash->blocks.check.buffer.u8,
|
||||
index_hash->records.check.buffer.u8,
|
||||
lzma_check_size(LZMA_CHECK_BEST)) != 0)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Finish the CRC32 calculation.
|
||||
index_hash->crc32 = lzma_crc32(in + in_start,
|
||||
*in_pos - in_start, index_hash->crc32);
|
||||
|
||||
index_hash->sequence = SEQ_CRC32;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CRC32:
|
||||
do {
|
||||
if (*in_pos == in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
if (((index_hash->crc32 >> (index_hash->pos * 8))
|
||||
& 0xFF) != in[(*in_pos)++])
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
} while (++index_hash->pos < 4);
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
out:
|
||||
// Update the CRC32,
|
||||
index_hash->crc32 = lzma_crc32(in + in_start,
|
||||
*in_pos - in_start, index_hash->crc32);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,521 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file mythread.h
|
||||
/// \brief Some threading related helper macros and functions
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MYTHREAD_H
|
||||
#define MYTHREAD_H
|
||||
|
||||
#include "sysdefs.h"
|
||||
|
||||
// If any type of threading is enabled, #define MYTHREAD_ENABLED.
|
||||
#if defined(MYTHREAD_POSIX) || defined(MYTHREAD_WIN95) \
|
||||
|| defined(MYTHREAD_VISTA)
|
||||
# define MYTHREAD_ENABLED 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MYTHREAD_ENABLED
|
||||
|
||||
////////////////////////////////////////
|
||||
// Shared between all threading types //
|
||||
////////////////////////////////////////
|
||||
|
||||
// Locks a mutex for a duration of a block.
|
||||
//
|
||||
// Perform mythread_mutex_lock(&mutex) in the beginning of a block
|
||||
// and mythread_mutex_unlock(&mutex) at the end of the block. "break"
|
||||
// may be used to unlock the mutex and jump out of the block.
|
||||
// mythread_sync blocks may be nested.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// mythread_sync(mutex) {
|
||||
// foo();
|
||||
// if (some_error)
|
||||
// break; // Skips bar()
|
||||
// bar();
|
||||
// }
|
||||
//
|
||||
// At least GCC optimizes the loops completely away so it doesn't slow
|
||||
// things down at all compared to plain mythread_mutex_lock(&mutex)
|
||||
// and mythread_mutex_unlock(&mutex) calls.
|
||||
//
|
||||
#define mythread_sync(mutex) mythread_sync_helper1(mutex, __LINE__)
|
||||
#define mythread_sync_helper1(mutex, line) mythread_sync_helper2(mutex, line)
|
||||
#define mythread_sync_helper2(mutex, line) \
|
||||
for (unsigned int mythread_i_ ## line = 0; \
|
||||
mythread_i_ ## line \
|
||||
? (mythread_mutex_unlock(&(mutex)), 0) \
|
||||
: (mythread_mutex_lock(&(mutex)), 1); \
|
||||
mythread_i_ ## line = 1) \
|
||||
for (unsigned int mythread_j_ ## line = 0; \
|
||||
!mythread_j_ ## line; \
|
||||
mythread_j_ ## line = 1)
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(MYTHREAD_ENABLED)
|
||||
|
||||
//////////////////
|
||||
// No threading //
|
||||
//////////////////
|
||||
|
||||
// Calls the given function once. This isn't thread safe.
|
||||
#define mythread_once(func) \
|
||||
do { \
|
||||
static bool once_ = false; \
|
||||
if (!once_) { \
|
||||
func(); \
|
||||
once_ = true; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#if !(defined(_WIN32) && !defined(__CYGWIN__))
|
||||
// Use sigprocmask() to set the signal mask in single-threaded programs.
|
||||
#include <signal.h>
|
||||
|
||||
static inline void
|
||||
mythread_sigmask(int how, const sigset_t *restrict set,
|
||||
sigset_t *restrict oset)
|
||||
{
|
||||
int ret = sigprocmask(how, set, oset);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#elif defined(MYTHREAD_POSIX)
|
||||
|
||||
////////////////////
|
||||
// Using pthreads //
|
||||
////////////////////
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MYTHREAD_RET_TYPE void *
|
||||
#define MYTHREAD_RET_VALUE NULL
|
||||
|
||||
typedef pthread_t mythread;
|
||||
typedef pthread_mutex_t mythread_mutex;
|
||||
|
||||
typedef struct {
|
||||
pthread_cond_t cond;
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
// Clock ID (CLOCK_REALTIME or CLOCK_MONOTONIC) associated with
|
||||
// the condition variable.
|
||||
clockid_t clk_id;
|
||||
#endif
|
||||
} mythread_cond;
|
||||
|
||||
typedef struct timespec mythread_condtime;
|
||||
|
||||
|
||||
// Calls the given function once in a thread-safe way.
|
||||
#define mythread_once(func) \
|
||||
do { \
|
||||
static pthread_once_t once_ = PTHREAD_ONCE_INIT; \
|
||||
pthread_once(&once_, &func); \
|
||||
} while (0)
|
||||
|
||||
|
||||
// Use pthread_sigmask() to set the signal mask in multi-threaded programs.
|
||||
// Do nothing on OpenVMS since it lacks pthread_sigmask().
|
||||
static inline void
|
||||
mythread_sigmask(int how, const sigset_t *restrict set,
|
||||
sigset_t *restrict oset)
|
||||
{
|
||||
#ifdef __VMS
|
||||
(void)how;
|
||||
(void)set;
|
||||
(void)oset;
|
||||
#else
|
||||
int ret = pthread_sigmask(how, set, oset);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Creates a new thread with all signals blocked. Returns zero on success
|
||||
// and non-zero on error.
|
||||
static inline int
|
||||
mythread_create(mythread *thread, void *(*func)(void *arg), void *arg)
|
||||
{
|
||||
sigset_t old;
|
||||
sigset_t all;
|
||||
sigfillset(&all);
|
||||
|
||||
mythread_sigmask(SIG_SETMASK, &all, &old);
|
||||
const int ret = pthread_create(thread, NULL, func, arg);
|
||||
mythread_sigmask(SIG_SETMASK, &old, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Joins a thread. Returns zero on success and non-zero on error.
|
||||
static inline int
|
||||
mythread_join(mythread thread)
|
||||
{
|
||||
return pthread_join(thread, NULL);
|
||||
}
|
||||
|
||||
|
||||
// Initiatlizes a mutex. Returns zero on success and non-zero on error.
|
||||
static inline int
|
||||
mythread_mutex_init(mythread_mutex *mutex)
|
||||
{
|
||||
return pthread_mutex_init(mutex, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_mutex_destroy(mythread_mutex *mutex)
|
||||
{
|
||||
int ret = pthread_mutex_destroy(mutex);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_mutex_lock(mythread_mutex *mutex)
|
||||
{
|
||||
int ret = pthread_mutex_lock(mutex);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_mutex_unlock(mythread_mutex *mutex)
|
||||
{
|
||||
int ret = pthread_mutex_unlock(mutex);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
|
||||
// Initializes a condition variable.
|
||||
//
|
||||
// Using CLOCK_MONOTONIC instead of the default CLOCK_REALTIME makes the
|
||||
// timeout in pthread_cond_timedwait() work correctly also if system time
|
||||
// is suddenly changed. Unfortunately CLOCK_MONOTONIC isn't available
|
||||
// everywhere while the default CLOCK_REALTIME is, so the default is
|
||||
// used if CLOCK_MONOTONIC isn't available.
|
||||
//
|
||||
// If clock_gettime() isn't available at all, gettimeofday() will be used.
|
||||
static inline int
|
||||
mythread_cond_init(mythread_cond *mycond)
|
||||
{
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
// NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1.
|
||||
# if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && HAVE_DECL_CLOCK_MONOTONIC
|
||||
struct timespec ts;
|
||||
pthread_condattr_t condattr;
|
||||
|
||||
// POSIX doesn't seem to *require* that pthread_condattr_setclock()
|
||||
// will fail if given an unsupported clock ID. Test that
|
||||
// CLOCK_MONOTONIC really is supported using clock_gettime().
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0
|
||||
&& pthread_condattr_init(&condattr) == 0) {
|
||||
int ret = pthread_condattr_setclock(
|
||||
&condattr, CLOCK_MONOTONIC);
|
||||
if (ret == 0)
|
||||
ret = pthread_cond_init(&mycond->cond, &condattr);
|
||||
|
||||
pthread_condattr_destroy(&condattr);
|
||||
|
||||
if (ret == 0) {
|
||||
mycond->clk_id = CLOCK_MONOTONIC;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If anything above fails, fall back to the default CLOCK_REALTIME.
|
||||
// POSIX requires that all implementations of clock_gettime() must
|
||||
// support at least CLOCK_REALTIME.
|
||||
# endif
|
||||
|
||||
mycond->clk_id = CLOCK_REALTIME;
|
||||
#endif
|
||||
|
||||
return pthread_cond_init(&mycond->cond, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_cond_destroy(mythread_cond *cond)
|
||||
{
|
||||
int ret = pthread_cond_destroy(&cond->cond);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_cond_signal(mythread_cond *cond)
|
||||
{
|
||||
int ret = pthread_cond_signal(&cond->cond);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex)
|
||||
{
|
||||
int ret = pthread_cond_wait(&cond->cond, mutex);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
// Waits on a condition or until a timeout expires. If the timeout expires,
|
||||
// non-zero is returned, otherwise zero is returned.
|
||||
static inline int
|
||||
mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex,
|
||||
const mythread_condtime *condtime)
|
||||
{
|
||||
int ret = pthread_cond_timedwait(&cond->cond, mutex, condtime);
|
||||
assert(ret == 0 || ret == ETIMEDOUT);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Sets condtime to the absolute time that is timeout_ms milliseconds
|
||||
// in the future. The type of the clock to use is taken from cond.
|
||||
static inline void
|
||||
mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
|
||||
uint32_t timeout_ms)
|
||||
{
|
||||
condtime->tv_sec = timeout_ms / 1000;
|
||||
condtime->tv_nsec = (timeout_ms % 1000) * 1000000;
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
struct timespec now;
|
||||
int ret = clock_gettime(cond->clk_id, &now);
|
||||
assert(ret == 0);
|
||||
(void)ret;
|
||||
|
||||
condtime->tv_sec += now.tv_sec;
|
||||
condtime->tv_nsec += now.tv_nsec;
|
||||
#else
|
||||
(void)cond;
|
||||
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
condtime->tv_sec += now.tv_sec;
|
||||
condtime->tv_nsec += now.tv_usec * 1000L;
|
||||
#endif
|
||||
|
||||
// tv_nsec must stay in the range [0, 999_999_999].
|
||||
if (condtime->tv_nsec >= 1000000000L) {
|
||||
condtime->tv_nsec -= 1000000000L;
|
||||
++condtime->tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#elif defined(MYTHREAD_WIN95) || defined(MYTHREAD_VISTA)
|
||||
|
||||
/////////////////////
|
||||
// Windows threads //
|
||||
/////////////////////
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifdef MYTHREAD_VISTA
|
||||
# undef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#define MYTHREAD_RET_TYPE unsigned int __stdcall
|
||||
#define MYTHREAD_RET_VALUE 0
|
||||
|
||||
typedef HANDLE mythread;
|
||||
typedef CRITICAL_SECTION mythread_mutex;
|
||||
|
||||
#ifdef MYTHREAD_WIN95
|
||||
typedef HANDLE mythread_cond;
|
||||
#else
|
||||
typedef CONDITION_VARIABLE mythread_cond;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// Tick count (milliseconds) in the beginning of the timeout.
|
||||
// NOTE: This is 32 bits so it wraps around after 49.7 days.
|
||||
// Multi-day timeouts may not work as expected.
|
||||
DWORD start;
|
||||
|
||||
// Length of the timeout in milliseconds. The timeout expires
|
||||
// when the current tick count minus "start" is equal or greater
|
||||
// than "timeout".
|
||||
DWORD timeout;
|
||||
} mythread_condtime;
|
||||
|
||||
|
||||
// mythread_once() is only available with Vista threads.
|
||||
#ifdef MYTHREAD_VISTA
|
||||
#define mythread_once(func) \
|
||||
do { \
|
||||
static INIT_ONCE once_ = INIT_ONCE_STATIC_INIT; \
|
||||
BOOL pending_; \
|
||||
if (!InitOnceBeginInitialize(&once_, 0, &pending_, NULL)) \
|
||||
abort(); \
|
||||
if (pending_) \
|
||||
func(); \
|
||||
if (!InitOnceComplete(&once, 0, NULL)) \
|
||||
abort(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
// mythread_sigmask() isn't available on Windows. Even a dummy version would
|
||||
// make no sense because the other POSIX signal functions are missing anyway.
|
||||
|
||||
|
||||
static inline int
|
||||
mythread_create(mythread *thread,
|
||||
unsigned int (__stdcall *func)(void *arg), void *arg)
|
||||
{
|
||||
uintptr_t ret = _beginthreadex(NULL, 0, func, arg, 0, NULL);
|
||||
if (ret == 0)
|
||||
return -1;
|
||||
|
||||
*thread = (HANDLE)ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mythread_join(mythread thread)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0)
|
||||
ret = -1;
|
||||
|
||||
if (!CloseHandle(thread))
|
||||
ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
mythread_mutex_init(mythread_mutex *mutex)
|
||||
{
|
||||
InitializeCriticalSection(mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_mutex_destroy(mythread_mutex *mutex)
|
||||
{
|
||||
DeleteCriticalSection(mutex);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_mutex_lock(mythread_mutex *mutex)
|
||||
{
|
||||
EnterCriticalSection(mutex);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_mutex_unlock(mythread_mutex *mutex)
|
||||
{
|
||||
LeaveCriticalSection(mutex);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
mythread_cond_init(mythread_cond *cond)
|
||||
{
|
||||
#ifdef MYTHREAD_WIN95
|
||||
*cond = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
return *cond == NULL ? -1 : 0;
|
||||
#else
|
||||
InitializeConditionVariable(cond);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_cond_destroy(mythread_cond *cond)
|
||||
{
|
||||
#ifdef MYTHREAD_WIN95
|
||||
CloseHandle(*cond);
|
||||
#else
|
||||
(void)cond;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_cond_signal(mythread_cond *cond)
|
||||
{
|
||||
#ifdef MYTHREAD_WIN95
|
||||
SetEvent(*cond);
|
||||
#else
|
||||
WakeConditionVariable(cond);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_cond_wait(mythread_cond *cond, mythread_mutex *mutex)
|
||||
{
|
||||
#ifdef MYTHREAD_WIN95
|
||||
LeaveCriticalSection(mutex);
|
||||
WaitForSingleObject(*cond, INFINITE);
|
||||
EnterCriticalSection(mutex);
|
||||
#else
|
||||
BOOL ret = SleepConditionVariableCS(cond, mutex, INFINITE);
|
||||
assert(ret);
|
||||
(void)ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int
|
||||
mythread_cond_timedwait(mythread_cond *cond, mythread_mutex *mutex,
|
||||
const mythread_condtime *condtime)
|
||||
{
|
||||
#ifdef MYTHREAD_WIN95
|
||||
LeaveCriticalSection(mutex);
|
||||
#endif
|
||||
|
||||
DWORD elapsed = GetTickCount() - condtime->start;
|
||||
DWORD timeout = elapsed >= condtime->timeout
|
||||
? 0 : condtime->timeout - elapsed;
|
||||
|
||||
#ifdef MYTHREAD_WIN95
|
||||
DWORD ret = WaitForSingleObject(*cond, timeout);
|
||||
assert(ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT);
|
||||
|
||||
EnterCriticalSection(mutex);
|
||||
|
||||
return ret == WAIT_TIMEOUT;
|
||||
#else
|
||||
BOOL ret = SleepConditionVariableCS(cond, mutex, timeout);
|
||||
assert(ret || GetLastError() == ERROR_TIMEOUT);
|
||||
return !ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
mythread_condtime_set(mythread_condtime *condtime, const mythread_cond *cond,
|
||||
uint32_t timeout)
|
||||
{
|
||||
(void)cond;
|
||||
condtime->start = GetTickCount();
|
||||
condtime->timeout = timeout;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,184 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file outqueue.c
|
||||
/// \brief Output queue handling in multithreaded coding
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "outqueue.h"
|
||||
|
||||
|
||||
/// This is to ease integer overflow checking: We may allocate up to
|
||||
/// 2 * LZMA_THREADS_MAX buffers and we need some extra memory for other
|
||||
/// data structures (that's the second /2).
|
||||
#define BUF_SIZE_MAX (UINT64_MAX / LZMA_THREADS_MAX / 2 / 2)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
get_options(uint64_t *bufs_alloc_size, uint32_t *bufs_count,
|
||||
uint64_t buf_size_max, uint32_t threads)
|
||||
{
|
||||
if (threads > LZMA_THREADS_MAX || buf_size_max > BUF_SIZE_MAX)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// The number of buffers is twice the number of threads.
|
||||
// This wastes RAM but keeps the threads busy when buffers
|
||||
// finish out of order.
|
||||
//
|
||||
// NOTE: If this is changed, update BUF_SIZE_MAX too.
|
||||
*bufs_count = threads * 2;
|
||||
*bufs_alloc_size = *bufs_count * buf_size_max;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern uint64_t
|
||||
lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads)
|
||||
{
|
||||
uint64_t bufs_alloc_size;
|
||||
uint32_t bufs_count;
|
||||
|
||||
if (get_options(&bufs_alloc_size, &bufs_count, buf_size_max, threads)
|
||||
!= LZMA_OK)
|
||||
return UINT64_MAX;
|
||||
|
||||
return sizeof(lzma_outq) + bufs_count * sizeof(lzma_outbuf)
|
||||
+ bufs_alloc_size;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_outq_init(lzma_outq *outq, const lzma_allocator *allocator,
|
||||
uint64_t buf_size_max, uint32_t threads)
|
||||
{
|
||||
uint64_t bufs_alloc_size;
|
||||
uint32_t bufs_count;
|
||||
|
||||
// Set bufs_count and bufs_alloc_size.
|
||||
return_if_error(get_options(&bufs_alloc_size, &bufs_count,
|
||||
buf_size_max, threads));
|
||||
|
||||
// Allocate memory if needed.
|
||||
if (outq->buf_size_max != buf_size_max
|
||||
|| outq->bufs_allocated != bufs_count) {
|
||||
lzma_outq_end(outq, allocator);
|
||||
|
||||
#if SIZE_MAX < UINT64_MAX
|
||||
if (bufs_alloc_size > SIZE_MAX)
|
||||
return LZMA_MEM_ERROR;
|
||||
#endif
|
||||
|
||||
outq->bufs = lzma_alloc(bufs_count * sizeof(lzma_outbuf),
|
||||
allocator);
|
||||
outq->bufs_mem = lzma_alloc((size_t)(bufs_alloc_size),
|
||||
allocator);
|
||||
|
||||
if (outq->bufs == NULL || outq->bufs_mem == NULL) {
|
||||
lzma_outq_end(outq, allocator);
|
||||
return LZMA_MEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the rest of the main structure. Initialization of
|
||||
// outq->bufs[] is done when they are actually needed.
|
||||
outq->buf_size_max = (size_t)(buf_size_max);
|
||||
outq->bufs_allocated = bufs_count;
|
||||
outq->bufs_pos = 0;
|
||||
outq->bufs_used = 0;
|
||||
outq->read_pos = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_free(outq->bufs, allocator);
|
||||
outq->bufs = NULL;
|
||||
|
||||
lzma_free(outq->bufs_mem, allocator);
|
||||
outq->bufs_mem = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_outbuf *
|
||||
lzma_outq_get_buf(lzma_outq *outq)
|
||||
{
|
||||
// Caller must have checked it with lzma_outq_has_buf().
|
||||
assert(outq->bufs_used < outq->bufs_allocated);
|
||||
|
||||
// Initialize the new buffer.
|
||||
lzma_outbuf *buf = &outq->bufs[outq->bufs_pos];
|
||||
buf->buf = outq->bufs_mem + outq->bufs_pos * outq->buf_size_max;
|
||||
buf->size = 0;
|
||||
buf->finished = false;
|
||||
|
||||
// Update the queue state.
|
||||
if (++outq->bufs_pos == outq->bufs_allocated)
|
||||
outq->bufs_pos = 0;
|
||||
|
||||
++outq->bufs_used;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
extern bool
|
||||
lzma_outq_is_readable(const lzma_outq *outq)
|
||||
{
|
||||
uint32_t i = outq->bufs_pos - outq->bufs_used;
|
||||
if (outq->bufs_pos < outq->bufs_used)
|
||||
i += outq->bufs_allocated;
|
||||
|
||||
return outq->bufs[i].finished;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_outq_read(lzma_outq *restrict outq, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
lzma_vli *restrict unpadded_size,
|
||||
lzma_vli *restrict uncompressed_size)
|
||||
{
|
||||
// There must be at least one buffer from which to read.
|
||||
if (outq->bufs_used == 0)
|
||||
return LZMA_OK;
|
||||
|
||||
// Get the buffer.
|
||||
uint32_t i = outq->bufs_pos - outq->bufs_used;
|
||||
if (outq->bufs_pos < outq->bufs_used)
|
||||
i += outq->bufs_allocated;
|
||||
|
||||
lzma_outbuf *buf = &outq->bufs[i];
|
||||
|
||||
// If it isn't finished yet, we cannot read from it.
|
||||
if (!buf->finished)
|
||||
return LZMA_OK;
|
||||
|
||||
// Copy from the buffer to output.
|
||||
lzma_bufcpy(buf->buf, &outq->read_pos, buf->size,
|
||||
out, out_pos, out_size);
|
||||
|
||||
// Return if we didn't get all the data from the buffer.
|
||||
if (outq->read_pos < buf->size)
|
||||
return LZMA_OK;
|
||||
|
||||
// The buffer was finished. Tell the caller its size information.
|
||||
*unpadded_size = buf->unpadded_size;
|
||||
*uncompressed_size = buf->uncompressed_size;
|
||||
|
||||
// Free this buffer for further use.
|
||||
--outq->bufs_used;
|
||||
outq->read_pos = 0;
|
||||
|
||||
return LZMA_STREAM_END;
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file outqueue.h
|
||||
/// \brief Output queue handling in multithreaded coding
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/// Output buffer for a single thread
|
||||
typedef struct {
|
||||
/// Pointer to the output buffer of lzma_outq.buf_size_max bytes
|
||||
uint8_t *buf;
|
||||
|
||||
/// Amount of data written to buf
|
||||
size_t size;
|
||||
|
||||
/// Additional size information
|
||||
lzma_vli unpadded_size;
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// True when no more data will be written into this buffer.
|
||||
///
|
||||
/// \note This is read by another thread and thus access
|
||||
/// to this variable needs a mutex.
|
||||
bool finished;
|
||||
|
||||
} lzma_outbuf;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// Array of buffers that are used cyclically.
|
||||
lzma_outbuf *bufs;
|
||||
|
||||
/// Memory allocated for all the buffers
|
||||
uint8_t *bufs_mem;
|
||||
|
||||
/// Amount of buffer space available in each buffer
|
||||
size_t buf_size_max;
|
||||
|
||||
/// Number of buffers allocated
|
||||
uint32_t bufs_allocated;
|
||||
|
||||
/// Position in the bufs array. The next buffer to be taken
|
||||
/// into use is bufs[bufs_pos].
|
||||
uint32_t bufs_pos;
|
||||
|
||||
/// Number of buffers in use
|
||||
uint32_t bufs_used;
|
||||
|
||||
/// Position in the buffer in lzma_outq_read()
|
||||
size_t read_pos;
|
||||
|
||||
} lzma_outq;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate the memory usage of an output queue
|
||||
*
|
||||
* \return Approximate memory usage in bytes or UINT64_MAX on error.
|
||||
*/
|
||||
extern uint64_t lzma_outq_memusage(uint64_t buf_size_max, uint32_t threads);
|
||||
|
||||
|
||||
/// \brief Initialize an output queue
|
||||
///
|
||||
/// \param outq Pointer to an output queue. Before calling
|
||||
/// this function the first time, *outq should
|
||||
/// have been zeroed with memzero() so that this
|
||||
/// function knows that there are no previous
|
||||
/// allocations to free.
|
||||
/// \param allocator Pointer to allocator or NULL
|
||||
/// \param buf_size_max Maximum amount of data that a single buffer
|
||||
/// in the queue may need to store.
|
||||
/// \param threads Number of buffers that may be in use
|
||||
/// concurrently. Note that more than this number
|
||||
/// of buffers will actually get allocated to
|
||||
/// improve performance when buffers finish
|
||||
/// out of order.
|
||||
///
|
||||
/// \return - LZMA_OK
|
||||
/// - LZMA_MEM_ERROR
|
||||
///
|
||||
extern lzma_ret lzma_outq_init(
|
||||
lzma_outq *outq, const lzma_allocator *allocator,
|
||||
uint64_t buf_size_max, uint32_t threads);
|
||||
|
||||
|
||||
/// \brief Free the memory associated with the output queue
|
||||
extern void lzma_outq_end(lzma_outq *outq, const lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// \brief Get a new buffer
|
||||
///
|
||||
/// lzma_outq_has_buf() must be used to check that there is a buffer
|
||||
/// available before calling lzma_outq_get_buf().
|
||||
///
|
||||
extern lzma_outbuf *lzma_outq_get_buf(lzma_outq *outq);
|
||||
|
||||
|
||||
/// \brief Test if there is data ready to be read
|
||||
///
|
||||
/// Call to this function must be protected with the same mutex that
|
||||
/// is used to protect lzma_outbuf.finished.
|
||||
///
|
||||
extern bool lzma_outq_is_readable(const lzma_outq *outq);
|
||||
|
||||
|
||||
/// \brief Read finished data
|
||||
///
|
||||
/// \param outq Pointer to an output queue
|
||||
/// \param out Beginning of the output buffer
|
||||
/// \param out_pos The next byte will be written to
|
||||
/// out[*out_pos].
|
||||
/// \param out_size Size of the out buffer; the first byte into
|
||||
/// which no data is written to is out[out_size].
|
||||
/// \param unpadded_size Unpadded Size from the Block encoder
|
||||
/// \param uncompressed_size Uncompressed Size from the Block encoder
|
||||
///
|
||||
/// \return - LZMA: All OK. Either no data was available or the buffer
|
||||
/// being read didn't become empty yet.
|
||||
/// - LZMA_STREAM_END: The buffer being read was finished.
|
||||
/// *unpadded_size and *uncompressed_size were set.
|
||||
///
|
||||
/// \note This reads lzma_outbuf.finished variables and thus call
|
||||
/// to this function needs to be protected with a mutex.
|
||||
///
|
||||
extern lzma_ret lzma_outq_read(lzma_outq *restrict outq,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size, lzma_vli *restrict unpadded_size,
|
||||
lzma_vli *restrict uncompressed_size);
|
||||
|
||||
|
||||
/// \brief Test if there is at least one buffer free
|
||||
///
|
||||
/// This must be used before getting a new buffer with lzma_outq_get_buf().
|
||||
///
|
||||
static inline bool
|
||||
lzma_outq_has_buf(const lzma_outq *outq)
|
||||
{
|
||||
return outq->bufs_used < outq->bufs_allocated;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Test if the queue is completely empty
|
||||
static inline bool
|
||||
lzma_outq_is_empty(const lzma_outq *outq)
|
||||
{
|
||||
return outq->bufs_used == 0;
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_buffer_decoder.c
|
||||
/// \brief Single-call .xz Stream decoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_decoder.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
|
||||
const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
{
|
||||
// Sanity checks
|
||||
if (in_pos == NULL || (in == NULL && *in_pos != in_size)
|
||||
|| *in_pos > in_size || out_pos == NULL
|
||||
|| (out == NULL && *out_pos != out_size)
|
||||
|| *out_pos > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Catch flags that are not allowed in buffer-to-buffer decoding.
|
||||
if (flags & LZMA_TELL_ANY_CHECK)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Initialize the Stream decoder.
|
||||
// TODO: We need something to tell the decoder that it can use the
|
||||
// output buffer as workspace, and thus save significant amount of RAM.
|
||||
lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
|
||||
lzma_ret ret = lzma_stream_decoder_init(
|
||||
&stream_decoder, allocator, *memlimit, flags);
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
// Save the positions so that we can restore them in case
|
||||
// an error occurs.
|
||||
const size_t in_start = *in_pos;
|
||||
const size_t out_start = *out_pos;
|
||||
|
||||
// Do the actual decoding.
|
||||
ret = stream_decoder.code(stream_decoder.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size,
|
||||
LZMA_FINISH);
|
||||
|
||||
if (ret == LZMA_STREAM_END) {
|
||||
ret = LZMA_OK;
|
||||
} else {
|
||||
// Something went wrong, restore the positions.
|
||||
*in_pos = in_start;
|
||||
*out_pos = out_start;
|
||||
|
||||
if (ret == LZMA_OK) {
|
||||
// Either the input was truncated or the
|
||||
// output buffer was too small.
|
||||
assert(*in_pos == in_size
|
||||
|| *out_pos == out_size);
|
||||
|
||||
// If all the input was consumed, then the
|
||||
// input is truncated, even if the output
|
||||
// buffer is also full. This is because
|
||||
// processing the last byte of the Stream
|
||||
// never produces output.
|
||||
if (*in_pos == in_size)
|
||||
ret = LZMA_DATA_ERROR;
|
||||
else
|
||||
ret = LZMA_BUF_ERROR;
|
||||
|
||||
} else if (ret == LZMA_MEMLIMIT_ERROR) {
|
||||
// Let the caller know how much memory would
|
||||
// have been needed.
|
||||
uint64_t memusage;
|
||||
(void)stream_decoder.memconfig(
|
||||
stream_decoder.coder,
|
||||
memlimit, &memusage, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free the decoder memory. This needs to be done even if
|
||||
// initialization fails, because the internal API doesn't
|
||||
// require the initialization function to free its memory on error.
|
||||
lzma_next_end(&stream_decoder, allocator);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_buffer_encoder.c
|
||||
/// \brief Single-call .xz Stream encoder
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "index.h"
|
||||
|
||||
|
||||
/// Maximum size of Index that has exactly one Record.
|
||||
/// Index Indicator + Number of Records + Record + CRC32 rounded up to
|
||||
/// the next multiple of four.
|
||||
#define INDEX_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 4 + 3) & ~3)
|
||||
|
||||
/// Stream Header, Stream Footer, and Index
|
||||
#define HEADERS_BOUND (2 * LZMA_STREAM_HEADER_SIZE + INDEX_BOUND)
|
||||
|
||||
|
||||
extern LZMA_API(size_t)
|
||||
lzma_stream_buffer_bound(size_t uncompressed_size)
|
||||
{
|
||||
// Get the maximum possible size of a Block.
|
||||
const size_t block_bound = lzma_block_buffer_bound(uncompressed_size);
|
||||
if (block_bound == 0)
|
||||
return 0;
|
||||
|
||||
// Catch the possible integer overflow and also prevent the size of
|
||||
// the Stream exceeding LZMA_VLI_MAX (theoretically possible on
|
||||
// 64-bit systems).
|
||||
if (my_min(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND)
|
||||
return 0;
|
||||
|
||||
return block_bound + HEADERS_BOUND;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
|
||||
const lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos_ptr, size_t out_size)
|
||||
{
|
||||
// Sanity checks
|
||||
if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX
|
||||
|| (in == NULL && in_size != 0) || out == NULL
|
||||
|| out_pos_ptr == NULL || *out_pos_ptr > out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (!lzma_check_is_supported(check))
|
||||
return LZMA_UNSUPPORTED_CHECK;
|
||||
|
||||
// Note for the paranoids: Index encoder prevents the Stream from
|
||||
// getting too big and still being accepted with LZMA_OK, and Block
|
||||
// encoder catches if the input is too big. So we don't need to
|
||||
// separately check if the buffers are too big.
|
||||
|
||||
// Use a local copy. We update *out_pos_ptr only if everything
|
||||
// succeeds.
|
||||
size_t out_pos = *out_pos_ptr;
|
||||
|
||||
// Check that there's enough space for both Stream Header and
|
||||
// Stream Footer.
|
||||
if (out_size - out_pos <= 2 * LZMA_STREAM_HEADER_SIZE)
|
||||
return LZMA_BUF_ERROR;
|
||||
|
||||
// Reserve space for Stream Footer so we don't need to check for
|
||||
// available space again before encoding Stream Footer.
|
||||
out_size -= LZMA_STREAM_HEADER_SIZE;
|
||||
|
||||
// Encode the Stream Header.
|
||||
lzma_stream_flags stream_flags = {
|
||||
.version = 0,
|
||||
.check = check,
|
||||
};
|
||||
|
||||
if (lzma_stream_header_encode(&stream_flags, out + out_pos)
|
||||
!= LZMA_OK)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
out_pos += LZMA_STREAM_HEADER_SIZE;
|
||||
|
||||
// Encode a Block but only if there is at least one byte of input.
|
||||
lzma_block block = {
|
||||
.version = 0,
|
||||
.check = check,
|
||||
.filters = filters,
|
||||
};
|
||||
|
||||
if (in_size > 0)
|
||||
return_if_error(lzma_block_buffer_encode(&block, allocator,
|
||||
in, in_size, out, &out_pos, out_size));
|
||||
|
||||
// Index
|
||||
{
|
||||
// Create an Index. It will have one Record if there was
|
||||
// at least one byte of input to encode. Otherwise the
|
||||
// Index will be empty.
|
||||
lzma_index *i = lzma_index_init(allocator);
|
||||
if (i == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
lzma_ret ret = LZMA_OK;
|
||||
|
||||
if (in_size > 0)
|
||||
ret = lzma_index_append(i, allocator,
|
||||
lzma_block_unpadded_size(&block),
|
||||
block.uncompressed_size);
|
||||
|
||||
// If adding the Record was successful, encode the Index
|
||||
// and get its size which will be stored into Stream Footer.
|
||||
if (ret == LZMA_OK) {
|
||||
ret = lzma_index_buffer_encode(
|
||||
i, out, &out_pos, out_size);
|
||||
|
||||
stream_flags.backward_size = lzma_index_size(i);
|
||||
}
|
||||
|
||||
lzma_index_end(i, allocator);
|
||||
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Stream Footer. We have already reserved space for this.
|
||||
if (lzma_stream_footer_encode(&stream_flags, out + out_pos)
|
||||
!= LZMA_OK)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
out_pos += LZMA_STREAM_HEADER_SIZE;
|
||||
|
||||
// Everything went fine, make the new output position available
|
||||
// to the application.
|
||||
*out_pos_ptr = out_pos;
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,462 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_decoder.c
|
||||
/// \brief Decodes .xz Streams
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_decoder.h"
|
||||
#include "block_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
enum {
|
||||
SEQ_STREAM_HEADER,
|
||||
SEQ_BLOCK_HEADER,
|
||||
SEQ_BLOCK,
|
||||
SEQ_INDEX,
|
||||
SEQ_STREAM_FOOTER,
|
||||
SEQ_STREAM_PADDING,
|
||||
} sequence;
|
||||
|
||||
/// Block or Metadata decoder. This takes little memory and the same
|
||||
/// data structure can be used to decode every Block Header, so it's
|
||||
/// a good idea to have a separate lzma_next_coder structure for it.
|
||||
lzma_next_coder block_decoder;
|
||||
|
||||
/// Block options decoded by the Block Header decoder and used by
|
||||
/// the Block decoder.
|
||||
lzma_block block_options;
|
||||
|
||||
/// Stream Flags from Stream Header
|
||||
lzma_stream_flags stream_flags;
|
||||
|
||||
/// Index is hashed so that it can be compared to the sizes of Blocks
|
||||
/// with O(1) memory usage.
|
||||
lzma_index_hash *index_hash;
|
||||
|
||||
/// Memory usage limit
|
||||
uint64_t memlimit;
|
||||
|
||||
/// Amount of memory actually needed (only an estimate)
|
||||
uint64_t memusage;
|
||||
|
||||
/// If true, LZMA_NO_CHECK is returned if the Stream has
|
||||
/// no integrity check.
|
||||
bool tell_no_check;
|
||||
|
||||
/// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
|
||||
/// an integrity check that isn't supported by this liblzma build.
|
||||
bool tell_unsupported_check;
|
||||
|
||||
/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
|
||||
bool tell_any_check;
|
||||
|
||||
/// If true, we will tell the Block decoder to skip calculating
|
||||
/// and verifying the integrity check.
|
||||
bool ignore_check;
|
||||
|
||||
/// If true, we will decode concatenated Streams that possibly have
|
||||
/// Stream Padding between or after them. LZMA_STREAM_END is returned
|
||||
/// once the application isn't giving us any new input, and we aren't
|
||||
/// in the middle of a Stream, and possible Stream Padding is a
|
||||
/// multiple of four bytes.
|
||||
bool concatenated;
|
||||
|
||||
/// When decoding concatenated Streams, this is true as long as we
|
||||
/// are decoding the first Stream. This is needed to avoid misleading
|
||||
/// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
|
||||
/// bytes.
|
||||
bool first_stream;
|
||||
|
||||
/// Write position in buffer[] and position in Stream Padding
|
||||
size_t pos;
|
||||
|
||||
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
|
||||
/// Block Header has biggest maximum size.
|
||||
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_decoder_reset(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
// Initialize the Index hash used to verify the Index.
|
||||
coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
|
||||
if (coder->index_hash == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Reset the rest of the variables.
|
||||
coder->sequence = SEQ_STREAM_HEADER;
|
||||
coder->pos = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_decode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
// When decoding the actual Block, it may be able to produce more
|
||||
// output even if we don't give it any new input.
|
||||
while (true)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_STREAM_HEADER: {
|
||||
// Copy the Stream Header to the internal buffer.
|
||||
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
|
||||
LZMA_STREAM_HEADER_SIZE);
|
||||
|
||||
// Return if we didn't get the whole Stream Header yet.
|
||||
if (coder->pos < LZMA_STREAM_HEADER_SIZE)
|
||||
return LZMA_OK;
|
||||
|
||||
coder->pos = 0;
|
||||
|
||||
// Decode the Stream Header.
|
||||
const lzma_ret ret = lzma_stream_header_decode(
|
||||
&coder->stream_flags, coder->buffer);
|
||||
if (ret != LZMA_OK)
|
||||
return ret == LZMA_FORMAT_ERROR && !coder->first_stream
|
||||
? LZMA_DATA_ERROR : ret;
|
||||
|
||||
// If we are decoding concatenated Streams, and the later
|
||||
// Streams have invalid Header Magic Bytes, we give
|
||||
// LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR.
|
||||
coder->first_stream = false;
|
||||
|
||||
// Copy the type of the Check so that Block Header and Block
|
||||
// decoders see it.
|
||||
coder->block_options.check = coder->stream_flags.check;
|
||||
|
||||
// Even if we return LZMA_*_CHECK below, we want
|
||||
// to continue from Block Header decoding.
|
||||
coder->sequence = SEQ_BLOCK_HEADER;
|
||||
|
||||
// Detect if there's no integrity check or if it is
|
||||
// unsupported if those were requested by the application.
|
||||
if (coder->tell_no_check && coder->stream_flags.check
|
||||
== LZMA_CHECK_NONE)
|
||||
return LZMA_NO_CHECK;
|
||||
|
||||
if (coder->tell_unsupported_check
|
||||
&& !lzma_check_is_supported(
|
||||
coder->stream_flags.check))
|
||||
return LZMA_UNSUPPORTED_CHECK;
|
||||
|
||||
if (coder->tell_any_check)
|
||||
return LZMA_GET_CHECK;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_BLOCK_HEADER: {
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
if (coder->pos == 0) {
|
||||
// Detect if it's Index.
|
||||
if (in[*in_pos] == 0x00) {
|
||||
coder->sequence = SEQ_INDEX;
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate the size of the Block Header. Note that
|
||||
// Block Header decoder wants to see this byte too
|
||||
// so don't advance *in_pos.
|
||||
coder->block_options.header_size
|
||||
= lzma_block_header_size_decode(
|
||||
in[*in_pos]);
|
||||
}
|
||||
|
||||
// Copy the Block Header to the internal buffer.
|
||||
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
|
||||
coder->block_options.header_size);
|
||||
|
||||
// Return if we didn't get the whole Block Header yet.
|
||||
if (coder->pos < coder->block_options.header_size)
|
||||
return LZMA_OK;
|
||||
|
||||
coder->pos = 0;
|
||||
|
||||
// Version 1 is needed to support the .ignore_check option.
|
||||
coder->block_options.version = 1;
|
||||
|
||||
// Set up a buffer to hold the filter chain. Block Header
|
||||
// decoder will initialize all members of this array so
|
||||
// we don't need to do it here.
|
||||
lzma_filter filters[LZMA_FILTERS_MAX + 1];
|
||||
coder->block_options.filters = filters;
|
||||
|
||||
// Decode the Block Header.
|
||||
return_if_error(lzma_block_header_decode(&coder->block_options,
|
||||
allocator, coder->buffer));
|
||||
|
||||
// If LZMA_IGNORE_CHECK was used, this flag needs to be set.
|
||||
// It has to be set after lzma_block_header_decode() because
|
||||
// it always resets this to false.
|
||||
coder->block_options.ignore_check = coder->ignore_check;
|
||||
|
||||
// Check the memory usage limit.
|
||||
const uint64_t memusage = lzma_raw_decoder_memusage(filters);
|
||||
lzma_ret ret;
|
||||
|
||||
if (memusage == UINT64_MAX) {
|
||||
// One or more unknown Filter IDs.
|
||||
ret = LZMA_OPTIONS_ERROR;
|
||||
} else {
|
||||
// Now we can set coder->memusage since we know that
|
||||
// the filter chain is valid. We don't want
|
||||
// lzma_memusage() to return UINT64_MAX in case of
|
||||
// invalid filter chain.
|
||||
coder->memusage = memusage;
|
||||
|
||||
if (memusage > coder->memlimit) {
|
||||
// The chain would need too much memory.
|
||||
ret = LZMA_MEMLIMIT_ERROR;
|
||||
} else {
|
||||
// Memory usage is OK.
|
||||
// Initialize the Block decoder.
|
||||
ret = lzma_block_decoder_init(
|
||||
&coder->block_decoder,
|
||||
allocator,
|
||||
&coder->block_options);
|
||||
}
|
||||
}
|
||||
|
||||
// Free the allocated filter options since they are needed
|
||||
// only to initialize the Block decoder.
|
||||
for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
|
||||
lzma_free(filters[i].options, allocator);
|
||||
|
||||
coder->block_options.filters = NULL;
|
||||
|
||||
// Check if memory usage calculation and Block enocoder
|
||||
// initialization succeeded.
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
coder->sequence = SEQ_BLOCK;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_BLOCK: {
|
||||
const lzma_ret ret = coder->block_decoder.code(
|
||||
coder->block_decoder.coder, allocator,
|
||||
in, in_pos, in_size, out, out_pos, out_size,
|
||||
action);
|
||||
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
// Block decoded successfully. Add the new size pair to
|
||||
// the Index hash.
|
||||
return_if_error(lzma_index_hash_append(coder->index_hash,
|
||||
lzma_block_unpadded_size(
|
||||
&coder->block_options),
|
||||
coder->block_options.uncompressed_size));
|
||||
|
||||
coder->sequence = SEQ_BLOCK_HEADER;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_INDEX: {
|
||||
// If we don't have any input, don't call
|
||||
// lzma_index_hash_decode() since it would return
|
||||
// LZMA_BUF_ERROR, which we must not do here.
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_OK;
|
||||
|
||||
// Decode the Index and compare it to the hash calculated
|
||||
// from the sizes of the Blocks (if any).
|
||||
const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
|
||||
in, in_pos, in_size);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
coder->sequence = SEQ_STREAM_FOOTER;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_STREAM_FOOTER: {
|
||||
// Copy the Stream Footer to the internal buffer.
|
||||
lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
|
||||
LZMA_STREAM_HEADER_SIZE);
|
||||
|
||||
// Return if we didn't get the whole Stream Footer yet.
|
||||
if (coder->pos < LZMA_STREAM_HEADER_SIZE)
|
||||
return LZMA_OK;
|
||||
|
||||
coder->pos = 0;
|
||||
|
||||
// Decode the Stream Footer. The decoder gives
|
||||
// LZMA_FORMAT_ERROR if the magic bytes don't match,
|
||||
// so convert that return code to LZMA_DATA_ERROR.
|
||||
lzma_stream_flags footer_flags;
|
||||
const lzma_ret ret = lzma_stream_footer_decode(
|
||||
&footer_flags, coder->buffer);
|
||||
if (ret != LZMA_OK)
|
||||
return ret == LZMA_FORMAT_ERROR
|
||||
? LZMA_DATA_ERROR : ret;
|
||||
|
||||
// Check that Index Size stored in the Stream Footer matches
|
||||
// the real size of the Index field.
|
||||
if (lzma_index_hash_size(coder->index_hash)
|
||||
!= footer_flags.backward_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Compare that the Stream Flags fields are identical in
|
||||
// both Stream Header and Stream Footer.
|
||||
return_if_error(lzma_stream_flags_compare(
|
||||
&coder->stream_flags, &footer_flags));
|
||||
|
||||
if (!coder->concatenated)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
coder->sequence = SEQ_STREAM_PADDING;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_STREAM_PADDING:
|
||||
assert(coder->concatenated);
|
||||
|
||||
// Skip over possible Stream Padding.
|
||||
while (true) {
|
||||
if (*in_pos >= in_size) {
|
||||
// Unless LZMA_FINISH was used, we cannot
|
||||
// know if there's more input coming later.
|
||||
if (action != LZMA_FINISH)
|
||||
return LZMA_OK;
|
||||
|
||||
// Stream Padding must be a multiple of
|
||||
// four bytes.
|
||||
return coder->pos == 0
|
||||
? LZMA_STREAM_END
|
||||
: LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
// If the byte is not zero, it probably indicates
|
||||
// beginning of a new Stream (or the file is corrupt).
|
||||
if (in[*in_pos] != 0x00)
|
||||
break;
|
||||
|
||||
++*in_pos;
|
||||
coder->pos = (coder->pos + 1) & 3;
|
||||
}
|
||||
|
||||
// Stream Padding must be a multiple of four bytes (empty
|
||||
// Stream Padding is OK).
|
||||
if (coder->pos != 0) {
|
||||
++*in_pos;
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
// Prepare to decode the next Stream.
|
||||
return_if_error(stream_decoder_reset(coder, allocator));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
// Never reached
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
stream_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->block_decoder, allocator);
|
||||
lzma_index_hash_end(coder->index_hash, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_check
|
||||
stream_decoder_get_check(const lzma_coder *coder)
|
||||
{
|
||||
return coder->stream_flags.check;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
|
||||
uint64_t *old_memlimit, uint64_t new_memlimit)
|
||||
{
|
||||
*memusage = coder->memusage;
|
||||
*old_memlimit = coder->memlimit;
|
||||
|
||||
if (new_memlimit != 0) {
|
||||
if (new_memlimit < coder->memusage)
|
||||
return LZMA_MEMLIMIT_ERROR;
|
||||
|
||||
coder->memlimit = new_memlimit;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_stream_decoder_init(
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
uint64_t memlimit, uint32_t flags)
|
||||
{
|
||||
lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
|
||||
|
||||
if (memlimit == 0)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (flags & ~LZMA_SUPPORTED_FLAGS)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &stream_decode;
|
||||
next->end = &stream_decoder_end;
|
||||
next->get_check = &stream_decoder_get_check;
|
||||
next->memconfig = &stream_decoder_memconfig;
|
||||
|
||||
next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
|
||||
next->coder->index_hash = NULL;
|
||||
}
|
||||
|
||||
next->coder->memlimit = memlimit;
|
||||
next->coder->memusage = LZMA_MEMUSAGE_BASE;
|
||||
next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
|
||||
next->coder->tell_unsupported_check
|
||||
= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
|
||||
next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
|
||||
next->coder->ignore_check = (flags & LZMA_IGNORE_CHECK) != 0;
|
||||
next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
|
||||
next->coder->first_stream = true;
|
||||
|
||||
return stream_decoder_reset(next->coder, allocator);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
{
|
||||
lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_decoder.h
|
||||
/// \brief Decodes .xz Streams
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_STREAM_DECODER_H
|
||||
#define LZMA_STREAM_DECODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
extern lzma_ret lzma_stream_decoder_init(
|
||||
lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
uint64_t memlimit, uint32_t flags);
|
||||
|
||||
#endif
|
||||
@@ -1,332 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_encoder.c
|
||||
/// \brief Encodes .xz Streams
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "block_encoder.h"
|
||||
#include "index_encoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
enum {
|
||||
SEQ_STREAM_HEADER,
|
||||
SEQ_BLOCK_INIT,
|
||||
SEQ_BLOCK_HEADER,
|
||||
SEQ_BLOCK_ENCODE,
|
||||
SEQ_INDEX_ENCODE,
|
||||
SEQ_STREAM_FOOTER,
|
||||
} sequence;
|
||||
|
||||
/// True if Block encoder has been initialized by
|
||||
/// stream_encoder_init() or stream_encoder_update()
|
||||
/// and thus doesn't need to be initialized in stream_encode().
|
||||
bool block_encoder_is_initialized;
|
||||
|
||||
/// Block
|
||||
lzma_next_coder block_encoder;
|
||||
|
||||
/// Options for the Block encoder
|
||||
lzma_block block_options;
|
||||
|
||||
/// The filter chain currently in use
|
||||
lzma_filter filters[LZMA_FILTERS_MAX + 1];
|
||||
|
||||
/// Index encoder. This is separate from Block encoder, because this
|
||||
/// doesn't take much memory, and when encoding multiple Streams
|
||||
/// with the same encoding options we avoid reallocating memory.
|
||||
lzma_next_coder index_encoder;
|
||||
|
||||
/// Index to hold sizes of the Blocks
|
||||
lzma_index *index;
|
||||
|
||||
/// Read position in buffer[]
|
||||
size_t buffer_pos;
|
||||
|
||||
/// Total number of bytes in buffer[]
|
||||
size_t buffer_size;
|
||||
|
||||
/// Buffer to hold Stream Header, Block Header, and Stream Footer.
|
||||
/// Block Header has biggest maximum size.
|
||||
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
block_encoder_init(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
// Prepare the Block options. Even though Block encoder doesn't need
|
||||
// compressed_size, uncompressed_size, and header_size to be
|
||||
// initialized, it is a good idea to do it here, because this way
|
||||
// we catch if someone gave us Filter ID that cannot be used in
|
||||
// Blocks/Streams.
|
||||
coder->block_options.compressed_size = LZMA_VLI_UNKNOWN;
|
||||
coder->block_options.uncompressed_size = LZMA_VLI_UNKNOWN;
|
||||
|
||||
return_if_error(lzma_block_header_size(&coder->block_options));
|
||||
|
||||
// Initialize the actual Block encoder.
|
||||
return lzma_block_encoder_init(&coder->block_encoder, allocator,
|
||||
&coder->block_options);
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_encode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size, lzma_action action)
|
||||
{
|
||||
// Main loop
|
||||
while (*out_pos < out_size)
|
||||
switch (coder->sequence) {
|
||||
case SEQ_STREAM_HEADER:
|
||||
case SEQ_BLOCK_HEADER:
|
||||
case SEQ_STREAM_FOOTER:
|
||||
lzma_bufcpy(coder->buffer, &coder->buffer_pos,
|
||||
coder->buffer_size, out, out_pos, out_size);
|
||||
if (coder->buffer_pos < coder->buffer_size)
|
||||
return LZMA_OK;
|
||||
|
||||
if (coder->sequence == SEQ_STREAM_FOOTER)
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
coder->buffer_pos = 0;
|
||||
++coder->sequence;
|
||||
break;
|
||||
|
||||
case SEQ_BLOCK_INIT: {
|
||||
if (*in_pos == in_size) {
|
||||
// If we are requested to flush or finish the current
|
||||
// Block, return LZMA_STREAM_END immediately since
|
||||
// there's nothing to do.
|
||||
if (action != LZMA_FINISH)
|
||||
return action == LZMA_RUN
|
||||
? LZMA_OK : LZMA_STREAM_END;
|
||||
|
||||
// The application had used LZMA_FULL_FLUSH to finish
|
||||
// the previous Block, but now wants to finish without
|
||||
// encoding new data, or it is simply creating an
|
||||
// empty Stream with no Blocks.
|
||||
//
|
||||
// Initialize the Index encoder, and continue to
|
||||
// actually encoding the Index.
|
||||
return_if_error(lzma_index_encoder_init(
|
||||
&coder->index_encoder, allocator,
|
||||
coder->index));
|
||||
coder->sequence = SEQ_INDEX_ENCODE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize the Block encoder unless it was already
|
||||
// initialized by stream_encoder_init() or
|
||||
// stream_encoder_update().
|
||||
if (!coder->block_encoder_is_initialized)
|
||||
return_if_error(block_encoder_init(coder, allocator));
|
||||
|
||||
// Make it false so that we don't skip the initialization
|
||||
// with the next Block.
|
||||
coder->block_encoder_is_initialized = false;
|
||||
|
||||
// Encode the Block Header. This shouldn't fail since we have
|
||||
// already initialized the Block encoder.
|
||||
if (lzma_block_header_encode(&coder->block_options,
|
||||
coder->buffer) != LZMA_OK)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
coder->buffer_size = coder->block_options.header_size;
|
||||
coder->sequence = SEQ_BLOCK_HEADER;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_BLOCK_ENCODE: {
|
||||
static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
|
||||
LZMA_RUN,
|
||||
LZMA_SYNC_FLUSH,
|
||||
LZMA_FINISH,
|
||||
LZMA_FINISH,
|
||||
LZMA_FINISH,
|
||||
};
|
||||
|
||||
const lzma_ret ret = coder->block_encoder.code(
|
||||
coder->block_encoder.coder, allocator,
|
||||
in, in_pos, in_size,
|
||||
out, out_pos, out_size, convert[action]);
|
||||
if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
|
||||
return ret;
|
||||
|
||||
// Add a new Index Record.
|
||||
const lzma_vli unpadded_size = lzma_block_unpadded_size(
|
||||
&coder->block_options);
|
||||
assert(unpadded_size != 0);
|
||||
return_if_error(lzma_index_append(coder->index, allocator,
|
||||
unpadded_size,
|
||||
coder->block_options.uncompressed_size));
|
||||
|
||||
coder->sequence = SEQ_BLOCK_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_INDEX_ENCODE: {
|
||||
// Call the Index encoder. It doesn't take any input, so
|
||||
// those pointers can be NULL.
|
||||
const lzma_ret ret = coder->index_encoder.code(
|
||||
coder->index_encoder.coder, allocator,
|
||||
NULL, NULL, 0,
|
||||
out, out_pos, out_size, LZMA_RUN);
|
||||
if (ret != LZMA_STREAM_END)
|
||||
return ret;
|
||||
|
||||
// Encode the Stream Footer into coder->buffer.
|
||||
const lzma_stream_flags stream_flags = {
|
||||
.version = 0,
|
||||
.backward_size = lzma_index_size(coder->index),
|
||||
.check = coder->block_options.check,
|
||||
};
|
||||
|
||||
if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
|
||||
!= LZMA_OK)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
|
||||
coder->sequence = SEQ_STREAM_FOOTER;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
stream_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->block_encoder, allocator);
|
||||
lzma_next_end(&coder->index_encoder, allocator);
|
||||
lzma_index_end(coder->index, allocator);
|
||||
|
||||
for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
|
||||
lzma_free(coder->filters[i].options, allocator);
|
||||
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_encoder_update(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
if (coder->sequence <= SEQ_BLOCK_INIT) {
|
||||
// There is no incomplete Block waiting to be finished,
|
||||
// thus we can change the whole filter chain. Start by
|
||||
// trying to initialize the Block encoder with the new
|
||||
// chain. This way we detect if the chain is valid.
|
||||
coder->block_encoder_is_initialized = false;
|
||||
coder->block_options.filters = (lzma_filter *)(filters);
|
||||
const lzma_ret ret = block_encoder_init(coder, allocator);
|
||||
coder->block_options.filters = coder->filters;
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
coder->block_encoder_is_initialized = true;
|
||||
|
||||
} else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
|
||||
// We are in the middle of a Block. Try to update only
|
||||
// the filter-specific options.
|
||||
return_if_error(coder->block_encoder.update(
|
||||
coder->block_encoder.coder, allocator,
|
||||
filters, reversed_filters));
|
||||
} else {
|
||||
// Trying to update the filter chain when we are already
|
||||
// encoding Index or Stream Footer.
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
// Free the copy of the old chain and make a copy of the new chain.
|
||||
for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
|
||||
lzma_free(coder->filters[i].options, allocator);
|
||||
|
||||
return lzma_filters_copy(filters, coder->filters, allocator);
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters, lzma_check check)
|
||||
{
|
||||
lzma_next_coder_init(&stream_encoder_init, next, allocator);
|
||||
|
||||
if (filters == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->code = &stream_encode;
|
||||
next->end = &stream_encoder_end;
|
||||
next->update = &stream_encoder_update;
|
||||
|
||||
next->coder->filters[0].id = LZMA_VLI_UNKNOWN;
|
||||
next->coder->block_encoder = LZMA_NEXT_CODER_INIT;
|
||||
next->coder->index_encoder = LZMA_NEXT_CODER_INIT;
|
||||
next->coder->index = NULL;
|
||||
}
|
||||
|
||||
// Basic initializations
|
||||
next->coder->sequence = SEQ_STREAM_HEADER;
|
||||
next->coder->block_options.version = 0;
|
||||
next->coder->block_options.check = check;
|
||||
|
||||
// Initialize the Index
|
||||
lzma_index_end(next->coder->index, allocator);
|
||||
next->coder->index = lzma_index_init(allocator);
|
||||
if (next->coder->index == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Encode the Stream Header
|
||||
lzma_stream_flags stream_flags = {
|
||||
.version = 0,
|
||||
.check = check,
|
||||
};
|
||||
return_if_error(lzma_stream_header_encode(
|
||||
&stream_flags, next->coder->buffer));
|
||||
|
||||
next->coder->buffer_pos = 0;
|
||||
next->coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
|
||||
|
||||
// Initialize the Block encoder. This way we detect unsupported
|
||||
// filter chains when initializing the Stream encoder instead of
|
||||
// giving an error after Stream Header has already written out.
|
||||
return stream_encoder_update(
|
||||
next->coder, allocator, filters, NULL);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_encoder(lzma_stream *strm,
|
||||
const lzma_filter *filters, lzma_check check)
|
||||
{
|
||||
lzma_next_strm_init(stream_encoder_init, strm, filters, check);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
|
||||
strm->internal->supported_actions[LZMA_FULL_BARRIER] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_common.c
|
||||
/// \brief Common stuff for Stream flags coders
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_flags_common.h"
|
||||
|
||||
|
||||
const uint8_t lzma_header_magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
|
||||
const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_flags_compare(
|
||||
const lzma_stream_flags *a, const lzma_stream_flags *b)
|
||||
{
|
||||
// We can compare only version 0 structures.
|
||||
if (a->version != 0 || b->version != 0)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Check type
|
||||
if ((unsigned int)(a->check) > LZMA_CHECK_ID_MAX
|
||||
|| (unsigned int)(b->check) > LZMA_CHECK_ID_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (a->check != b->check)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
// Backward Sizes are compared only if they are known in both.
|
||||
if (a->backward_size != LZMA_VLI_UNKNOWN
|
||||
&& b->backward_size != LZMA_VLI_UNKNOWN) {
|
||||
if (!is_backward_size_valid(a) || !is_backward_size_valid(b))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (a->backward_size != b->backward_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_common.h
|
||||
/// \brief Common stuff for Stream flags coders
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_STREAM_FLAGS_COMMON_H
|
||||
#define LZMA_STREAM_FLAGS_COMMON_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/// Size of the Stream Flags field
|
||||
#define LZMA_STREAM_FLAGS_SIZE 2
|
||||
|
||||
extern const uint8_t lzma_header_magic[6];
|
||||
extern const uint8_t lzma_footer_magic[2];
|
||||
|
||||
|
||||
static inline bool
|
||||
is_backward_size_valid(const lzma_stream_flags *options)
|
||||
{
|
||||
return options->backward_size >= LZMA_BACKWARD_SIZE_MIN
|
||||
&& options->backward_size <= LZMA_BACKWARD_SIZE_MAX
|
||||
&& (options->backward_size & 3) == 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,82 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_decoder.c
|
||||
/// \brief Decodes Stream Header and Stream Footer from .xz files
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_flags_common.h"
|
||||
|
||||
|
||||
static bool
|
||||
stream_flags_decode(lzma_stream_flags *options, const uint8_t *in)
|
||||
{
|
||||
// Reserved bits must be unset.
|
||||
if (in[0] != 0x00 || (in[1] & 0xF0))
|
||||
return true;
|
||||
|
||||
options->version = 0;
|
||||
options->check = in[1] & 0x0F;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
|
||||
{
|
||||
// Magic
|
||||
if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
|
||||
return LZMA_FORMAT_ERROR;
|
||||
#if 0
|
||||
// Verify the CRC32 so we can distinguish between corrupt
|
||||
// and unsupported files.
|
||||
const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
|
||||
LZMA_STREAM_FLAGS_SIZE, 0);
|
||||
if (crc != unaligned_read32le(in + sizeof(lzma_header_magic)
|
||||
+ LZMA_STREAM_FLAGS_SIZE))
|
||||
return LZMA_DATA_ERROR;
|
||||
#endif
|
||||
// Stream Flags
|
||||
if (stream_flags_decode(options, in + sizeof(lzma_header_magic)))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Set Backward Size to indicate unknown value. That way
|
||||
// lzma_stream_flags_compare() can be used to compare Stream Header
|
||||
// and Stream Footer while keeping it useful also for comparing
|
||||
// two Stream Footers.
|
||||
options->backward_size = LZMA_VLI_UNKNOWN;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
|
||||
{
|
||||
// Magic
|
||||
if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
|
||||
lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
|
||||
return LZMA_FORMAT_ERROR;
|
||||
#if 0
|
||||
// CRC32
|
||||
const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
|
||||
sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
|
||||
if (crc != unaligned_read32le(in))
|
||||
return LZMA_DATA_ERROR;
|
||||
#endif
|
||||
// Stream Flags
|
||||
if (stream_flags_decode(options, in + sizeof(uint32_t) * 2))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Backward Size
|
||||
options->backward_size = unaligned_read32le(in + sizeof(uint32_t));
|
||||
options->backward_size = (options->backward_size + 1) * 4;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_encoder.c
|
||||
/// \brief Encodes Stream Header and Stream Footer for .xz files
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stream_flags_common.h"
|
||||
|
||||
|
||||
static bool
|
||||
stream_flags_encode(const lzma_stream_flags *options, uint8_t *out)
|
||||
{
|
||||
if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
|
||||
return true;
|
||||
|
||||
out[0] = 0x00;
|
||||
out[1] = options->check;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
|
||||
{
|
||||
assert(sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE
|
||||
+ 4 == LZMA_STREAM_HEADER_SIZE);
|
||||
|
||||
if (options->version != 0)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Magic
|
||||
memcpy(out, lzma_header_magic, sizeof(lzma_header_magic));
|
||||
|
||||
// Stream Flags
|
||||
if (stream_flags_encode(options, out + sizeof(lzma_header_magic)))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// CRC32 of the Stream Header
|
||||
const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic),
|
||||
LZMA_STREAM_FLAGS_SIZE, 0);
|
||||
|
||||
unaligned_write32le(out + sizeof(lzma_header_magic)
|
||||
+ LZMA_STREAM_FLAGS_SIZE, crc);
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
|
||||
{
|
||||
assert(2 * 4 + LZMA_STREAM_FLAGS_SIZE + sizeof(lzma_footer_magic)
|
||||
== LZMA_STREAM_HEADER_SIZE);
|
||||
|
||||
if (options->version != 0)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Backward Size
|
||||
if (!is_backward_size_valid(options))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
unaligned_write32le(out + 4, options->backward_size / 4 - 1);
|
||||
|
||||
// Stream Flags
|
||||
if (stream_flags_encode(options, out + 2 * 4))
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// CRC32
|
||||
const uint32_t crc = lzma_crc32(
|
||||
out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0);
|
||||
|
||||
unaligned_write32le(out, crc);
|
||||
|
||||
// Magic
|
||||
memcpy(out + 2 * 4 + LZMA_STREAM_FLAGS_SIZE,
|
||||
lzma_footer_magic, sizeof(lzma_footer_magic));
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_cpucores.c
|
||||
/// \brief Get the number of CPU cores online
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_cpucores.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0500
|
||||
# endif
|
||||
# include <windows.h>
|
||||
|
||||
// FreeBSD
|
||||
#elif defined(TUKLIB_CPUCORES_CPUSET)
|
||||
# include <sys/param.h>
|
||||
# include <sys/cpuset.h>
|
||||
|
||||
#elif defined(TUKLIB_CPUCORES_SYSCTL)
|
||||
# ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# include <sys/sysctl.h>
|
||||
|
||||
#elif defined(TUKLIB_CPUCORES_SYSCONF)
|
||||
# include <unistd.h>
|
||||
|
||||
// HP-UX
|
||||
#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
|
||||
# include <sys/param.h>
|
||||
# include <sys/pstat.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern uint32_t
|
||||
tuklib_cpucores(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
ret = sysinfo.dwNumberOfProcessors;
|
||||
|
||||
#elif defined(TUKLIB_CPUCORES_CPUSET)
|
||||
cpuset_t set;
|
||||
if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
|
||||
sizeof(set), &set) == 0) {
|
||||
# ifdef CPU_COUNT
|
||||
ret = CPU_COUNT(&set);
|
||||
# else
|
||||
for (unsigned i = 0; i < CPU_SETSIZE; ++i)
|
||||
if (CPU_ISSET(i, &set))
|
||||
++ret;
|
||||
# endif
|
||||
}
|
||||
|
||||
#elif defined(TUKLIB_CPUCORES_SYSCTL)
|
||||
int name[2] = { CTL_HW, HW_NCPU };
|
||||
int cpus;
|
||||
size_t cpus_size = sizeof(cpus);
|
||||
if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
|
||||
&& cpus_size == sizeof(cpus) && cpus > 0)
|
||||
ret = cpus;
|
||||
|
||||
#elif defined(TUKLIB_CPUCORES_SYSCONF)
|
||||
# ifdef _SC_NPROCESSORS_ONLN
|
||||
// Most systems
|
||||
const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
# else
|
||||
// IRIX
|
||||
const long cpus = sysconf(_SC_NPROC_ONLN);
|
||||
# endif
|
||||
if (cpus > 0)
|
||||
ret = cpus;
|
||||
|
||||
#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
|
||||
struct pst_dynamic pst;
|
||||
if (pstat_getdynamic(&pst, sizeof(pst), 1, 0) != -1)
|
||||
ret = pst.psd_proc_cnt;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_cpucores.h
|
||||
/// \brief Get the number of CPU cores online
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_CPUCORES_H
|
||||
#define TUKLIB_CPUCORES_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
TUKLIB_DECLS_BEGIN
|
||||
|
||||
#define tuklib_cpucores TUKLIB_SYMBOL(tuklib_cpucores)
|
||||
extern uint32_t tuklib_cpucores(void);
|
||||
|
||||
TUKLIB_DECLS_END
|
||||
#endif
|
||||
@@ -1,57 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_exit.c
|
||||
/// \brief Close stdout and stderr, and exit
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tuklib_gettext.h"
|
||||
#include "tuklib_progname.h"
|
||||
#include "tuklib_exit.h"
|
||||
|
||||
|
||||
extern void
|
||||
tuklib_exit(int status, int err_status, int show_error)
|
||||
{
|
||||
if (status != err_status) {
|
||||
// Close stdout. If something goes wrong,
|
||||
// print an error message to stderr.
|
||||
const int ferror_err = ferror(stdout);
|
||||
const int fclose_err = fclose(stdout);
|
||||
if (ferror_err || fclose_err) {
|
||||
status = err_status;
|
||||
|
||||
// If it was fclose() that failed, we have the reason
|
||||
// in errno. If only ferror() indicated an error,
|
||||
// we have no idea what the reason was.
|
||||
if (show_error)
|
||||
fprintf(stderr, "%s: %s: %s\n", progname,
|
||||
_("Writing to standard "
|
||||
"output failed"),
|
||||
fclose_err ? strerror(errno)
|
||||
: _("Unknown error"));
|
||||
}
|
||||
}
|
||||
|
||||
if (status != err_status) {
|
||||
// Close stderr. If something goes wrong, there's
|
||||
// nothing where we could print an error message.
|
||||
// Just set the exit status.
|
||||
const int ferror_err = ferror(stderr);
|
||||
const int fclose_err = fclose(stderr);
|
||||
if (fclose_err || ferror_err)
|
||||
status = err_status;
|
||||
}
|
||||
|
||||
exit(status);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_exit.h
|
||||
/// \brief Close stdout and stderr, and exit
|
||||
/// \note Requires tuklib_progname and tuklib_gettext modules
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_EXIT_H
|
||||
#define TUKLIB_EXIT_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
TUKLIB_DECLS_BEGIN
|
||||
|
||||
#define tuklib_exit TUKLIB_SYMBOL(tuklib_exit)
|
||||
extern void tuklib_exit(int status, int err_status, int show_error)
|
||||
tuklib_attr_noreturn;
|
||||
|
||||
TUKLIB_DECLS_END
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_gettext.h
|
||||
/// \brief Wrapper for gettext and friends
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_GETTEXT_H
|
||||
#define TUKLIB_GETTEXT_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
#include <locale.h>
|
||||
|
||||
#ifndef TUKLIB_GETTEXT
|
||||
# ifdef ENABLE_NLS
|
||||
# define TUKLIB_GETTEXT 1
|
||||
# else
|
||||
# define TUKLIB_GETTEXT 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TUKLIB_GETTEXT
|
||||
# include <libintl.h>
|
||||
# define tuklib_gettext_init(package, localedir) \
|
||||
do { \
|
||||
setlocale(LC_ALL, ""); \
|
||||
bindtextdomain(package, localedir); \
|
||||
textdomain(package); \
|
||||
} while (0)
|
||||
# define _(msgid) gettext(msgid)
|
||||
#else
|
||||
# define tuklib_gettext_init(package, localedir) \
|
||||
setlocale(LC_ALL, "")
|
||||
# define _(msgid) (msgid)
|
||||
# define ngettext(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2))
|
||||
#endif
|
||||
#define N_(msgid) msgid
|
||||
|
||||
#endif
|
||||
@@ -1,66 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_mstr.h
|
||||
/// \brief Utility functions for handling multibyte strings
|
||||
///
|
||||
/// If not enough multibyte string support is available in the C library,
|
||||
/// these functions keep working with the assumption that all strings
|
||||
/// are in a single-byte character set without combining characters, e.g.
|
||||
/// US-ASCII or ISO-8859-*.
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_MBSTR_H
|
||||
#define TUKLIB_MBSTR_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
TUKLIB_DECLS_BEGIN
|
||||
|
||||
#define tuklib_mbstr_width TUKLIB_SYMBOL(tuklib_mbstr_width)
|
||||
extern size_t tuklib_mbstr_width(const char *str, size_t *bytes);
|
||||
///<
|
||||
/// \brief Get the number of columns needed for the multibyte string
|
||||
///
|
||||
/// This is somewhat similar to wcswidth() but works on multibyte strings.
|
||||
///
|
||||
/// \param str String whose width is to be calculated. If the
|
||||
/// current locale uses a multibyte character set
|
||||
/// that has shift states, the string must begin
|
||||
/// and end in the initial shift state.
|
||||
/// \param bytes If this is not NULL, *bytes is set to the
|
||||
/// value returned by strlen(str) (even if an
|
||||
/// error occurs when calculating the width).
|
||||
///
|
||||
/// \return On success, the number of columns needed to display the
|
||||
/// string e.g. in a terminal emulator is returned. On error,
|
||||
/// (size_t)-1 is returned. Possible errors include invalid,
|
||||
/// partial, or non-printable multibyte character in str, or
|
||||
/// that str doesn't end in the initial shift state.
|
||||
|
||||
#define tuklib_mbstr_fw TUKLIB_SYMBOL(tuklib_mbstr_fw)
|
||||
extern int tuklib_mbstr_fw(const char *str, int columns_min);
|
||||
///<
|
||||
/// \brief Get the field width for printf() e.g. to align table columns
|
||||
///
|
||||
/// Printing simple tables to a terminal can be done using the field field
|
||||
/// feature in the printf() format string, but it works only with single-byte
|
||||
/// character sets. To do the same with multibyte strings, tuklib_mbstr_fw()
|
||||
/// can be used to calculate appropriate field width.
|
||||
///
|
||||
/// The behavior of this function is undefined, if
|
||||
/// - str is NULL or not terminated with '\0';
|
||||
/// - columns_min <= 0; or
|
||||
/// - the calculated field width exceeds INT_MAX.
|
||||
///
|
||||
/// \return If tuklib_mbstr_width(str, NULL) fails, -1 is returned.
|
||||
/// If str needs more columns than columns_min, zero is returned.
|
||||
/// Otherwise a positive integer is returned, which can be
|
||||
/// used as the field width, e.g. printf("%*s", fw, str).
|
||||
|
||||
TUKLIB_DECLS_END
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_mstr_fw.c
|
||||
/// \brief Get the field width for printf() e.g. to align table columns
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_mbstr.h"
|
||||
|
||||
|
||||
extern int
|
||||
tuklib_mbstr_fw(const char *str, int columns_min)
|
||||
{
|
||||
size_t len;
|
||||
const size_t width = tuklib_mbstr_width(str, &len);
|
||||
if (width == (size_t)-1)
|
||||
return -1;
|
||||
|
||||
if (width > (size_t)columns_min)
|
||||
return 0;
|
||||
|
||||
if (width < (size_t)columns_min)
|
||||
len += (size_t)columns_min - width;
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_mstr_width.c
|
||||
/// \brief Calculate width of a multibyte string
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_mbstr.h"
|
||||
|
||||
#if defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern size_t
|
||||
tuklib_mbstr_width(const char *str, size_t *bytes)
|
||||
{
|
||||
const size_t len = strlen(str);
|
||||
if (bytes != NULL)
|
||||
*bytes = len;
|
||||
|
||||
#if !(defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH))
|
||||
// In single-byte mode, the width of the string is the same
|
||||
// as its length.
|
||||
return len;
|
||||
|
||||
#else
|
||||
mbstate_t state;
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
||||
size_t width = 0;
|
||||
size_t i = 0;
|
||||
|
||||
// Convert one multibyte character at a time to wchar_t
|
||||
// and get its width using wcwidth().
|
||||
while (i < len) {
|
||||
wchar_t wc;
|
||||
const size_t ret = mbrtowc(&wc, str + i, len - i, &state);
|
||||
if (ret < 1 || ret > len)
|
||||
return (size_t)-1;
|
||||
|
||||
i += ret;
|
||||
|
||||
const int wc_width = wcwidth(wc);
|
||||
if (wc_width < 0)
|
||||
return (size_t)-1;
|
||||
|
||||
width += wc_width;
|
||||
}
|
||||
|
||||
// Require that the string ends in the initial shift state.
|
||||
// This way the caller can be combine the string with other
|
||||
// strings without needing to worry about the shift states.
|
||||
if (!mbsinit(&state))
|
||||
return (size_t)-1;
|
||||
|
||||
return width;
|
||||
#endif
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_open_stdxxx.c
|
||||
/// \brief Make sure that file descriptors 0, 1, and 2 are open
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_open_stdxxx.h"
|
||||
|
||||
#ifndef TUKLIB_DOSLIKE
|
||||
# include <stdlib.h>
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern void
|
||||
tuklib_open_stdxxx(int err_status)
|
||||
{
|
||||
#ifdef TUKLIB_DOSLIKE
|
||||
// Do nothing, just silence warnings.
|
||||
(void)err_status;
|
||||
|
||||
#else
|
||||
for (int i = 0; i <= 2; ++i) {
|
||||
// We use fcntl() to check if the file descriptor is open.
|
||||
if (fcntl(i, F_GETFD) == -1 && errno == EBADF) {
|
||||
// With stdin, we could use /dev/full so that
|
||||
// writing to stdin would fail. However, /dev/full
|
||||
// is Linux specific, and if the program tries to
|
||||
// write to stdin, there's already a problem anyway.
|
||||
const int fd = open("/dev/null", O_NOCTTY
|
||||
| (i == 0 ? O_WRONLY : O_RDONLY));
|
||||
|
||||
if (fd != i) {
|
||||
if (fd != -1)
|
||||
(void)close(fd);
|
||||
|
||||
// Something went wrong. Exit with the
|
||||
// exit status we were given. Don't try
|
||||
// to print an error message, since stderr
|
||||
// may very well be non-existent. This
|
||||
// error should be extremely rare.
|
||||
exit(err_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_open_stdxxx.h
|
||||
/// \brief Make sure that file descriptors 0, 1, and 2 are open
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_OPEN_STDXXX_H
|
||||
#define TUKLIB_OPEN_STDXXX_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
TUKLIB_DECLS_BEGIN
|
||||
|
||||
#define tuklib_open_stdxx TUKLIB_SYMBOL(tuklib_open_stdxxx)
|
||||
extern void tuklib_open_stdxxx(int err_status);
|
||||
|
||||
TUKLIB_DECLS_END
|
||||
#endif
|
||||
@@ -1,215 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_physmem.c
|
||||
/// \brief Get the amount of physical memory
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_physmem.h"
|
||||
|
||||
// We want to use Windows-specific code on Cygwin, which also has memory
|
||||
// information available via sysconf(), but on Cygwin 1.5 and older it
|
||||
// gives wrong results (from our point of view).
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0500
|
||||
# endif
|
||||
# include <windows.h>
|
||||
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSMISC
|
||||
# include <os2.h>
|
||||
|
||||
#elif defined(__DJGPP__)
|
||||
# include <dpmi.h>
|
||||
|
||||
#elif defined(__VMS)
|
||||
# include <lib$routines.h>
|
||||
# include <syidef.h>
|
||||
# include <ssdef.h>
|
||||
|
||||
#elif defined(AMIGA) || defined(__AROS__)
|
||||
# define __USE_INLINE__
|
||||
# include <proto/exec.h>
|
||||
|
||||
#elif defined(__QNX__)
|
||||
# include <sys/syspage.h>
|
||||
# include <string.h>
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_AIX)
|
||||
# include <sys/systemcfg.h>
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_SYSCONF)
|
||||
# include <unistd.h>
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_SYSCTL)
|
||||
# ifdef HAVE_SYS_PARAM_H
|
||||
# include <sys/param.h>
|
||||
# endif
|
||||
# include <sys/sysctl.h>
|
||||
|
||||
// Tru64
|
||||
#elif defined(TUKLIB_PHYSMEM_GETSYSINFO)
|
||||
# include <sys/sysinfo.h>
|
||||
# include <machine/hal_sysinfo.h>
|
||||
|
||||
// HP-UX
|
||||
#elif defined(TUKLIB_PHYSMEM_PSTAT_GETSTATIC)
|
||||
# include <sys/param.h>
|
||||
# include <sys/pstat.h>
|
||||
|
||||
// IRIX
|
||||
#elif defined(TUKLIB_PHYSMEM_GETINVENT_R)
|
||||
# include <invent.h>
|
||||
|
||||
// This sysinfo() is Linux-specific.
|
||||
#elif defined(TUKLIB_PHYSMEM_SYSINFO)
|
||||
# include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern uint64_t
|
||||
tuklib_physmem(void)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
if ((GetVersion() & 0xFF) >= 5) {
|
||||
// Windows 2000 and later have GlobalMemoryStatusEx() which
|
||||
// supports reporting values greater than 4 GiB. To keep the
|
||||
// code working also on older Windows versions, use
|
||||
// GlobalMemoryStatusEx() conditionally.
|
||||
HMODULE kernel32 = GetModuleHandle("kernel32.dll");
|
||||
if (kernel32 != NULL) {
|
||||
BOOL (WINAPI *gmse)(LPMEMORYSTATUSEX) = GetProcAddress(
|
||||
kernel32, "GlobalMemoryStatusEx");
|
||||
if (gmse != NULL) {
|
||||
MEMORYSTATUSEX meminfo;
|
||||
meminfo.dwLength = sizeof(meminfo);
|
||||
if (gmse(&meminfo))
|
||||
ret = meminfo.ullTotalPhys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
// GlobalMemoryStatus() is supported by Windows 95 and later,
|
||||
// so it is fine to link against it unconditionally. Note that
|
||||
// GlobalMemoryStatus() has no return value.
|
||||
MEMORYSTATUS meminfo;
|
||||
meminfo.dwLength = sizeof(meminfo);
|
||||
GlobalMemoryStatus(&meminfo);
|
||||
ret = meminfo.dwTotalPhys;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
unsigned long mem;
|
||||
if (DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM,
|
||||
&mem, sizeof(mem)) == 0)
|
||||
ret = mem;
|
||||
|
||||
#elif defined(__DJGPP__)
|
||||
__dpmi_free_mem_info meminfo;
|
||||
if (__dpmi_get_free_memory_information(&meminfo) == 0
|
||||
&& meminfo.total_number_of_physical_pages
|
||||
!= (unsigned long)-1)
|
||||
ret = (uint64_t)meminfo.total_number_of_physical_pages * 4096;
|
||||
|
||||
#elif defined(__VMS)
|
||||
int vms_mem;
|
||||
int val = SYI$_MEMSIZE;
|
||||
if (LIB$GETSYI(&val, &vms_mem, 0, 0, 0, 0) == SS$_NORMAL)
|
||||
ret = (uint64_t)vms_mem * 8192;
|
||||
|
||||
#elif defined(AMIGA) || defined(__AROS__)
|
||||
ret = AvailMem(MEMF_TOTAL);
|
||||
|
||||
#elif defined(__QNX__)
|
||||
const struct asinfo_entry *entries = SYSPAGE_ENTRY(asinfo);
|
||||
size_t count = SYSPAGE_ENTRY_SIZE(asinfo) / sizeof(struct asinfo_entry);
|
||||
const char *strings = SYSPAGE_ENTRY(strings)->data;
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
if (strcmp(strings + entries[i].name, "ram") == 0)
|
||||
ret += entries[i].end - entries[i].start + 1;
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_AIX)
|
||||
ret = _system_configuration.physmem;
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_SYSCONF)
|
||||
const long pagesize = sysconf(_SC_PAGESIZE);
|
||||
const long pages = sysconf(_SC_PHYS_PAGES);
|
||||
if (pagesize != -1 && pages != -1)
|
||||
// According to docs, pagesize * pages can overflow.
|
||||
// Simple case is 32-bit box with 4 GiB or more RAM,
|
||||
// which may report exactly 4 GiB of RAM, and "long"
|
||||
// being 32-bit will overflow. Casting to uint64_t
|
||||
// hopefully avoids overflows in the near future.
|
||||
ret = (uint64_t)pagesize * (uint64_t)pages;
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_SYSCTL)
|
||||
int name[2] = {
|
||||
CTL_HW,
|
||||
#ifdef HW_PHYSMEM64
|
||||
HW_PHYSMEM64
|
||||
#else
|
||||
HW_PHYSMEM
|
||||
#endif
|
||||
};
|
||||
union {
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
} mem;
|
||||
size_t mem_ptr_size = sizeof(mem.u64);
|
||||
if (sysctl(name, 2, &mem.u64, &mem_ptr_size, NULL, 0) != -1) {
|
||||
// IIRC, 64-bit "return value" is possible on some 64-bit
|
||||
// BSD systems even with HW_PHYSMEM (instead of HW_PHYSMEM64),
|
||||
// so support both.
|
||||
if (mem_ptr_size == sizeof(mem.u64))
|
||||
ret = mem.u64;
|
||||
else if (mem_ptr_size == sizeof(mem.u32))
|
||||
ret = mem.u32;
|
||||
}
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_GETSYSINFO)
|
||||
// Docs are unclear if "start" is needed, but it doesn't hurt
|
||||
// much to have it.
|
||||
int memkb;
|
||||
int start = 0;
|
||||
if (getsysinfo(GSI_PHYSMEM, (caddr_t)&memkb, sizeof(memkb), &start)
|
||||
!= -1)
|
||||
ret = (uint64_t)memkb * 1024;
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_PSTAT_GETSTATIC)
|
||||
struct pst_static pst;
|
||||
if (pstat_getstatic(&pst, sizeof(pst), 1, 0) != -1)
|
||||
ret = (uint64_t)pst.physical_memory * (uint64_t)pst.page_size;
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_GETINVENT_R)
|
||||
inv_state_t *st = NULL;
|
||||
if (setinvent_r(&st) != -1) {
|
||||
inventory_t *i;
|
||||
while ((i = getinvent_r(st)) != NULL) {
|
||||
if (i->inv_class == INV_MEMORY
|
||||
&& i->inv_type == INV_MAIN_MB) {
|
||||
ret = (uint64_t)i->inv_state << 20;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
endinvent_r(st);
|
||||
}
|
||||
|
||||
#elif defined(TUKLIB_PHYSMEM_SYSINFO)
|
||||
struct sysinfo si;
|
||||
if (sysinfo(&si) == 0)
|
||||
ret = (uint64_t)si.totalram * si.mem_unit;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_physmem.h
|
||||
/// \brief Get the amount of physical memory
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_PHYSMEM_H
|
||||
#define TUKLIB_PHYSMEM_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
TUKLIB_DECLS_BEGIN
|
||||
|
||||
#define tuklib_physmem TUKLIB_SYMBOL(tuklib_physmem)
|
||||
extern uint64_t tuklib_physmem(void);
|
||||
///<
|
||||
/// \brief Get the amount of physical memory in bytes
|
||||
///
|
||||
/// \return Amount of physical memory in bytes. On error, zero is
|
||||
/// returned.
|
||||
|
||||
TUKLIB_DECLS_END
|
||||
#endif
|
||||
@@ -1,50 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_progname.c
|
||||
/// \brief Program name to be displayed in messages
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tuklib_progname.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#if !HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
char *progname = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
extern void
|
||||
tuklib_progname_init(char **argv)
|
||||
{
|
||||
#ifdef TUKLIB_DOSLIKE
|
||||
// On these systems, argv[0] always has the full path and .exe
|
||||
// suffix even if the user just types the plain program name.
|
||||
// We modify argv[0] to make it nicer to read.
|
||||
|
||||
// Strip the leading path.
|
||||
char *p = argv[0] + strlen(argv[0]);
|
||||
while (argv[0] < p && p[-1] != '/' && p[-1] != '\\')
|
||||
--p;
|
||||
|
||||
argv[0] = p;
|
||||
|
||||
// Strip the .exe suffix.
|
||||
p = strrchr(p, '.');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
|
||||
// Make it lowercase.
|
||||
for (p = argv[0]; *p != '\0'; ++p)
|
||||
if (*p >= 'A' && *p <= 'Z')
|
||||
*p = *p - 'A' + 'a';
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
return;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_progname.h
|
||||
/// \brief Program name to be displayed in messages
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_PROGNAME_H
|
||||
#define TUKLIB_PROGNAME_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
#include <errno.h>
|
||||
|
||||
TUKLIB_DECLS_BEGIN
|
||||
|
||||
#if HAVE_DECL_PROGRAM_INVOCATION_NAME
|
||||
# define progname program_invocation_name
|
||||
#else
|
||||
# define progname TUKLIB_SYMBOL(tuklib_progname)
|
||||
extern char *progname;
|
||||
#endif
|
||||
|
||||
#define tuklib_progname_init TUKLIB_SYMBOL(tuklib_progname_init)
|
||||
extern void tuklib_progname_init(char **argv);
|
||||
|
||||
TUKLIB_DECLS_END
|
||||
#endif
|
||||
@@ -1,86 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file vli_decoder.c
|
||||
/// \brief Decodes variable-length integers
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size)
|
||||
{
|
||||
// If we haven't been given vli_pos, work in single-call mode.
|
||||
size_t vli_pos_internal = 0;
|
||||
if (vli_pos == NULL) {
|
||||
vli_pos = &vli_pos_internal;
|
||||
*vli = 0;
|
||||
|
||||
// If there's no input, use LZMA_DATA_ERROR. This way it is
|
||||
// easy to decode VLIs from buffers that have known size,
|
||||
// and get the correct error code in case the buffer is
|
||||
// too short.
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
} else {
|
||||
// Initialize *vli when starting to decode a new integer.
|
||||
if (*vli_pos == 0)
|
||||
*vli = 0;
|
||||
|
||||
// Validate the arguments.
|
||||
if (*vli_pos >= LZMA_VLI_BYTES_MAX
|
||||
|| (*vli >> (*vli_pos * 7)) != 0)
|
||||
return LZMA_PROG_ERROR;;
|
||||
|
||||
if (*in_pos >= in_size)
|
||||
return LZMA_BUF_ERROR;
|
||||
}
|
||||
|
||||
do {
|
||||
// Read the next byte. Use a temporary variable so that we
|
||||
// can update *in_pos immediately.
|
||||
const uint8_t byte = in[*in_pos];
|
||||
++*in_pos;
|
||||
|
||||
// Add the newly read byte to *vli.
|
||||
*vli += (lzma_vli)(byte & 0x7F) << (*vli_pos * 7);
|
||||
++*vli_pos;
|
||||
|
||||
// Check if this is the last byte of a multibyte integer.
|
||||
if ((byte & 0x80) == 0) {
|
||||
// We don't allow using variable-length integers as
|
||||
// padding i.e. the encoding must use the most the
|
||||
// compact form.
|
||||
if (byte == 0x00 && *vli_pos > 1)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
return vli_pos == &vli_pos_internal
|
||||
? LZMA_OK : LZMA_STREAM_END;
|
||||
}
|
||||
|
||||
// There is at least one more byte coming. If we have already
|
||||
// read maximum number of bytes, the integer is considered
|
||||
// corrupt.
|
||||
//
|
||||
// If we need bigger integers in future, old versions liblzma
|
||||
// will confusingly indicate the file being corrupt istead of
|
||||
// unsupported. I suppose it's still better this way, because
|
||||
// in the foreseeable future (writing this in 2008) the only
|
||||
// reason why files would appear having over 63-bit integers
|
||||
// is that the files are simply corrupt.
|
||||
if (*vli_pos == LZMA_VLI_BYTES_MAX)
|
||||
return LZMA_DATA_ERROR;
|
||||
|
||||
} while (*in_pos < in_size);
|
||||
|
||||
return vli_pos == &vli_pos_internal ? LZMA_DATA_ERROR : LZMA_OK;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file vli_encoder.c
|
||||
/// \brief Encodes variable-length integers
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size)
|
||||
{
|
||||
// If we haven't been given vli_pos, work in single-call mode.
|
||||
size_t vli_pos_internal = 0;
|
||||
if (vli_pos == NULL) {
|
||||
vli_pos = &vli_pos_internal;
|
||||
|
||||
// In single-call mode, we expect that the caller has
|
||||
// reserved enough output space.
|
||||
if (*out_pos >= out_size)
|
||||
return LZMA_PROG_ERROR;
|
||||
} else {
|
||||
// This never happens when we are called by liblzma, but
|
||||
// may happen if called directly from an application.
|
||||
if (*out_pos >= out_size)
|
||||
return LZMA_BUF_ERROR;
|
||||
}
|
||||
|
||||
// Validate the arguments.
|
||||
if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_MAX)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Shift vli so that the next bits to encode are the lowest. In
|
||||
// single-call mode this never changes vli since *vli_pos is zero.
|
||||
vli >>= *vli_pos * 7;
|
||||
|
||||
// Write the non-last bytes in a loop.
|
||||
while (vli >= 0x80) {
|
||||
// We don't need *vli_pos during this function call anymore,
|
||||
// but update it here so that it is ready if we need to
|
||||
// return before the whole integer has been decoded.
|
||||
++*vli_pos;
|
||||
assert(*vli_pos < LZMA_VLI_BYTES_MAX);
|
||||
|
||||
// Write the next byte.
|
||||
out[*out_pos] = (uint8_t)(vli) | 0x80;
|
||||
vli >>= 7;
|
||||
|
||||
if (++*out_pos == out_size)
|
||||
return vli_pos == &vli_pos_internal
|
||||
? LZMA_PROG_ERROR : LZMA_OK;
|
||||
}
|
||||
|
||||
// Write the last byte.
|
||||
out[*out_pos] = (uint8_t)(vli);
|
||||
++*out_pos;
|
||||
++*vli_pos;
|
||||
|
||||
return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END;
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file vli_size.c
|
||||
/// \brief Calculates the encoded size of a variable-length integer
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_vli_size(lzma_vli vli)
|
||||
{
|
||||
if (vli > LZMA_VLI_MAX)
|
||||
return 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
do {
|
||||
vli >>= 7;
|
||||
++i;
|
||||
} while (vli != 0);
|
||||
|
||||
assert(i <= LZMA_VLI_BYTES_MAX);
|
||||
return i;
|
||||
}
|
||||
@@ -318,7 +318,7 @@
|
||||
#define PACKAGE_NAME "XZ Utils"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "XZ Utils 5.2.1"
|
||||
#define PACKAGE_STRING "XZ Utils 5.2.3"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "xz"
|
||||
@@ -327,7 +327,7 @@
|
||||
#define PACKAGE_URL "http://tukaani.org/xz/"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "5.2.1"
|
||||
#define PACKAGE_VERSION "5.2.3"
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
@@ -414,7 +414,7 @@
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "5.2.1"
|
||||
#define VERSION "5.2.3"
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
|
||||
+33
-27
@@ -20,7 +20,7 @@
|
||||
#include "lz_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// Dictionary (history buffer)
|
||||
lzma_dict dict;
|
||||
|
||||
@@ -48,7 +48,7 @@ struct lzma_coder_s {
|
||||
size_t size;
|
||||
uint8_t buffer[LZMA_BUFFER_SIZE];
|
||||
} temp;
|
||||
};
|
||||
} lzma_coder;
|
||||
|
||||
|
||||
static void
|
||||
@@ -125,13 +125,15 @@ decode_buffer(lzma_coder *coder,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lz_decode(lzma_coder *coder,
|
||||
lz_decode(void *coder_ptr,
|
||||
const lzma_allocator *allocator lzma_attribute((__unused__)),
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
lzma_action action)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
if (coder->next.code == NULL)
|
||||
return decode_buffer(coder, in, in_pos, in_size,
|
||||
out, out_pos, out_size);
|
||||
@@ -184,8 +186,10 @@ lz_decode(lzma_coder *coder,
|
||||
|
||||
|
||||
static void
|
||||
lz_decoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
lz_decoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder->dict.buf, allocator);
|
||||
|
||||
@@ -207,24 +211,26 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lzma_lz_options *lz_options))
|
||||
{
|
||||
// Allocate the base structure if it isn't already allocated.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &lz_decode;
|
||||
next->end = &lz_decoder_end;
|
||||
|
||||
next->coder->dict.buf = NULL;
|
||||
next->coder->dict.size = 0;
|
||||
next->coder->lz = LZMA_LZ_DECODER_INIT;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->dict.buf = NULL;
|
||||
coder->dict.size = 0;
|
||||
coder->lz = LZMA_LZ_DECODER_INIT;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Allocate and initialize the LZ-based decoder. It will also give
|
||||
// us the dictionary size.
|
||||
lzma_lz_options lz_options;
|
||||
return_if_error(lz_init(&next->coder->lz, allocator,
|
||||
return_if_error(lz_init(&coder->lz, allocator,
|
||||
filters[0].options, &lz_options));
|
||||
|
||||
// If the dictionary size is very small, increase it to 4096 bytes.
|
||||
@@ -248,14 +254,14 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15));
|
||||
|
||||
// Allocate and initialize the dictionary.
|
||||
if (next->coder->dict.size != lz_options.dict_size) {
|
||||
lzma_free(next->coder->dict.buf, allocator);
|
||||
next->coder->dict.buf
|
||||
if (coder->dict.size != lz_options.dict_size) {
|
||||
lzma_free(coder->dict.buf, allocator);
|
||||
coder->dict.buf
|
||||
= lzma_alloc(lz_options.dict_size, allocator);
|
||||
if (next->coder->dict.buf == NULL)
|
||||
if (coder->dict.buf == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder->dict.size = lz_options.dict_size;
|
||||
coder->dict.size = lz_options.dict_size;
|
||||
}
|
||||
|
||||
lz_decoder_reset(next->coder);
|
||||
@@ -268,21 +274,20 @@ lzma_lz_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
const size_t copy_size = my_min(lz_options.preset_dict_size,
|
||||
lz_options.dict_size);
|
||||
const size_t offset = lz_options.preset_dict_size - copy_size;
|
||||
memcpy(next->coder->dict.buf, lz_options.preset_dict + offset,
|
||||
memcpy(coder->dict.buf, lz_options.preset_dict + offset,
|
||||
copy_size);
|
||||
next->coder->dict.pos = copy_size;
|
||||
next->coder->dict.full = copy_size;
|
||||
coder->dict.pos = copy_size;
|
||||
coder->dict.full = copy_size;
|
||||
}
|
||||
|
||||
// Miscellaneous initializations
|
||||
next->coder->next_finished = false;
|
||||
next->coder->this_finished = false;
|
||||
next->coder->temp.pos = 0;
|
||||
next->coder->temp.size = 0;
|
||||
coder->next_finished = false;
|
||||
coder->this_finished = false;
|
||||
coder->temp.pos = 0;
|
||||
coder->temp.size = 0;
|
||||
|
||||
// Initialize the next filter in the chain, if any.
|
||||
return lzma_next_filter_init(&next->coder->next, allocator,
|
||||
filters + 1);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -294,7 +299,8 @@ lzma_lz_decoder_memusage(size_t dictionary_size)
|
||||
|
||||
|
||||
extern void
|
||||
lzma_lz_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
|
||||
lzma_lz_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size);
|
||||
}
|
||||
|
||||
@@ -53,21 +53,20 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
/// Data specific to the LZ-based decoder
|
||||
lzma_coder *coder;
|
||||
void *coder;
|
||||
|
||||
/// Function to decode from in[] to *dict
|
||||
lzma_ret (*code)(lzma_coder *restrict coder,
|
||||
lzma_ret (*code)(void *coder,
|
||||
lzma_dict *restrict dict, const uint8_t *restrict in,
|
||||
size_t *restrict in_pos, size_t in_size);
|
||||
|
||||
void (*reset)(lzma_coder *coder, const void *options);
|
||||
void (*reset)(void *coder, const void *options);
|
||||
|
||||
/// Set the uncompressed size
|
||||
void (*set_uncompressed)(lzma_coder *coder,
|
||||
lzma_vli uncompressed_size);
|
||||
void (*set_uncompressed)(void *coder, lzma_vli uncompressed_size);
|
||||
|
||||
/// Free allocated resources
|
||||
void (*end)(lzma_coder *coder, const lzma_allocator *allocator);
|
||||
void (*end)(void *coder, const lzma_allocator *allocator);
|
||||
|
||||
} lzma_lz_decoder;
|
||||
|
||||
@@ -92,7 +91,7 @@ extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next,
|
||||
extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size);
|
||||
|
||||
extern void lzma_lz_decoder_uncompressed(
|
||||
lzma_coder *coder, lzma_vli uncompressed_size);
|
||||
void *coder, lzma_vli uncompressed_size);
|
||||
|
||||
|
||||
//////////////////////
|
||||
|
||||
+34
-23
@@ -23,7 +23,7 @@
|
||||
#include "memcmplen.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
/// LZ-based encoder e.g. LZMA
|
||||
lzma_lz_encoder lz;
|
||||
|
||||
@@ -32,7 +32,7 @@ struct lzma_coder_s {
|
||||
|
||||
/// Next coder in the chain
|
||||
lzma_next_coder next;
|
||||
};
|
||||
} lzma_coder;
|
||||
|
||||
|
||||
/// \brief Moves the data in the input window to free space for new data
|
||||
@@ -157,12 +157,14 @@ fill_window(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lz_encode(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
lz_encode(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const uint8_t *restrict in, size_t *restrict in_pos,
|
||||
size_t in_size,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size, lzma_action action)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
while (*out_pos < out_size
|
||||
&& (*in_pos < in_size || action != LZMA_RUN)) {
|
||||
// Read more data to coder->mf.buffer if needed.
|
||||
@@ -481,8 +483,10 @@ lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
|
||||
|
||||
|
||||
static void
|
||||
lz_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
lz_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
|
||||
lzma_free(coder->mf.son, allocator);
|
||||
@@ -500,10 +504,12 @@ lz_encoder_end(lzma_coder *coder, const lzma_allocator *allocator)
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lz_encoder_update(lzma_coder *coder, const lzma_allocator *allocator,
|
||||
lz_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_filter *filters_null lzma_attribute((__unused__)),
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
lzma_coder *coder = coder_ptr;
|
||||
|
||||
if (coder->lz.options_update == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
@@ -528,46 +534,51 @@ lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
|
||||
#endif
|
||||
|
||||
// Allocate and initialize the base data structure.
|
||||
if (next->coder == NULL) {
|
||||
next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (next->coder == NULL)
|
||||
lzma_coder *coder = next->coder;
|
||||
if (coder == NULL) {
|
||||
coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
if (coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
next->coder = coder;
|
||||
next->code = &lz_encode;
|
||||
next->end = &lz_encoder_end;
|
||||
next->update = &lz_encoder_update;
|
||||
|
||||
next->coder->lz.coder = NULL;
|
||||
next->coder->lz.code = NULL;
|
||||
next->coder->lz.end = NULL;
|
||||
coder->lz.coder = NULL;
|
||||
coder->lz.code = NULL;
|
||||
coder->lz.end = NULL;
|
||||
|
||||
next->coder->mf.buffer = NULL;
|
||||
next->coder->mf.hash = NULL;
|
||||
next->coder->mf.son = NULL;
|
||||
next->coder->mf.hash_count = 0;
|
||||
next->coder->mf.sons_count = 0;
|
||||
// mf.size is initialized to silence Valgrind
|
||||
// when used on optimized binaries (GCC may reorder
|
||||
// code in a way that Valgrind gets unhappy).
|
||||
coder->mf.buffer = NULL;
|
||||
coder->mf.size = 0;
|
||||
coder->mf.hash = NULL;
|
||||
coder->mf.son = NULL;
|
||||
coder->mf.hash_count = 0;
|
||||
coder->mf.sons_count = 0;
|
||||
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
// Initialize the LZ-based encoder.
|
||||
lzma_lz_options lz_options;
|
||||
return_if_error(lz_init(&next->coder->lz, allocator,
|
||||
return_if_error(lz_init(&coder->lz, allocator,
|
||||
filters[0].options, &lz_options));
|
||||
|
||||
// Setup the size information into next->coder->mf and deallocate
|
||||
// Setup the size information into coder->mf and deallocate
|
||||
// old buffers if they have wrong size.
|
||||
if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
|
||||
if (lz_encoder_prepare(&coder->mf, allocator, &lz_options))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
// Allocate new buffers if needed, and do the rest of
|
||||
// the initialization.
|
||||
if (lz_encoder_init(&next->coder->mf, allocator, &lz_options))
|
||||
if (lz_encoder_init(&coder->mf, allocator, &lz_options))
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
// Initialize the next filter in the chain, if any.
|
||||
return lzma_next_filter_init(&next->coder->next, allocator,
|
||||
filters + 1);
|
||||
return lzma_next_filter_init(&coder->next, allocator, filters + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -191,19 +191,18 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
/// Data specific to the LZ-based encoder
|
||||
lzma_coder *coder;
|
||||
void *coder;
|
||||
|
||||
/// Function to encode from *dict to out[]
|
||||
lzma_ret (*code)(lzma_coder *restrict coder,
|
||||
lzma_ret (*code)(void *coder,
|
||||
lzma_mf *restrict mf, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size);
|
||||
|
||||
/// Free allocated resources
|
||||
void (*end)(lzma_coder *coder, const lzma_allocator *allocator);
|
||||
void (*end)(void *coder, const lzma_allocator *allocator);
|
||||
|
||||
/// Update the options in the middle of the encoding.
|
||||
lzma_ret (*options_update)(lzma_coder *coder,
|
||||
const lzma_filter *filter);
|
||||
lzma_ret (*options_update)(void *coder, const lzma_filter *filter);
|
||||
|
||||
} lzma_lz_encoder;
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ typedef struct {
|
||||
} lzma_length_decoder;
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
typedef struct {
|
||||
///////////////////
|
||||
// Probabilities //
|
||||
///////////////////
|
||||
@@ -277,14 +277,16 @@ struct lzma_coder_s {
|
||||
/// If decoding a literal: match byte.
|
||||
/// If decoding a match: length of the match.
|
||||
uint32_t len;
|
||||
};
|
||||
} lzma_lzma1_decoder;
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
|
||||
lzma_decode(void *coder_ptr, lzma_dict *restrict dictptr,
|
||||
const uint8_t *restrict in,
|
||||
size_t *restrict in_pos, size_t in_size)
|
||||
{
|
||||
lzma_lzma1_decoder *restrict coder = coder_ptr;
|
||||
|
||||
////////////////////
|
||||
// Initialization //
|
||||
////////////////////
|
||||
@@ -840,23 +842,17 @@ out:
|
||||
|
||||
|
||||
static void
|
||||
lzma_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
|
||||
lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
|
||||
{
|
||||
lzma_lzma1_decoder *coder = coder_ptr;
|
||||
coder->uncompressed_size = uncompressed_size;
|
||||
}
|
||||
|
||||
/*
|
||||
extern void
|
||||
lzma_lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
|
||||
{
|
||||
// This is hack.
|
||||
(*(lzma_coder **)(coder))->uncompressed_size = uncompressed_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
lzma_decoder_reset(lzma_coder *coder, const void *opt)
|
||||
lzma_decoder_reset(void *coder_ptr, const void *opt)
|
||||
{
|
||||
lzma_lzma1_decoder *coder = coder_ptr;
|
||||
const lzma_options_lzma *options = opt;
|
||||
|
||||
// NOTE: We assume that lc/lp/pb are valid since they were
|
||||
@@ -941,7 +937,7 @@ lzma_lzma_decoder_create(lzma_lz_decoder *lz, const lzma_allocator *allocator,
|
||||
const void *opt, lzma_lz_options *lz_options)
|
||||
{
|
||||
if (lz->coder == NULL) {
|
||||
lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
lz->coder = lzma_alloc(sizeof(lzma_lzma1_decoder), allocator);
|
||||
if (lz->coder == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
@@ -1014,7 +1010,8 @@ extern uint64_t
|
||||
lzma_lzma_decoder_memusage_nocheck(const void *options)
|
||||
{
|
||||
const lzma_options_lzma *const opt = options;
|
||||
return sizeof(lzma_coder) + lzma_lz_decoder_memusage(opt->dict_size);
|
||||
return sizeof(lzma_lzma1_decoder)
|
||||
+ lzma_lz_decoder_memusage(opt->dict_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ literal_matched(lzma_range_encoder *rc, probability *subcoder,
|
||||
|
||||
|
||||
static inline void
|
||||
literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
|
||||
literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position)
|
||||
{
|
||||
// Locate the literal byte to be encoded and the subcoder.
|
||||
const uint8_t cur_byte = mf->buffer[
|
||||
@@ -140,7 +140,7 @@ length(lzma_range_encoder *rc, lzma_length_encoder *lc,
|
||||
///////////
|
||||
|
||||
static inline void
|
||||
match(lzma_coder *coder, const uint32_t pos_state,
|
||||
match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
|
||||
const uint32_t distance, const uint32_t len)
|
||||
{
|
||||
update_match(coder->state);
|
||||
@@ -187,7 +187,7 @@ match(lzma_coder *coder, const uint32_t pos_state,
|
||||
////////////////////
|
||||
|
||||
static inline void
|
||||
rep_match(lzma_coder *coder, const uint32_t pos_state,
|
||||
rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state,
|
||||
const uint32_t rep, const uint32_t len)
|
||||
{
|
||||
if (rep == 0) {
|
||||
@@ -231,7 +231,7 @@ rep_match(lzma_coder *coder, const uint32_t pos_state,
|
||||
//////////
|
||||
|
||||
static void
|
||||
encode_symbol(lzma_coder *coder, lzma_mf *mf,
|
||||
encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf,
|
||||
uint32_t back, uint32_t len, uint32_t position)
|
||||
{
|
||||
const uint32_t pos_state = position & coder->pos_mask;
|
||||
@@ -265,7 +265,7 @@ encode_symbol(lzma_coder *coder, lzma_mf *mf,
|
||||
|
||||
|
||||
static bool
|
||||
encode_init(lzma_coder *coder, lzma_mf *mf)
|
||||
encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf)
|
||||
{
|
||||
assert(mf_position(mf) == 0);
|
||||
|
||||
@@ -293,7 +293,7 @@ encode_init(lzma_coder *coder, lzma_mf *mf)
|
||||
|
||||
|
||||
static void
|
||||
encode_eopm(lzma_coder *coder, uint32_t position)
|
||||
encode_eopm(lzma_lzma1_encoder *coder, uint32_t position)
|
||||
{
|
||||
const uint32_t pos_state = position & coder->pos_mask;
|
||||
rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1);
|
||||
@@ -309,7 +309,7 @@ encode_eopm(lzma_coder *coder, uint32_t position)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size, uint32_t limit)
|
||||
{
|
||||
@@ -402,7 +402,7 @@ lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
|
||||
static lzma_ret
|
||||
lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_encode(void *coder, lzma_mf *restrict mf,
|
||||
uint8_t *restrict out, size_t *restrict out_pos,
|
||||
size_t out_size)
|
||||
{
|
||||
@@ -473,7 +473,8 @@ length_encoder_reset(lzma_length_encoder *lencoder,
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
|
||||
lzma_lzma_encoder_reset(lzma_lzma1_encoder *coder,
|
||||
const lzma_options_lzma *options)
|
||||
{
|
||||
if (!is_options_valid(options))
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
@@ -545,18 +546,18 @@ lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_lzma_encoder_create(lzma_coder **coder_ptr,
|
||||
lzma_lzma_encoder_create(void **coder_ptr,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_options_lzma *options, lzma_lz_options *lz_options)
|
||||
{
|
||||
// Allocate lzma_coder if it wasn't already allocated.
|
||||
// Allocate lzma_lzma1_encoder if it wasn't already allocated.
|
||||
if (*coder_ptr == NULL) {
|
||||
*coder_ptr = lzma_alloc(sizeof(lzma_coder), allocator);
|
||||
*coder_ptr = lzma_alloc(sizeof(lzma_lzma1_encoder), allocator);
|
||||
if (*coder_ptr == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
}
|
||||
|
||||
lzma_coder *coder = *coder_ptr;
|
||||
lzma_lzma1_encoder *coder = *coder_ptr;
|
||||
|
||||
// Set compression mode. We haven't validates the options yet,
|
||||
// but it's OK here, since nothing bad happens with invalid
|
||||
@@ -636,7 +637,7 @@ lzma_lzma_encoder_memusage(const void *options)
|
||||
if (lz_memusage == UINT64_MAX)
|
||||
return UINT64_MAX;
|
||||
|
||||
return (uint64_t)(sizeof(lzma_coder)) + lz_memusage;
|
||||
return (uint64_t)(sizeof(lzma_lzma1_encoder)) + lz_memusage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
typedef struct lzma_lzma1_encoder_s lzma_lzma1_encoder;
|
||||
|
||||
|
||||
extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next,
|
||||
const lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
@@ -36,16 +39,16 @@ extern bool lzma_lzma_lclppb_encode(
|
||||
|
||||
/// Initializes raw LZMA encoder; this is used by LZMA2.
|
||||
extern lzma_ret lzma_lzma_encoder_create(
|
||||
lzma_coder **coder_ptr, const lzma_allocator *allocator,
|
||||
void **coder_ptr, const lzma_allocator *allocator,
|
||||
const lzma_options_lzma *options, lzma_lz_options *lz_options);
|
||||
|
||||
|
||||
/// Resets an already initialized LZMA encoder; this is used by LZMA2.
|
||||
extern lzma_ret lzma_lzma_encoder_reset(
|
||||
lzma_coder *coder, const lzma_options_lzma *options);
|
||||
lzma_lzma1_encoder *coder, const lzma_options_lzma *options);
|
||||
|
||||
|
||||
extern lzma_ret lzma_lzma_encode(lzma_coder *restrict coder,
|
||||
extern lzma_ret lzma_lzma_encode(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf, uint8_t *restrict out,
|
||||
size_t *restrict out_pos, size_t out_size,
|
||||
uint32_t read_limit);
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
|
||||
extern void
|
||||
lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma_optimum_fast(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf,
|
||||
uint32_t *restrict back_res, uint32_t *restrict len_res)
|
||||
{
|
||||
const uint32_t nice_len = mf->nice_len;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
////////////
|
||||
|
||||
static uint32_t
|
||||
get_literal_price(const lzma_coder *const coder, const uint32_t pos,
|
||||
get_literal_price(const lzma_lzma1_encoder *const coder, const uint32_t pos,
|
||||
const uint32_t prev_byte, const bool match_mode,
|
||||
uint32_t match_byte, uint32_t symbol)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ get_len_price(const lzma_length_encoder *const lencoder,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_short_rep_price(const lzma_coder *const coder,
|
||||
get_short_rep_price(const lzma_lzma1_encoder *const coder,
|
||||
const lzma_lzma_state state, const uint32_t pos_state)
|
||||
{
|
||||
return rc_bit_0_price(coder->is_rep0[state])
|
||||
@@ -74,7 +74,7 @@ get_short_rep_price(const lzma_coder *const coder,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
get_pure_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
|
||||
const lzma_lzma_state state, uint32_t pos_state)
|
||||
{
|
||||
uint32_t price;
|
||||
@@ -99,7 +99,7 @@ get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
get_rep_price(const lzma_lzma1_encoder *const coder, const uint32_t rep_index,
|
||||
const uint32_t len, const lzma_lzma_state state,
|
||||
const uint32_t pos_state)
|
||||
{
|
||||
@@ -109,7 +109,7 @@ get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
get_dist_len_price(const lzma_coder *const coder, const uint32_t dist,
|
||||
get_dist_len_price(const lzma_lzma1_encoder *const coder, const uint32_t dist,
|
||||
const uint32_t len, const uint32_t pos_state)
|
||||
{
|
||||
const uint32_t dist_state = get_dist_state(len);
|
||||
@@ -130,7 +130,7 @@ get_dist_len_price(const lzma_coder *const coder, const uint32_t dist,
|
||||
|
||||
|
||||
static void
|
||||
fill_dist_prices(lzma_coder *coder)
|
||||
fill_dist_prices(lzma_lzma1_encoder *coder)
|
||||
{
|
||||
for (uint32_t dist_state = 0; dist_state < DIST_STATES; ++dist_state) {
|
||||
|
||||
@@ -185,7 +185,7 @@ fill_dist_prices(lzma_coder *coder)
|
||||
|
||||
|
||||
static void
|
||||
fill_align_prices(lzma_coder *coder)
|
||||
fill_align_prices(lzma_lzma1_encoder *coder)
|
||||
{
|
||||
for (uint32_t i = 0; i < ALIGN_SIZE; ++i)
|
||||
coder->align_prices[i] = rc_bittree_reverse_price(
|
||||
@@ -221,7 +221,7 @@ make_short_rep(lzma_optimal *optimal)
|
||||
|
||||
|
||||
static void
|
||||
backward(lzma_coder *restrict coder, uint32_t *restrict len_res,
|
||||
backward(lzma_lzma1_encoder *restrict coder, uint32_t *restrict len_res,
|
||||
uint32_t *restrict back_res, uint32_t cur)
|
||||
{
|
||||
coder->opts_end_index = cur;
|
||||
@@ -269,7 +269,7 @@ backward(lzma_coder *restrict coder, uint32_t *restrict len_res,
|
||||
//////////
|
||||
|
||||
static inline uint32_t
|
||||
helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
helper1(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf,
|
||||
uint32_t *restrict back_res, uint32_t *restrict len_res,
|
||||
uint32_t position)
|
||||
{
|
||||
@@ -441,7 +441,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
helper2(lzma_lzma1_encoder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
uint32_t len_end, uint32_t position, const uint32_t cur,
|
||||
const uint32_t nice_len, const uint32_t buf_avail_full)
|
||||
{
|
||||
@@ -797,7 +797,8 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
|
||||
|
||||
|
||||
extern void
|
||||
lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
|
||||
lzma_lzma_optimum_normal(lzma_lzma1_encoder *restrict coder,
|
||||
lzma_mf *restrict mf,
|
||||
uint32_t *restrict back_res, uint32_t *restrict len_res,
|
||||
uint32_t position)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//
|
||||
/// \file lzma_encoder_presets.c
|
||||
/// \brief Encoder presets
|
||||
/// \note xz needs this even when only decoding is enabled.
|
||||
//
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
@@ -32,7 +33,7 @@ lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
|
||||
|
||||
static const uint8_t dict_pow2[]
|
||||
= { 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 };
|
||||
options->dict_size = UINT32_C(1) << dict_pow2[level];
|
||||
options->dict_size = UINT32_C(1) << dict_pow2[level];
|
||||
|
||||
if (level <= 3) {
|
||||
options->mode = LZMA_MODE_FAST;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user