moved mojosetup to submodule; synchronized with updated mojosetup version [ci skip]
This commit is contained in:
parent
48d0d2afbf
commit
41baf43bf5
|
@ -39,6 +39,7 @@ $RECYCLE.BIN/
|
|||
*.tar
|
||||
*.zip
|
||||
*.bz2
|
||||
*.tar.xz
|
||||
|
||||
## Logs and databases
|
||||
*.log
|
||||
|
|
|
@ -4,3 +4,6 @@
|
|||
[submodule "source/masterserver"]
|
||||
path = source/masterserver
|
||||
url = https://github.com/MegaGlest/megaglest-masterserver.git
|
||||
[submodule "mk/linux/tools-for-standalone-client/installer/mojosetup"]
|
||||
path = mk/linux/tools-for-standalone-client/installer/mojosetup
|
||||
url = https://github.com/MegaGlest-Community/mojosetup-fork.git
|
||||
|
|
|
@ -66,10 +66,10 @@ echo
|
|||
echo '===== Updating Linux Installer ======'
|
||||
# local GAME_VERSION = "x.x.x";
|
||||
echo 'Linux Installer version # before:'
|
||||
grep -E '^local GAME_VERSION = "[^"]*";$' mojosetup/megaglest-installer/scripts/config.lua
|
||||
sed -i 's/^local GAME_VERSION = "[^"]*";$/local GAME_VERSION = "'$CURRENT_VERSION'";/' mojosetup/megaglest-installer/scripts/config.lua
|
||||
grep -E '^local GAME_VERSION = "[^"]*";$' tools-for-standalone-client/installer/scripts/config.lua
|
||||
sed -i 's/^local GAME_VERSION = "[^"]*";$/local GAME_VERSION = "'$CURRENT_VERSION'";/' tools-for-standalone-client/installer/scripts/config.lua
|
||||
echo 'Linux Installer version # after:'
|
||||
grep -E '^local GAME_VERSION = "[^"]*";$' mojosetup/megaglest-installer/scripts/config.lua
|
||||
grep -E '^local GAME_VERSION = "[^"]*";$' tools-for-standalone-client/installer/scripts/config.lua
|
||||
echo
|
||||
echo '===== Updating Windows Installer ======'
|
||||
# !define APVER 3.6.0
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/build
|
||||
/cmake-build
|
|
@ -1,846 +0,0 @@
|
|||
# MojoSetup; a portable, flexible installation application.
|
||||
#
|
||||
# Please see the file LICENSE.txt in the source's root directory.
|
||||
#
|
||||
# This file written by Ryan C. Gordon.
|
||||
|
||||
|
||||
|
||||
# The "BINARY SIZE +=" comments note about how much bulk, in kilobytes, a
|
||||
# given option adds to the binary on x86 Linux (built with gcc 3.3.6
|
||||
# MinSizeRel options and stripped, uncompressed). These numbers will vary,
|
||||
# and even on the original test system, become incorrect over time.
|
||||
# Only choose options you want/need to squeeze every byte off the download.
|
||||
|
||||
|
||||
# !!! FIXME: this is stupid.
|
||||
IF(NOT BEOS)
|
||||
IF(APPLE)
|
||||
PROJECT(MojoSetup)
|
||||
ELSE(APPLE)
|
||||
PROJECT(MojoSetup C)
|
||||
ENDIF(APPLE)
|
||||
ELSE(NOT BEOS)
|
||||
PROJECT(MojoSetup CXX)
|
||||
ENDIF(NOT BEOS)
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.4)
|
||||
|
||||
# !!! FIXME: correct this to new policy and bump minimum cmake requirement.
|
||||
IF(COMMAND CMAKE_POLICY)
|
||||
# Use old policy when it comes to escaping macros,
|
||||
# Specifically the one in quotes below.
|
||||
CMAKE_POLICY(SET CMP0005 OLD)
|
||||
ENDIF(COMMAND CMAKE_POLICY)
|
||||
|
||||
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND hg tip --template hg-{rev}:{node|short}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE HGVERSION_RC
|
||||
OUTPUT_VARIABLE MOJOSETUP_VERSION
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
IF(HGVERSION_RC)
|
||||
SET(MOJOSETUP_VERSION "???")
|
||||
ENDIF(HGVERSION_RC)
|
||||
|
||||
# !!! FIXME: ditch this when Gary's curses patches go into a formal CMake
|
||||
# !!! FIXME: release, and just bump the minimum required version to it.
|
||||
# Search our own cmakemodules first.
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/misc")
|
||||
|
||||
# I hate that they define "WIN32" ... we're about to move to Win64...I hope!
|
||||
IF(WIN32 AND NOT WINDOWS)
|
||||
SET(WINDOWS TRUE)
|
||||
ENDIF(WIN32 AND NOT WINDOWS)
|
||||
|
||||
# Bleh, let's do it for "APPLE" too.
|
||||
IF(APPLE AND NOT MACOSX)
|
||||
SET(MACOSX TRUE)
|
||||
ENDIF(APPLE AND NOT MACOSX)
|
||||
|
||||
# And this might be wrong...
|
||||
IF (CMAKE_SYSTEM MATCHES OS2)
|
||||
SET(OS2 TRUE)
|
||||
ENDIF (CMAKE_SYSTEM MATCHES OS2)
|
||||
|
||||
IF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
SET(SOLARIS TRUE)
|
||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
|
||||
INCLUDE(CheckIncludeFile)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
INCLUDE(TestBigEndian)
|
||||
|
||||
# See if C99 "restrict" keyword is available to us.
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"int test_restrict(const char * restrict ptr); int main(void) { return 0; }"
|
||||
MOJOSETUP_HAVE_RESTRICT_KEYWORD
|
||||
)
|
||||
IF(NOT MOJOSETUP_HAVE_RESTRICT_KEYWORD)
|
||||
# See if __restrict__ keyword is available to us.
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"int test_restrict(const char * __restrict__ ptr); int main(void) { return 0; }"
|
||||
MOJOSETUP_HAVE_GNU_RESTRICT_KEYWORD
|
||||
)
|
||||
#IF(MOJOSETUP_HAVE_GNU_RESTRICT_KEYWORD)
|
||||
# ADD_DEFINITIONS(-Drestrict=__restrict__)
|
||||
#ELSE(MOJOSETUP_HAVE_GNU_RESTRICT_KEYWORD)
|
||||
ADD_DEFINITIONS("-Drestrict=\"\"")
|
||||
#ENDIF(MOJOSETUP_HAVE_GNU_RESTRICT_KEYWORD)
|
||||
ENDIF(NOT MOJOSETUP_HAVE_RESTRICT_KEYWORD)
|
||||
|
||||
ADD_DEFINITIONS(-D__MOJOSETUP__=1)
|
||||
ADD_DEFINITIONS(-DAPPID=mojosetup)
|
||||
ADD_DEFINITIONS(-DAPPREV="${MOJOSETUP_VERSION}")
|
||||
ADD_DEFINITIONS(-D_REENTRANT)
|
||||
ADD_DEFINITIONS(-D_THREAD_SAFE)
|
||||
|
||||
INCLUDE_DIRECTORIES(.)
|
||||
INCLUDE_DIRECTORIES(lua/src)
|
||||
|
||||
IF(WINDOWS)
|
||||
ADD_DEFINITIONS(-DPLATFORM_WINDOWS=1)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
|
||||
SET(USES_WINMAIN WIN32)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} shell32)
|
||||
ENDIF(WINDOWS)
|
||||
|
||||
IF(MACOSX)
|
||||
ADD_DEFINITIONS(-DPLATFORM_MACOSX=1)
|
||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
||||
ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} "-mmacosx-version-min=10.2")
|
||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} "-framework Carbon")
|
||||
ENDIF(MACOSX)
|
||||
|
||||
IF(BEOS)
|
||||
ADD_DEFINITIONS(-DPLATFORM_BEOS=1)
|
||||
ENDIF(BEOS)
|
||||
|
||||
IF(UNIX)
|
||||
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
|
||||
ADD_DEFINITIONS(-DPLATFORM_UNIX=1)
|
||||
ADD_DEFINITIONS(-DLUA_USE_MKSTEMP=1) # as opposed to tmpnam(), yuck!
|
||||
# No _setjmp/_longjmp in BeOS 5 (or Haiku, at the moment).
|
||||
IF(NOT BEOS)
|
||||
ADD_DEFINITIONS(-DLUA_USE_ULONGJMP=1)
|
||||
ENDIF(NOT BEOS)
|
||||
ENDIF(UNIX)
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
ADD_DEFINITIONS(-pipe -Wall -fsigned-char)
|
||||
|
||||
# See if -fvisibility=hidden is available to us.
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#if ((defined(__GNUC__)) && (__GNUC__ >= 4))
|
||||
int main(int argc, char **argv) { int is_gcc4 = 1; return 0; }
|
||||
#else
|
||||
#error This is not gcc4.
|
||||
#endif
|
||||
" MOJOSETUP_IS_GCC4)
|
||||
|
||||
IF(MOJOSETUP_IS_GCC4)
|
||||
IF(NOT OS2 AND NOT SOLARIS) # Not supported on OS/2 or Solaris.
|
||||
ADD_DEFINITIONS(-fvisibility=hidden)
|
||||
ENDIF(NOT OS2 AND NOT SOLARIS)
|
||||
ENDIF(MOJOSETUP_IS_GCC4)
|
||||
|
||||
# See if -fno-stack-protector is available to us.
|
||||
# It doesn't seem to work well, and it adds bulk to the binary.
|
||||
CHECK_C_COMPILER_FLAG("-fno-stack-protector" MOJOSETUP_GCC_HAS_STACKPROT)
|
||||
IF(MOJOSETUP_GCC_HAS_STACKPROT)
|
||||
ADD_DEFINITIONS(-fno-stack-protector)
|
||||
ENDIF(MOJOSETUP_GCC_HAS_STACKPROT)
|
||||
|
||||
# !!! FIXME: probably not safe long-term.
|
||||
# CMake mailing list had this hack for getting rid of -rdynamic:
|
||||
# http://public.kitware.com/pipermail/cmake/2006-July/010404.html
|
||||
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
|
||||
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
|
||||
# Don't use -rpath.
|
||||
SET(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
IF(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
|
||||
ADD_DEFINITIONS(-erroff=E_EMPTY_TRANSLATION_UNIT)
|
||||
ADD_DEFINITIONS(-xldscope=hidden)
|
||||
ENDIF(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
|
||||
|
||||
|
||||
|
||||
TEST_BIG_ENDIAN(MOJOSETUP_IS_BIGENDIAN)
|
||||
IF(MOJOSETUP_IS_BIGENDIAN)
|
||||
ADD_DEFINITIONS(-DPLATFORM_BIGENDIAN=1)
|
||||
ELSE(MOJOSETUP_IS_BIGENDIAN)
|
||||
ADD_DEFINITIONS(-DPLATFORM_LITTLEENDIAN=1)
|
||||
ENDIF(MOJOSETUP_IS_BIGENDIAN)
|
||||
|
||||
SET(BZLIB_DIR bzip2)
|
||||
SET(BZLIB_SRCS
|
||||
${BZLIB_DIR}/blocksort.c
|
||||
${BZLIB_DIR}/huffman.c
|
||||
${BZLIB_DIR}/crctable.c
|
||||
${BZLIB_DIR}/randtable.c
|
||||
${BZLIB_DIR}/compress.c
|
||||
${BZLIB_DIR}/decompress.c
|
||||
${BZLIB_DIR}/bzlib.c
|
||||
)
|
||||
|
||||
SET(LIBLZMA_DIR liblzma)
|
||||
SET(LIBLZMA_SRCS
|
||||
${LIBLZMA_DIR}/check/check.c
|
||||
${LIBLZMA_DIR}/common/block_buffer_decoder.c
|
||||
${LIBLZMA_DIR}/common/block_decoder.c
|
||||
${LIBLZMA_DIR}/common/block_header_decoder.c
|
||||
${LIBLZMA_DIR}/common/block_util.c
|
||||
${LIBLZMA_DIR}/common/common.c
|
||||
${LIBLZMA_DIR}/common/easy_decoder_memusage.c
|
||||
${LIBLZMA_DIR}/common/easy_preset.c
|
||||
${LIBLZMA_DIR}/common/filter_buffer_decoder.c
|
||||
${LIBLZMA_DIR}/common/filter_common.c
|
||||
${LIBLZMA_DIR}/common/filter_decoder.c
|
||||
${LIBLZMA_DIR}/common/filter_flags_decoder.c
|
||||
${LIBLZMA_DIR}/common/index.c
|
||||
${LIBLZMA_DIR}/common/index_decoder.c
|
||||
${LIBLZMA_DIR}/common/index_hash.c
|
||||
${LIBLZMA_DIR}/common/stream_decoder.c
|
||||
${LIBLZMA_DIR}/common/stream_flags_common.c
|
||||
${LIBLZMA_DIR}/common/stream_flags_decoder.c
|
||||
${LIBLZMA_DIR}/common/vli_decoder.c
|
||||
${LIBLZMA_DIR}/common/vli_size.c
|
||||
${LIBLZMA_DIR}/delta/delta_common.c
|
||||
${LIBLZMA_DIR}/delta/delta_decoder.c
|
||||
${LIBLZMA_DIR}/lz/lz_decoder.c
|
||||
${LIBLZMA_DIR}/lzma/lzma2_decoder.c
|
||||
${LIBLZMA_DIR}/lzma/lzma_decoder.c
|
||||
${LIBLZMA_DIR}/lzma/lzma_encoder_presets.c
|
||||
${LIBLZMA_DIR}/simple/arm.c
|
||||
${LIBLZMA_DIR}/simple/armthumb.c
|
||||
${LIBLZMA_DIR}/simple/ia64.c
|
||||
${LIBLZMA_DIR}/simple/powerpc.c
|
||||
${LIBLZMA_DIR}/simple/simple_coder.c
|
||||
${LIBLZMA_DIR}/simple/simple_decoder.c
|
||||
${LIBLZMA_DIR}/simple/sparc.c
|
||||
${LIBLZMA_DIR}/simple/x86.c
|
||||
)
|
||||
|
||||
SET(LIBFETCH_DIR libfetch)
|
||||
SET(LIBFETCH_SRCS
|
||||
${LIBFETCH_DIR}/fetch.c
|
||||
${LIBFETCH_DIR}/common.c
|
||||
${LIBFETCH_DIR}/ftp.c
|
||||
${LIBFETCH_DIR}/http.c
|
||||
)
|
||||
|
||||
SET(LUA_DIR lua)
|
||||
SET(LUA_SRCS
|
||||
${LUA_DIR}/src/lapi.c
|
||||
${LUA_DIR}/src/ldebug.c
|
||||
${LUA_DIR}/src/ldo.c
|
||||
${LUA_DIR}/src/ldump.c
|
||||
${LUA_DIR}/src/lfunc.c
|
||||
${LUA_DIR}/src/lgc.c
|
||||
${LUA_DIR}/src/lmem.c
|
||||
${LUA_DIR}/src/lobject.c
|
||||
${LUA_DIR}/src/lopcodes.c
|
||||
${LUA_DIR}/src/lstate.c
|
||||
${LUA_DIR}/src/lstring.c
|
||||
${LUA_DIR}/src/ltable.c
|
||||
${LUA_DIR}/src/ltm.c
|
||||
${LUA_DIR}/src/lundump.c
|
||||
${LUA_DIR}/src/lvm.c
|
||||
${LUA_DIR}/src/lzio.c
|
||||
${LUA_DIR}/src/lauxlib.c
|
||||
${LUA_DIR}/src/lbaselib.c
|
||||
${LUA_DIR}/src/lstrlib.c
|
||||
${LUA_DIR}/src/ltablib.c
|
||||
${LUA_DIR}/src/lctype.c
|
||||
)
|
||||
|
||||
SET(LUA_PARSER_SRCS
|
||||
${LUA_DIR}/src/lparser.c
|
||||
${LUA_DIR}/src/llex.c
|
||||
${LUA_DIR}/src/lcode.c
|
||||
)
|
||||
|
||||
SET(MOJOSETUP_SRCS
|
||||
buildver.c
|
||||
mojosetup.c
|
||||
gui.c
|
||||
fileio.c
|
||||
archive_zip.c
|
||||
archive_tar.c
|
||||
archive_uz2.c
|
||||
archive_pck.c
|
||||
archive_pkg.c
|
||||
checksum_crc32.c
|
||||
checksum_md5.c
|
||||
checksum_sha1.c
|
||||
platform_unix.c
|
||||
platform_windows.c
|
||||
lua_glue.c
|
||||
${LUA_SRCS}
|
||||
)
|
||||
|
||||
# Have to separate this, so CMake doesn't try to link in C++ support on other
|
||||
# platforms.
|
||||
IF(BEOS)
|
||||
SET(MOJOSETUP_SRCS ${MOJOSETUP_SRCS} platform_beos.cpp)
|
||||
ENDIF(BEOS)
|
||||
|
||||
SET(MOJOLUAC_SRCS
|
||||
${LUA_SRCS}
|
||||
${LUA_PARSER_SRCS}
|
||||
${LUA_DIR}/src/luac.c
|
||||
${LUA_DIR}/src/linit.c
|
||||
${LUA_DIR}/src/lctype.c
|
||||
${LUA_DIR}/src/ldblib.c
|
||||
${LUA_DIR}/src/liolib.c
|
||||
${LUA_DIR}/src/lmathlib.c
|
||||
${LUA_DIR}/src/loslib.c
|
||||
${LUA_DIR}/src/lbitlib.c
|
||||
${LUA_DIR}/src/lcorolib.c
|
||||
${LUA_DIR}/src/loadlib.c
|
||||
)
|
||||
|
||||
SET(STBIMAGE_SRCS
|
||||
stb_image.c
|
||||
)
|
||||
|
||||
# Disabling the parser cuts the Lua binary bits by about 35%, plus .luac files
|
||||
# are almost always smaller than the original scripts. The downside is you
|
||||
# (and end users in the field) can't just tweak a script without recompiling
|
||||
# it, but even that's not an unclimbable obstacle.
|
||||
# In reality, you probably want to keep the parser, though, unless you REALLY
|
||||
# must save every single byte in the download.
|
||||
# YOU NEED THE PARSER IF YOU WANT MANIFESTS WRITTEN OUT.
|
||||
# YOU NEED THE PARSER IF YOU WANT THE UNINSTALLER TO WORK.
|
||||
# DON'T DISABLE THIS NOW IF YOU DON'T ABSOLUTELY HAVE TO.
|
||||
# BINARY SIZE += 19
|
||||
OPTION(MOJOSETUP_LUA_PARSER "Bigger binary but scripts don't need to be compiled." TRUE)
|
||||
IF(MOJOSETUP_LUA_PARSER)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_PARSER_SRCS})
|
||||
ELSE(MOJOSETUP_LUA_PARSER)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/etc/noparser.c)
|
||||
ADD_DEFINITIONS(-DDISABLE_LUA_PARSER=1)
|
||||
ENDIF(MOJOSETUP_LUA_PARSER)
|
||||
|
||||
|
||||
# Kludge for Linux x86/amd64 bins...
|
||||
IF(UNIX AND NOT MACOSX) # Just use Mach-O Universal/"fat" binaries on OS X.
|
||||
OPTION(MOJOSETUP_MULTIARCH "Allow multiarch hack." FALSE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_MULTIARCH)
|
||||
IF(MOJOSETUP_MULTIARCH)
|
||||
ADD_DEFINITIONS(-DSUPPORT_MULTIARCH=1)
|
||||
ENDIF(MOJOSETUP_MULTIARCH)
|
||||
ENDIF(UNIX AND NOT MACOSX)
|
||||
|
||||
|
||||
# Optional bits of the Lua runtime library...
|
||||
|
||||
# BINARY SIZE += 4.5
|
||||
OPTION(MOJOSETUP_LUALIB_IO "Add Lua 'io' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_IO)
|
||||
IF(MOJOSETUP_LUALIB_IO)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_IO=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/liolib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_IO)
|
||||
|
||||
# BINARY SIZE += 2.5
|
||||
OPTION(MOJOSETUP_LUALIB_OS "Add Lua 'os' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_OS)
|
||||
IF(MOJOSETUP_LUALIB_OS)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_OS=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/loslib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_OS)
|
||||
|
||||
# BINARY SIZE += 3.5
|
||||
OPTION(MOJOSETUP_LUALIB_MATH "Add Lua 'math' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_MATH)
|
||||
IF(MOJOSETUP_LUALIB_MATH)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_MATH=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/lmathlib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_MATH)
|
||||
|
||||
# BINARY SIZE += 3.5
|
||||
OPTION(MOJOSETUP_LUALIB_DB "Add Lua 'db' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_DB)
|
||||
IF(MOJOSETUP_LUALIB_DB)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_DB=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/ldblib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_DB)
|
||||
|
||||
# BINARY SIZE += 4
|
||||
OPTION(MOJOSETUP_LUALIB_PACKAGE "Add Lua 'package' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_PACKAGE)
|
||||
IF(MOJOSETUP_LUALIB_PACKAGE)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_PACKAGE=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/loadlib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_PACKAGE)
|
||||
|
||||
# BINARY SIZE += ?
|
||||
OPTION(MOJOSETUP_LUALIB_BIT "Add Lua 'bit' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_BIT)
|
||||
IF(MOJOSETUP_LUALIB_BIT)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_BIT=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/lbitlib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_BIT)
|
||||
|
||||
# BINARY SIZE += ?
|
||||
OPTION(MOJOSETUP_LUALIB_CORO "Add Lua 'coro' library" TRUE)
|
||||
MARK_AS_ADVANCED(MOJOSETUP_LUALIB_CORO)
|
||||
IF(MOJOSETUP_LUALIB_CORO)
|
||||
ADD_DEFINITIONS(-DSUPPORT_LUALIB_CORO=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LUA_DIR}/src/lcorolib.c)
|
||||
ENDIF(MOJOSETUP_LUALIB_CORO)
|
||||
|
||||
|
||||
# Checksums...
|
||||
|
||||
# BINARY SIZE += !!! FIXME: check this.
|
||||
OPTION(MOJOSETUP_CHECKSUM_CRC32 "Enable CRC-32 checksum support" TRUE)
|
||||
IF(MOJOSETUP_CHECKSUM_CRC32)
|
||||
ADD_DEFINITIONS(-DSUPPORT_CRC32=1)
|
||||
ENDIF(MOJOSETUP_CHECKSUM_CRC32)
|
||||
|
||||
# BINARY SIZE += !!! FIXME: check this.
|
||||
OPTION(MOJOSETUP_CHECKSUM_MD5 "Enable MD5 checksum support" TRUE)
|
||||
IF(MOJOSETUP_CHECKSUM_MD5)
|
||||
ADD_DEFINITIONS(-DSUPPORT_MD5=1)
|
||||
ENDIF(MOJOSETUP_CHECKSUM_MD5)
|
||||
|
||||
# BINARY SIZE += !!! FIXME: check this.
|
||||
OPTION(MOJOSETUP_CHECKSUM_SHA1 "Enable SHA-1 checksum support" TRUE)
|
||||
IF(MOJOSETUP_CHECKSUM_SHA1)
|
||||
ADD_DEFINITIONS(-DSUPPORT_SHA1=1)
|
||||
ENDIF(MOJOSETUP_CHECKSUM_SHA1)
|
||||
|
||||
|
||||
# GUI plugins...
|
||||
|
||||
MACRO(MOJOSETUP_ADD_LIBRARY _TARGET _SRCS)
|
||||
ADD_LIBRARY(${_TARGET} SHARED ${_SRCS})
|
||||
SET(MOJOSETUP_TARGETS "${MOJOSETUP_TARGETS};${_TARGET}")
|
||||
ENDMACRO(MOJOSETUP_ADD_LIBRARY)
|
||||
|
||||
|
||||
# BINARY SIZE += 2.5
|
||||
OPTION(MOJOSETUP_GUI_STDIO "Enable stdio GUI" TRUE)
|
||||
IF(MOJOSETUP_GUI_STDIO)
|
||||
ADD_DEFINITIONS(-DSUPPORT_GUI_STDIO=1)
|
||||
OPTION(MOJOSETUP_GUI_STDIO_STATIC "Statically link stdio GUI" TRUE)
|
||||
IF(MOJOSETUP_GUI_STDIO_STATIC)
|
||||
ADD_DEFINITIONS(-DGUI_STATIC_LINK_STDIO=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_stdio.c)
|
||||
ELSE(MOJOSETUP_GUI_STDIO_STATIC)
|
||||
MOJOSETUP_ADD_LIBRARY(mojosetupgui_stdio gui_stdio.c)
|
||||
ENDIF(MOJOSETUP_GUI_STDIO_STATIC)
|
||||
ENDIF(MOJOSETUP_GUI_STDIO)
|
||||
|
||||
# BINARY SIZE += !!! FIXME: check this.
|
||||
SET(CURSES_NEED_WIDE TRUE)
|
||||
SET(CURSES_NEED_NCURSES TRUE)
|
||||
FIND_PACKAGE(Curses)
|
||||
IF(CURSES_FOUND)
|
||||
OPTION(MOJOSETUP_GUI_NCURSES "Enable ncurses GUI" TRUE)
|
||||
IF(MOJOSETUP_GUI_NCURSES)
|
||||
ADD_DEFINITIONS(-DSUPPORT_GUI_NCURSES=1)
|
||||
INCLUDE_DIRECTORIES(CURSES_INCLUDE_DIR)
|
||||
|
||||
IF(CURSES_HAVE_NCURSESW_NCURSES_H)
|
||||
ADD_DEFINITIONS(-DHAVE_NCURSESW_NCURSES_H)
|
||||
ELSEIF(CURSES_HAVE_NCURSESW_CURSES_H)
|
||||
ADD_DEFINITIONS(-DHAVE_NCURSESW_CURSES_H)
|
||||
ELSEIF(CURSES_HAVE_NCURSESW_H)
|
||||
ADD_DEFINITIONS(-DHAVE_NCURSESW_H)
|
||||
ENDIF(CURSES_HAVE_NCURSESW_NCURSES_H)
|
||||
|
||||
OPTION(MOJOSETUP_GUI_NCURSES_STATIC "Statically link ncurses GUI" FALSE)
|
||||
IF(MOJOSETUP_GUI_NCURSES_STATIC)
|
||||
ADD_DEFINITIONS(-DGUI_STATIC_LINK_NCURSES=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_ncurses.c)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} ${CURSES_LIBRARIES})
|
||||
ELSE(MOJOSETUP_GUI_NCURSES_STATIC)
|
||||
MOJOSETUP_ADD_LIBRARY(mojosetupgui_ncurses gui_ncurses.c)
|
||||
TARGET_LINK_LIBRARIES(mojosetupgui_ncurses ${CURSES_LIBRARIES})
|
||||
ENDIF(MOJOSETUP_GUI_NCURSES_STATIC)
|
||||
ENDIF(MOJOSETUP_GUI_NCURSES)
|
||||
ENDIF(CURSES_FOUND)
|
||||
|
||||
IF(MACOSX)
|
||||
OPTION(MOJOSETUP_GUI_COCOA "Enable Cocoa GUI" TRUE)
|
||||
IF(MOJOSETUP_GUI_COCOA)
|
||||
ADD_DEFINITIONS(-DSUPPORT_GUI_COCOA=1)
|
||||
OPTION(MOJOSETUP_GUI_COCOA_STATIC "Statically link Cocoa GUI" TRUE)
|
||||
IF(MOJOSETUP_GUI_COCOA_STATIC)
|
||||
ADD_DEFINITIONS(-DGUI_STATIC_LINK_COCOA=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_cocoa.m)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} "-framework Cocoa")
|
||||
ELSE(MOJOSETUP_GUI_COCOA_STATIC)
|
||||
MOJOSETUP_ADD_LIBRARY(mojosetupgui_cocoa gui_cocoa.m)
|
||||
TARGET_LINK_LIBRARIES(mojosetupgui_cocoa
|
||||
"-framework Carbon -framework Cocoa -mmacosx-version-min=10.2"
|
||||
)
|
||||
ENDIF(MOJOSETUP_GUI_COCOA_STATIC)
|
||||
ENDIF(MOJOSETUP_GUI_COCOA)
|
||||
ENDIF(MACOSX)
|
||||
|
||||
IF(UNIX)
|
||||
IF(NOT BEOS)
|
||||
IF(NOT MACOSX)
|
||||
#FIND_PACKAGE(PkgConfig)
|
||||
#PKGCONFIG(libgtk-2.0 LIBGTK_INCLUDE_DIR LIBGTK_LINK_DIR LIBGTK_LINK_FLAGS LIBGTK_CFLAGS)
|
||||
# !!! FIXME
|
||||
SET(LIBGTK_LINK_FLAGS "-lgtk-x11-2.0 -lgdk-x11-2.0 -lgmodule-2.0 -ldl -lgobject-2.0 -lglib-2.0 -lgdk_pixbuf-2.0 -lgio-2.0")
|
||||
SET(LIBGTK_CFLAGS "-DPNG_NO_MMX_CODE `pkg-config --cflags --libs gtk+-2.0` -I/usr/include/atk-1.0 `pkg-config --cflags --libs gdk-2.0` -I/usr/include/cairo -I/usr/include/pango-1.0 `pkg-config --cflags --libs glib-2.0` -I/usr/include/freetype2 -I/usr/include/libpng12")
|
||||
IF(NOT LIBGTK_LINK_FLAGS)
|
||||
MESSAGE(STATUS "Can't find GTK+v2 headers/libraries. Can't build GTK+ GUI.")
|
||||
ELSE(NOT LIBGTK_LINK_FLAGS)
|
||||
OPTION(MOJOSETUP_GUI_GTKPLUS2 "Enable GTK+ 2.0 GUI" TRUE)
|
||||
IF(MOJOSETUP_GUI_GTKPLUS2)
|
||||
ADD_DEFINITIONS(-DSUPPORT_GUI_GTKPLUS2=1)
|
||||
#INCLUDE_DIRECTORIES(${LIBGTK_INCLUDE_DIR})
|
||||
OPTION(MOJOSETUP_GUI_GTKPLUS2_STATIC "Statically link GTK+ GUI" FALSE)
|
||||
IF(MOJOSETUP_GUI_GTKPLUS2_STATIC)
|
||||
ADD_DEFINITIONS(-DGUI_STATIC_LINK_GTKPLUS2=1 ${LIBGTK_CFLAGS})
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_gtkplus2.c)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} ${LIBGTK_LINK_FLAGS})
|
||||
ELSE(MOJOSETUP_GUI_GTKPLUS2_STATIC)
|
||||
MOJOSETUP_ADD_LIBRARY(mojosetupgui_gtkplus2 gui_gtkplus2.c)
|
||||
ADD_DEFINITIONS(${LIBGTK_CFLAGS})
|
||||
TARGET_LINK_LIBRARIES(mojosetupgui_gtkplus2 ${LIBGTK_LINK_FLAGS})
|
||||
ENDIF(MOJOSETUP_GUI_GTKPLUS2_STATIC)
|
||||
ENDIF(MOJOSETUP_GUI_GTKPLUS2)
|
||||
ENDIF(NOT LIBGTK_LINK_FLAGS)
|
||||
ENDIF(NOT MACOSX)
|
||||
ENDIF(NOT BEOS)
|
||||
ENDIF(UNIX)
|
||||
|
||||
# BINARY SIZE += !!! FIXME: check this.
|
||||
OPTION(MOJOSETUP_GUI_WWW "Enable www GUI" FALSE) # !!! FIXME: make TRUE
|
||||
IF(MOJOSETUP_GUI_WWW)
|
||||
ADD_DEFINITIONS(-DSUPPORT_GUI_WWW=1)
|
||||
OPTION(MOJOSETUP_GUI_WWW_STATIC "Statically link www GUI" FALSE)
|
||||
IF(MOJOSETUP_GUI_WWW_STATIC)
|
||||
ADD_DEFINITIONS(-DGUI_STATIC_LINK_WWW=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} gui_www.c)
|
||||
IF(WINDOWS)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} wsock32)
|
||||
ENDIF(WINDOWS)
|
||||
ELSE(MOJOSETUP_GUI_WWW_STATIC)
|
||||
MOJOSETUP_ADD_LIBRARY(mojosetupgui_www gui_www.c)
|
||||
IF(WINDOWS)
|
||||
TARGET_LINK_LIBRARIES(mojosetupgui_www wsock32)
|
||||
ENDIF(WINDOWS)
|
||||
ENDIF(MOJOSETUP_GUI_WWW_STATIC)
|
||||
SET(MOJOSETUP_USES_SOCKETS TRUE)
|
||||
ENDIF(MOJOSETUP_GUI_WWW)
|
||||
|
||||
|
||||
# Archivers...
|
||||
|
||||
# BINARY SIZE += 8
|
||||
OPTION(MOJOSETUP_ARCHIVE_ZIP "Enable ZIP support" TRUE)
|
||||
IF(MOJOSETUP_ARCHIVE_ZIP)
|
||||
ADD_DEFINITIONS(-DSUPPORT_ZIP=1)
|
||||
SET(MOJOSETUP_NEED_ZLIB TRUE)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_ZIP)
|
||||
|
||||
# BINARY SIZE += 2
|
||||
OPTION(MOJOSETUP_ARCHIVE_TAR "Enable TAR support" TRUE)
|
||||
IF(MOJOSETUP_ARCHIVE_TAR)
|
||||
# !!! FIXME: the gzip/bzip2/xz support doesn't require .tar archives now.
|
||||
# !!! FIXME: Maybe not ask here, so the questions look the same everywhere.
|
||||
ADD_DEFINITIONS(-DSUPPORT_TAR=1)
|
||||
OPTION(MOJOSETUP_ARCHIVE_TAR_GZ "Enable TAR.GZ support" TRUE)
|
||||
IF(MOJOSETUP_ARCHIVE_TAR_GZ)
|
||||
SET(MOJOSETUP_INPUT_GZIP TRUE)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_TAR_GZ)
|
||||
|
||||
OPTION(MOJOSETUP_ARCHIVE_TAR_BZ2 "Enable TAR.BZ2 support" TRUE)
|
||||
IF(MOJOSETUP_ARCHIVE_TAR_BZ2)
|
||||
SET(MOJOSETUP_INPUT_BZIP2 TRUE)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_TAR_BZ2)
|
||||
|
||||
OPTION(MOJOSETUP_ARCHIVE_TAR_XZ "Enable TAR.XZ support" TRUE)
|
||||
IF(MOJOSETUP_ARCHIVE_TAR_XZ)
|
||||
SET(MOJOSETUP_INPUT_XZ TRUE)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_TAR_XZ)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_TAR)
|
||||
|
||||
OPTION(MOJOSETUP_ARCHIVE_UZ2 "Enable UZ2 support" FALSE)
|
||||
IF(MOJOSETUP_ARCHIVE_UZ2)
|
||||
ADD_DEFINITIONS(-DSUPPORT_UZ2=1)
|
||||
SET(MOJOSETUP_NEED_ZLIB TRUE)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_UZ2)
|
||||
|
||||
OPTION(MOJOSETUP_ARCHIVE_PCK "Enable PCK support" FALSE)
|
||||
IF(MOJOSETUP_ARCHIVE_PCK)
|
||||
ADD_DEFINITIONS(-DSUPPORT_PCK=1)
|
||||
SET(MOJOSETUP_INPUT_GZIP TRUE)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_PCK)
|
||||
|
||||
OPTION(MOJOSETUP_ARCHIVE_PKG "Enable PKG support" FALSE)
|
||||
IF(MOJOSETUP_ARCHIVE_PKG)
|
||||
ADD_DEFINITIONS(-DSUPPORT_PKG=1)
|
||||
ENDIF(MOJOSETUP_ARCHIVE_PKG)
|
||||
|
||||
# Input decoders...
|
||||
|
||||
# BINARY SIZE += 1.5
|
||||
IF(NOT MOJOSETUP_INPUT_GZIP) # optional if something didn't force it.
|
||||
OPTION(MOJOSETUP_INPUT_GZIP "Enable GZIP support" FALSE)
|
||||
ENDIF(NOT MOJOSETUP_INPUT_GZIP)
|
||||
|
||||
IF(MOJOSETUP_INPUT_GZIP)
|
||||
ADD_DEFINITIONS(-DSUPPORT_GZIP=1)
|
||||
SET(MOJOSETUP_NEED_ZLIB TRUE)
|
||||
ENDIF(MOJOSETUP_INPUT_GZIP)
|
||||
|
||||
# BINARY SIZE += 1.5
|
||||
IF(NOT MOJOSETUP_INPUT_BZIP2) # optional if something didn't force it.
|
||||
OPTION(MOJOSETUP_INPUT_BZIP2 "Enable BZIP2 support" FALSE)
|
||||
ENDIF(NOT MOJOSETUP_INPUT_BZIP2)
|
||||
|
||||
IF(MOJOSETUP_INPUT_BZIP2)
|
||||
ADD_DEFINITIONS(-DSUPPORT_BZIP2=1)
|
||||
ADD_DEFINITIONS(-DBZ_NO_STDIO=1)
|
||||
SET(MOJOSETUP_NEED_BZLIB TRUE)
|
||||
ENDIF(MOJOSETUP_INPUT_BZIP2)
|
||||
|
||||
# BINARY SIZE += ???
|
||||
IF(NOT MOJOSETUP_INPUT_XZ) # optional if something didn't force it.
|
||||
OPTION(MOJOSETUP_INPUT_XZ "Enable XZ support" FALSE)
|
||||
ENDIF(NOT MOJOSETUP_INPUT_XZ)
|
||||
|
||||
IF(MOJOSETUP_INPUT_XZ)
|
||||
ADD_DEFINITIONS(-DSUPPORT_XZ=1)
|
||||
SET(MOJOSETUP_NEED_LIBLZMA TRUE)
|
||||
ENDIF(MOJOSETUP_INPUT_XZ)
|
||||
|
||||
|
||||
# Image decoders for GUIs...
|
||||
|
||||
OPTION(MOJOSETUP_IMAGE_JPG "Enable JPG support" TRUE)
|
||||
IF(MOJOSETUP_IMAGE_JPG)
|
||||
ADD_DEFINITIONS(-DSUPPORT_JPG=1)
|
||||
SET(MOJOSETUP_NEED_STBIMAGE TRUE)
|
||||
ENDIF(MOJOSETUP_IMAGE_JPG)
|
||||
|
||||
OPTION(MOJOSETUP_IMAGE_PNG "Enable PNG support" TRUE)
|
||||
IF(MOJOSETUP_IMAGE_PNG)
|
||||
ADD_DEFINITIONS(-DSUPPORT_PNG=1)
|
||||
SET(MOJOSETUP_NEED_STBIMAGE TRUE)
|
||||
ENDIF(MOJOSETUP_IMAGE_PNG)
|
||||
|
||||
OPTION(MOJOSETUP_IMAGE_TGA "Enable TGA support" FALSE)
|
||||
IF(MOJOSETUP_IMAGE_TGA)
|
||||
ADD_DEFINITIONS(-DSUPPORT_TGA=1)
|
||||
SET(MOJOSETUP_NEED_STBIMAGE TRUE)
|
||||
ENDIF(MOJOSETUP_IMAGE_TGA)
|
||||
|
||||
OPTION(MOJOSETUP_IMAGE_BMP "Enable BMP support" FALSE)
|
||||
IF(MOJOSETUP_IMAGE_BMP)
|
||||
ADD_DEFINITIONS(-DSUPPORT_BMP=1)
|
||||
SET(MOJOSETUP_NEED_STBIMAGE TRUE)
|
||||
ENDIF(MOJOSETUP_IMAGE_BMP)
|
||||
|
||||
OPTION(MOJOSETUP_IMAGE_PSD "Enable PSD support" FALSE)
|
||||
IF(MOJOSETUP_IMAGE_PSD)
|
||||
ADD_DEFINITIONS(-DSUPPORT_PSD=1)
|
||||
SET(MOJOSETUP_NEED_STBIMAGE TRUE)
|
||||
ENDIF(MOJOSETUP_IMAGE_PSD)
|
||||
|
||||
OPTION(MOJOSETUP_IMAGE_HDR "Enable HDR support" FALSE)
|
||||
IF(MOJOSETUP_IMAGE_HDR)
|
||||
ADD_DEFINITIONS(-DSUPPORT_HDR=1)
|
||||
SET(MOJOSETUP_NEED_STBIMAGE TRUE)
|
||||
ENDIF(MOJOSETUP_IMAGE_HDR)
|
||||
|
||||
IF(MOJOSETUP_NEED_STBIMAGE)
|
||||
ADD_DEFINITIONS(-DSUPPORT_STBIMAGE=1)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${STBIMAGE_SRCS})
|
||||
ENDIF(MOJOSETUP_NEED_STBIMAGE)
|
||||
|
||||
|
||||
# Networking...
|
||||
|
||||
# BINARY SIZE += 5 ...plus libfetch
|
||||
OPTION(MOJOSETUP_URL_HTTP "Enable http:// support" TRUE)
|
||||
IF(MOJOSETUP_URL_HTTP)
|
||||
ADD_DEFINITIONS(-DSUPPORT_URL_HTTP=1)
|
||||
SET(MOJOSETUP_NEED_LIBFETCH TRUE)
|
||||
ENDIF(MOJOSETUP_URL_HTTP)
|
||||
|
||||
# BINARY SIZE += 9 ...plus libfetch
|
||||
OPTION(MOJOSETUP_URL_FTP "Enable ftp:// support" TRUE)
|
||||
IF(MOJOSETUP_URL_FTP)
|
||||
ADD_DEFINITIONS(-DSUPPORT_URL_FTP=1)
|
||||
SET(MOJOSETUP_NEED_LIBFETCH TRUE)
|
||||
ENDIF(MOJOSETUP_URL_FTP)
|
||||
|
||||
# BINARY SIZE += 10
|
||||
IF(MOJOSETUP_NEED_LIBFETCH)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LIBFETCH_SRCS})
|
||||
# Had to spin up some threads in libfetch...lame.
|
||||
# !!! FIXME: CMake will do -lpthread on Mac OS X, but it doesn't need it.
|
||||
IF(NOT MACOSX)
|
||||
FIND_PACKAGE(Threads)
|
||||
ENDIF(NOT MACOSX)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||
SET(MOJOSETUP_USES_SOCKETS TRUE)
|
||||
ENDIF(MOJOSETUP_NEED_LIBFETCH)
|
||||
|
||||
IF(MOJOSETUP_USES_SOCKETS)
|
||||
IF(SOLARIS)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} "socket")
|
||||
ENDIF(SOLARIS)
|
||||
ENDIF(MOJOSETUP_USES_SOCKETS)
|
||||
|
||||
|
||||
# Middleware...
|
||||
|
||||
IF(MOJOSETUP_NEED_ZLIB)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} miniz.c)
|
||||
ENDIF(MOJOSETUP_NEED_ZLIB)
|
||||
|
||||
IF(MOJOSETUP_NEED_BZLIB)
|
||||
SET(HAVE_SYSTEM_BZLIB FALSE)
|
||||
CHECK_INCLUDE_FILE(bzlib.h HAVE_BZLIB_H)
|
||||
IF(HAVE_BZLIB_H)
|
||||
CHECK_LIBRARY_EXISTS("bz2" "BZ2_bzDecompress" "" HAVE_LIBBZ2)
|
||||
IF(HAVE_LIBBZ2)
|
||||
SET(HAVE_SYSTEM_BZLIB TRUE)
|
||||
ENDIF(HAVE_LIBBZ2)
|
||||
ENDIF(HAVE_BZLIB_H)
|
||||
|
||||
IF(HAVE_SYSTEM_BZLIB)
|
||||
OPTION(MOJOSETUP_INTERNAL_BZLIB "Link own bzlib instead of system library" FALSE)
|
||||
ELSE(HAVE_SYSTEM_BZLIB)
|
||||
SET(MOJOSETUP_INTERNAL_BZLIB TRUE)
|
||||
ENDIF(HAVE_SYSTEM_BZLIB)
|
||||
|
||||
# BINARY SIZE += 46
|
||||
IF(MOJOSETUP_INTERNAL_BZLIB)
|
||||
ADD_DEFINITIONS(-DMOJOSETUP_INTERNAL_BZLIB=1)
|
||||
INCLUDE_DIRECTORIES(${BZLIB_DIR})
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${BZLIB_SRCS})
|
||||
ELSE(MOJOSETUP_INTERNAL_BZLIB)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} bz2)
|
||||
ENDIF(MOJOSETUP_INTERNAL_BZLIB)
|
||||
ENDIF(MOJOSETUP_NEED_BZLIB)
|
||||
|
||||
IF(MOJOSETUP_NEED_LIBLZMA)
|
||||
SET(HAVE_SYSTEM_LIBLZMA FALSE)
|
||||
CHECK_INCLUDE_FILE(lzma.h HAVE_LZMA_H)
|
||||
IF(HAVE_LZMA_H)
|
||||
CHECK_LIBRARY_EXISTS("lzma" "lzma_stream_decoder" "" HAVE_LIBLZMA)
|
||||
IF(HAVE_LIBLZMA)
|
||||
SET(HAVE_SYSTEM_LIBLZMA TRUE)
|
||||
ENDIF(HAVE_LIBLZMA)
|
||||
ENDIF(HAVE_LZMA_H)
|
||||
|
||||
IF(HAVE_SYSTEM_LIBLZMA)
|
||||
OPTION(MOJOSETUP_INTERNAL_LIBLZMA "Link own liblzma instead of system library" FALSE)
|
||||
ELSE(HAVE_SYSTEM_LIBLZMA)
|
||||
SET(MOJOSETUP_INTERNAL_LIBLZMA TRUE)
|
||||
ENDIF(HAVE_SYSTEM_LIBLZMA)
|
||||
|
||||
# BINARY SIZE += ???
|
||||
IF(MOJOSETUP_INTERNAL_LIBLZMA)
|
||||
ADD_DEFINITIONS(-DMOJOSETUP_INTERNAL_LIBLZMA=1)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/api)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/common)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/check)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/delta)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/lz)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/lzma)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/rangecoder)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_DIR}/simple)
|
||||
SET(OPTIONAL_SRCS ${OPTIONAL_SRCS} ${LIBLZMA_SRCS})
|
||||
ELSE(MOJOSETUP_INTERNAL_LIBLZMA)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} lzma)
|
||||
ENDIF(MOJOSETUP_INTERNAL_LIBLZMA)
|
||||
ENDIF(MOJOSETUP_NEED_LIBLZMA)
|
||||
|
||||
IF(UNIX)
|
||||
CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
|
||||
IF(HAVE_UCRED_H)
|
||||
ADD_DEFINITIONS(-DMOJOSETUP_HAVE_SYS_UCRED_H=1)
|
||||
ENDIF(HAVE_UCRED_H)
|
||||
|
||||
CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
|
||||
IF(HAVE_MNTENT_H)
|
||||
ADD_DEFINITIONS(-DMOJOSETUP_HAVE_MNTENT_H=1)
|
||||
ENDIF(HAVE_MNTENT_H)
|
||||
|
||||
# !!! FIXME: Solaris fails this, because mnttab.h implicitly
|
||||
# !!! FIXME: depends on other system headers. :(
|
||||
#CHECK_INCLUDE_FILE(sys/mnttab.h HAVE_SYS_MNTTAB_H)
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#include <stdio.h>
|
||||
#include <sys/mnttab.h>
|
||||
int main(int argc, char **argv) { return 0; }
|
||||
" HAVE_SYS_MNTTAB_H)
|
||||
|
||||
IF(HAVE_SYS_MNTTAB_H)
|
||||
ADD_DEFINITIONS(-DMOJOSETUP_HAVE_SYS_MNTTAB_H=1)
|
||||
ENDIF(HAVE_SYS_MNTTAB_H)
|
||||
|
||||
IF(NOT MACOSX)
|
||||
CHECK_LIBRARY_EXISTS("dl" "dlopen" "" HAVE_LIBDL)
|
||||
IF(HAVE_LIBDL)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} dl)
|
||||
ENDIF(HAVE_LIBDL)
|
||||
CHECK_LIBRARY_EXISTS("m" "sin" "" HAVE_LIBM)
|
||||
IF(HAVE_LIBM)
|
||||
SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} m)
|
||||
ENDIF(HAVE_LIBM)
|
||||
ENDIF(NOT MACOSX)
|
||||
ENDIF(UNIX)
|
||||
|
||||
OPTION(MOJOSETUP_BUILD_LUAC "Build separate Lua compiler" TRUE)
|
||||
IF(MOJOSETUP_BUILD_LUAC)
|
||||
ADD_EXECUTABLE(mojoluac ${MOJOLUAC_SRCS})
|
||||
TARGET_LINK_LIBRARIES(mojoluac ${OPTIONAL_LIBS})
|
||||
GET_TARGET_PROPERTY(MOJOLUAC_LOCATION mojoluac LOCATION)
|
||||
# !!! FIXME: actually compile this.
|
||||
ADD_CUSTOM_TARGET(lua "${MOJOLUAC_LOCATION}" -p ${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.lua)
|
||||
ENDIF(MOJOSETUP_BUILD_LUAC)
|
||||
|
||||
ADD_EXECUTABLE(mojosetup ${USES_WINMAIN} ${MOJOSETUP_SRCS} ${OPTIONAL_SRCS})
|
||||
GET_TARGET_PROPERTY(MOJOSETUP_BINARY_LOCATION mojosetup LOCATION)
|
||||
TARGET_LINK_LIBRARIES(mojosetup ${OPTIONAL_LIBS})
|
||||
SET(MOJOSETUP_TARGETS "${MOJOSETUP_TARGETS};mojosetup")
|
||||
|
||||
ADD_EXECUTABLE(make_self_extracting misc/make_self_extracting.c)
|
||||
|
||||
# For cobbling together a skeleton installer...
|
||||
|
||||
# !!! FIXME: all of these custom .cmake files are built-in commands in CMake 2.6.(4?) ...!
|
||||
ADD_CUSTOM_TARGET(skeleton
|
||||
COMMENT "Assembling Skeleton..."
|
||||
COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton -P ${CMAKE_SOURCE_DIR}/misc/rm_recurse.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton/scripts -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton/guis -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DDIR=${CMAKE_BINARY_DIR}/skeleton/data -P ${CMAKE_SOURCE_DIR}/misc/mkdir.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DFROM=${CMAKE_SOURCE_DIR}/scripts/*.lua -DTO=${CMAKE_BINARY_DIR}/skeleton/scripts -P ${CMAKE_SOURCE_DIR}/misc/cp.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DFROM=${CMAKE_SOURCE_DIR}/*mojosetupgui*.* -DTO=${CMAKE_BINARY_DIR}/skeleton/guis -P ${CMAKE_SOURCE_DIR}/misc/cp.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -DFROM=${MOJOSETUP_BINARY_LOCATION} -DTO=${CMAKE_BINARY_DIR}/skeleton -P ${CMAKE_SOURCE_DIR}/misc/cp.cmake
|
||||
)
|
||||
|
||||
ADD_DEPENDENCIES(skeleton ${MOJOSETUP_TARGETS})
|
||||
|
||||
# end of CMakeLists.txt ...
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
|
||||
|
||||
(Please note that other pieces of code in MojoSetup fall under BSD-like and/or
|
||||
public domain licenses: lua, libfetch, zlib, bzlib, liblzma, stb_image, etc.
|
||||
All software statically linked to MojoSetup was explicitly chosen to be
|
||||
friendly with closed-source software, in case the installer needs a
|
||||
proprietary change. I am not a lawyer and this is not legal advice. Please
|
||||
have a lawyer consider the licenses if you have any concerns.)
|
||||
|
|
@ -1,295 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Steffen Pankratz.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fileio.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if !SUPPORT_PCK
|
||||
MojoArchive *MojoArchive_createPCK(MojoInput *io) { return NULL; }
|
||||
#else
|
||||
|
||||
#define PCK_MAGIC 0x534c4850
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 Magic; // 4 bytes, has to be PCK_MAGIC (0x534c4850)
|
||||
uint32 StartOfBinaryData; // 4 bytes, offset to the data
|
||||
} PCKheader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int8 filename[60]; // 60 bytes, null terminated
|
||||
uint32 filesize; // 4 bytes
|
||||
} PCKentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64 fileCount;
|
||||
uint64 dataStart;
|
||||
uint64 nextFileStart;
|
||||
int64 nextEnumPos;
|
||||
MojoArchiveEntry *archiveEntries;
|
||||
} PCKinfo;
|
||||
|
||||
static boolean MojoInput_pck_ready(MojoInput *io)
|
||||
{
|
||||
return true; // !!! FIXME?
|
||||
} // MojoInput_pck_ready
|
||||
|
||||
static int64 MojoInput_pck_read(MojoInput *io, void *buf, uint32 bufsize)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
int64 pos = io->tell(io);
|
||||
if ((pos + bufsize) > entry->filesize)
|
||||
bufsize = (uint32) (entry->filesize - pos);
|
||||
return ar->io->read(ar->io, buf, bufsize);
|
||||
} // MojoInput_pck_read
|
||||
|
||||
static boolean MojoInput_pck_seek(MojoInput *io, uint64 pos)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const PCKinfo *info = (PCKinfo *) ar->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
boolean retval = false;
|
||||
if (pos < ((uint64) entry->filesize))
|
||||
{
|
||||
const uint64 newpos = (info->nextFileStart - entry->filesize) + pos;
|
||||
retval = ar->io->seek(ar->io, newpos);
|
||||
} // if
|
||||
return retval;
|
||||
} // MojoInput_pck_seek
|
||||
|
||||
static int64 MojoInput_pck_tell(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const PCKinfo *info = (PCKinfo *) ar->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
return ar->io->tell(ar->io) - (info->nextFileStart - entry->filesize);
|
||||
} // MojoInput_pck_tell
|
||||
|
||||
static int64 MojoInput_pck_length(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
return entry->filesize;
|
||||
} // MojoInput_pck_length
|
||||
|
||||
static MojoInput *MojoInput_pck_duplicate(MojoInput *io)
|
||||
{
|
||||
MojoInput *retval = NULL;
|
||||
fatal(_("BUG: Can't duplicate pck inputs")); // !!! FIXME: why not?
|
||||
return retval;
|
||||
} // MojoInput_pck_duplicate
|
||||
|
||||
static void MojoInput_pck_close(MojoInput *io)
|
||||
{
|
||||
free(io);
|
||||
} // MojoInput_pck_close
|
||||
|
||||
// MojoArchive implementation...
|
||||
|
||||
static boolean MojoArchive_pck_enumerate(MojoArchive *ar)
|
||||
{
|
||||
MojoArchiveEntry *archiveEntries = NULL;
|
||||
PCKinfo *info = (PCKinfo *) ar->opaque;
|
||||
const int dataStart = info->dataStart;
|
||||
const int fileCount = dataStart / sizeof (PCKentry);
|
||||
const size_t len = fileCount * sizeof (MojoArchiveEntry);
|
||||
PCKentry fileEntry;
|
||||
uint64 i, realFileCount = 0;
|
||||
char directory[256] = {'\0'};
|
||||
MojoInput *io = ar->io;
|
||||
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
|
||||
archiveEntries = (MojoArchiveEntry *) xmalloc(len);
|
||||
|
||||
for (i = 0; i < fileCount; i++)
|
||||
{
|
||||
int dotdot;
|
||||
int64 br;
|
||||
|
||||
br = io->read(io, fileEntry.filename, sizeof (fileEntry.filename));
|
||||
if (br != sizeof (fileEntry.filename))
|
||||
return false;
|
||||
else if (!MojoInput_readui32(io, &fileEntry.filesize))
|
||||
return false;
|
||||
|
||||
dotdot = (strcmp(fileEntry.filename, "..") == 0);
|
||||
|
||||
if ((!dotdot) && (fileEntry.filesize == 0x80000000))
|
||||
{
|
||||
MojoArchiveEntry *entry = &archiveEntries[realFileCount];
|
||||
|
||||
strcat(directory, fileEntry.filename);
|
||||
strcat(directory, "/");
|
||||
|
||||
entry->filename = xstrdup(directory);
|
||||
entry->type = MOJOARCHIVE_ENTRY_DIR;
|
||||
entry->perms = MojoPlatform_defaultDirPerms();
|
||||
entry->filesize = 0;
|
||||
realFileCount++;
|
||||
} // if
|
||||
|
||||
else if ((dotdot) && (fileEntry.filesize == 0x80000000))
|
||||
{
|
||||
// remove trailing path separator
|
||||
char *pathSep;
|
||||
const size_t strLength = strlen(directory);
|
||||
directory[strLength - 1] = '\0';
|
||||
|
||||
pathSep = strrchr(directory, '/');
|
||||
if(pathSep != NULL)
|
||||
{
|
||||
pathSep++;
|
||||
*pathSep = '\0';
|
||||
} // if
|
||||
} // else if
|
||||
|
||||
else
|
||||
{
|
||||
MojoArchiveEntry *entry = &archiveEntries[realFileCount];
|
||||
if (directory[0] == '\0')
|
||||
entry->filename = xstrdup(fileEntry.filename);
|
||||
else
|
||||
{
|
||||
const size_t len = sizeof (char) * strlen(directory) +
|
||||
strlen(fileEntry.filename) + 1;
|
||||
entry->filename = (char *) xmalloc(len);
|
||||
strcat(entry->filename, directory);
|
||||
strcat(entry->filename, fileEntry.filename);
|
||||
} // else
|
||||
|
||||
entry->perms = MojoPlatform_defaultFilePerms();
|
||||
entry->type = MOJOARCHIVE_ENTRY_FILE;
|
||||
entry->filesize = fileEntry.filesize;
|
||||
|
||||
realFileCount++;
|
||||
} // else
|
||||
} // for
|
||||
|
||||
info->fileCount = realFileCount;
|
||||
info->archiveEntries = archiveEntries;
|
||||
info->nextEnumPos = 0;
|
||||
info->nextFileStart = dataStart;
|
||||
|
||||
return true;
|
||||
} // MojoArchive_pck_enumerate
|
||||
|
||||
|
||||
static const MojoArchiveEntry *MojoArchive_pck_enumNext(MojoArchive *ar)
|
||||
{
|
||||
PCKinfo *info = (PCKinfo *) ar->opaque;
|
||||
const MojoArchiveEntry *entry = &info->archiveEntries[info->nextEnumPos];
|
||||
|
||||
if (info->nextEnumPos >= info->fileCount)
|
||||
return NULL;
|
||||
|
||||
if (!ar->io->seek(ar->io, info->nextFileStart))
|
||||
return NULL;
|
||||
|
||||
info->nextEnumPos++;
|
||||
info->nextFileStart += entry->filesize;
|
||||
|
||||
memcpy(&ar->prevEnum, entry, sizeof (ar->prevEnum));
|
||||
|
||||
return &ar->prevEnum;
|
||||
} // MojoArchive_pck_enumNext
|
||||
|
||||
|
||||
static MojoInput *MojoArchive_pck_openCurrentEntry(MojoArchive *ar)
|
||||
{
|
||||
MojoInput *io = NULL;
|
||||
io = (MojoInput *) xmalloc(sizeof (MojoInput));
|
||||
io->ready = MojoInput_pck_ready;
|
||||
io->read = MojoInput_pck_read;
|
||||
io->seek = MojoInput_pck_seek;
|
||||
io->tell = MojoInput_pck_tell;
|
||||
io->length = MojoInput_pck_length;
|
||||
io->duplicate = MojoInput_pck_duplicate;
|
||||
io->close = MojoInput_pck_close;
|
||||
io->opaque = ar;
|
||||
return io;
|
||||
} // MojoArchive_pck_openCurrentEntry
|
||||
|
||||
|
||||
static void MojoArchive_pck_close(MojoArchive *ar)
|
||||
{
|
||||
int i;
|
||||
PCKinfo *info = (PCKinfo *) ar->opaque;
|
||||
ar->io->close(ar->io);
|
||||
|
||||
for (i = 0; i < info->fileCount; i++)
|
||||
{
|
||||
MojoArchiveEntry *entry = &info->archiveEntries[i];
|
||||
free(entry->filename);
|
||||
} // for
|
||||
|
||||
free(info->archiveEntries);
|
||||
free(info);
|
||||
free(ar);
|
||||
} // MojoArchive_pck_close
|
||||
|
||||
|
||||
MojoArchive *MojoArchive_createPCK(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = NULL;
|
||||
PCKinfo *pckInfo = NULL;
|
||||
PCKheader pckHeader;
|
||||
|
||||
if (!MojoInput_readui32(io, &pckHeader.Magic))
|
||||
return NULL;
|
||||
else if (!MojoInput_readui32(io, &pckHeader.StartOfBinaryData))
|
||||
return NULL;
|
||||
|
||||
// Check if this is a *.pck file.
|
||||
if (pckHeader.Magic != PCK_MAGIC)
|
||||
return NULL;
|
||||
|
||||
pckInfo = (PCKinfo *) xmalloc(sizeof (PCKinfo));
|
||||
pckInfo->dataStart = pckHeader.StartOfBinaryData + sizeof (PCKheader);
|
||||
|
||||
ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
|
||||
ar->opaque = pckInfo;
|
||||
ar->enumerate = MojoArchive_pck_enumerate;
|
||||
ar->enumNext = MojoArchive_pck_enumNext;
|
||||
ar->openCurrentEntry = MojoArchive_pck_openCurrentEntry;
|
||||
ar->close = MojoArchive_pck_close;
|
||||
ar->io = io;
|
||||
|
||||
return ar;
|
||||
} // MojoArchive_createPCK
|
||||
|
||||
#endif // SUPPORT_PCK
|
||||
|
||||
// end of archive_pck.c ...
|
||||
|
|
@ -1,250 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Steffen Pankratz.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fileio.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if !SUPPORT_PKG
|
||||
MojoArchive *MojoArchive_createPKG(MojoInput *io) { return NULL; }
|
||||
#else
|
||||
|
||||
#define PKG_MAGIC 0x4f504b47
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 magic; // 4 bytes, has to be PKG_MAGIC (0x4f504b47)
|
||||
uint32 fileCount; // 4 bytes, number of files in the archive
|
||||
} PKGheader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64 nextFileStart;
|
||||
} PKGinfo;
|
||||
|
||||
static boolean MojoInput_pkg_ready(MojoInput *io)
|
||||
{
|
||||
return true;
|
||||
} // MojoInput_pkg_ready
|
||||
|
||||
static int64 MojoInput_pkg_read(MojoInput *io, void *buf, uint32 bufsize)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
int64 pos = io->tell(io);
|
||||
if ((pos + bufsize) > entry->filesize)
|
||||
bufsize = (uint32) (entry->filesize - pos);
|
||||
return ar->io->read(ar->io, buf, bufsize);
|
||||
} // MojoInput_pkg_read
|
||||
|
||||
static boolean MojoInput_pkg_seek(MojoInput *io, uint64 pos)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const PKGinfo *info = (PKGinfo *) ar->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
boolean retval = false;
|
||||
if (pos < ((uint64) entry->filesize))
|
||||
{
|
||||
const uint64 newpos = (info->nextFileStart - entry->filesize) + pos;
|
||||
retval = ar->io->seek(ar->io, newpos);
|
||||
} // if
|
||||
return retval;
|
||||
} // MojoInput_pkg_seek
|
||||
|
||||
static int64 MojoInput_pkg_tell(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const PKGinfo *info = (PKGinfo *) ar->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
return ar->io->tell(ar->io) - (info->nextFileStart - entry->filesize);
|
||||
} // MojoInput_pkg_tell
|
||||
|
||||
static int64 MojoInput_pkg_length(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = (MojoArchive *) io->opaque;
|
||||
const MojoArchiveEntry *entry = &ar->prevEnum;
|
||||
return entry->filesize;
|
||||
} // MojoInput_pkg_length
|
||||
|
||||
static MojoInput *MojoInput_pkg_duplicate(MojoInput *io)
|
||||
{
|
||||
MojoInput *retval = NULL;
|
||||
fatal(_("BUG: Can't duplicate pkg inputs")); // !!! FIXME: why not?
|
||||
return retval;
|
||||
} // MojoInput_pkg_duplicate
|
||||
|
||||
static void MojoInput_pkg_close(MojoInput *io)
|
||||
{
|
||||
free(io);
|
||||
} // MojoInput_pkg_close
|
||||
|
||||
// MojoArchive implementation...
|
||||
|
||||
static boolean MojoArchive_pkg_enumerate(MojoArchive *ar)
|
||||
{
|
||||
PKGinfo *info = (PKGinfo *) ar->opaque;
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
|
||||
info->nextFileStart = sizeof (PKGheader);
|
||||
return true;
|
||||
} // MojoArchive_pkg_enumerate
|
||||
|
||||
|
||||
static const MojoArchiveEntry *MojoArchive_pkg_enumNext(MojoArchive *ar)
|
||||
{
|
||||
PKGinfo *info = (PKGinfo *) ar->opaque;
|
||||
MojoInput *io = ar->io;
|
||||
int64 ret = 0;
|
||||
uint32 pathNameLength = 0;
|
||||
uint64 pathNameStart = 0;
|
||||
uint32 fileNameLength = 0;
|
||||
uint64 fileNameStart = 0;
|
||||
uint32 fileSize = 0;
|
||||
char* backSlash = NULL;
|
||||
|
||||
if (!ar->io->seek(ar->io, info->nextFileStart))
|
||||
return NULL;
|
||||
|
||||
// read the path name length
|
||||
if (!MojoInput_readui32(io, &pathNameLength))
|
||||
return NULL;
|
||||
|
||||
pathNameStart = ar->io->tell(ar->io);
|
||||
|
||||
// skip reading the path name for now
|
||||
if (!ar->io->seek(ar->io, pathNameStart + pathNameLength))
|
||||
return NULL;
|
||||
|
||||
// read the file name length
|
||||
if (!MojoInput_readui32(io, &fileNameLength))
|
||||
return NULL;
|
||||
|
||||
fileNameStart = ar->io->tell(ar->io);
|
||||
|
||||
// as both strings are null terminated, we need one byte less
|
||||
ar->prevEnum.filename = (char *) xmalloc(pathNameLength + fileNameLength -1);
|
||||
|
||||
// go to the start of the path name
|
||||
if (!ar->io->seek(ar->io, pathNameStart))
|
||||
return NULL;
|
||||
|
||||
// read the path name
|
||||
ret = io->read(io, ar->prevEnum.filename, pathNameLength);
|
||||
if (ret != pathNameLength)
|
||||
return false;
|
||||
|
||||
// replace backslashes with slashes in the path name
|
||||
while((backSlash = strchr(ar->prevEnum.filename, '\\')))
|
||||
*backSlash = '/';
|
||||
|
||||
// go the start of the file name
|
||||
if (!ar->io->seek(ar->io, fileNameStart))
|
||||
return NULL;
|
||||
|
||||
// read the file name
|
||||
ret = io->read(io, ar->prevEnum.filename + pathNameLength - 1, fileNameLength);
|
||||
if (ret != fileNameLength)
|
||||
return false;
|
||||
|
||||
// read the file size
|
||||
if (!MojoInput_readui32(io, &fileSize))
|
||||
return NULL;
|
||||
|
||||
// skip the next 8 bytes, probably some kind of check sum
|
||||
if (!ar->io->seek(ar->io, ar->io->tell(ar->io) + 8))
|
||||
return NULL;
|
||||
|
||||
ar->prevEnum.filesize = fileSize;
|
||||
ar->prevEnum.perms = MojoPlatform_defaultFilePerms();
|
||||
ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;
|
||||
|
||||
info->nextFileStart = ar->io->tell(ar->io) + ar->prevEnum.filesize;
|
||||
|
||||
return &ar->prevEnum;
|
||||
} // MojoArchive_pkg_enumNext
|
||||
|
||||
|
||||
static MojoInput *MojoArchive_pkg_openCurrentEntry(MojoArchive *ar)
|
||||
{
|
||||
MojoInput *io = NULL;
|
||||
io = (MojoInput *) xmalloc(sizeof (MojoInput));
|
||||
io->ready = MojoInput_pkg_ready;
|
||||
io->read = MojoInput_pkg_read;
|
||||
io->seek = MojoInput_pkg_seek;
|
||||
io->tell = MojoInput_pkg_tell;
|
||||
io->length = MojoInput_pkg_length;
|
||||
io->duplicate = MojoInput_pkg_duplicate;
|
||||
io->close = MojoInput_pkg_close;
|
||||
io->opaque = ar;
|
||||
return io;
|
||||
} // MojoArchive_pkg_openCurrentEntry
|
||||
|
||||
|
||||
static void MojoArchive_pkg_close(MojoArchive *ar)
|
||||
{
|
||||
PKGinfo *info = (PKGinfo *) ar->opaque;
|
||||
ar->io->close(ar->io);
|
||||
|
||||
free(info);
|
||||
free(ar);
|
||||
} // MojoArchive_pkg_close
|
||||
|
||||
|
||||
MojoArchive *MojoArchive_createPKG(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = NULL;
|
||||
PKGinfo *pkgInfo = NULL;
|
||||
PKGheader pkgHeader;
|
||||
|
||||
if (!MojoInput_readui32(io, &pkgHeader.magic))
|
||||
return NULL;
|
||||
else if (!MojoInput_readui32(io, &pkgHeader.fileCount))
|
||||
return NULL;
|
||||
|
||||
// Check if this is a *.pkg file.
|
||||
if (pkgHeader.magic != PKG_MAGIC)
|
||||
return NULL;
|
||||
|
||||
pkgInfo = (PKGinfo *) xmalloc(sizeof (PKGinfo));
|
||||
|
||||
ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
|
||||
ar->opaque = pkgInfo;
|
||||
ar->enumerate = MojoArchive_pkg_enumerate;
|
||||
ar->enumNext = MojoArchive_pkg_enumNext;
|
||||
ar->openCurrentEntry = MojoArchive_pkg_openCurrentEntry;
|
||||
ar->close = MojoArchive_pkg_close;
|
||||
ar->io = io;
|
||||
|
||||
return ar;
|
||||
} // MojoArchive_createPKG
|
||||
|
||||
#endif // SUPPORT_PKG
|
||||
|
||||
// end of archive_pkg.c ...
|
|
@ -1,372 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
// Specs for the tar format can be found here...
|
||||
// http://www.gnu.org/software/tar/manual/html_section/Standard.html
|
||||
|
||||
#include "fileio.h"
|
||||
|
||||
#if !SUPPORT_TAR
|
||||
MojoArchive *MojoArchive_createTAR(MojoInput *io) { return NULL; }
|
||||
#else
|
||||
|
||||
// MojoInput implementation...
|
||||
|
||||
// Decompression is handled in the parent MojoInput, so this just needs to
|
||||
// make sure we stay within the bounds of the tarfile entry.
|
||||
|
||||
typedef struct TARinput
|
||||
{
|
||||
int64 fsize;
|
||||
int64 offset;
|
||||
MojoArchive *ar;
|
||||
} TARinput;
|
||||
|
||||
typedef struct TARinfo
|
||||
{
|
||||
MojoInput *input;
|
||||
uint64 curFileStart;
|
||||
uint64 nextEnumPos;
|
||||
} TARinfo;
|
||||
|
||||
static boolean MojoInput_tar_ready(MojoInput *io)
|
||||
{
|
||||
return true; // !!! FIXME: ready if there are bytes uncompressed.
|
||||
} // MojoInput_tar_ready
|
||||
|
||||
static int64 MojoInput_tar_read(MojoInput *io, void *buf, uint32 bufsize)
|
||||
{
|
||||
TARinput *input = (TARinput *) io->opaque;
|
||||
int64 pos = io->tell(io);
|
||||
if ((pos + bufsize) > input->fsize)
|
||||
bufsize = (uint32) (input->fsize - pos);
|
||||
return input->ar->io->read(input->ar->io, buf, bufsize);
|
||||
} // MojoInput_tar_read
|
||||
|
||||
static boolean MojoInput_tar_seek(MojoInput *io, uint64 pos)
|
||||
{
|
||||
TARinput *input = (TARinput *) io->opaque;
|
||||
boolean retval = false;
|
||||
if (pos < ((uint64) input->fsize))
|
||||
retval = input->ar->io->seek(input->ar->io, input->offset + pos);
|
||||
return retval;
|
||||
} // MojoInput_tar_seek
|
||||
|
||||
static int64 MojoInput_tar_tell(MojoInput *io)
|
||||
{
|
||||
TARinput *input = (TARinput *) io->opaque;
|
||||
return input->ar->io->tell(input->ar->io) - input->offset;
|
||||
} // MojoInput_tar_tell
|
||||
|
||||
static int64 MojoInput_tar_length(MojoInput *io)
|
||||
{
|
||||
return ((TARinput *) io->opaque)->fsize;
|
||||
} // MojoInput_tar_length
|
||||
|
||||
static MojoInput *MojoInput_tar_duplicate(MojoInput *io)
|
||||
{
|
||||
MojoInput *retval = NULL;
|
||||
fatal(_("BUG: Can't duplicate tar inputs")); // !!! FIXME: why not?
|
||||
#if 0
|
||||
TARinput *input = (TARinput *) io->opaque;
|
||||
MojoInput *origio = (MojoInput *) io->opaque;
|
||||
MojoInput *newio = origio->duplicate(origio);
|
||||
|
||||
if (newio != NULL)
|
||||
{
|
||||
TARinput *newopaque = (TARinput *) xmalloc(sizeof (TARinput));
|
||||
newopaque->origio = newio;
|
||||
newopaque->fsize = input->fsize;
|
||||
newopaque->offset = input->offset;
|
||||
retval = (MojoInput *) xmalloc(sizeof (MojoInput));
|
||||
memcpy(retval, io, sizeof (MojoInput));
|
||||
retval->opaque = newopaque;
|
||||
} // if
|
||||
#endif
|
||||
return retval;
|
||||
} // MojoInput_tar_duplicate
|
||||
|
||||
static void MojoInput_tar_close(MojoInput *io)
|
||||
{
|
||||
TARinput *input = (TARinput *) io->opaque;
|
||||
TARinfo *info = (TARinfo *) input->ar->opaque;
|
||||
//input->ar->io->close(input->ar->io);
|
||||
info->input = NULL;
|
||||
free(input);
|
||||
free(io);
|
||||
} // MojoInput_tar_close
|
||||
|
||||
|
||||
// MojoArchive implementation...
|
||||
|
||||
static boolean MojoArchive_tar_enumerate(MojoArchive *ar)
|
||||
{
|
||||
TARinfo *info = (TARinfo *) ar->opaque;
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
if (info->input != NULL)
|
||||
fatal("BUG: tar entry still open on new enumeration");
|
||||
info->curFileStart = info->nextEnumPos = 0;
|
||||
return true;
|
||||
} // MojoArchive_tar_enumerate
|
||||
|
||||
|
||||
// These are byte offsets where fields start in the tar header blocks.
|
||||
#define TAR_FNAME 0
|
||||
#define TAR_FNAMELEN 100
|
||||
#define TAR_MODE 100
|
||||
#define TAR_MODELEN 8
|
||||
#define TAR_UID 108
|
||||
#define TAR_UIDLEN 8
|
||||
#define TAR_GID 116
|
||||
#define TAR_GIDLEN 8
|
||||
#define TAR_SIZE 124
|
||||
#define TAR_SIZELEN 12
|
||||
#define TAR_MTIME 136
|
||||
#define TAR_MTIMELEN 12
|
||||
#define TAR_CHKSUM 148
|
||||
#define TAR_CHKSUMLEN 8
|
||||
#define TAR_TYPE 156
|
||||
#define TAR_TYPELEN 1
|
||||
#define TAR_LINKNAME 157
|
||||
#define TAR_LINKNAMELEN 100
|
||||
#define TAR_MAGIC 257
|
||||
#define TAR_MAGICLEN 6
|
||||
#define TAR_VERSION 263
|
||||
#define TAR_VERSIONLEN 2
|
||||
#define TAR_UNAME 265
|
||||
#define TAR_UNAMELEN 32
|
||||
#define TAR_GNAME 297
|
||||
#define TAR_GNAMELEN 32
|
||||
#define TAR_DEVMAJOR 329
|
||||
#define TAR_DEVMAJORLEN 8
|
||||
#define TAR_DEVMINOR 337
|
||||
#define TAR_DEVMINORLEN 8
|
||||
#define TAR_FNAMEPRE 345
|
||||
#define TAR_FNAMEPRELEN 155
|
||||
|
||||
// tar entry types...
|
||||
#define TAR_TYPE_FILE '0'
|
||||
#define TAR_TYPE_HARDLINK '1'
|
||||
#define TAR_TYPE_SYMLINK '2'
|
||||
#define TAR_TYPE_CHARDEV '3'
|
||||
#define TAR_TYPE_BLOCKDEV '4'
|
||||
#define TAR_TYPE_DIRECTORY '5'
|
||||
#define TAR_TYPE_FIFO '6'
|
||||
|
||||
static boolean is_ustar(const uint8 *block)
|
||||
{
|
||||
return ( (memcmp(&block[TAR_MAGIC], "ustar ", TAR_MAGICLEN) == 0) ||
|
||||
(memcmp(&block[TAR_MAGIC], "ustar\0", TAR_MAGICLEN) == 0) );
|
||||
} // is_ustar
|
||||
|
||||
static int64 octal_convert(const uint8 *str, const size_t len)
|
||||
{
|
||||
int64 retval = 0;
|
||||
int64 multiplier = 1;
|
||||
const uint8 *end = str + len;
|
||||
const uint8 *ptr;
|
||||
|
||||
while ((*str == ' ') && (str != end))
|
||||
str++;
|
||||
|
||||
ptr = str;
|
||||
while ((ptr != end) && (*ptr >= '0') && (*ptr <= '7'))
|
||||
ptr++;
|
||||
|
||||
while (--ptr >= str)
|
||||
{
|
||||
uint64 val = *ptr - '0';
|
||||
retval += val * multiplier;
|
||||
multiplier *= 8;
|
||||
} // while
|
||||
|
||||
return retval;
|
||||
} // octal_convert
|
||||
|
||||
|
||||
static const MojoArchiveEntry *MojoArchive_tar_enumNext(MojoArchive *ar)
|
||||
{
|
||||
TARinfo *info = (TARinfo *) ar->opaque;
|
||||
boolean zeroes = true;
|
||||
boolean ustar = false;
|
||||
uint8 scratch[512];
|
||||
uint8 block[512];
|
||||
size_t fnamelen = 0;
|
||||
int type = 0;
|
||||
|
||||
memset(scratch, '\0', sizeof (scratch));
|
||||
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
if (info->input != NULL)
|
||||
fatal("BUG: tar entry still open on new enumeration");
|
||||
|
||||
if (!ar->io->seek(ar->io, info->nextEnumPos))
|
||||
return NULL;
|
||||
|
||||
// Find a non-zero block of data. Tarballs have two 512 blocks filled with
|
||||
// null bytes at the end of the archive, but you can cat tarballs
|
||||
// together, so you can't treat them as EOF indicators. Just skip them.
|
||||
while (zeroes)
|
||||
{
|
||||
if (ar->io->read(ar->io, block, sizeof (block)) != sizeof (block))
|
||||
return NULL; // !!! FIXME: fatal() ?
|
||||
zeroes = (memcmp(block, scratch, sizeof (block)) == 0);
|
||||
} // while
|
||||
|
||||
// !!! FIXME We should probably check the checksum.
|
||||
|
||||
ustar = is_ustar(block);
|
||||
|
||||
ar->prevEnum.perms = (uint16) octal_convert(&block[TAR_MODE], TAR_MODELEN);
|
||||
ar->prevEnum.filesize = octal_convert(&block[TAR_SIZE], TAR_SIZELEN);
|
||||
info->curFileStart = info->nextEnumPos + 512;
|
||||
info->nextEnumPos += 512 + ar->prevEnum.filesize;
|
||||
if (ar->prevEnum.filesize % 512)
|
||||
info->nextEnumPos += 512 - (ar->prevEnum.filesize % 512);
|
||||
|
||||
// We count on (scratch) being zeroed out here!
|
||||
// prefix of filename is at the end for legacy compat.
|
||||
if (ustar)
|
||||
memcpy(scratch, &block[TAR_FNAMEPRE], TAR_FNAMEPRELEN);
|
||||
fnamelen = strlen((const char *) scratch);
|
||||
memcpy(&scratch[fnamelen], &block[TAR_FNAME], TAR_FNAMELEN);
|
||||
fnamelen += strlen((const char *) &scratch[fnamelen]);
|
||||
|
||||
if (fnamelen == 0)
|
||||
return NULL; // corrupt file. !!! FIXME: fatal() ?
|
||||
|
||||
ar->prevEnum.filename = xstrdup((const char *) scratch);
|
||||
|
||||
type = block[TAR_TYPE];
|
||||
if (type == 0) // some archivers do the file type as 0 instead of '0'.
|
||||
type = TAR_TYPE_FILE;
|
||||
|
||||
if (ar->prevEnum.filename[fnamelen-1] == '/')
|
||||
{
|
||||
while (ar->prevEnum.filename[fnamelen-1] == '/')
|
||||
ar->prevEnum.filename[--fnamelen] = '\0';
|
||||
|
||||
// legacy tar entries don't have a dir type, they just append a '/' to
|
||||
// the filename...
|
||||
if ((!ustar) && (type == TAR_TYPE_FILE))
|
||||
type = TAR_TYPE_DIRECTORY;
|
||||
} // if
|
||||
|
||||
ar->prevEnum.type = MOJOARCHIVE_ENTRY_UNKNOWN;
|
||||
if (type == TAR_TYPE_FILE)
|
||||
ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;
|
||||
else if (type == TAR_TYPE_DIRECTORY)
|
||||
ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR;
|
||||
else if (type == TAR_TYPE_SYMLINK)
|
||||
{
|
||||
ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK;
|
||||
memcpy(scratch, &block[TAR_LINKNAME], TAR_LINKNAMELEN);
|
||||
scratch[TAR_LINKNAMELEN] = '\0'; // just in case.
|
||||
ar->prevEnum.linkdest = xstrdup((const char *) scratch);
|
||||
} // else if
|
||||
|
||||
return &ar->prevEnum;
|
||||
} // MojoArchive_tar_enumNext
|
||||
|
||||
|
||||
static MojoInput *MojoArchive_tar_openCurrentEntry(MojoArchive *ar)
|
||||
{
|
||||
TARinfo *info = (TARinfo *) ar->opaque;
|
||||
MojoInput *io = NULL;
|
||||
TARinput *opaque = NULL;
|
||||
|
||||
if (info->curFileStart == 0)
|
||||
return NULL;
|
||||
|
||||
// Can't open multiple, since we would end up decompressing twice
|
||||
// to enumerate the next file, so I imposed this limitation for now.
|
||||
if (info->input != NULL)
|
||||
fatal("BUG: tar entry double open");
|
||||
|
||||
// !!! FIXME: replace this with MojoInput_newFromSubset()?
|
||||
|
||||
opaque = (TARinput *) xmalloc(sizeof (TARinput));
|
||||
opaque->ar = ar;
|
||||
opaque->fsize = ar->prevEnum.filesize;
|
||||
opaque->offset = info->curFileStart;
|
||||
|
||||
io = (MojoInput *) xmalloc(sizeof (MojoInput));
|
||||
io->ready = MojoInput_tar_ready;
|
||||
io->read = MojoInput_tar_read;
|
||||
io->seek = MojoInput_tar_seek;
|
||||
io->tell = MojoInput_tar_tell;
|
||||
io->length = MojoInput_tar_length;
|
||||
io->duplicate = MojoInput_tar_duplicate;
|
||||
io->close = MojoInput_tar_close;
|
||||
io->opaque = opaque;
|
||||
info->input = io;
|
||||
return io;
|
||||
} // MojoArchive_tar_openCurrentEntry
|
||||
|
||||
|
||||
static void MojoArchive_tar_close(MojoArchive *ar)
|
||||
{
|
||||
TARinfo *info = (TARinfo *) ar->opaque;
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
ar->io->close(ar->io);
|
||||
free(info);
|
||||
free(ar);
|
||||
} // MojoArchive_tar_close
|
||||
|
||||
|
||||
MojoArchive *MojoArchive_createTAR(MojoInput *io)
|
||||
{
|
||||
MojoArchive *ar = NULL;
|
||||
uint8 sig[512];
|
||||
const int64 br = io->read(io, sig, sizeof (sig));
|
||||
|
||||
// See if this is a tar archive. We only support "USTAR" format,
|
||||
// since it has a detectable header. GNU and BSD tar has been creating
|
||||
// these for years, so it's okay to ignore other ones, I guess.
|
||||
if ((!io->seek(io, 0)) || (br != sizeof (sig)) || (!is_ustar(sig)) )
|
||||
return NULL;
|
||||
|
||||
// okay, it's a tarball, we're good to go.
|
||||
|
||||
ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
|
||||
ar->opaque = (TARinfo *) xmalloc(sizeof (TARinfo));
|
||||
ar->enumerate = MojoArchive_tar_enumerate;
|
||||
ar->enumNext = MojoArchive_tar_enumNext;
|
||||
ar->openCurrentEntry = MojoArchive_tar_openCurrentEntry;
|
||||
ar->close = MojoArchive_tar_close;
|
||||
ar->io = io;
|
||||
return ar;
|
||||
} // MojoArchive_createTAR
|
||||
|
||||
#endif // SUPPORT_TAR
|
||||
|
||||
// end of archive_tar.c ...
|
||||
|
|
@ -1,373 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "fileio.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if !SUPPORT_UZ2
|
||||
MojoArchive *MojoArchive_createUZ2(MojoInput *io) { return NULL; }
|
||||
#else
|
||||
|
||||
// UZ2 format is a simple compressed file format used by UnrealEngine2.
|
||||
// it's just a stream of blocks like this:
|
||||
// uint32 compressed size
|
||||
// uint32 uncompressed size
|
||||
// uint8 data[compressed size] <-- unpacks to (uncompressed size) bytes.
|
||||
// Decompression is handled by zlib's "uncompress" function.
|
||||
|
||||
#include "miniz.h"
|
||||
|
||||
#define MAXCOMPSIZE 32768
|
||||
#define MAXUNCOMPSIZE 33096 // MAXCOMPSIZE + 1%
|
||||
|
||||
|
||||
// MojoInput implementation...
|
||||
|
||||
// Decompression is handled in the parent MojoInput, so this just needs to
|
||||
// make sure we stay within the bounds of the tarfile entry.
|
||||
|
||||
typedef struct UZ2input
|
||||
{
|
||||
MojoInput *io;
|
||||
int64 fsize;
|
||||
uint64 position;
|
||||
uint32 compsize;
|
||||
uint8 compbuf[MAXCOMPSIZE];
|
||||
uint32 uncompsize;
|
||||
uint8 uncompbuf[MAXUNCOMPSIZE];
|
||||
uint32 uncompindex;
|
||||
} UZ2input;
|
||||
|
||||
typedef struct UZ2info
|
||||
{
|
||||
char *outname;
|
||||
int64 outsize;
|
||||
boolean enumerated;
|
||||
} UZ2info;
|
||||
|
||||
static boolean unpack(UZ2input *inp)
|
||||
{
|
||||
MojoInput *io = inp->io;
|
||||
uLongf ul = (uLongf) inp->uncompsize;
|
||||
|
||||
// we checked these formally elsewhere.
|
||||
assert(inp->compsize > 0);
|
||||
assert(inp->uncompsize > 0);
|
||||
assert(inp->compsize <= MAXCOMPSIZE);
|
||||
assert(inp->uncompsize <= MAXUNCOMPSIZE);
|
||||
|
||||
if (io->read(io, inp->compbuf, inp->compsize) != inp->compsize)
|
||||
return false;
|
||||
if (uncompress(inp->uncompbuf, &ul, inp->compbuf, inp->compsize) != Z_OK)
|
||||
return false;
|
||||
if (ul != ((uLongf) inp->uncompsize)) // corrupt data.
|
||||
return false;
|
||||
|
||||
inp->uncompindex = 0;
|
||||
return true;
|
||||
} // unpack
|
||||
|
||||
static boolean MojoInput_uz2_ready(MojoInput *io)
|
||||
{
|
||||
UZ2input *input = (UZ2input *) io->opaque;
|
||||
if (input->uncompsize > 0)
|
||||
return true;
|
||||
return true; // !!! FIXME: need to know we have a full compressed block.
|
||||
} // MojoInput_uz2_ready
|
||||
|
||||
static int64 MojoInput_uz2_read(MojoInput *io, void *_buf, uint32 bufsize)
|
||||
{
|
||||
uint8 *buf = (uint8 *) _buf;
|
||||
UZ2input *input = (UZ2input *) io->opaque;
|
||||
int64 retval = 0;
|
||||
while (bufsize > 0)
|
||||
{
|
||||
const uint32 available = input->uncompsize - input->uncompindex;
|
||||
const uint32 cpy = (available < bufsize) ? available : bufsize;
|
||||
if (available == 0)
|
||||
{
|
||||
if (input->position == input->fsize)
|
||||
return 0;
|
||||
else if (!MojoInput_readui32(input->io, &input->compsize))
|
||||
return (retval == 0) ? -1 : retval;
|
||||
else if (!MojoInput_readui32(input->io, &input->uncompsize))
|
||||
return (retval == 0) ? -1 : retval;
|
||||
else if (!unpack(input))
|
||||
return (retval == 0) ? -1 : retval;
|
||||
continue; // try again.
|
||||
} // if
|
||||
|
||||
memcpy(buf, input->uncompbuf + input->uncompindex, cpy);
|
||||
buf += cpy;
|
||||
bufsize -= cpy;
|
||||
retval += cpy;
|
||||
input->uncompindex += cpy;
|
||||
input->position += cpy;
|
||||
} // while
|
||||
|
||||
return retval;
|
||||
} // MojoInput_uz2_read
|
||||
|
||||
static boolean MojoInput_uz2_seek(MojoInput *io, uint64 pos)
|
||||
{
|
||||
UZ2input *input = (UZ2input *) io->opaque;
|
||||
int64 seekpos = 0;
|
||||
|
||||
// in a perfect world, this wouldn't seek from the start if moving
|
||||
// forward. But oh well.
|
||||
input->position = 0;
|
||||
while (input->position < pos)
|
||||
{
|
||||
if (!input->io->seek(input->io, seekpos))
|
||||
return false;
|
||||
else if (!MojoInput_readui32(io, &input->compsize))
|
||||
return false;
|
||||
else if (!MojoInput_readui32(io, &input->uncompsize))
|
||||
return false;
|
||||
|
||||
// we checked these formally elsewhere.
|
||||
assert(input->compsize > 0);
|
||||
assert(input->uncompsize > 0);
|
||||
assert(input->compsize <= MAXCOMPSIZE);
|
||||
assert(input->uncompsize <= MAXUNCOMPSIZE);
|
||||
|
||||
input->position += input->uncompsize;
|
||||
seekpos += (sizeof (uint32) * 2) + input->compsize;
|
||||
} // while
|
||||
|
||||
// we are positioned on the compressed block that contains the seek target.
|
||||
if (!unpack(input))
|
||||
return false;
|
||||
|
||||
input->position -= input->uncompsize;
|
||||
input->uncompindex = (uint32) (pos - input->position);
|
||||
input->position += input->uncompindex;
|
||||
|
||||
return true;
|
||||
} // MojoInput_uz2_seek
|
||||
|
||||
static int64 MojoInput_uz2_tell(MojoInput *io)
|
||||
{
|
||||
return (int64) (((UZ2input *) io->opaque)->position);
|
||||
} // MojoInput_uz2_tell
|
||||
|
||||
static int64 MojoInput_uz2_length(MojoInput *io)
|
||||
{
|
||||
return ((UZ2input *) io->opaque)->fsize;
|
||||
} // MojoInput_uz2_length
|
||||
|
||||
static MojoInput *MojoInput_uz2_duplicate(MojoInput *io)
|
||||
{
|
||||
MojoInput *retval = NULL;
|
||||
UZ2input *input = (UZ2input *) io->opaque;
|
||||
MojoInput *newio = input->io->duplicate(input->io);
|
||||
|
||||
if (newio != NULL)
|
||||
{
|
||||
UZ2input *newopaque = (UZ2input *) xmalloc(sizeof (UZ2input));
|
||||
newopaque->io = newio;
|
||||
newopaque->fsize = input->fsize;
|
||||
// everything else is properly zero'd by xmalloc().
|
||||
retval = (MojoInput *) xmalloc(sizeof (MojoInput));
|
||||
memcpy(retval, io, sizeof (MojoInput));
|
||||
retval->opaque = newopaque;
|
||||
} // if
|
||||
|
||||
return retval;
|
||||
} // MojoInput_uz2_duplicate
|
||||
|
||||
static void MojoInput_uz2_close(MojoInput *io)
|
||||
{
|
||||
UZ2input *input = (UZ2input *) io->opaque;
|
||||
input->io->close(input->io);
|
||||
free(input);
|
||||
free(io);
|
||||
} // MojoInput_uz2_close
|
||||
|
||||
|
||||
// MojoArchive implementation...
|
||||
|
||||
static boolean MojoArchive_uz2_enumerate(MojoArchive *ar)
|
||||
{
|
||||
UZ2info *info = (UZ2info *) ar->opaque;
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
info->enumerated = false;
|
||||
return true;
|
||||
} // MojoArchive_uz2_enumerate
|
||||
|
||||
|
||||
static const MojoArchiveEntry *MojoArchive_uz2_enumNext(MojoArchive *ar)
|
||||
{
|
||||
UZ2info *info = (UZ2info *) ar->opaque;
|
||||
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
if (info->enumerated)
|
||||
return NULL; // only one file in this "archive".
|
||||
|
||||
ar->prevEnum.perms = MojoPlatform_defaultFilePerms();
|
||||
ar->prevEnum.filesize = info->outsize;
|
||||
ar->prevEnum.filename = xstrdup(info->outname);
|
||||
ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;
|
||||
|
||||
info->enumerated = true;
|
||||
return &ar->prevEnum;
|
||||
} // MojoArchive_uz2_enumNext
|
||||
|
||||
|
||||
static MojoInput *MojoArchive_uz2_openCurrentEntry(MojoArchive *ar)
|
||||
{
|
||||
UZ2info *info = (UZ2info *) ar->opaque;
|
||||
MojoInput *io = NULL;
|
||||
UZ2input *opaque = NULL;
|
||||
MojoInput *dupio = NULL;
|
||||
|
||||
if (!info->enumerated)
|
||||
return NULL;
|
||||
|
||||
dupio = ar->io->duplicate(ar->io);
|
||||
if (dupio == NULL)
|
||||
return NULL;
|
||||
|
||||
opaque = (UZ2input *) xmalloc(sizeof (UZ2input));
|
||||
opaque->io = dupio;
|
||||
opaque->fsize = info->outsize;
|
||||
// rest is zero'd by xmalloc().
|
||||
|
||||
io = (MojoInput *) xmalloc(sizeof (MojoInput));
|
||||
io->ready = MojoInput_uz2_ready;
|
||||
io->read = MojoInput_uz2_read;
|
||||
io->seek = MojoInput_uz2_seek;
|
||||
io->tell = MojoInput_uz2_tell;
|
||||
io->length = MojoInput_uz2_length;
|
||||
io->duplicate = MojoInput_uz2_duplicate;
|
||||
io->close = MojoInput_uz2_close;
|
||||
io->opaque = opaque;
|
||||
|
||||
return io;
|
||||
} // MojoArchive_uz2_openCurrentEntry
|
||||
|
||||
|
||||
static void MojoArchive_uz2_close(MojoArchive *ar)
|
||||
{
|
||||
UZ2info *info = (UZ2info *) ar->opaque;
|
||||
MojoArchive_resetEntry(&ar->prevEnum);
|
||||
ar->io->close(ar->io);
|
||||
free(info->outname);
|
||||
free(info);
|
||||
free(ar);
|
||||
} // MojoArchive_uz2_close
|
||||
|
||||
|
||||
// Unfortunately, we have to walk the whole file, but we don't have to actually
|
||||
// do any decompression work here. Just seek, read 8 bytes, repeat until EOF.
|
||||
static int64 calculate_uz2_outsize(MojoInput *io)
|
||||
{
|
||||
int64 retval = 0;
|
||||
uint32 compsize = 0;
|
||||
uint32 uncompsize = 0;
|
||||
int64 pos = 0;
|
||||
|
||||
if (!io->seek(io, 0))
|
||||
return -1;
|
||||
|
||||
while (MojoInput_readui32(io, &compsize))
|
||||
{
|
||||
if (!MojoInput_readui32(io, &uncompsize))
|
||||
return -1;
|
||||
else if ((compsize > MAXCOMPSIZE) || (uncompsize > MAXUNCOMPSIZE))
|
||||
return -1;
|
||||
else if ((compsize == 0) || (uncompsize == 0))
|
||||
return -1;
|
||||
retval += uncompsize;
|
||||
pos += (sizeof (uint32) * 2) + compsize;
|
||||
if (!io->seek(io, pos))
|
||||
return -1;
|
||||
} // while
|
||||
|
||||
if (!io->seek(io, 0)) // make sure we're back to the start.
|
||||
return -1;
|
||||
|
||||
return retval;
|
||||
} // calculate_uz2_outsize
|
||||
|
||||
|
||||
MojoArchive *MojoArchive_createUZ2(MojoInput *io, const char *origfname)
|
||||
{
|
||||
MojoArchive *ar = NULL;
|
||||
const char *fname = NULL;
|
||||
char *outname = NULL;
|
||||
size_t len = 0;
|
||||
int64 outsize = 0;
|
||||
UZ2info *uz2info = NULL;
|
||||
|
||||
// There's no magic in a UZ2 that allows us to identify the format.
|
||||
// The higher-level won't call this unless the file extension in
|
||||
// (origfname) is ".uz2"
|
||||
|
||||
// Figure out the output name ("x.uz2" would produce "x").
|
||||
if (origfname == NULL)
|
||||
return NULL; // just in case.
|
||||
fname = strrchr(origfname, '/');
|
||||
if (fname == NULL)
|
||||
fname = origfname;
|
||||
else
|
||||
fname++;
|
||||
|
||||
len = strlen(fname) - 4; // -4 == ".uz2"
|
||||
if (strcasecmp(fname + len, ".uz2") != 0)
|
||||
return NULL; // just in case.
|
||||
|
||||
outsize = calculate_uz2_outsize(io);
|
||||
if (outsize < 0)
|
||||
return NULL; // wasn't really a uz2? Corrupt/truncated file?
|
||||
outname = (char *) xmalloc(len+1);
|
||||
memcpy(outname, fname, len);
|
||||
outname[len] = '\0';
|
||||
|
||||
uz2info = (UZ2info *) xmalloc(sizeof (UZ2info));
|
||||
uz2info->enumerated = false;
|
||||
uz2info->outname = outname;
|
||||
uz2info->outsize = outsize;
|
||||
|
||||
ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
|
||||
ar->opaque = uz2info;
|
||||
ar->enumerate = MojoArchive_uz2_enumerate;
|
||||
ar->enumNext = MojoArchive_uz2_enumNext;
|
||||
ar->openCurrentEntry = MojoArchive_uz2_openCurrentEntry;
|
||||
ar->close = MojoArchive_uz2_close;
|
||||
ar->io = io;
|
||||
return ar;
|
||||
} // MojoArchive_createUZ2
|
||||
|
||||
#endif // SUPPORT_UZ2
|
||||
|
||||
// end of archive_uz2.c ...
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is in a separate file so that we can recompile it every time
|
||||
* without it forcing a recompile on something ccache would otherwise not
|
||||
* have to rebuild...this file's checksum changes every time you build it
|
||||
* due to the __DATE__ and __TIME__ macros.
|
||||
*
|
||||
* The makefile will rebuild this file everytime it relinks an executable
|
||||
* so that we'll always have a unique build string.
|
||||
*
|
||||
* APPNAME and APPREV need to be predefined in the build system.
|
||||
* The rest are supposed to be supplied by the compiler.
|
||||
*/
|
||||
|
||||
#ifndef APPID
|
||||
#error Please define APPID in the build system.
|
||||
#endif
|
||||
|
||||
#ifndef APPREV
|
||||
#error Please define APPREV in the build system.
|
||||
#endif
|
||||
|
||||
#if (defined __GNUC__)
|
||||
# define VERSTR2(x) #x
|
||||
# define VERSTR(x) VERSTR2(x)
|
||||
# define COMPILERVER " " VERSTR(__GNUC__) "." VERSTR(__GNUC_MINOR__) "." VERSTR(__GNUC_PATCHLEVEL__)
|
||||
#elif (defined __SUNPRO_C)
|
||||
# define VERSTR2(x) #x
|
||||
# define VERSTR(x) VERSTR2(x)
|
||||
# define COMPILERVER " " VERSTR(__SUNPRO_C)
|
||||
#elif (defined __VERSION__)
|
||||
# define COMPILERVER " " __VERSION__
|
||||
#else
|
||||
# define COMPILERVER ""
|
||||
#endif
|
||||
|
||||
#ifndef __DATE__
|
||||
#define __DATE__ "(Unknown build date)"
|
||||
#endif
|
||||
|
||||
#ifndef __TIME__
|
||||
#define __TIME__ "(Unknown build time)"
|
||||
#endif
|
||||
|
||||
#ifndef COMPILER
|
||||
#if (defined __GNUC__)
|
||||
#define COMPILER "GCC"
|
||||
#elif (defined _MSC_VER)
|
||||
#define COMPILER "Visual Studio"
|
||||
#elif (defined __SUNPRO_C)
|
||||
#define COMPILER "Sun Studio"
|
||||
#else
|
||||
#error Please define your platform.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// macro mess so we can turn APPID and APPREV into a string literal...
|
||||
#define MAKEBUILDVERSTRINGLITERAL2(id, rev) \
|
||||
#id ", revision " #rev ", built " __DATE__ " " __TIME__ \
|
||||
", by " COMPILER COMPILERVER
|
||||
|
||||
#define MAKEBUILDVERSTRINGLITERAL(id, rev) MAKEBUILDVERSTRINGLITERAL2(id, rev)
|
||||
|
||||
const char *GBuildVer = MAKEBUILDVERSTRINGLITERAL(APPID, APPREV);
|
||||
|
||||
// end of buildver.c ...
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,282 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Public header file for the library. ---*/
|
||||
/*--- bzlib.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#ifndef _BZLIB_H
|
||||
#define _BZLIB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BZ_RUN 0
|
||||
#define BZ_FLUSH 1
|
||||
#define BZ_FINISH 2
|
||||
|
||||
#define BZ_OK 0
|
||||
#define BZ_RUN_OK 1
|
||||
#define BZ_FLUSH_OK 2
|
||||
#define BZ_FINISH_OK 3
|
||||
#define BZ_STREAM_END 4
|
||||
#define BZ_SEQUENCE_ERROR (-1)
|
||||
#define BZ_PARAM_ERROR (-2)
|
||||
#define BZ_MEM_ERROR (-3)
|
||||
#define BZ_DATA_ERROR (-4)
|
||||
#define BZ_DATA_ERROR_MAGIC (-5)
|
||||
#define BZ_IO_ERROR (-6)
|
||||
#define BZ_UNEXPECTED_EOF (-7)
|
||||
#define BZ_OUTBUFF_FULL (-8)
|
||||
#define BZ_CONFIG_ERROR (-9)
|
||||
|
||||
typedef
|
||||
struct {
|
||||
char *next_in;
|
||||
unsigned int avail_in;
|
||||
unsigned int total_in_lo32;
|
||||
unsigned int total_in_hi32;
|
||||
|
||||
char *next_out;
|
||||
unsigned int avail_out;
|
||||
unsigned int total_out_lo32;
|
||||
unsigned int total_out_hi32;
|
||||
|
||||
void *state;
|
||||
|
||||
void *(*bzalloc)(void *,int,int);
|
||||
void (*bzfree)(void *,void *);
|
||||
void *opaque;
|
||||
}
|
||||
bz_stream;
|
||||
|
||||
|
||||
#ifndef BZ_IMPORT
|
||||
#define BZ_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
/* Need a definitition for FILE */
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# ifdef small
|
||||
/* windows.h define small to char */
|
||||
# undef small
|
||||
# endif
|
||||
# ifdef BZ_EXPORT
|
||||
# define BZ_API(func) WINAPI func
|
||||
# define BZ_EXTERN extern
|
||||
# else
|
||||
/* import windows dll dynamically */
|
||||
# define BZ_API(func) (WINAPI * func)
|
||||
# define BZ_EXTERN
|
||||
# endif
|
||||
#else
|
||||
# define BZ_API(func) func
|
||||
# define BZ_EXTERN extern
|
||||
#endif
|
||||
|
||||
|
||||
/*-- Core (low-level) library functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressInit) (
|
||||
bz_stream* strm,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompress) (
|
||||
bz_stream* strm,
|
||||
int action
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd) (
|
||||
bz_stream* strm
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit) (
|
||||
bz_stream *strm,
|
||||
int verbosity,
|
||||
int small
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompress) (
|
||||
bz_stream* strm
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd) (
|
||||
bz_stream *strm
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*-- High(er) level library functions --*/
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
#define BZ_MAX_UNUSED 5000
|
||||
|
||||
typedef void BZFILE;
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzReadOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int verbosity,
|
||||
int small,
|
||||
void* unused,
|
||||
int nUnused
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void** unused,
|
||||
int* nUnused
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzRead) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN BZFILE* BZ_API(BZ2_bzWriteOpen) (
|
||||
int* bzerror,
|
||||
FILE* f,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWrite) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in,
|
||||
unsigned int* nbytes_out
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64) (
|
||||
int* bzerror,
|
||||
BZFILE* b,
|
||||
int abandon,
|
||||
unsigned int* nbytes_in_lo32,
|
||||
unsigned int* nbytes_in_hi32,
|
||||
unsigned int* nbytes_out_lo32,
|
||||
unsigned int* nbytes_out_hi32
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
/*-- Utility functions --*/
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress) (
|
||||
char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int blockSize100k,
|
||||
int verbosity,
|
||||
int workFactor
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress) (
|
||||
char* dest,
|
||||
unsigned int* destLen,
|
||||
char* source,
|
||||
unsigned int sourceLen,
|
||||
int small,
|
||||
int verbosity
|
||||
);
|
||||
|
||||
|
||||
/*--
|
||||
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
|
||||
to support better zlib compatibility.
|
||||
This code is not _officially_ part of libbzip2 (yet);
|
||||
I haven't tested it, documented it, or considered the
|
||||
threading-safeness of it.
|
||||
If this code breaks, please contact both Yoshioka and me.
|
||||
--*/
|
||||
|
||||
BZ_EXTERN const char * BZ_API(BZ2_bzlibVersion) (
|
||||
void
|
||||
);
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
BZ_EXTERN BZFILE * BZ_API(BZ2_bzopen) (
|
||||
const char *path,
|
||||
const char *mode
|
||||
);
|
||||
|
||||
BZ_EXTERN BZFILE * BZ_API(BZ2_bzdopen) (
|
||||
int fd,
|
||||
const char *mode
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzread) (
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzwrite) (
|
||||
BZFILE* b,
|
||||
void* buf,
|
||||
int len
|
||||
);
|
||||
|
||||
BZ_EXTERN int BZ_API(BZ2_bzflush) (
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN void BZ_API(BZ2_bzclose) (
|
||||
BZFILE* b
|
||||
);
|
||||
|
||||
BZ_EXTERN const char * BZ_API(BZ2_bzerror) (
|
||||
BZFILE *b,
|
||||
int *errnum
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end bzlib.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1,509 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Private header file for the library. ---*/
|
||||
/*--- bzlib_private.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#ifndef _BZLIB_PRIVATE_H
|
||||
#define _BZLIB_PRIVATE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "bzlib.h"
|
||||
|
||||
|
||||
|
||||
/*-- General stuff. --*/
|
||||
|
||||
#define BZ_VERSION "1.0.6, 6-Sept-2010"
|
||||
|
||||
typedef char Char;
|
||||
typedef unsigned char Bool;
|
||||
typedef unsigned char UChar;
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#define True ((Bool)1)
|
||||
#define False ((Bool)0)
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define __inline__ /* */
|
||||
#endif
|
||||
|
||||
#ifndef BZ_NO_STDIO
|
||||
|
||||
extern void BZ2_bz__AssertH__fail ( int errcode );
|
||||
#define AssertH(cond,errcode) \
|
||||
{ if (!(cond)) BZ2_bz__AssertH__fail ( errcode ); }
|
||||
|
||||
#if BZ_DEBUG
|
||||
#define AssertD(cond,msg) \
|
||||
{ if (!(cond)) { \
|
||||
fprintf ( stderr, \
|
||||
"\n\nlibbzip2(debug build): internal error\n\t%s\n", msg );\
|
||||
exit(1); \
|
||||
}}
|
||||
#else
|
||||
#define AssertD(cond,msg) /* */
|
||||
#endif
|
||||
|
||||
#define VPrintf0(zf) \
|
||||
fprintf(stderr,zf)
|
||||
#define VPrintf1(zf,za1) \
|
||||
fprintf(stderr,zf,za1)
|
||||
#define VPrintf2(zf,za1,za2) \
|
||||
fprintf(stderr,zf,za1,za2)
|
||||
#define VPrintf3(zf,za1,za2,za3) \
|
||||
fprintf(stderr,zf,za1,za2,za3)
|
||||
#define VPrintf4(zf,za1,za2,za3,za4) \
|
||||
fprintf(stderr,zf,za1,za2,za3,za4)
|
||||
#define VPrintf5(zf,za1,za2,za3,za4,za5) \
|
||||
fprintf(stderr,zf,za1,za2,za3,za4,za5)
|
||||
|
||||
#else
|
||||
|
||||
extern void bz_internal_error ( int errcode );
|
||||
#define AssertH(cond,errcode) \
|
||||
{ if (!(cond)) bz_internal_error ( errcode ); }
|
||||
#define AssertD(cond,msg) do { } while (0)
|
||||
#define VPrintf0(zf) do { } while (0)
|
||||
#define VPrintf1(zf,za1) do { } while (0)
|
||||
#define VPrintf2(zf,za1,za2) do { } while (0)
|
||||
#define VPrintf3(zf,za1,za2,za3) do { } while (0)
|
||||
#define VPrintf4(zf,za1,za2,za3,za4) do { } while (0)
|
||||
#define VPrintf5(zf,za1,za2,za3,za4,za5) do { } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque,(nnn),1)
|
||||
#define BZFREE(ppp) (strm->bzfree)(strm->opaque,(ppp))
|
||||
|
||||
|
||||
/*-- Header bytes. --*/
|
||||
|
||||
#define BZ_HDR_B 0x42 /* 'B' */
|
||||
#define BZ_HDR_Z 0x5a /* 'Z' */
|
||||
#define BZ_HDR_h 0x68 /* 'h' */
|
||||
#define BZ_HDR_0 0x30 /* '0' */
|
||||
|
||||
/*-- Constants for the back end. --*/
|
||||
|
||||
#define BZ_MAX_ALPHA_SIZE 258
|
||||
#define BZ_MAX_CODE_LEN 23
|
||||
|
||||
#define BZ_RUNA 0
|
||||
#define BZ_RUNB 1
|
||||
|
||||
#define BZ_N_GROUPS 6
|
||||
#define BZ_G_SIZE 50
|
||||
#define BZ_N_ITERS 4
|
||||
|
||||
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
|
||||
|
||||
|
||||
|
||||
/*-- Stuff for randomising repetitive blocks. --*/
|
||||
|
||||
extern Int32 BZ2_rNums[512];
|
||||
|
||||
#define BZ_RAND_DECLS \
|
||||
Int32 rNToGo; \
|
||||
Int32 rTPos \
|
||||
|
||||
#define BZ_RAND_INIT_MASK \
|
||||
s->rNToGo = 0; \
|
||||
s->rTPos = 0 \
|
||||
|
||||
#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
|
||||
|
||||
#define BZ_RAND_UPD_MASK \
|
||||
if (s->rNToGo == 0) { \
|
||||
s->rNToGo = BZ2_rNums[s->rTPos]; \
|
||||
s->rTPos++; \
|
||||
if (s->rTPos == 512) s->rTPos = 0; \
|
||||
} \
|
||||
s->rNToGo--;
|
||||
|
||||
|
||||
|
||||
/*-- Stuff for doing CRCs. --*/
|
||||
|
||||
extern UInt32 BZ2_crc32Table[256];
|
||||
|
||||
#define BZ_INITIALISE_CRC(crcVar) \
|
||||
{ \
|
||||
crcVar = 0xffffffffL; \
|
||||
}
|
||||
|
||||
#define BZ_FINALISE_CRC(crcVar) \
|
||||
{ \
|
||||
crcVar = ~(crcVar); \
|
||||
}
|
||||
|
||||
#define BZ_UPDATE_CRC(crcVar,cha) \
|
||||
{ \
|
||||
crcVar = (crcVar << 8) ^ \
|
||||
BZ2_crc32Table[(crcVar >> 24) ^ \
|
||||
((UChar)cha)]; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-- States and modes for compression. --*/
|
||||
|
||||
#define BZ_M_IDLE 1
|
||||
#define BZ_M_RUNNING 2
|
||||
#define BZ_M_FLUSHING 3
|
||||
#define BZ_M_FINISHING 4
|
||||
|
||||
#define BZ_S_OUTPUT 1
|
||||
#define BZ_S_INPUT 2
|
||||
|
||||
#define BZ_N_RADIX 2
|
||||
#define BZ_N_QSORT 12
|
||||
#define BZ_N_SHELL 18
|
||||
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
|
||||
|
||||
|
||||
|
||||
|
||||
/*-- Structure holding all the compression-side stuff. --*/
|
||||
|
||||
typedef
|
||||
struct {
|
||||
/* pointer back to the struct bz_stream */
|
||||
bz_stream* strm;
|
||||
|
||||
/* mode this stream is in, and whether inputting */
|
||||
/* or outputting data */
|
||||
Int32 mode;
|
||||
Int32 state;
|
||||
|
||||
/* remembers avail_in when flush/finish requested */
|
||||
UInt32 avail_in_expect;
|
||||
|
||||
/* for doing the block sorting */
|
||||
UInt32* arr1;
|
||||
UInt32* arr2;
|
||||
UInt32* ftab;
|
||||
Int32 origPtr;
|
||||
|
||||
/* aliases for arr1 and arr2 */
|
||||
UInt32* ptr;
|
||||
UChar* block;
|
||||
UInt16* mtfv;
|
||||
UChar* zbits;
|
||||
|
||||
/* for deciding when to use the fallback sorting algorithm */
|
||||
Int32 workFactor;
|
||||
|
||||
/* run-length-encoding of the input */
|
||||
UInt32 state_in_ch;
|
||||
Int32 state_in_len;
|
||||
BZ_RAND_DECLS;
|
||||
|
||||
/* input and output limits and current posns */
|
||||
Int32 nblock;
|
||||
Int32 nblockMAX;
|
||||
Int32 numZ;
|
||||
Int32 state_out_pos;
|
||||
|
||||
/* map of bytes used in block */
|
||||
Int32 nInUse;
|
||||
Bool inUse[256];
|
||||
UChar unseqToSeq[256];
|
||||
|
||||
/* the buffer for bit stream creation */
|
||||
UInt32 bsBuff;
|
||||
Int32 bsLive;
|
||||
|
||||
/* block and combined CRCs */
|
||||
UInt32 blockCRC;
|
||||
UInt32 combinedCRC;
|
||||
|
||||
/* misc administratium */
|
||||
Int32 verbosity;
|
||||
Int32 blockNo;
|
||||
Int32 blockSize100k;
|
||||
|
||||
/* stuff for coding the MTF values */
|
||||
Int32 nMTF;
|
||||
Int32 mtfFreq [BZ_MAX_ALPHA_SIZE];
|
||||
UChar selector [BZ_MAX_SELECTORS];
|
||||
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 rfreq [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
/* second dimension: only 3 needed; 4 makes index calculations faster */
|
||||
UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
|
||||
|
||||
}
|
||||
EState;
|
||||
|
||||
|
||||
|
||||
/*-- externs for compression. --*/
|
||||
|
||||
extern void
|
||||
BZ2_blockSort ( EState* );
|
||||
|
||||
extern void
|
||||
BZ2_compressBlock ( EState*, Bool );
|
||||
|
||||
extern void
|
||||
BZ2_bsInitWrite ( EState* );
|
||||
|
||||
extern void
|
||||
BZ2_hbAssignCodes ( Int32*, UChar*, Int32, Int32, Int32 );
|
||||
|
||||
extern void
|
||||
BZ2_hbMakeCodeLengths ( UChar*, Int32*, Int32, Int32 );
|
||||
|
||||
|
||||
|
||||
/*-- states for decompression. --*/
|
||||
|
||||
#define BZ_X_IDLE 1
|
||||
#define BZ_X_OUTPUT 2
|
||||
|
||||
#define BZ_X_MAGIC_1 10
|
||||
#define BZ_X_MAGIC_2 11
|
||||
#define BZ_X_MAGIC_3 12
|
||||
#define BZ_X_MAGIC_4 13
|
||||
#define BZ_X_BLKHDR_1 14
|
||||
#define BZ_X_BLKHDR_2 15
|
||||
#define BZ_X_BLKHDR_3 16
|
||||
#define BZ_X_BLKHDR_4 17
|
||||
#define BZ_X_BLKHDR_5 18
|
||||
#define BZ_X_BLKHDR_6 19
|
||||
#define BZ_X_BCRC_1 20
|
||||
#define BZ_X_BCRC_2 21
|
||||
#define BZ_X_BCRC_3 22
|
||||
#define BZ_X_BCRC_4 23
|
||||
#define BZ_X_RANDBIT 24
|
||||
#define BZ_X_ORIGPTR_1 25
|
||||
#define BZ_X_ORIGPTR_2 26
|
||||
#define BZ_X_ORIGPTR_3 27
|
||||
#define BZ_X_MAPPING_1 28
|
||||
#define BZ_X_MAPPING_2 29
|
||||
#define BZ_X_SELECTOR_1 30
|
||||
#define BZ_X_SELECTOR_2 31
|
||||
#define BZ_X_SELECTOR_3 32
|
||||
#define BZ_X_CODING_1 33
|
||||
#define BZ_X_CODING_2 34
|
||||
#define BZ_X_CODING_3 35
|
||||
#define BZ_X_MTF_1 36
|
||||
#define BZ_X_MTF_2 37
|
||||
#define BZ_X_MTF_3 38
|
||||
#define BZ_X_MTF_4 39
|
||||
#define BZ_X_MTF_5 40
|
||||
#define BZ_X_MTF_6 41
|
||||
#define BZ_X_ENDHDR_2 42
|
||||
#define BZ_X_ENDHDR_3 43
|
||||
#define BZ_X_ENDHDR_4 44
|
||||
#define BZ_X_ENDHDR_5 45
|
||||
#define BZ_X_ENDHDR_6 46
|
||||
#define BZ_X_CCRC_1 47
|
||||
#define BZ_X_CCRC_2 48
|
||||
#define BZ_X_CCRC_3 49
|
||||
#define BZ_X_CCRC_4 50
|
||||
|
||||
|
||||
|
||||
/*-- Constants for the fast MTF decoder. --*/
|
||||
|
||||
#define MTFA_SIZE 4096
|
||||
#define MTFL_SIZE 16
|
||||
|
||||
|
||||
|
||||
/*-- Structure holding all the decompression-side stuff. --*/
|
||||
|
||||
typedef
|
||||
struct {
|
||||
/* pointer back to the struct bz_stream */
|
||||
bz_stream* strm;
|
||||
|
||||
/* state indicator for this stream */
|
||||
Int32 state;
|
||||
|
||||
/* for doing the final run-length decoding */
|
||||
UChar state_out_ch;
|
||||
Int32 state_out_len;
|
||||
Bool blockRandomised;
|
||||
BZ_RAND_DECLS;
|
||||
|
||||
/* the buffer for bit stream reading */
|
||||
UInt32 bsBuff;
|
||||
Int32 bsLive;
|
||||
|
||||
/* misc administratium */
|
||||
Int32 blockSize100k;
|
||||
Bool smallDecompress;
|
||||
Int32 currBlockNo;
|
||||
Int32 verbosity;
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform */
|
||||
Int32 origPtr;
|
||||
UInt32 tPos;
|
||||
Int32 k0;
|
||||
Int32 unzftab[256];
|
||||
Int32 nblock_used;
|
||||
Int32 cftab[257];
|
||||
Int32 cftabCopy[257];
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform (FAST) */
|
||||
UInt32 *tt;
|
||||
|
||||
/* for undoing the Burrows-Wheeler transform (SMALL) */
|
||||
UInt16 *ll16;
|
||||
UChar *ll4;
|
||||
|
||||
/* stored and calculated CRCs */
|
||||
UInt32 storedBlockCRC;
|
||||
UInt32 storedCombinedCRC;
|
||||
UInt32 calculatedBlockCRC;
|
||||
UInt32 calculatedCombinedCRC;
|
||||
|
||||
/* map of bytes used in block */
|
||||
Int32 nInUse;
|
||||
Bool inUse[256];
|
||||
Bool inUse16[16];
|
||||
UChar seqToUnseq[256];
|
||||
|
||||
/* for decoding the MTF values */
|
||||
UChar mtfa [MTFA_SIZE];
|
||||
Int32 mtfbase[256 / MTFL_SIZE];
|
||||
UChar selector [BZ_MAX_SELECTORS];
|
||||
UChar selectorMtf[BZ_MAX_SELECTORS];
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
|
||||
Int32 limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 minLens[BZ_N_GROUPS];
|
||||
|
||||
/* save area for scalars in the main decompress code */
|
||||
Int32 save_i;
|
||||
Int32 save_j;
|
||||
Int32 save_t;
|
||||
Int32 save_alphaSize;
|
||||
Int32 save_nGroups;
|
||||
Int32 save_nSelectors;
|
||||
Int32 save_EOB;
|
||||
Int32 save_groupNo;
|
||||
Int32 save_groupPos;
|
||||
Int32 save_nextSym;
|
||||
Int32 save_nblockMAX;
|
||||
Int32 save_nblock;
|
||||
Int32 save_es;
|
||||
Int32 save_N;
|
||||
Int32 save_curr;
|
||||
Int32 save_zt;
|
||||
Int32 save_zn;
|
||||
Int32 save_zvec;
|
||||
Int32 save_zj;
|
||||
Int32 save_gSel;
|
||||
Int32 save_gMinlen;
|
||||
Int32* save_gLimit;
|
||||
Int32* save_gBase;
|
||||
Int32* save_gPerm;
|
||||
|
||||
}
|
||||
DState;
|
||||
|
||||
|
||||
|
||||
/*-- Macros for decompression. --*/
|
||||
|
||||
#define BZ_GET_FAST(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
|
||||
s->tPos = s->tt[s->tPos]; \
|
||||
cccc = (UChar)(s->tPos & 0xff); \
|
||||
s->tPos >>= 8;
|
||||
|
||||
#define BZ_GET_FAST_C(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \
|
||||
c_tPos = c_tt[c_tPos]; \
|
||||
cccc = (UChar)(c_tPos & 0xff); \
|
||||
c_tPos >>= 8;
|
||||
|
||||
#define SET_LL4(i,n) \
|
||||
{ if (((i) & 0x1) == 0) \
|
||||
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); else \
|
||||
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
|
||||
}
|
||||
|
||||
#define GET_LL4(i) \
|
||||
((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
|
||||
|
||||
#define SET_LL(i,n) \
|
||||
{ s->ll16[i] = (UInt16)(n & 0x0000ffff); \
|
||||
SET_LL4(i, n >> 16); \
|
||||
}
|
||||
|
||||
#define GET_LL(i) \
|
||||
(((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
|
||||
|
||||
#define BZ_GET_SMALL(cccc) \
|
||||
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
|
||||
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
|
||||
cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
|
||||
s->tPos = GET_LL(s->tPos);
|
||||
|
||||
|
||||
/*-- externs for decompression. --*/
|
||||
|
||||
extern Int32
|
||||
BZ2_indexIntoF ( Int32, Int32* );
|
||||
|
||||
extern Int32
|
||||
BZ2_decompress ( DState* );
|
||||
|
||||
extern void
|
||||
BZ2_hbCreateDecodeTables ( Int32*, Int32*, Int32*, UChar*,
|
||||
Int32, Int32, Int32 );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*-- BZ_NO_STDIO seems to make NULL disappear on some platforms. --*/
|
||||
|
||||
#ifdef BZ_NO_STDIO
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end bzlib_private.h ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1,672 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Compression machinery (not incl block sorting) ---*/
|
||||
/*--- compress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* CHANGES
|
||||
0.9.0 -- original version.
|
||||
0.9.0a/b -- no changes in this file.
|
||||
0.9.0c -- changed setting of nGroups in sendMTFValues()
|
||||
so as to do a bit better on small files
|
||||
*/
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- Bit stream I/O ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_bsInitWrite ( EState* s )
|
||||
{
|
||||
s->bsLive = 0;
|
||||
s->bsBuff = 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void bsFinishWrite ( EState* s )
|
||||
{
|
||||
while (s->bsLive > 0) {
|
||||
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
|
||||
s->numZ++;
|
||||
s->bsBuff <<= 8;
|
||||
s->bsLive -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define bsNEEDW(nz) \
|
||||
{ \
|
||||
while (s->bsLive >= 8) { \
|
||||
s->zbits[s->numZ] \
|
||||
= (UChar)(s->bsBuff >> 24); \
|
||||
s->numZ++; \
|
||||
s->bsBuff <<= 8; \
|
||||
s->bsLive -= 8; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
__inline__
|
||||
void bsW ( EState* s, Int32 n, UInt32 v )
|
||||
{
|
||||
bsNEEDW ( n );
|
||||
s->bsBuff |= (v << (32 - s->bsLive - n));
|
||||
s->bsLive += n;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void bsPutUInt32 ( EState* s, UInt32 u )
|
||||
{
|
||||
bsW ( s, 8, (u >> 24) & 0xffL );
|
||||
bsW ( s, 8, (u >> 16) & 0xffL );
|
||||
bsW ( s, 8, (u >> 8) & 0xffL );
|
||||
bsW ( s, 8, u & 0xffL );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void bsPutUChar ( EState* s, UChar c )
|
||||
{
|
||||
bsW( s, 8, (UInt32)c );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
/*--- The back end proper ---*/
|
||||
/*---------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void makeMaps_e ( EState* s )
|
||||
{
|
||||
Int32 i;
|
||||
s->nInUse = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (s->inUse[i]) {
|
||||
s->unseqToSeq[i] = s->nInUse;
|
||||
s->nInUse++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void generateMTFValues ( EState* s )
|
||||
{
|
||||
UChar yy[256];
|
||||
Int32 i, j;
|
||||
Int32 zPend;
|
||||
Int32 wr;
|
||||
Int32 EOB;
|
||||
|
||||
/*
|
||||
After sorting (eg, here),
|
||||
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
|
||||
and
|
||||
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
|
||||
holds the original block data.
|
||||
|
||||
The first thing to do is generate the MTF values,
|
||||
and put them in
|
||||
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
|
||||
Because there are strictly fewer or equal MTF values
|
||||
than block values, ptr values in this area are overwritten
|
||||
with MTF values only when they are no longer needed.
|
||||
|
||||
The final compressed bitstream is generated into the
|
||||
area starting at
|
||||
(UChar*) (&((UChar*)s->arr2)[s->nblock])
|
||||
|
||||
These storage aliases are set up in bzCompressInit(),
|
||||
except for the last one, which is arranged in
|
||||
compressBlock().
|
||||
*/
|
||||
UInt32* ptr = s->ptr;
|
||||
UChar* block = s->block;
|
||||
UInt16* mtfv = s->mtfv;
|
||||
|
||||
makeMaps_e ( s );
|
||||
EOB = s->nInUse+1;
|
||||
|
||||
for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
|
||||
|
||||
wr = 0;
|
||||
zPend = 0;
|
||||
for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
|
||||
|
||||
for (i = 0; i < s->nblock; i++) {
|
||||
UChar ll_i;
|
||||
AssertD ( wr <= i, "generateMTFValues(1)" );
|
||||
j = ptr[i]-1; if (j < 0) j += s->nblock;
|
||||
ll_i = s->unseqToSeq[block[j]];
|
||||
AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
|
||||
|
||||
if (yy[0] == ll_i) {
|
||||
zPend++;
|
||||
} else {
|
||||
|
||||
if (zPend > 0) {
|
||||
zPend--;
|
||||
while (True) {
|
||||
if (zPend & 1) {
|
||||
mtfv[wr] = BZ_RUNB; wr++;
|
||||
s->mtfFreq[BZ_RUNB]++;
|
||||
} else {
|
||||
mtfv[wr] = BZ_RUNA; wr++;
|
||||
s->mtfFreq[BZ_RUNA]++;
|
||||
}
|
||||
if (zPend < 2) break;
|
||||
zPend = (zPend - 2) / 2;
|
||||
};
|
||||
zPend = 0;
|
||||
}
|
||||
{
|
||||
register UChar rtmp;
|
||||
register UChar* ryy_j;
|
||||
register UChar rll_i;
|
||||
rtmp = yy[1];
|
||||
yy[1] = yy[0];
|
||||
ryy_j = &(yy[1]);
|
||||
rll_i = ll_i;
|
||||
while ( rll_i != rtmp ) {
|
||||
register UChar rtmp2;
|
||||
ryy_j++;
|
||||
rtmp2 = rtmp;
|
||||
rtmp = *ryy_j;
|
||||
*ryy_j = rtmp2;
|
||||
};
|
||||
yy[0] = rtmp;
|
||||
j = ryy_j - &(yy[0]);
|
||||
mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (zPend > 0) {
|
||||
zPend--;
|
||||
while (True) {
|
||||
if (zPend & 1) {
|
||||
mtfv[wr] = BZ_RUNB; wr++;
|
||||
s->mtfFreq[BZ_RUNB]++;
|
||||
} else {
|
||||
mtfv[wr] = BZ_RUNA; wr++;
|
||||
s->mtfFreq[BZ_RUNA]++;
|
||||
}
|
||||
if (zPend < 2) break;
|
||||
zPend = (zPend - 2) / 2;
|
||||
};
|
||||
zPend = 0;
|
||||
}
|
||||
|
||||
mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
|
||||
|
||||
s->nMTF = wr;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define BZ_LESSER_ICOST 0
|
||||
#define BZ_GREATER_ICOST 15
|
||||
|
||||
static
|
||||
void sendMTFValues ( EState* s )
|
||||
{
|
||||
Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
|
||||
Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
|
||||
Int32 nGroups, nBytes;
|
||||
|
||||
/*--
|
||||
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
is a global since the decoder also needs it.
|
||||
|
||||
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
|
||||
are also globals only used in this proc.
|
||||
Made global to keep stack frame size small.
|
||||
--*/
|
||||
|
||||
|
||||
UInt16 cost[BZ_N_GROUPS];
|
||||
Int32 fave[BZ_N_GROUPS];
|
||||
|
||||
UInt16* mtfv = s->mtfv;
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
|
||||
"%d+2 syms in use\n",
|
||||
s->nblock, s->nMTF, s->nInUse );
|
||||
|
||||
alphaSize = s->nInUse+2;
|
||||
for (t = 0; t < BZ_N_GROUPS; t++)
|
||||
for (v = 0; v < alphaSize; v++)
|
||||
s->len[t][v] = BZ_GREATER_ICOST;
|
||||
|
||||
/*--- Decide how many coding tables to use ---*/
|
||||
AssertH ( s->nMTF > 0, 3001 );
|
||||
if (s->nMTF < 200) nGroups = 2; else
|
||||
if (s->nMTF < 600) nGroups = 3; else
|
||||
if (s->nMTF < 1200) nGroups = 4; else
|
||||
if (s->nMTF < 2400) nGroups = 5; else
|
||||
nGroups = 6;
|
||||
|
||||
/*--- Generate an initial set of coding tables ---*/
|
||||
{
|
||||
Int32 nPart, remF, tFreq, aFreq;
|
||||
|
||||
nPart = nGroups;
|
||||
remF = s->nMTF;
|
||||
gs = 0;
|
||||
while (nPart > 0) {
|
||||
tFreq = remF / nPart;
|
||||
ge = gs-1;
|
||||
aFreq = 0;
|
||||
while (aFreq < tFreq && ge < alphaSize-1) {
|
||||
ge++;
|
||||
aFreq += s->mtfFreq[ge];
|
||||
}
|
||||
|
||||
if (ge > gs
|
||||
&& nPart != nGroups && nPart != 1
|
||||
&& ((nGroups-nPart) % 2 == 1)) {
|
||||
aFreq -= s->mtfFreq[ge];
|
||||
ge--;
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf5( " initial group %d, [%d .. %d], "
|
||||
"has %d syms (%4.1f%%)\n",
|
||||
nPart, gs, ge, aFreq,
|
||||
(100.0 * (float)aFreq) / (float)(s->nMTF) );
|
||||
|
||||
for (v = 0; v < alphaSize; v++)
|
||||
if (v >= gs && v <= ge)
|
||||
s->len[nPart-1][v] = BZ_LESSER_ICOST; else
|
||||
s->len[nPart-1][v] = BZ_GREATER_ICOST;
|
||||
|
||||
nPart--;
|
||||
gs = ge+1;
|
||||
remF -= aFreq;
|
||||
}
|
||||
}
|
||||
|
||||
/*---
|
||||
Iterate up to BZ_N_ITERS times to improve the tables.
|
||||
---*/
|
||||
for (iter = 0; iter < BZ_N_ITERS; iter++) {
|
||||
|
||||
for (t = 0; t < nGroups; t++) fave[t] = 0;
|
||||
|
||||
for (t = 0; t < nGroups; t++)
|
||||
for (v = 0; v < alphaSize; v++)
|
||||
s->rfreq[t][v] = 0;
|
||||
|
||||
/*---
|
||||
Set up an auxiliary length table which is used to fast-track
|
||||
the common case (nGroups == 6).
|
||||
---*/
|
||||
if (nGroups == 6) {
|
||||
for (v = 0; v < alphaSize; v++) {
|
||||
s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
|
||||
s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
|
||||
s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
|
||||
}
|
||||
}
|
||||
|
||||
nSelectors = 0;
|
||||
totc = 0;
|
||||
gs = 0;
|
||||
while (True) {
|
||||
|
||||
/*--- Set group start & end marks. --*/
|
||||
if (gs >= s->nMTF) break;
|
||||
ge = gs + BZ_G_SIZE - 1;
|
||||
if (ge >= s->nMTF) ge = s->nMTF-1;
|
||||
|
||||
/*--
|
||||
Calculate the cost of this group as coded
|
||||
by each of the coding tables.
|
||||
--*/
|
||||
for (t = 0; t < nGroups; t++) cost[t] = 0;
|
||||
|
||||
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||
/*--- fast track the common case ---*/
|
||||
register UInt32 cost01, cost23, cost45;
|
||||
register UInt16 icv;
|
||||
cost01 = cost23 = cost45 = 0;
|
||||
|
||||
# define BZ_ITER(nn) \
|
||||
icv = mtfv[gs+(nn)]; \
|
||||
cost01 += s->len_pack[icv][0]; \
|
||||
cost23 += s->len_pack[icv][1]; \
|
||||
cost45 += s->len_pack[icv][2]; \
|
||||
|
||||
BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
|
||||
BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
|
||||
BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
|
||||
BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
|
||||
BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
|
||||
BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
|
||||
BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
|
||||
BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
|
||||
BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
|
||||
BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
|
||||
|
||||
# undef BZ_ITER
|
||||
|
||||
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
|
||||
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
|
||||
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
|
||||
|
||||
} else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++) {
|
||||
UInt16 icv = mtfv[i];
|
||||
for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
|
||||
}
|
||||
}
|
||||
|
||||
/*--
|
||||
Find the coding table which is best for this group,
|
||||
and record its identity in the selector table.
|
||||
--*/
|
||||
bc = 999999999; bt = -1;
|
||||
for (t = 0; t < nGroups; t++)
|
||||
if (cost[t] < bc) { bc = cost[t]; bt = t; };
|
||||
totc += bc;
|
||||
fave[bt]++;
|
||||
s->selector[nSelectors] = bt;
|
||||
nSelectors++;
|
||||
|
||||
/*--
|
||||
Increment the symbol frequencies for the selected table.
|
||||
--*/
|
||||
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||
/*--- fast track the common case ---*/
|
||||
|
||||
# define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
|
||||
|
||||
BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
|
||||
BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
|
||||
BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
|
||||
BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
|
||||
BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
|
||||
BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
|
||||
BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
|
||||
BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
|
||||
BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
|
||||
BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
|
||||
|
||||
# undef BZ_ITUR
|
||||
|
||||
} else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++)
|
||||
s->rfreq[bt][ mtfv[i] ]++;
|
||||
}
|
||||
|
||||
gs = ge+1;
|
||||
}
|
||||
if (s->verbosity >= 3) {
|
||||
VPrintf2 ( " pass %d: size is %d, grp uses are ",
|
||||
iter+1, totc/8 );
|
||||
for (t = 0; t < nGroups; t++)
|
||||
VPrintf1 ( "%d ", fave[t] );
|
||||
VPrintf0 ( "\n" );
|
||||
}
|
||||
|
||||
/*--
|
||||
Recompute the tables based on the accumulated frequencies.
|
||||
--*/
|
||||
/* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
|
||||
comment in huffman.c for details. */
|
||||
for (t = 0; t < nGroups; t++)
|
||||
BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
|
||||
alphaSize, 17 /*20*/ );
|
||||
}
|
||||
|
||||
|
||||
AssertH( nGroups < 8, 3002 );
|
||||
AssertH( nSelectors < 32768 &&
|
||||
nSelectors <= (2 + (900000 / BZ_G_SIZE)),
|
||||
3003 );
|
||||
|
||||
|
||||
/*--- Compute MTF values for the selectors. ---*/
|
||||
{
|
||||
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
|
||||
for (i = 0; i < nGroups; i++) pos[i] = i;
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
ll_i = s->selector[i];
|
||||
j = 0;
|
||||
tmp = pos[j];
|
||||
while ( ll_i != tmp ) {
|
||||
j++;
|
||||
tmp2 = tmp;
|
||||
tmp = pos[j];
|
||||
pos[j] = tmp2;
|
||||
};
|
||||
pos[0] = tmp;
|
||||
s->selectorMtf[i] = j;
|
||||
}
|
||||
};
|
||||
|
||||
/*--- Assign actual codes for the tables. --*/
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
minLen = 32;
|
||||
maxLen = 0;
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
|
||||
if (s->len[t][i] < minLen) minLen = s->len[t][i];
|
||||
}
|
||||
AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
|
||||
AssertH ( !(minLen < 1), 3005 );
|
||||
BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
|
||||
minLen, maxLen, alphaSize );
|
||||
}
|
||||
|
||||
/*--- Transmit the mapping table. ---*/
|
||||
{
|
||||
Bool inUse16[16];
|
||||
for (i = 0; i < 16; i++) {
|
||||
inUse16[i] = False;
|
||||
for (j = 0; j < 16; j++)
|
||||
if (s->inUse[i * 16 + j]) inUse16[i] = True;
|
||||
}
|
||||
|
||||
nBytes = s->numZ;
|
||||
for (i = 0; i < 16; i++)
|
||||
if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (inUse16[i])
|
||||
for (j = 0; j < 16; j++) {
|
||||
if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
|
||||
}
|
||||
|
||||
/*--- Now the selectors. ---*/
|
||||
nBytes = s->numZ;
|
||||
bsW ( s, 3, nGroups );
|
||||
bsW ( s, 15, nSelectors );
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
|
||||
bsW(s,1,0);
|
||||
}
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1( "selectors %d, ", s->numZ-nBytes );
|
||||
|
||||
/*--- Now the coding tables. ---*/
|
||||
nBytes = s->numZ;
|
||||
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
Int32 curr = s->len[t][0];
|
||||
bsW ( s, 5, curr );
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
|
||||
while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
|
||||
bsW ( s, 1, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
|
||||
|
||||
/*--- And finally, the block data proper ---*/
|
||||
nBytes = s->numZ;
|
||||
selCtr = 0;
|
||||
gs = 0;
|
||||
while (True) {
|
||||
if (gs >= s->nMTF) break;
|
||||
ge = gs + BZ_G_SIZE - 1;
|
||||
if (ge >= s->nMTF) ge = s->nMTF-1;
|
||||
AssertH ( s->selector[selCtr] < nGroups, 3006 );
|
||||
|
||||
if (nGroups == 6 && 50 == ge-gs+1) {
|
||||
/*--- fast track the common case ---*/
|
||||
UInt16 mtfv_i;
|
||||
UChar* s_len_sel_selCtr
|
||||
= &(s->len[s->selector[selCtr]][0]);
|
||||
Int32* s_code_sel_selCtr
|
||||
= &(s->code[s->selector[selCtr]][0]);
|
||||
|
||||
# define BZ_ITAH(nn) \
|
||||
mtfv_i = mtfv[gs+(nn)]; \
|
||||
bsW ( s, \
|
||||
s_len_sel_selCtr[mtfv_i], \
|
||||
s_code_sel_selCtr[mtfv_i] )
|
||||
|
||||
BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
|
||||
BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
|
||||
BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
|
||||
BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
|
||||
BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
|
||||
BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
|
||||
BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
|
||||
BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
|
||||
BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
|
||||
BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
|
||||
|
||||
# undef BZ_ITAH
|
||||
|
||||
} else {
|
||||
/*--- slow version which correctly handles all situations ---*/
|
||||
for (i = gs; i <= ge; i++) {
|
||||
bsW ( s,
|
||||
s->len [s->selector[selCtr]] [mtfv[i]],
|
||||
s->code [s->selector[selCtr]] [mtfv[i]] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gs = ge+1;
|
||||
selCtr++;
|
||||
}
|
||||
AssertH( selCtr == nSelectors, 3007 );
|
||||
|
||||
if (s->verbosity >= 3)
|
||||
VPrintf1( "codes %d\n", s->numZ-nBytes );
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_compressBlock ( EState* s, Bool is_last_block )
|
||||
{
|
||||
if (s->nblock > 0) {
|
||||
|
||||
BZ_FINALISE_CRC ( s->blockCRC );
|
||||
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
|
||||
s->combinedCRC ^= s->blockCRC;
|
||||
if (s->blockNo > 1) s->numZ = 0;
|
||||
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf4( " block %d: crc = 0x%08x, "
|
||||
"combined CRC = 0x%08x, size = %d\n",
|
||||
s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
|
||||
|
||||
BZ2_blockSort ( s );
|
||||
}
|
||||
|
||||
s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
|
||||
|
||||
/*-- If this is the first block, create the stream header. --*/
|
||||
if (s->blockNo == 1) {
|
||||
BZ2_bsInitWrite ( s );
|
||||
bsPutUChar ( s, BZ_HDR_B );
|
||||
bsPutUChar ( s, BZ_HDR_Z );
|
||||
bsPutUChar ( s, BZ_HDR_h );
|
||||
bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
|
||||
}
|
||||
|
||||
if (s->nblock > 0) {
|
||||
|
||||
bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
|
||||
bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
|
||||
bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
|
||||
|
||||
/*-- Now the block's CRC, so it is in a known place. --*/
|
||||
bsPutUInt32 ( s, s->blockCRC );
|
||||
|
||||
/*--
|
||||
Now a single bit indicating (non-)randomisation.
|
||||
As of version 0.9.5, we use a better sorting algorithm
|
||||
which makes randomisation unnecessary. So always set
|
||||
the randomised bit to 'no'. Of course, the decoder
|
||||
still needs to be able to handle randomised blocks
|
||||
so as to maintain backwards compatibility with
|
||||
older versions of bzip2.
|
||||
--*/
|
||||
bsW(s,1,0);
|
||||
|
||||
bsW ( s, 24, s->origPtr );
|
||||
generateMTFValues ( s );
|
||||
sendMTFValues ( s );
|
||||
}
|
||||
|
||||
|
||||
/*-- If this is the last block, add the stream trailer. --*/
|
||||
if (is_last_block) {
|
||||
|
||||
bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
|
||||
bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
|
||||
bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
|
||||
bsPutUInt32 ( s, s->combinedCRC );
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
|
||||
bsFinishWrite ( s );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end compress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1,104 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Table for doing CRCs ---*/
|
||||
/*--- crctable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
/*--
|
||||
I think this is an implementation of the AUTODIN-II,
|
||||
Ethernet & FDDI 32-bit CRC standard. Vaguely derived
|
||||
from code by Rob Warnock, in Section 51 of the
|
||||
comp.compression FAQ.
|
||||
--*/
|
||||
|
||||
UInt32 BZ2_crc32Table[256] = {
|
||||
|
||||
/*-- Ugly, innit? --*/
|
||||
|
||||
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
|
||||
0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
|
||||
0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
|
||||
0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
|
||||
0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
|
||||
0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
|
||||
0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
|
||||
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
|
||||
0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
|
||||
0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
|
||||
0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
|
||||
0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
|
||||
0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
|
||||
0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
|
||||
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
|
||||
0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
|
||||
0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
|
||||
0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
|
||||
0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
|
||||
0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
|
||||
0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
|
||||
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
|
||||
0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
|
||||
0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
|
||||
0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
|
||||
0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
|
||||
0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
|
||||
0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
|
||||
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
|
||||
0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
|
||||
0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
|
||||
0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
|
||||
0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
|
||||
0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
|
||||
0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
|
||||
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
|
||||
0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
|
||||
0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
|
||||
0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
|
||||
0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
|
||||
0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
|
||||
0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
|
||||
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
|
||||
0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
|
||||
0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
|
||||
0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
|
||||
0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
|
||||
0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
|
||||
0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
|
||||
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
|
||||
0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
|
||||
0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
|
||||
0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
|
||||
0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
|
||||
0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
|
||||
0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
|
||||
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
|
||||
0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
|
||||
0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
|
||||
0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
|
||||
0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
|
||||
0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
|
||||
0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
|
||||
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end crctable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1,646 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Decompression machinery ---*/
|
||||
/*--- decompress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
static
|
||||
void makeMaps_d ( DState* s )
|
||||
{
|
||||
Int32 i;
|
||||
s->nInUse = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (s->inUse[i]) {
|
||||
s->seqToUnseq[s->nInUse] = i;
|
||||
s->nInUse++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define RETURN(rrr) \
|
||||
{ retVal = rrr; goto save_state_and_return; };
|
||||
|
||||
#define GET_BITS(lll,vvv,nnn) \
|
||||
case lll: s->state = lll; \
|
||||
while (True) { \
|
||||
if (s->bsLive >= nnn) { \
|
||||
UInt32 v; \
|
||||
v = (s->bsBuff >> \
|
||||
(s->bsLive-nnn)) & ((1 << nnn)-1); \
|
||||
s->bsLive -= nnn; \
|
||||
vvv = v; \
|
||||
break; \
|
||||
} \
|
||||
if (s->strm->avail_in == 0) RETURN(BZ_OK); \
|
||||
s->bsBuff \
|
||||
= (s->bsBuff << 8) | \
|
||||
((UInt32) \
|
||||
(*((UChar*)(s->strm->next_in)))); \
|
||||
s->bsLive += 8; \
|
||||
s->strm->next_in++; \
|
||||
s->strm->avail_in--; \
|
||||
s->strm->total_in_lo32++; \
|
||||
if (s->strm->total_in_lo32 == 0) \
|
||||
s->strm->total_in_hi32++; \
|
||||
}
|
||||
|
||||
#define GET_UCHAR(lll,uuu) \
|
||||
GET_BITS(lll,uuu,8)
|
||||
|
||||
#define GET_BIT(lll,uuu) \
|
||||
GET_BITS(lll,uuu,1)
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define GET_MTF_VAL(label1,label2,lval) \
|
||||
{ \
|
||||
if (groupPos == 0) { \
|
||||
groupNo++; \
|
||||
if (groupNo >= nSelectors) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
groupPos = BZ_G_SIZE; \
|
||||
gSel = s->selector[groupNo]; \
|
||||
gMinlen = s->minLens[gSel]; \
|
||||
gLimit = &(s->limit[gSel][0]); \
|
||||
gPerm = &(s->perm[gSel][0]); \
|
||||
gBase = &(s->base[gSel][0]); \
|
||||
} \
|
||||
groupPos--; \
|
||||
zn = gMinlen; \
|
||||
GET_BITS(label1, zvec, zn); \
|
||||
while (1) { \
|
||||
if (zn > 20 /* the longest code */) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
if (zvec <= gLimit[zn]) break; \
|
||||
zn++; \
|
||||
GET_BIT(label2, zj); \
|
||||
zvec = (zvec << 1) | zj; \
|
||||
}; \
|
||||
if (zvec - gBase[zn] < 0 \
|
||||
|| zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
|
||||
RETURN(BZ_DATA_ERROR); \
|
||||
lval = gPerm[zvec - gBase[zn]]; \
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
Int32 BZ2_decompress ( DState* s )
|
||||
{
|
||||
UChar uc;
|
||||
Int32 retVal;
|
||||
Int32 minLen, maxLen;
|
||||
bz_stream* strm = s->strm;
|
||||
|
||||
/* stuff that needs to be saved/restored */
|
||||
Int32 i;
|
||||
Int32 j;
|
||||
Int32 t;
|
||||
Int32 alphaSize;
|
||||
Int32 nGroups;
|
||||
Int32 nSelectors;
|
||||
Int32 EOB;
|
||||
Int32 groupNo;
|
||||
Int32 groupPos;
|
||||
Int32 nextSym;
|
||||
Int32 nblockMAX;
|
||||
Int32 nblock;
|
||||
Int32 es;
|
||||
Int32 N;
|
||||
Int32 curr;
|
||||
Int32 zt;
|
||||
Int32 zn;
|
||||
Int32 zvec;
|
||||
Int32 zj;
|
||||
Int32 gSel;
|
||||
Int32 gMinlen;
|
||||
Int32* gLimit;
|
||||
Int32* gBase;
|
||||
Int32* gPerm;
|
||||
|
||||
if (s->state == BZ_X_MAGIC_1) {
|
||||
/*initialise the save area*/
|
||||
s->save_i = 0;
|
||||
s->save_j = 0;
|
||||
s->save_t = 0;
|
||||
s->save_alphaSize = 0;
|
||||
s->save_nGroups = 0;
|
||||
s->save_nSelectors = 0;
|
||||
s->save_EOB = 0;
|
||||
s->save_groupNo = 0;
|
||||
s->save_groupPos = 0;
|
||||
s->save_nextSym = 0;
|
||||
s->save_nblockMAX = 0;
|
||||
s->save_nblock = 0;
|
||||
s->save_es = 0;
|
||||
s->save_N = 0;
|
||||
s->save_curr = 0;
|
||||
s->save_zt = 0;
|
||||
s->save_zn = 0;
|
||||
s->save_zvec = 0;
|
||||
s->save_zj = 0;
|
||||
s->save_gSel = 0;
|
||||
s->save_gMinlen = 0;
|
||||
s->save_gLimit = NULL;
|
||||
s->save_gBase = NULL;
|
||||
s->save_gPerm = NULL;
|
||||
}
|
||||
|
||||
/*restore from the save area*/
|
||||
i = s->save_i;
|
||||
j = s->save_j;
|
||||
t = s->save_t;
|
||||
alphaSize = s->save_alphaSize;
|
||||
nGroups = s->save_nGroups;
|
||||
nSelectors = s->save_nSelectors;
|
||||
EOB = s->save_EOB;
|
||||
groupNo = s->save_groupNo;
|
||||
groupPos = s->save_groupPos;
|
||||
nextSym = s->save_nextSym;
|
||||
nblockMAX = s->save_nblockMAX;
|
||||
nblock = s->save_nblock;
|
||||
es = s->save_es;
|
||||
N = s->save_N;
|
||||
curr = s->save_curr;
|
||||
zt = s->save_zt;
|
||||
zn = s->save_zn;
|
||||
zvec = s->save_zvec;
|
||||
zj = s->save_zj;
|
||||
gSel = s->save_gSel;
|
||||
gMinlen = s->save_gMinlen;
|
||||
gLimit = s->save_gLimit;
|
||||
gBase = s->save_gBase;
|
||||
gPerm = s->save_gPerm;
|
||||
|
||||
retVal = BZ_OK;
|
||||
|
||||
switch (s->state) {
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_1, uc);
|
||||
if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_2, uc);
|
||||
if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_UCHAR(BZ_X_MAGIC_3, uc)
|
||||
if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
|
||||
GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
|
||||
if (s->blockSize100k < (BZ_HDR_0 + 1) ||
|
||||
s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
|
||||
s->blockSize100k -= BZ_HDR_0;
|
||||
|
||||
if (s->smallDecompress) {
|
||||
s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
|
||||
s->ll4 = BZALLOC(
|
||||
((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
|
||||
);
|
||||
if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
|
||||
} else {
|
||||
s->tt = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
|
||||
if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
|
||||
}
|
||||
|
||||
GET_UCHAR(BZ_X_BLKHDR_1, uc);
|
||||
|
||||
if (uc == 0x17) goto endhdr_2;
|
||||
if (uc != 0x31) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_2, uc);
|
||||
if (uc != 0x41) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_3, uc);
|
||||
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_4, uc);
|
||||
if (uc != 0x26) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_5, uc);
|
||||
if (uc != 0x53) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_BLKHDR_6, uc);
|
||||
if (uc != 0x59) RETURN(BZ_DATA_ERROR);
|
||||
|
||||
s->currBlockNo++;
|
||||
if (s->verbosity >= 2)
|
||||
VPrintf1 ( "\n [%d: huff+mtf ", s->currBlockNo );
|
||||
|
||||
s->storedBlockCRC = 0;
|
||||
GET_UCHAR(BZ_X_BCRC_1, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_2, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_3, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_BCRC_4, uc);
|
||||
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
|
||||
|
||||
GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
|
||||
|
||||
s->origPtr = 0;
|
||||
GET_UCHAR(BZ_X_ORIGPTR_1, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
GET_UCHAR(BZ_X_ORIGPTR_2, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
GET_UCHAR(BZ_X_ORIGPTR_3, uc);
|
||||
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
|
||||
|
||||
if (s->origPtr < 0)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
if (s->origPtr > 10 + 100000*s->blockSize100k)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*--- Receive the mapping table ---*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
GET_BIT(BZ_X_MAPPING_1, uc);
|
||||
if (uc == 1)
|
||||
s->inUse16[i] = True; else
|
||||
s->inUse16[i] = False;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) s->inUse[i] = False;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
if (s->inUse16[i])
|
||||
for (j = 0; j < 16; j++) {
|
||||
GET_BIT(BZ_X_MAPPING_2, uc);
|
||||
if (uc == 1) s->inUse[i * 16 + j] = True;
|
||||
}
|
||||
makeMaps_d ( s );
|
||||
if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
|
||||
alphaSize = s->nInUse+2;
|
||||
|
||||
/*--- Now the selectors ---*/
|
||||
GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
|
||||
if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
|
||||
GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
|
||||
if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
j = 0;
|
||||
while (True) {
|
||||
GET_BIT(BZ_X_SELECTOR_3, uc);
|
||||
if (uc == 0) break;
|
||||
j++;
|
||||
if (j >= nGroups) RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
s->selectorMtf[i] = j;
|
||||
}
|
||||
|
||||
/*--- Undo the MTF values for the selectors. ---*/
|
||||
{
|
||||
UChar pos[BZ_N_GROUPS], tmp, v;
|
||||
for (v = 0; v < nGroups; v++) pos[v] = v;
|
||||
|
||||
for (i = 0; i < nSelectors; i++) {
|
||||
v = s->selectorMtf[i];
|
||||
tmp = pos[v];
|
||||
while (v > 0) { pos[v] = pos[v-1]; v--; }
|
||||
pos[0] = tmp;
|
||||
s->selector[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*--- Now the coding tables ---*/
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
GET_BITS(BZ_X_CODING_1, curr, 5);
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
while (True) {
|
||||
if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
|
||||
GET_BIT(BZ_X_CODING_2, uc);
|
||||
if (uc == 0) break;
|
||||
GET_BIT(BZ_X_CODING_3, uc);
|
||||
if (uc == 0) curr++; else curr--;
|
||||
}
|
||||
s->len[t][i] = curr;
|
||||
}
|
||||
}
|
||||
|
||||
/*--- Create the Huffman decoding tables ---*/
|
||||
for (t = 0; t < nGroups; t++) {
|
||||
minLen = 32;
|
||||
maxLen = 0;
|
||||
for (i = 0; i < alphaSize; i++) {
|
||||
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
|
||||
if (s->len[t][i] < minLen) minLen = s->len[t][i];
|
||||
}
|
||||
BZ2_hbCreateDecodeTables (
|
||||
&(s->limit[t][0]),
|
||||
&(s->base[t][0]),
|
||||
&(s->perm[t][0]),
|
||||
&(s->len[t][0]),
|
||||
minLen, maxLen, alphaSize
|
||||
);
|
||||
s->minLens[t] = minLen;
|
||||
}
|
||||
|
||||
/*--- Now the MTF values ---*/
|
||||
|
||||
EOB = s->nInUse+1;
|
||||
nblockMAX = 100000 * s->blockSize100k;
|
||||
groupNo = -1;
|
||||
groupPos = 0;
|
||||
|
||||
for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
|
||||
|
||||
/*-- MTF init --*/
|
||||
{
|
||||
Int32 ii, jj, kk;
|
||||
kk = MTFA_SIZE-1;
|
||||
for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
|
||||
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
|
||||
s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
|
||||
kk--;
|
||||
}
|
||||
s->mtfbase[ii] = kk + 1;
|
||||
}
|
||||
}
|
||||
/*-- end MTF init --*/
|
||||
|
||||
nblock = 0;
|
||||
GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
|
||||
|
||||
while (True) {
|
||||
|
||||
if (nextSym == EOB) break;
|
||||
|
||||
if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
|
||||
|
||||
es = -1;
|
||||
N = 1;
|
||||
do {
|
||||
/* Check that N doesn't get too big, so that es doesn't
|
||||
go negative. The maximum value that can be
|
||||
RUNA/RUNB encoded is equal to the block size (post
|
||||
the initial RLE), viz, 900k, so bounding N at 2
|
||||
million should guard against overflow without
|
||||
rejecting any legitimate inputs. */
|
||||
if (N >= 2*1024*1024) RETURN(BZ_DATA_ERROR);
|
||||
if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
|
||||
if (nextSym == BZ_RUNB) es = es + (1+1) * N;
|
||||
N = N * 2;
|
||||
GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
|
||||
}
|
||||
while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
|
||||
|
||||
es++;
|
||||
uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
|
||||
s->unzftab[uc] += es;
|
||||
|
||||
if (s->smallDecompress)
|
||||
while (es > 0) {
|
||||
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||
s->ll16[nblock] = (UInt16)uc;
|
||||
nblock++;
|
||||
es--;
|
||||
}
|
||||
else
|
||||
while (es > 0) {
|
||||
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||
s->tt[nblock] = (UInt32)uc;
|
||||
nblock++;
|
||||
es--;
|
||||
};
|
||||
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- uc = MTF ( nextSym-1 ) --*/
|
||||
{
|
||||
Int32 ii, jj, kk, pp, lno, off;
|
||||
UInt32 nn;
|
||||
nn = (UInt32)(nextSym - 1);
|
||||
|
||||
if (nn < MTFL_SIZE) {
|
||||
/* avoid general-case expense */
|
||||
pp = s->mtfbase[0];
|
||||
uc = s->mtfa[pp+nn];
|
||||
while (nn > 3) {
|
||||
Int32 z = pp+nn;
|
||||
s->mtfa[(z) ] = s->mtfa[(z)-1];
|
||||
s->mtfa[(z)-1] = s->mtfa[(z)-2];
|
||||
s->mtfa[(z)-2] = s->mtfa[(z)-3];
|
||||
s->mtfa[(z)-3] = s->mtfa[(z)-4];
|
||||
nn -= 4;
|
||||
}
|
||||
while (nn > 0) {
|
||||
s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
|
||||
};
|
||||
s->mtfa[pp] = uc;
|
||||
} else {
|
||||
/* general case */
|
||||
lno = nn / MTFL_SIZE;
|
||||
off = nn % MTFL_SIZE;
|
||||
pp = s->mtfbase[lno] + off;
|
||||
uc = s->mtfa[pp];
|
||||
while (pp > s->mtfbase[lno]) {
|
||||
s->mtfa[pp] = s->mtfa[pp-1]; pp--;
|
||||
};
|
||||
s->mtfbase[lno]++;
|
||||
while (lno > 0) {
|
||||
s->mtfbase[lno]--;
|
||||
s->mtfa[s->mtfbase[lno]]
|
||||
= s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
|
||||
lno--;
|
||||
}
|
||||
s->mtfbase[0]--;
|
||||
s->mtfa[s->mtfbase[0]] = uc;
|
||||
if (s->mtfbase[0] == 0) {
|
||||
kk = MTFA_SIZE-1;
|
||||
for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
|
||||
for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
|
||||
s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
|
||||
kk--;
|
||||
}
|
||||
s->mtfbase[ii] = kk + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-- end uc = MTF ( nextSym-1 ) --*/
|
||||
|
||||
s->unzftab[s->seqToUnseq[uc]]++;
|
||||
if (s->smallDecompress)
|
||||
s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
|
||||
s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
|
||||
nblock++;
|
||||
|
||||
GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we know what nblock is, we can do a better sanity
|
||||
check on s->origPtr.
|
||||
*/
|
||||
if (s->origPtr < 0 || s->origPtr >= nblock)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
|
||||
/*-- Set up cftab to facilitate generation of T^(-1) --*/
|
||||
/* Check: unzftab entries in range. */
|
||||
for (i = 0; i <= 255; i++) {
|
||||
if (s->unzftab[i] < 0 || s->unzftab[i] > nblock)
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
/* Actually generate cftab. */
|
||||
s->cftab[0] = 0;
|
||||
for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
|
||||
for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
|
||||
/* Check: cftab entries in range. */
|
||||
for (i = 0; i <= 256; i++) {
|
||||
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
|
||||
/* s->cftab[i] can legitimately be == nblock */
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
/* Check: cftab entries non-descending. */
|
||||
for (i = 1; i <= 256; i++) {
|
||||
if (s->cftab[i-1] > s->cftab[i]) {
|
||||
RETURN(BZ_DATA_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
s->state_out_len = 0;
|
||||
s->state_out_ch = 0;
|
||||
BZ_INITIALISE_CRC ( s->calculatedBlockCRC );
|
||||
s->state = BZ_X_OUTPUT;
|
||||
if (s->verbosity >= 2) VPrintf0 ( "rt+rld" );
|
||||
|
||||
if (s->smallDecompress) {
|
||||
|
||||
/*-- Make a copy of cftab, used in generation of T --*/
|
||||
for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
|
||||
|
||||
/*-- compute the T vector --*/
|
||||
for (i = 0; i < nblock; i++) {
|
||||
uc = (UChar)(s->ll16[i]);
|
||||
SET_LL(i, s->cftabCopy[uc]);
|
||||
s->cftabCopy[uc]++;
|
||||
}
|
||||
|
||||
/*-- Compute T^(-1) by pointer reversal on T --*/
|
||||
i = s->origPtr;
|
||||
j = GET_LL(i);
|
||||
do {
|
||||
Int32 tmp = GET_LL(j);
|
||||
SET_LL(j, i);
|
||||
i = j;
|
||||
j = tmp;
|
||||
}
|
||||
while (i != s->origPtr);
|
||||
|
||||
s->tPos = s->origPtr;
|
||||
s->nblock_used = 0;
|
||||
if (s->blockRandomised) {
|
||||
BZ_RAND_INIT_MASK;
|
||||
BZ_GET_SMALL(s->k0); s->nblock_used++;
|
||||
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
|
||||
} else {
|
||||
BZ_GET_SMALL(s->k0); s->nblock_used++;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*-- compute the T^(-1) vector --*/
|
||||
for (i = 0; i < nblock; i++) {
|
||||
uc = (UChar)(s->tt[i] & 0xff);
|
||||
s->tt[s->cftab[uc]] |= (i << 8);
|
||||
s->cftab[uc]++;
|
||||
}
|
||||
|
||||
s->tPos = s->tt[s->origPtr] >> 8;
|
||||
s->nblock_used = 0;
|
||||
if (s->blockRandomised) {
|
||||
BZ_RAND_INIT_MASK;
|
||||
BZ_GET_FAST(s->k0); s->nblock_used++;
|
||||
BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
|
||||
} else {
|
||||
BZ_GET_FAST(s->k0); s->nblock_used++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RETURN(BZ_OK);
|
||||
|
||||
|
||||
|
||||
endhdr_2:
|
||||
|
||||
GET_UCHAR(BZ_X_ENDHDR_2, uc);
|
||||
if (uc != 0x72) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_3, uc);
|
||||
if (uc != 0x45) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_4, uc);
|
||||
if (uc != 0x38) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_5, uc);
|
||||
if (uc != 0x50) RETURN(BZ_DATA_ERROR);
|
||||
GET_UCHAR(BZ_X_ENDHDR_6, uc);
|
||||
if (uc != 0x90) RETURN(BZ_DATA_ERROR);
|
||||
|
||||
s->storedCombinedCRC = 0;
|
||||
GET_UCHAR(BZ_X_CCRC_1, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_2, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_3, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
GET_UCHAR(BZ_X_CCRC_4, uc);
|
||||
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
|
||||
|
||||
s->state = BZ_X_IDLE;
|
||||
RETURN(BZ_STREAM_END);
|
||||
|
||||
default: AssertH ( False, 4001 );
|
||||
}
|
||||
|
||||
AssertH ( False, 4002 );
|
||||
|
||||
save_state_and_return:
|
||||
|
||||
s->save_i = i;
|
||||
s->save_j = j;
|
||||
s->save_t = t;
|
||||
s->save_alphaSize = alphaSize;
|
||||
s->save_nGroups = nGroups;
|
||||
s->save_nSelectors = nSelectors;
|
||||
s->save_EOB = EOB;
|
||||
s->save_groupNo = groupNo;
|
||||
s->save_groupPos = groupPos;
|
||||
s->save_nextSym = nextSym;
|
||||
s->save_nblockMAX = nblockMAX;
|
||||
s->save_nblock = nblock;
|
||||
s->save_es = es;
|
||||
s->save_N = N;
|
||||
s->save_curr = curr;
|
||||
s->save_zt = zt;
|
||||
s->save_zn = zn;
|
||||
s->save_zvec = zvec;
|
||||
s->save_zj = zj;
|
||||
s->save_gSel = gSel;
|
||||
s->save_gMinlen = gMinlen;
|
||||
s->save_gLimit = gLimit;
|
||||
s->save_gBase = gBase;
|
||||
s->save_gPerm = gPerm;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end decompress.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1,205 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Huffman coding low-level stuff ---*/
|
||||
/*--- huffman.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
|
||||
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
|
||||
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
|
||||
|
||||
#define ADDWEIGHTS(zw1,zw2) \
|
||||
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
|
||||
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
|
||||
|
||||
#define UPHEAP(z) \
|
||||
{ \
|
||||
Int32 zz, tmp; \
|
||||
zz = z; tmp = heap[zz]; \
|
||||
while (weight[tmp] < weight[heap[zz >> 1]]) { \
|
||||
heap[zz] = heap[zz >> 1]; \
|
||||
zz >>= 1; \
|
||||
} \
|
||||
heap[zz] = tmp; \
|
||||
}
|
||||
|
||||
#define DOWNHEAP(z) \
|
||||
{ \
|
||||
Int32 zz, yy, tmp; \
|
||||
zz = z; tmp = heap[zz]; \
|
||||
while (True) { \
|
||||
yy = zz << 1; \
|
||||
if (yy > nHeap) break; \
|
||||
if (yy < nHeap && \
|
||||
weight[heap[yy+1]] < weight[heap[yy]]) \
|
||||
yy++; \
|
||||
if (weight[tmp] < weight[heap[yy]]) break; \
|
||||
heap[zz] = heap[yy]; \
|
||||
zz = yy; \
|
||||
} \
|
||||
heap[zz] = tmp; \
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbMakeCodeLengths ( UChar *len,
|
||||
Int32 *freq,
|
||||
Int32 alphaSize,
|
||||
Int32 maxLen )
|
||||
{
|
||||
/*--
|
||||
Nodes and heap entries run from 1. Entry 0
|
||||
for both the heap and nodes is a sentinel.
|
||||
--*/
|
||||
Int32 nNodes, nHeap, n1, n2, i, j, k;
|
||||
Bool tooLong;
|
||||
|
||||
Int32 heap [ BZ_MAX_ALPHA_SIZE + 2 ];
|
||||
Int32 weight [ BZ_MAX_ALPHA_SIZE * 2 ];
|
||||
Int32 parent [ BZ_MAX_ALPHA_SIZE * 2 ];
|
||||
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
|
||||
|
||||
while (True) {
|
||||
|
||||
nNodes = alphaSize;
|
||||
nHeap = 0;
|
||||
|
||||
heap[0] = 0;
|
||||
weight[0] = 0;
|
||||
parent[0] = -2;
|
||||
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
parent[i] = -1;
|
||||
nHeap++;
|
||||
heap[nHeap] = i;
|
||||
UPHEAP(nHeap);
|
||||
}
|
||||
|
||||
AssertH( nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001 );
|
||||
|
||||
while (nHeap > 1) {
|
||||
n1 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
||||
n2 = heap[1]; heap[1] = heap[nHeap]; nHeap--; DOWNHEAP(1);
|
||||
nNodes++;
|
||||
parent[n1] = parent[n2] = nNodes;
|
||||
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
|
||||
parent[nNodes] = -1;
|
||||
nHeap++;
|
||||
heap[nHeap] = nNodes;
|
||||
UPHEAP(nHeap);
|
||||
}
|
||||
|
||||
AssertH( nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002 );
|
||||
|
||||
tooLong = False;
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
j = 0;
|
||||
k = i;
|
||||
while (parent[k] >= 0) { k = parent[k]; j++; }
|
||||
len[i-1] = j;
|
||||
if (j > maxLen) tooLong = True;
|
||||
}
|
||||
|
||||
if (! tooLong) break;
|
||||
|
||||
/* 17 Oct 04: keep-going condition for the following loop used
|
||||
to be 'i < alphaSize', which missed the last element,
|
||||
theoretically leading to the possibility of the compressor
|
||||
looping. However, this count-scaling step is only needed if
|
||||
one of the generated Huffman code words is longer than
|
||||
maxLen, which up to and including version 1.0.2 was 20 bits,
|
||||
which is extremely unlikely. In version 1.0.3 maxLen was
|
||||
changed to 17 bits, which has minimal effect on compression
|
||||
ratio, but does mean this scaling step is used from time to
|
||||
time, enough to verify that it works.
|
||||
|
||||
This means that bzip2-1.0.3 and later will only produce
|
||||
Huffman codes with a maximum length of 17 bits. However, in
|
||||
order to preserve backwards compatibility with bitstreams
|
||||
produced by versions pre-1.0.3, the decompressor must still
|
||||
handle lengths of up to 20. */
|
||||
|
||||
for (i = 1; i <= alphaSize; i++) {
|
||||
j = weight[i] >> 8;
|
||||
j = 1 + (j / 2);
|
||||
weight[i] = j << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbAssignCodes ( Int32 *code,
|
||||
UChar *length,
|
||||
Int32 minLen,
|
||||
Int32 maxLen,
|
||||
Int32 alphaSize )
|
||||
{
|
||||
Int32 n, vec, i;
|
||||
|
||||
vec = 0;
|
||||
for (n = minLen; n <= maxLen; n++) {
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
if (length[i] == n) { code[i] = vec; vec++; };
|
||||
vec <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------*/
|
||||
void BZ2_hbCreateDecodeTables ( Int32 *limit,
|
||||
Int32 *base,
|
||||
Int32 *perm,
|
||||
UChar *length,
|
||||
Int32 minLen,
|
||||
Int32 maxLen,
|
||||
Int32 alphaSize )
|
||||
{
|
||||
Int32 pp, i, j, vec;
|
||||
|
||||
pp = 0;
|
||||
for (i = minLen; i <= maxLen; i++)
|
||||
for (j = 0; j < alphaSize; j++)
|
||||
if (length[j] == i) { perm[pp] = j; pp++; };
|
||||
|
||||
for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
|
||||
for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
|
||||
|
||||
for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
|
||||
|
||||
for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
|
||||
vec = 0;
|
||||
|
||||
for (i = minLen; i <= maxLen; i++) {
|
||||
vec += (base[i+1] - base[i]);
|
||||
limit[i] = vec-1;
|
||||
vec <<= 1;
|
||||
}
|
||||
for (i = minLen + 1; i <= maxLen; i++)
|
||||
base[i] = ((limit[i-1] + 1) << 1) - base[i];
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end huffman.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1,84 +0,0 @@
|
|||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- Table for randomising repetitive blocks ---*/
|
||||
/*--- randtable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
This file is part of bzip2/libbzip2, a program and library for
|
||||
lossless, block-sorting data compression.
|
||||
|
||||
bzip2/libbzip2 version 1.0.6 of 6 September 2010
|
||||
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
|
||||
|
||||
Please read the WARNING, DISCLAIMER and PATENTS sections in the
|
||||
README file.
|
||||
|
||||
This program is released under the terms of the license contained
|
||||
in the file LICENSE.
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "bzlib_private.h"
|
||||
|
||||
|
||||
/*---------------------------------------------*/
|
||||
Int32 BZ2_rNums[512] = {
|
||||
619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
|
||||
985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
|
||||
733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
||||
419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
|
||||
878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
|
||||
862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
||||
150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
|
||||
170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
|
||||
73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
||||
909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
|
||||
641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
|
||||
161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
||||
382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
|
||||
98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
|
||||
227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
||||
469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
|
||||
184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
|
||||
715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
||||
951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
|
||||
652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
|
||||
645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
||||
609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
|
||||
653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
|
||||
411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
||||
170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
|
||||
857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
|
||||
669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
||||
944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
|
||||
344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
|
||||
897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
||||
433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
|
||||
686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
|
||||
946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
||||
978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
|
||||
680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
|
||||
707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
||||
297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
|
||||
134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
|
||||
343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
||||
140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
|
||||
170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
|
||||
369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
||||
804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
|
||||
896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
|
||||
661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
||||
768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
|
||||
61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
|
||||
372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
||||
780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
|
||||
920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
|
||||
645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
||||
936, 638
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------*/
|
||||
/*--- end randtable.c ---*/
|
||||
/*-------------------------------------------------------------*/
|
|
@ -1 +0,0 @@
|
|||
bzip2-1.0.6
|
|
@ -1,112 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
*/
|
||||
|
||||
#include "universal.h"
|
||||
|
||||
#if SUPPORT_CRC32
|
||||
|
||||
void MojoCrc32_init(MojoCrc32 *context)
|
||||
{
|
||||
*context = (MojoCrc32) 0xFFFFFFFF;
|
||||
} // MojoCrc32_init
|
||||
|
||||
|
||||
void MojoCrc32_append(MojoCrc32 *_crc, const uint8 *buf, uint32 len)
|
||||
{
|
||||
uint32 crc = (uint32) *_crc;
|
||||
|
||||
uint32 n;
|
||||
for (n = 0; n < len; n++)
|
||||
{
|
||||
uint32 xorval = (uint32) ((crc ^ buf[n]) & 0xFF);
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
|
||||
crc = xorval ^ (crc >> 8);
|
||||
} // for
|
||||
|
||||
*_crc = (MojoCrc32) crc;
|
||||
} // MojoCrc32_append
|
||||
|
||||
|
||||
void MojoCrc32_finish(MojoCrc32 *context, uint32 *digest)
|
||||
{
|
||||
*digest = (*context ^ 0xFFFFFFFF);
|
||||
} // MojoCrc32_finish
|
||||
|
||||
|
||||
#endif // SUPPORT_CRC32
|
||||
|
||||
#if TEST_CRC32
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
MojoCrc32 ctx;
|
||||
MojoCrc32_init(&ctx);
|
||||
in = fopen(argv[i], "rb");
|
||||
if (!in)
|
||||
perror("fopen");
|
||||
else
|
||||
{
|
||||
uint32 digest = 0;
|
||||
int err = 0;
|
||||
while ( (!err) && (!feof(in)) )
|
||||
{
|
||||
uint8 buf[1024];
|
||||
size_t rc = fread(buf, 1, sizeof (buf), in);
|
||||
if (rc > 0)
|
||||
MojoCrc32_append(&ctx, buf, rc);
|
||||
err = ferror(in);
|
||||
} // while
|
||||
|
||||
if (err)
|
||||
perror("fread");
|
||||
fclose(in);
|
||||
MojoCrc32_finish(&ctx, &digest);
|
||||
if (!err)
|
||||
printf("%s: %X\n", argv[i], (unsigned int) digest);
|
||||
} // else
|
||||
} // for
|
||||
|
||||
return 0;
|
||||
} // main
|
||||
#endif
|
||||
|
||||
// end of checksum_crc32.c ...
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#include "universal.h"
|
||||
|
||||
#if SUPPORT_MD5
|
||||
|
||||
// MD5 code originally from http://sourceforge.net/projects/libmd5-rfc/
|
||||
// License: zlib.
|
||||
// I cleaned it up a little for MojoSetup's specific purposes. --ryan.
|
||||
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
//#ifdef ARCH_IS_BIG_ENDIAN
|
||||
//# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
//#else
|
||||
//# define BYTE_ORDER 0
|
||||
//#endif
|
||||
#if PLATFORM_BIGENDIAN
|
||||
# define BYTE_ORDER 1
|
||||
#else
|
||||
# define BYTE_ORDER -1
|
||||
#endif
|
||||
|
||||
#define T_MASK ((uint32)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
|
||||
static void
|
||||
MojoMd5_process(MojoMd5 *pms, const uint8 *data /*[64]*/)
|
||||
{
|
||||
uint32
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
uint32 t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
uint32 X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
uint32 xbuf[16];
|
||||
const uint32 *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const uint8 *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const uint8 *)0) & 3)) {
|
||||
/* data are properly aligned */
|
||||
X = (const uint32 *)data;
|
||||
} else {
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const uint8 *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
MojoMd5_init(MojoMd5 *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
MojoMd5_append(MojoMd5 *pms, const uint8 *data, int nbytes)
|
||||
{
|
||||
const uint8 *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
uint32 nbits = (uint32)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
pms->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset) {
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
MojoMd5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
MojoMd5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
MojoMd5_finish(MojoMd5 *pms, uint8 digest[16])
|
||||
{
|
||||
const uint8 pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
uint8 data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (uint8)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
MojoMd5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
MojoMd5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (uint8)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
|
||||
#endif // SUPPORT_MD5
|
||||
|
||||
#if TEST_MD5
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
MojoMd5 ctx;
|
||||
MojoMd5_init(&ctx);
|
||||
in = fopen(argv[i], "rb");
|
||||
if (!in)
|
||||
perror("fopen");
|
||||
else
|
||||
{
|
||||
uint8 dig[16];
|
||||
int err = 0;
|
||||
while ( (!err) && (!feof(in)) )
|
||||
{
|
||||
uint8 buf[1024];
|
||||
size_t rc = fread(buf, 1, sizeof (buf), in);
|
||||
if (rc > 0)
|
||||
MojoMd5_append(&ctx, buf, rc);
|
||||
err = ferror(in);
|
||||
} // while
|
||||
|
||||
if (err)
|
||||
perror("fread");
|
||||
fclose(in);
|
||||
MojoMd5_finish(&ctx, dig);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
printf("%s: %x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x\n", argv[i],
|
||||
(int) dig[0], (int) dig[1], (int) dig[2], (int) dig[3],
|
||||
(int) dig[4], (int) dig[5], (int) dig[6], (int) dig[7],
|
||||
(int) dig[8], (int) dig[9], (int) dig[10], (int) dig[11],
|
||||
(int) dig[12], (int) dig[13], (int) dig[14], (int) dig[15]);
|
||||
} // if
|
||||
} // else
|
||||
} // for
|
||||
|
||||
return 0;
|
||||
} // main
|
||||
#endif
|
||||
|
||||
// end of checksum_md5.c ...
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "universal.h"
|
||||
|
||||
#if SUPPORT_SHA1
|
||||
|
||||
// SHA-1 code originally from ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c
|
||||
// License: public domain.
|
||||
// I cleaned it up a little for MojoSetup's specific purposes. --ryan.
|
||||
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <steve@edmweb.com>
|
||||
100% Public Domain
|
||||
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#if PLATFORM_LITTLEENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||
|(rol(block->l[i],8)&0x00FF00FF))
|
||||
#else
|
||||
#define blk0(i) block->l[i]
|
||||
#endif
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
static void MojoSha1_transform(uint32 state[5], const uint8 buffer[64])
|
||||
{
|
||||
uint32 a, b, c, d, e;
|
||||
typedef union {
|
||||
uint8 c[64];
|
||||
uint32 l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
static uint8 workspace[64];
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
memcpy(block, buffer, 64);
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
}
|
||||
|
||||
|
||||
/* MojoSha1_init - Initialize new context */
|
||||
|
||||
void MojoSha1_init(MojoSha1 *context)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void MojoSha1_append(MojoSha1 *context, const uint8 *data, uint32 len)
|
||||
{
|
||||
uint32 i, j;
|
||||
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
MojoSha1_transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
MojoSha1_transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void MojoSha1_finish(MojoSha1 *context, uint8 digest[20])
|
||||
{
|
||||
uint32 i;
|
||||
uint8 finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (uint8)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
MojoSha1_append(context, (uint8 *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
MojoSha1_append(context, (uint8 *)"\0", 1);
|
||||
}
|
||||
MojoSha1_append(context, finalcount, 8); /* Should cause a MojoSha1_transform() */
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (uint8)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(&finalcount, 0, 8);
|
||||
MojoSha1_transform(context->state, context->buffer);
|
||||
}
|
||||
|
||||
#endif // SUPPORT_SHA1
|
||||
|
||||
#if TEST_SHA1
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
FILE *in = NULL;
|
||||
MojoSha1 ctx;
|
||||
MojoSha1_init(&ctx);
|
||||
in = fopen(argv[i], "rb");
|
||||
if (!in)
|
||||
perror("fopen");
|
||||
else
|
||||
{
|
||||
uint8 dig[20];
|
||||
int err = 0;
|
||||
while ( (!err) && (!feof(in)) )
|
||||
{
|
||||
uint8 buf[1024];
|
||||
size_t rc = fread(buf, 1, sizeof (buf), in);
|
||||
if (rc > 0)
|
||||
MojoSha1_append(&ctx, buf, rc);
|
||||
err = ferror(in);
|
||||
} // while
|
||||
|
||||
if (err)
|
||||
perror("fread");
|
||||
fclose(in);
|
||||
MojoSha1_finish(&ctx, dig);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
printf("%s: %x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x\n",
|
||||
argv[i],
|
||||
(int) dig[0], (int) dig[1], (int) dig[2], (int) dig[3],
|
||||
(int) dig[4], (int) dig[5], (int) dig[6], (int) dig[7],
|
||||
(int) dig[8], (int) dig[9], (int) dig[10], (int) dig[11],
|
||||
(int) dig[12], (int) dig[13], (int) dig[14], (int) dig[15],
|
||||
(int) dig[16], (int) dig[17], (int) dig[18], (int) dig[19]);
|
||||
} // if
|
||||
} // else
|
||||
} // for
|
||||
|
||||
return 0;
|
||||
} // main
|
||||
#endif
|
||||
|
||||
// end of checksum_sha1.c ...
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,182 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCL_FILEIO_H_
|
||||
#define _INCL_FILEIO_H_
|
||||
|
||||
#include "universal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* File i/o may go through multiple layers: the archive attached to the binary,
|
||||
* then an archive in there that's being read entirely out of memory that's
|
||||
* being uncompressed to on the fly, or it might be a straight read from a
|
||||
* regular uncompressed file on physical media. It might be a single file
|
||||
* compressed with bzip2. As such, we have to have an abstraction over the
|
||||
* usual channels...basically what we need here is archives-within-archives,
|
||||
* done transparently and with arbitrary depth, although usually not more
|
||||
* than one deep. This also works as a general transport layer, so the
|
||||
* abstraction could be extended to network connections and such, too.
|
||||
*/
|
||||
|
||||
// Abstract input interface. Files, memory, archive entries, etc.
|
||||
typedef struct MojoInput MojoInput;
|
||||
struct MojoInput
|
||||
{
|
||||
// public
|
||||
boolean (*ready)(MojoInput *io);
|
||||
int64 (*read)(MojoInput *io, void *buf, uint32 bufsize);
|
||||
boolean (*seek)(MojoInput *io, uint64 pos);
|
||||
int64 (*tell)(MojoInput *io);
|
||||
int64 (*length)(MojoInput *io);
|
||||
MojoInput* (*duplicate)(MojoInput *io);
|
||||
void (*close)(MojoInput *io);
|
||||
|
||||
// private
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
// If constant == 0, then this copies the memory, so you may free (ptr) after
|
||||
// this function returns in that case.
|
||||
MojoInput *MojoInput_newFromMemory(const uint8 *ptr, uint32 len, int constant);
|
||||
|
||||
// Get a MojoInput for a real file in the physical filesystem.
|
||||
MojoInput *MojoInput_newFromFile(const char *fname);
|
||||
|
||||
// Make a subset range of (io) look like the entire file. This will take over
|
||||
// control of (io), closing it when done, so never reference (io) directly
|
||||
// again, if this call succeeds.
|
||||
MojoInput *MojoInput_newFromSubset(MojoInput *io, const uint64 start,
|
||||
const uint64 end);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MOJOARCHIVE_ENTRY_UNKNOWN = 0,
|
||||
MOJOARCHIVE_ENTRY_FILE,
|
||||
MOJOARCHIVE_ENTRY_DIR,
|
||||
MOJOARCHIVE_ENTRY_SYMLINK,
|
||||
} MojoArchiveEntryType;
|
||||
|
||||
// Abstract archive interface. Archives, directories, etc.
|
||||
typedef struct MojoArchiveEntry
|
||||
{
|
||||
char *filename;
|
||||
char *linkdest;
|
||||
MojoArchiveEntryType type;
|
||||
int64 filesize;
|
||||
uint16 perms;
|
||||
} MojoArchiveEntry;
|
||||
|
||||
void MojoArchive_resetEntry(MojoArchiveEntry *info);
|
||||
|
||||
|
||||
typedef struct MojoArchive MojoArchive;
|
||||
struct MojoArchive
|
||||
{
|
||||
// public
|
||||
boolean (*enumerate)(MojoArchive *ar);
|
||||
const MojoArchiveEntry* (*enumNext)(MojoArchive *ar);
|
||||
MojoInput* (*openCurrentEntry)(MojoArchive *ar);
|
||||
void (*close)(MojoArchive *ar);
|
||||
|
||||
// private
|
||||
MojoInput *io;
|
||||
MojoArchiveEntry prevEnum;
|
||||
int64 offsetOfStart; // byte offset in MojoInput where archive starts.
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
MojoArchive *MojoArchive_newFromDirectory(const char *dirname);
|
||||
MojoArchive *MojoArchive_newFromInput(MojoInput *io, const char *origfname);
|
||||
|
||||
// This will reset enumeration in the archive, don't use it while iterating!
|
||||
// Also, this can be very slow depending on the archive in question, so
|
||||
// try to limit your random access filename lookups to known-fast quantities
|
||||
// (like directories on the physical filesystem or a zipfile...tarballs and
|
||||
// zipfiles-in-zipfiles will bog down here, for example).
|
||||
MojoInput *MojoInput_newFromArchivePath(MojoArchive *ar, const char *fname);
|
||||
|
||||
// Wrap (origio) in a new MojoInput that decompresses a compressed stream
|
||||
// on the fly. Returns NULL on error or if (origio) isn't a supported
|
||||
// compressed format. The returned MojoInput wraps the original input;
|
||||
// closing the returned MojoInput will close (origio), too, and you should
|
||||
// consider origio lost. If this function returns non-NULL, you should not,
|
||||
// under any circumstances, interact directly with origio again, as the
|
||||
// new MojoInput now owns it.
|
||||
MojoInput *MojoInput_newCompressedStream(MojoInput *origio);
|
||||
|
||||
// !!! FIXME: fill in missing documentation here.
|
||||
extern MojoArchive *GBaseArchive;
|
||||
extern const char *GBaseArchivePath;
|
||||
MojoArchive *MojoArchive_initBaseArchive(void);
|
||||
void MojoArchive_deinitBaseArchive(void);
|
||||
|
||||
typedef boolean (*MojoInput_FileCopyCallback)(uint32 ticks, int64 justwrote,
|
||||
int64 bw, int64 total, void *data);
|
||||
boolean MojoInput_toPhysicalFile(MojoInput *in, const char *fname, uint16 perms,
|
||||
MojoChecksums *checksums, int64 maxbytes,
|
||||
MojoInput_FileCopyCallback cb, void *data);
|
||||
|
||||
MojoInput *MojoInput_newFromURL(const char *url);
|
||||
|
||||
// Read a littleendian, unsigned 16-bit integer from (io), swapping it to
|
||||
// the correct byteorder for the platform, and moving the file pointer
|
||||
// ahead 2 bytes. Returns true on successful read and fills the swapped
|
||||
// value into (*ui16), false on i/o error or EOF.
|
||||
boolean MojoInput_readui16(MojoInput *io, uint16 *ui16);
|
||||
|
||||
// Read a littleendian, unsigned 32-bit integer from (io), swapping it to
|
||||
// the correct byteorder for the platform, and moving the file pointer
|
||||
// ahead 4 bytes. Returns true on successful read and fills the swapped
|
||||
// value into (*ui32), false on i/o error or EOF.
|
||||
boolean MojoInput_readui32(MojoInput *io, uint32 *ui32);
|
||||
|
||||
// Read a littleendian, unsigned 64-bit integer from (io), swapping it to
|
||||
// the correct byteorder for the platform, and moving the file pointer
|
||||
// ahead 8 bytes. Returns true on successful read and fills the swapped
|
||||
// value into (*ui64), false on i/o error or EOF.
|
||||
boolean MojoInput_readui64(MojoInput *io, uint64 *ui64);
|
||||
|
||||
// (Please note that there are not bigendian versions of MojoInput_readuiXX()
|
||||
// at the moment, as we don't need them for our current feature set. However,
|
||||
// they could be added easily enough.)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// end of fileio.h ...
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gui.h"
|
||||
#include "platform.h"
|
||||
#include "fileio.h"
|
||||
|
||||
typedef struct S_PLUGINLIST
|
||||
{
|
||||
void *lib;
|
||||
const MojoGui *gui;
|
||||
MojoGuiPluginPriority priority;
|
||||
struct S_PLUGINLIST *next;
|
||||
} PluginList;
|
||||
|
||||
const MojoGui *GGui = NULL;
|
||||
static PluginList *pluginDetails = NULL;
|
||||
|
||||
static const MojoGuiEntryPoint staticGui[] =
|
||||
{
|
||||
#if GUI_STATIC_LINK_STDIO
|
||||
MojoGuiPlugin_stdio,
|
||||
#endif
|
||||
#if GUI_STATIC_LINK_COCOA
|
||||
MojoGuiPlugin_cocoa,
|
||||
#endif
|
||||
#if GUI_STATIC_LINK_GTKPLUS2
|
||||
MojoGuiPlugin_gtkplus2,
|
||||
#endif
|
||||
#if GUI_STATIC_LINK_WWW
|
||||
MojoGuiPlugin_www,
|
||||
#endif
|
||||
#if GUI_STATIC_LINK_NCURSES
|
||||
MojoGuiPlugin_ncurses,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static MojoGuiPluginPriority calcGuiPriority(const MojoGui *gui)
|
||||
{
|
||||
MojoGuiPluginPriority retval;
|
||||
|
||||
retval = gui->priority(MojoPlatform_istty());
|
||||
|
||||
// If the plugin isn't saying "don't try me at all" then see if the
|
||||
// user explicitly wants this one.
|
||||
if (retval != MOJOGUI_PRIORITY_NEVER_TRY)
|
||||
{
|
||||
static const char *envr = NULL;
|
||||
if (envr == NULL)
|
||||
envr = cmdlinestr("ui", "MOJOSETUP_UI", NULL);
|
||||
if ((envr != NULL) && (strcasecmp(envr, gui->name()) == 0))
|
||||
retval = MOJOGUI_PRIORITY_USER_REQUESTED;
|
||||
} // if
|
||||
|
||||
return retval;
|
||||
} // calcGuiPriority
|
||||
|
||||
|
||||
static PluginList *initGuiPluginsByPriority(PluginList *plugins)
|
||||
{
|
||||
MojoGuiPluginPriority p;
|
||||
for (p = MOJOGUI_PRIORITY_USER_REQUESTED; p < MOJOGUI_PRIORITY_TOTAL; p++)
|
||||
{
|
||||
PluginList *i;
|
||||
for (i = plugins->next; i != NULL; i = i->next)
|
||||
{
|
||||
if ( (i->priority == p) && (i->gui->init()) )
|
||||
{
|
||||
logInfo("Selected '%0' UI.", i->gui->name());
|
||||
return i;
|
||||
} // if
|
||||
} // for
|
||||
} // for
|
||||
|
||||
return NULL;
|
||||
} // initGuiPluginsByPriority
|
||||
|
||||
|
||||
static void deleteGuiPlugin(PluginList *plugin)
|
||||
{
|
||||
if (plugin != NULL)
|
||||
{
|
||||
if (plugin->gui)
|
||||
plugin->gui->deinit();
|
||||
if (plugin->lib)
|
||||
MojoPlatform_dlclose(plugin->lib);
|
||||
free(plugin);
|
||||
} // if
|
||||
} // deleteGuiPlugin
|
||||
|
||||
|
||||
static boolean tryGuiPlugin(PluginList *plugins, MojoGuiEntryPoint entry)
|
||||
{
|
||||
boolean retval = false;
|
||||
const MojoGui *gui = entry(MOJOGUI_INTERFACE_REVISION, &GEntryPoints);
|
||||
if (gui != NULL)
|
||||
{
|
||||
PluginList *plug = xmalloc(sizeof (PluginList));
|
||||
plug->lib = NULL;
|
||||
plug->gui = gui;
|
||||
plug->priority = calcGuiPriority(gui);
|
||||
plug->next = plugins->next;
|
||||
plugins->next = plug;
|
||||
retval = true;
|
||||
} // if
|
||||
|
||||
return retval;
|
||||
} // tryGuiPlugin
|
||||
|
||||
|
||||
static void loadStaticGuiPlugins(PluginList *plugins)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; staticGui[i] != NULL; i++)
|
||||
tryGuiPlugin(plugins, staticGui[i]);
|
||||
} // loadStaticGuiPlugins
|
||||
|
||||
|
||||
static boolean loadDynamicGuiPlugin(PluginList *plugins, MojoArchive *ar)
|
||||
{
|
||||
boolean rc = false;
|
||||
void *lib = NULL;
|
||||
MojoInput *io = ar->openCurrentEntry(ar);
|
||||
if (io != NULL)
|
||||
{
|
||||
const uint32 imglen = (uint32) io->length(io);
|
||||
uint8 *img = (uint8 *) xmalloc(imglen);
|
||||
const uint32 br = (uint32) io->read(io, img, imglen);
|
||||
io->close(io);
|
||||
if (br == imglen)
|
||||
lib = MojoPlatform_dlopen(img, imglen);
|
||||
free(img);
|
||||
} // if
|
||||
|
||||
if (lib != NULL)
|
||||
{
|
||||
void *addr = MojoPlatform_dlsym(lib, MOJOGUI_ENTRY_POINT_STR);
|
||||
MojoGuiEntryPoint entry = (MojoGuiEntryPoint) addr;
|
||||
if (entry != NULL)
|
||||
{
|
||||
if ((rc = tryGuiPlugin(plugins, entry)) == false)
|
||||
MojoPlatform_dlclose(lib);
|
||||
} // if
|
||||
} // if
|
||||
|
||||
return rc;
|
||||
} // loadDynamicGuiPlugin
|
||||
|
||||
|
||||
static void loadDynamicGuiPlugins(PluginList *plugins)
|
||||
{
|
||||
if (GBaseArchive->enumerate(GBaseArchive))
|
||||
{
|
||||
const MojoArchiveEntry *entinfo;
|
||||
while ((entinfo = GBaseArchive->enumNext(GBaseArchive)) != NULL)
|
||||
{
|
||||
if (entinfo->type != MOJOARCHIVE_ENTRY_FILE)
|
||||
continue;
|
||||
|
||||
if (strncmp(entinfo->filename, "guis/", 5) != 0)
|
||||
continue;
|
||||
|
||||
loadDynamicGuiPlugin(plugins, GBaseArchive);
|
||||
} // while
|
||||
} // if
|
||||
} // loadDynamicGuiPlugins
|
||||
|
||||
|
||||
const MojoGui *MojoGui_initGuiPlugin(void)
|
||||
{
|
||||
PluginList plugins;
|
||||
PluginList *i = NULL;
|
||||
|
||||
if (pluginDetails != NULL)
|
||||
return pluginDetails->gui;
|
||||
|
||||
memset(&plugins, '\0', sizeof (plugins));
|
||||
assert(GGui == NULL);
|
||||
|
||||
loadDynamicGuiPlugins(&plugins);
|
||||
loadStaticGuiPlugins(&plugins);
|
||||
|
||||
pluginDetails = initGuiPluginsByPriority(&plugins);
|
||||
|
||||
// cleanout unused plugins...
|
||||
i = plugins.next;
|
||||
while (i != NULL)
|
||||
{
|
||||
PluginList *next = i->next;
|
||||
if (i != pluginDetails)
|
||||
deleteGuiPlugin(i);
|
||||
i = next;
|
||||
} // while
|
||||
|
||||
if (pluginDetails != NULL)
|
||||
{
|
||||
GGui = pluginDetails->gui;
|
||||
pluginDetails->next = NULL;
|
||||
} // if
|
||||
|
||||
return GGui;
|
||||
} // MojoGui_findGuiPlugin
|
||||
|
||||
|
||||
void MojoGui_deinitGuiPlugin(void)
|
||||
{
|
||||
GGui = NULL;
|
||||
deleteGuiPlugin(pluginDetails);
|
||||
pluginDetails = NULL;
|
||||
} // MojoGui_deinitGuiPlugin
|
||||
|
||||
// end of gui.c ...
|
||||
|
|
@ -1,325 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _INCL_GUI_H_
|
||||
#define _INCL_GUI_H_
|
||||
|
||||
#include "universal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MOJOGUI_PRIORITY_NEVER_TRY = 0,
|
||||
MOJOGUI_PRIORITY_USER_REQUESTED,
|
||||
MOJOGUI_PRIORITY_TRY_FIRST,
|
||||
MOJOGUI_PRIORITY_TRY_NORMAL,
|
||||
MOJOGUI_PRIORITY_TRY_LAST,
|
||||
MOJOGUI_PRIORITY_TRY_ABSOLUTELY_LAST,
|
||||
MOJOGUI_PRIORITY_TOTAL
|
||||
} MojoGuiPluginPriority;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MOJOGUI_NO,
|
||||
MOJOGUI_YES,
|
||||
MOJOGUI_ALWAYS,
|
||||
MOJOGUI_NEVER
|
||||
} MojoGuiYNAN;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Abstract GUI interfaces.
|
||||
*/
|
||||
|
||||
typedef struct MojoGuiSetupOptions MojoGuiSetupOptions;
|
||||
struct MojoGuiSetupOptions
|
||||
{
|
||||
const char *description;
|
||||
const char *tooltip;
|
||||
boolean value;
|
||||
boolean is_group_parent;
|
||||
uint64 size;
|
||||
int opaque; // GUI drivers shouldn't touch this.
|
||||
void *guiopaque; // For GUI drivers. App won't touch or free this.
|
||||
MojoGuiSetupOptions *next_sibling;
|
||||
MojoGuiSetupOptions *child;
|
||||
};
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MOJOGUI_SPLASH_NONE,
|
||||
MOJOGUI_SPLASH_TOP,
|
||||
MOJOGUI_SPLASH_LEFT,
|
||||
MOJOGUI_SPLASH_RIGHT,
|
||||
MOJOGUI_SPLASH_BOTTOM,
|
||||
MOJOGUI_SPLASH_BACKGROUND,
|
||||
} MojoGuiSplashPos;
|
||||
|
||||
typedef struct MojoGuiSplash MojoGuiSplash;
|
||||
struct MojoGuiSplash
|
||||
{
|
||||
const uint8 *rgba; // framebuffer.
|
||||
uint32 w; // width in pixels.
|
||||
uint32 h; // height in pixels.
|
||||
MojoGuiSplashPos position; // where to put the splash.
|
||||
};
|
||||
|
||||
|
||||
#define MOJOGUI_ENTRY_POINT MojoSetup_Gui_GetInterface
|
||||
#define MOJOGUI_ENTRY_POINT_STR DEFINE_TO_STR(MOJOGUI_ENTRY_POINT)
|
||||
|
||||
// Increment this value when MojoGui's structure changes.
|
||||
#define MOJOGUI_INTERFACE_REVISION 6
|
||||
|
||||
typedef struct MojoGui MojoGui;
|
||||
struct MojoGui
|
||||
{
|
||||
uint8 (*priority)(boolean istty);
|
||||
const char* (*name)(void);
|
||||
boolean (*init)(void);
|
||||
void (*deinit)(void);
|
||||
void (*msgbox)(const char *title, const char *text);
|
||||
boolean (*promptyn)(const char *title, const char *text, boolean def);
|
||||
MojoGuiYNAN (*promptynan)(const char *title, const char *text, boolean def);
|
||||
boolean (*start)(const char *title, const MojoGuiSplash *splash);
|
||||
void (*stop)(void);
|
||||
int (*readme)(const char *name, const uint8 *data, size_t len,
|
||||
boolean can_back, boolean can_fwd);
|
||||
int (*options)(MojoGuiSetupOptions *opts,
|
||||
boolean can_back, boolean can_fwd);
|
||||
char * (*destination)(const char **recommendations, int recnum,
|
||||
int *command, boolean can_back, boolean can_fwd);
|
||||
int (*productkey)(const char *desc, const char *fmt, char *buf,
|
||||
const int buflen, boolean can_back, boolean can_fwd);
|
||||
boolean (*insertmedia)(const char *medianame);
|
||||
void (*progressitem)(void);
|
||||
boolean (*progress)(const char *type, const char *component,
|
||||
int percent, const char *item, boolean can_cancel);
|
||||
void (*final)(const char *msg);
|
||||
};
|
||||
|
||||
typedef const MojoGui* (*MojoGuiEntryPoint)(int revision,
|
||||
const MojoSetupEntryPoints *e);
|
||||
|
||||
#if !BUILDING_EXTERNAL_PLUGIN
|
||||
extern const MojoGui *GGui;
|
||||
const MojoGui *MojoGui_initGuiPlugin(void);
|
||||
void MojoGui_deinitGuiPlugin(void);
|
||||
#else
|
||||
|
||||
__EXPORT__ const MojoGui *MOJOGUI_ENTRY_POINT(int revision,
|
||||
const MojoSetupEntryPoints *e);
|
||||
|
||||
/*
|
||||
* We do this as a macro so we only have to update one place, and it
|
||||
* enforces some details in the plugins. Without effort, plugins don't
|
||||
* support anything but the latest version of the interface.
|
||||
*/
|
||||
#define MOJOGUI_PLUGIN(module) \
|
||||
static const MojoSetupEntryPoints *entry = NULL; \
|
||||
static uint8 MojoGui_##module##_priority(boolean istty); \
|
||||
static const char* MojoGui_##module##_name(void) { return #module; } \
|
||||
static boolean MojoGui_##module##_init(void); \
|
||||
static void MojoGui_##module##_deinit(void); \
|
||||
static void MojoGui_##module##_msgbox(const char *title, const char *text); \
|
||||
static boolean MojoGui_##module##_promptyn(const char *t1, const char *t2, \
|
||||
boolean d); \
|
||||
static MojoGuiYNAN MojoGui_##module##_promptynan(const char *t1, \
|
||||
const char *t2, boolean d); \
|
||||
static boolean MojoGui_##module##_start(const char *t, \
|
||||
const MojoGuiSplash *splash); \
|
||||
static void MojoGui_##module##_stop(void); \
|
||||
static int MojoGui_##module##_readme(const char *name, const uint8 *data, \
|
||||
size_t len, boolean can_back, \
|
||||
boolean can_fwd); \
|
||||
static int MojoGui_##module##_options(MojoGuiSetupOptions *opts, \
|
||||
boolean can_back, boolean can_fwd); \
|
||||
static char *MojoGui_##module##_destination(const char **r, int recnum, \
|
||||
int *command, boolean can_back, boolean can_fwd); \
|
||||
static int MojoGui_##module##_productkey(const char *desc, const char *fmt, \
|
||||
char *buf, const int buflen, boolean can_back, \
|
||||
boolean can_fwd); \
|
||||
static boolean MojoGui_##module##_insertmedia(const char *medianame); \
|
||||
static void MojoGui_##module##_progressitem(void); \
|
||||
static boolean MojoGui_##module##_progress(const char *typ, const char *comp, \
|
||||
int percent, const char *item, \
|
||||
boolean can_cancel); \
|
||||
static void MojoGui_##module##_final(const char *msg); \
|
||||
const MojoGui *MojoGuiPlugin_##module(int rev, const MojoSetupEntryPoints *e) \
|
||||
{ \
|
||||
if (rev == MOJOGUI_INTERFACE_REVISION) { \
|
||||
static const MojoGui retval = { \
|
||||
MojoGui_##module##_priority, \
|
||||
MojoGui_##module##_name, \
|
||||
MojoGui_##module##_init, \
|
||||
MojoGui_##module##_deinit, \
|
||||
MojoGui_##module##_msgbox, \
|
||||
MojoGui_##module##_promptyn, \
|
||||
MojoGui_##module##_promptynan, \
|
||||
MojoGui_##module##_start, \
|
||||
MojoGui_##module##_stop, \
|
||||
MojoGui_##module##_readme, \
|
||||
MojoGui_##module##_options, \
|
||||
MojoGui_##module##_destination, \
|
||||
MojoGui_##module##_productkey, \
|
||||
MojoGui_##module##_insertmedia, \
|
||||
MojoGui_##module##_progressitem, \
|
||||
MojoGui_##module##_progress, \
|
||||
MojoGui_##module##_final, \
|
||||
}; \
|
||||
entry = e; \
|
||||
return &retval; \
|
||||
} \
|
||||
return NULL; \
|
||||
} \
|
||||
|
||||
#define CREATE_MOJOGUI_ENTRY_POINT(module) \
|
||||
const MojoGui *MOJOGUI_ENTRY_POINT(int rev, const MojoSetupEntryPoints *e) \
|
||||
{ \
|
||||
return MojoGuiPlugin_##module(rev, e); \
|
||||
} \
|
||||
|
||||
|
||||
// Redefine things that need to go through the plugin entry point interface,
|
||||
// so plugins calling into the MojoSetup core can use the same code as the
|
||||
// rest of the app.
|
||||
|
||||
#ifdef _
|
||||
#undef _
|
||||
#endif
|
||||
#define _(x) entry->translate(x)
|
||||
|
||||
#ifdef xmalloc
|
||||
#undef xmalloc
|
||||
#endif
|
||||
#define xmalloc(x) entry->xmalloc(x)
|
||||
|
||||
#ifdef xrealloc
|
||||
#undef xrealloc
|
||||
#endif
|
||||
#define xrealloc(x,y) entry->xrealloc(x,y)
|
||||
|
||||
#ifdef xstrdup
|
||||
#undef xstrdup
|
||||
#endif
|
||||
#define xstrdup(x) entry->xstrdup(x)
|
||||
|
||||
#ifdef xstrncpy
|
||||
#undef xstrncpy
|
||||
#endif
|
||||
#define xstrncpy(x,y,z) entry->xstrcpy(x,y,z)
|
||||
|
||||
#ifdef logWarning
|
||||
#undef logWarning
|
||||
#endif
|
||||
#define logWarning entry->logWarning
|
||||
|
||||
#ifdef logError
|
||||
#undef logError
|
||||
#endif
|
||||
#define logError entry->logError
|
||||
|
||||
#ifdef logInfo
|
||||
#undef logInfo
|
||||
#endif
|
||||
#define logInfo entry->logInfo
|
||||
|
||||
#ifdef logDebug
|
||||
#undef logDebug
|
||||
#endif
|
||||
#define logDebug entry->logDebug
|
||||
|
||||
#ifdef format
|
||||
#undef format
|
||||
#endif
|
||||
#define format entry->format
|
||||
|
||||
#ifdef numstr
|
||||
#undef numstr
|
||||
#endif
|
||||
#define numstr(x) entry->numstr(x)
|
||||
|
||||
#ifdef ticks
|
||||
#undef ticks
|
||||
#endif
|
||||
#define ticks() entry->ticks()
|
||||
|
||||
#ifdef utf8codepoint
|
||||
#undef utf8codepoint
|
||||
#endif
|
||||
#define utf8codepoint(x) entry->utf8codepoint(x)
|
||||
|
||||
#ifdef utf8len
|
||||
#undef utf8len
|
||||
#endif
|
||||
#define utf8len(x) entry->utf8len(x)
|
||||
|
||||
#ifdef splitText
|
||||
#undef splitText
|
||||
#endif
|
||||
#define splitText(w,x,y,z) entry->splitText(w,x,y,z)
|
||||
|
||||
#ifdef isValidProductKey
|
||||
#undef isValidProductKey
|
||||
#endif
|
||||
#define isValidProductKey(x,y) entry->isValidProductKey(x,y)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* make some decisions about which GUI plugins to build...
|
||||
* We list them all here, but some are built, some aren't. Some are DLLs,
|
||||
* some aren't...
|
||||
*/
|
||||
|
||||
const MojoGui *MojoGuiPlugin_stdio(int rev, const MojoSetupEntryPoints *e);
|
||||
const MojoGui *MojoGuiPlugin_ncurses(int rev, const MojoSetupEntryPoints *e);
|
||||
const MojoGui *MojoGuiPlugin_gtkplus2(int rev, const MojoSetupEntryPoints *e);
|
||||
const MojoGui *MojoGuiPlugin_www(int rev, const MojoSetupEntryPoints *e);
|
||||
const MojoGui *MojoGuiPlugin_cocoa(int rev, const MojoSetupEntryPoints *e);
|
||||
|
||||
// !!! FIXME: Qt? KDE? Gnome? Console? wxWidgets?
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// end of gui.h ...
|
||||
|
|
@ -1,822 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
*/
|
||||
|
||||
#if !SUPPORT_GUI_COCOA
|
||||
#error Something is wrong in the build system.
|
||||
#endif
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#undef true
|
||||
#undef false
|
||||
|
||||
#define BUILDING_EXTERNAL_PLUGIN 1
|
||||
#include "gui.h"
|
||||
|
||||
MOJOGUI_PLUGIN(cocoa)
|
||||
|
||||
#if !GUI_STATIC_LINK_COCOA
|
||||
CREATE_MOJOGUI_ENTRY_POINT(cocoa)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLICK_BACK=-1,
|
||||
CLICK_CANCEL,
|
||||
CLICK_NEXT,
|
||||
CLICK_NONE
|
||||
} ClickValue;
|
||||
|
||||
// This nasty hack is because we appear to need to be under
|
||||
// -[NSApp run] when calling things like NSRunAlertPanel().
|
||||
// So we push a custom event, call -[NSApp run], catch it, do
|
||||
// the panel, then call -[NSApp stop]. Yuck.
|
||||
typedef enum
|
||||
{
|
||||
CUSTOMEVENT_BASEVALUE=3234,
|
||||
CUSTOMEVENT_RUNQUEUE,
|
||||
CUSTOMEVENT_MSGBOX,
|
||||
CUSTOMEVENT_PROMPTYN,
|
||||
CUSTOMEVENT_PROMPTYNAN,
|
||||
CUSTOMEVENT_INSERTMEDIA,
|
||||
} CustomEvent;
|
||||
|
||||
|
||||
static NSAutoreleasePool *GAutoreleasePool = nil;
|
||||
|
||||
@interface MojoSetupController : NSView
|
||||
{
|
||||
IBOutlet NSButton *BackButton;
|
||||
IBOutlet NSButton *CancelButton;
|
||||
IBOutlet NSComboBox *DestinationCombo;
|
||||
IBOutlet NSTextField *FinalText;
|
||||
IBOutlet NSWindow *MainWindow;
|
||||
IBOutlet NSButton *NextButton;
|
||||
IBOutlet NSProgressIndicator *ProgressBar;
|
||||
IBOutlet NSTextField *ProgressComponentLabel;
|
||||
IBOutlet NSTextField *ProgressItemLabel;
|
||||
IBOutlet NSTextView *ReadmeText;
|
||||
IBOutlet NSTabView *TabView;
|
||||
IBOutlet NSTextField *TitleLabel;
|
||||
IBOutlet NSMenuItem *QuitMenuItem;
|
||||
IBOutlet NSMenuItem *AboutMenuItem;
|
||||
IBOutlet NSMenuItem *HideMenuItem;
|
||||
IBOutlet NSMenuItem *WindowMenuItem;
|
||||
IBOutlet NSMenuItem *HideOthersMenuItem;
|
||||
IBOutlet NSMenuItem *ShowAllMenuItem;
|
||||
IBOutlet NSMenuItem *ServicesMenuItem;
|
||||
IBOutlet NSMenuItem *MinimizeMenuItem;
|
||||
IBOutlet NSMenuItem *ZoomMenuItem;
|
||||
IBOutlet NSMenuItem *BringAllToFrontMenuItem;
|
||||
IBOutlet NSView *OptionsView;
|
||||
ClickValue clickValue;
|
||||
boolean canForward;
|
||||
boolean needToBreakEventLoop;
|
||||
boolean finalPage;
|
||||
MojoGuiYNAN answerYNAN;
|
||||
MojoGuiSetupOptions *mojoOpts;
|
||||
}
|
||||
- (void)awakeFromNib;
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
|
||||
- (void)prepareWidgets:(const char*)winTitle;
|
||||
- (void)unprepareWidgets;
|
||||
- (void)fireCustomEvent:(CustomEvent)eventType data1:(NSInteger)data1 data2:(NSInteger)data2 atStart:(BOOL)atStart;
|
||||
- (void)doCustomEvent:(NSEvent *)event;
|
||||
- (void)doMsgBox:(const char *)title text:(const char *)text;
|
||||
- (void)doPromptYN:(const char *)title text:(const char *)text;
|
||||
- (void)doPromptYNAN:(const char *)title text:(const char *)text;
|
||||
- (void)doInsertMedia:(const char *)medianame;
|
||||
- (MojoGuiYNAN)getAnswerYNAN;
|
||||
- (IBAction)backClicked:(NSButton *)sender;
|
||||
- (IBAction)cancelClicked:(NSButton *)sender;
|
||||
- (IBAction)nextClicked:(NSButton *)sender;
|
||||
- (IBAction)browseClicked:(NSButton *)sender;
|
||||
- (IBAction)menuQuit:(NSMenuItem *)sender;
|
||||
- (int)doPage:(NSString *)pageId title:(const char *)_title canBack:(boolean)canBack canFwd:(boolean)canFwd canCancel:(boolean)canCancel canFwdAtStart:(boolean)canFwdAtStart shouldBlock:(BOOL)shouldBlock;
|
||||
- (int)doReadme:(const char *)title text:(NSString *)text canBack:(boolean)canBack canFwd:(boolean)canFwd;
|
||||
- (void)setOptionTreeSensitivity:(MojoGuiSetupOptions *)opts enabled:(boolean)val;
|
||||
- (void)optionToggled:(id)toggle;
|
||||
- (NSView *)newOptionLevel:(NSView *)box;
|
||||
- (void)buildOptions:(MojoGuiSetupOptions *)opts view:(NSView *)box sensitive:(boolean)sensitive;
|
||||
- (int)doOptions:(MojoGuiSetupOptions *)opts canBack:(boolean)canBack canFwd:(boolean)canFwd;
|
||||
- (char *)doDestination:(const char **)recommends recnum:(int)recnum command:(int *)command canBack:(boolean)canBack canFwd:(boolean)canFwd;
|
||||
- (int)doProductKey:(const char *)desc fmt:(const char *)fmt buf:(char *)buf buflen:(const int)buflen canBack:(boolean)canBack canFwd:(boolean)canFwd;
|
||||
- (int)doProgress:(const char *)type component:(const char *)component percent:(int)percent item:(const char *)item canCancel:(boolean)canCancel;
|
||||
- (void)doFinal:(const char *)msg;
|
||||
@end // interface MojoSetupController
|
||||
|
||||
@implementation MojoSetupController
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
clickValue = CLICK_NONE;
|
||||
canForward = false;
|
||||
answerYNAN = MOJOGUI_NO;
|
||||
needToBreakEventLoop = false;
|
||||
finalPage = false;
|
||||
mojoOpts = nil;
|
||||
} // awakeFromNib
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
printf("didfinishlaunching\n");
|
||||
[NSApp stop:self]; // break out of NSApp::run()
|
||||
} // applicationDidFinishLaunching
|
||||
|
||||
- (void)prepareWidgets:(const char*)winTitle
|
||||
{
|
||||
#if 1
|
||||
[BackButton setTitle:[NSString stringWithUTF8String:_("Back")]];
|
||||
[NextButton setTitle:[NSString stringWithUTF8String:_("Next")]];
|
||||
[CancelButton setTitle:[NSString stringWithUTF8String:_("Cancel")]];
|
||||
#else
|
||||
// !!! FIXME: there's probably a better way to do this.
|
||||
// Set the correct localization for the buttons, then resize them so
|
||||
// the new text fits perfectly. After that, we need to reposition
|
||||
// them so they don't look scattered.
|
||||
NSRect frameBack = [BackButton frame];
|
||||
NSRect frameNext = [NextButton frame];
|
||||
NSRect frameCancel = [CancelButton frame];
|
||||
const float startX = frameCancel.origin.x + frameCancel.size.width;
|
||||
const float spacing = (frameBack.origin.x + frameBack.size.width) - frameNext.origin.x;
|
||||
[BackButton setTitle:[NSString stringWithUTF8String:_("Back")]];
|
||||
[NextButton setTitle:[NSString stringWithUTF8String:_("Next")]];
|
||||
[CancelButton setTitle:[NSString stringWithUTF8String:_("Cancel")]];
|
||||
[BackButton sizeToFit];
|
||||
[NextButton sizeToFit];
|
||||
[CancelButton sizeToFit];
|
||||
frameBack = [BackButton frame];
|
||||
frameNext = [NextButton frame];
|
||||
frameCancel = [CancelButton frame];
|
||||
frameCancel.origin.x = startX - frameCancel.size.width;
|
||||
frameNext.origin.x = (frameCancel.origin.x - frameNext.size.width) - spacing;
|
||||
frameBack.origin.x = (frameNext.origin.x - frameBack.size.width) - spacing;
|
||||
[CancelButton setFrame:frameCancel];
|
||||
[CancelButton setNeedsDisplay:YES];
|
||||
[NextButton setFrame:frameNext];
|
||||
[NextButton setNeedsDisplay:YES];
|
||||
[BackButton setFrame:frameBack];
|
||||
[BackButton setNeedsDisplay:YES];
|
||||
#endif
|
||||
|
||||
[ProgressBar setUsesThreadedAnimation:YES]; // we don't pump fast enough.
|
||||
[ProgressBar startAnimation:self];
|
||||
|
||||
[WindowMenuItem setTitle:[NSString stringWithUTF8String:_("Window")]];
|
||||
[HideOthersMenuItem setTitle:[NSString stringWithUTF8String:_("Hide Others")]];
|
||||
[ShowAllMenuItem setTitle:[NSString stringWithUTF8String:_("Show All")]];
|
||||
[ServicesMenuItem setTitle:[NSString stringWithUTF8String:_("Services")]];
|
||||
[MinimizeMenuItem setTitle:[NSString stringWithUTF8String:_("Minimize")]];
|
||||
[ZoomMenuItem setTitle:[NSString stringWithUTF8String:_("Zoom")]];
|
||||
[BringAllToFrontMenuItem setTitle:[NSString stringWithUTF8String:_("Bring All to Front")]];
|
||||
|
||||
NSString *appName;
|
||||
appName = (NSString *) [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
|
||||
if (appName == nil)
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
const char *utf8AppName = [appName UTF8String];
|
||||
char *text;
|
||||
|
||||
text = format(_("About %0"), utf8AppName);
|
||||
[AboutMenuItem setTitle:[NSString stringWithUTF8String:text]];
|
||||
free(text);
|
||||
|
||||
text = format(_("Hide %0"), utf8AppName);
|
||||
[HideMenuItem setTitle:[NSString stringWithUTF8String:text]];
|
||||
free(text);
|
||||
|
||||
text = format(_("Quit %0"), utf8AppName);
|
||||
[QuitMenuItem setTitle:[NSString stringWithUTF8String:text]];
|
||||
free(text);
|
||||
|
||||
[MainWindow setTitle:[NSString stringWithUTF8String:winTitle]];
|
||||
[MainWindow center];
|
||||
[MainWindow makeKeyAndOrderFront:self];
|
||||
} // prepareWidgets
|
||||
|
||||
- (void)unprepareWidgets
|
||||
{
|
||||
[MainWindow orderOut:self];
|
||||
} // unprepareWidgets
|
||||
|
||||
- (void)fireCustomEvent:(CustomEvent)eventType data1:(NSInteger)data1 data2:(NSInteger)data2 atStart:(BOOL)atStart
|
||||
{
|
||||
NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:(short)eventType data1:data1 data2:data2];
|
||||
[NSApp postEvent:event atStart:atStart];
|
||||
[NSApp run]; // event handler _must_ call -[NSApp stop], or you block here forever.
|
||||
} // fireCustomEvent
|
||||
|
||||
- (void)doCustomEvent:(NSEvent*)event
|
||||
{
|
||||
printf("custom event!\n");
|
||||
switch ((CustomEvent) [event subtype])
|
||||
{
|
||||
case CUSTOMEVENT_RUNQUEUE:
|
||||
if ([NSApp modalWindow] != nil)
|
||||
{
|
||||
// If we're in a modal thing, so don't break the event loop.
|
||||
// Just make a note to break it later.
|
||||
needToBreakEventLoop = true;
|
||||
return;
|
||||
} // if
|
||||
break; // we just need the -[NSApp stop] call.
|
||||
case CUSTOMEVENT_MSGBOX:
|
||||
[self doMsgBox:(const char *)[event data1] text:(const char *)[event data2]];
|
||||
break;
|
||||
case CUSTOMEVENT_PROMPTYN:
|
||||
[self doPromptYN:(const char *)[event data1] text:(const char *)[event data2]];
|
||||
break;
|
||||
case CUSTOMEVENT_PROMPTYNAN:
|
||||
[self doPromptYNAN:(const char *)[event data1] text:(const char *)[event data2]];
|
||||
break;
|
||||
case CUSTOMEVENT_INSERTMEDIA:
|
||||
[self doInsertMedia:(const char *)[event data1]];
|
||||
break;
|
||||
default:
|
||||
return; // let it go without breaking the event loop.
|
||||
} // switch
|
||||
|
||||
[NSApp stop:self]; // break the event loop.
|
||||
} // doCustomEvent
|
||||
|
||||
- (void)doMsgBox:(const char *)title text:(const char *)text
|
||||
{
|
||||
NSString *titlestr = [NSString stringWithUTF8String:title];
|
||||
NSString *textstr = [NSString stringWithUTF8String:text];
|
||||
NSString *okstr = [NSString stringWithUTF8String:_("OK")];
|
||||
NSRunInformationalAlertPanel(titlestr, textstr, okstr, nil, nil);
|
||||
if (needToBreakEventLoop)
|
||||
{
|
||||
needToBreakEventLoop = false;
|
||||
[self fireCustomEvent:CUSTOMEVENT_RUNQUEUE data1:0 data2:0 atStart:NO];
|
||||
} // if
|
||||
} // doMsgBox
|
||||
|
||||
- (void)doPromptYN:(const char *)title text:(const char *)text
|
||||
{
|
||||
NSString *titlestr = [NSString stringWithUTF8String:title];
|
||||
NSString *textstr = [NSString stringWithUTF8String:text];
|
||||
NSString *yesstr = [NSString stringWithUTF8String:_("Yes")];
|
||||
NSString *nostr = [NSString stringWithUTF8String:_("No")];
|
||||
const NSInteger rc = NSRunAlertPanel(titlestr, textstr, yesstr, nostr, nil);
|
||||
answerYNAN = ((rc == NSAlertDefaultReturn) ? MOJOGUI_YES : MOJOGUI_NO);
|
||||
if (needToBreakEventLoop)
|
||||
{
|
||||
needToBreakEventLoop = false;
|
||||
[self fireCustomEvent:CUSTOMEVENT_RUNQUEUE data1:0 data2:0 atStart:NO];
|
||||
} // if
|
||||
} // doPromptYN
|
||||
|
||||
- (void)doPromptYNAN:(const char *)title text:(const char *)text
|
||||
{
|
||||
// !!! FIXME
|
||||
[self doPromptYN:title text:text];
|
||||
} // doPromptYN
|
||||
|
||||
- (void)doInsertMedia:(const char *)medianame
|
||||
{
|
||||
NSString *title = [NSString stringWithUTF8String:_("Media change")];
|
||||
char *fmt = xstrdup(_("Please insert '%0'"));
|
||||
char *_text = format(fmt, medianame);
|
||||
NSString *text = [NSString stringWithUTF8String:_text];
|
||||
free(_text);
|
||||
free(fmt);
|
||||
NSString *okstr = [NSString stringWithUTF8String:_("OK")];
|
||||
NSString *cancelstr = [NSString stringWithUTF8String:_("Cancel")];
|
||||
const NSInteger rc = NSRunAlertPanel(title, text, okstr, cancelstr, nil);
|
||||
answerYNAN = ((rc == NSAlertDefaultReturn) ? MOJOGUI_YES : MOJOGUI_NO);
|
||||
if (needToBreakEventLoop)
|
||||
{
|
||||
needToBreakEventLoop = false;
|
||||
[self fireCustomEvent:CUSTOMEVENT_RUNQUEUE data1:0 data2:0 atStart:NO];
|
||||
} // if
|
||||
} // doInsertMedia
|
||||
|
||||
- (MojoGuiYNAN)getAnswerYNAN
|
||||
{
|
||||
return answerYNAN;
|
||||
} // getAnswerYNAN
|
||||
|
||||
- (IBAction)backClicked:(NSButton *)sender
|
||||
{
|
||||
clickValue = CLICK_BACK;
|
||||
[NSApp stop:self];
|
||||
} // backClicked
|
||||
|
||||
- (IBAction)cancelClicked:(NSButton *)sender
|
||||
{
|
||||
char *title = xstrdup(_("Cancel installation"));
|
||||
char *text = xstrdup(_("Are you sure you want to cancel installation?"));
|
||||
[self doPromptYN:title text:text];
|
||||
free(title);
|
||||
free(text);
|
||||
if (answerYNAN == MOJOGUI_YES)
|
||||
{
|
||||
clickValue = CLICK_CANCEL;
|
||||
[NSApp stop:self];
|
||||
} // if
|
||||
} // cancelClicked
|
||||
|
||||
- (IBAction)nextClicked:(NSButton *)sender
|
||||
{
|
||||
clickValue = CLICK_NEXT;
|
||||
[NSApp stop:self];
|
||||
} // nextClicked
|
||||
|
||||
- (IBAction)browseClicked:(NSButton *)sender
|
||||
{
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
[panel setTitle:[NSString stringWithUTF8String:_("Destination")]];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
[panel setCanCreateDirectories:YES];
|
||||
[panel setCanChooseDirectories:YES];
|
||||
[panel setCanChooseFiles:NO];
|
||||
if ([panel runModal] == NSOKButton)
|
||||
[DestinationCombo setStringValue:[panel filename]];
|
||||
} // browseClicked
|
||||
|
||||
- (IBAction)menuQuit:(NSMenuItem *)sender
|
||||
{
|
||||
if (finalPage) // make this work like you clicked "finished".
|
||||
[self nextClicked:nil];
|
||||
else if ([CancelButton isEnabled]) // make this work like you clicked "cancel".
|
||||
[self cancelClicked:nil];
|
||||
} // menuQuit
|
||||
|
||||
- (int)doPage:(NSString *)pageId title:(const char *)_title canBack:(boolean)canBack canFwd:(boolean)canFwd canCancel:(boolean)canCancel canFwdAtStart:(boolean)canFwdAtStart shouldBlock:(BOOL)shouldBlock
|
||||
{
|
||||
[TitleLabel setStringValue:[NSString stringWithUTF8String:_title]];
|
||||
clickValue = CLICK_NONE;
|
||||
canForward = canFwd;
|
||||
[BackButton setEnabled:canBack ? YES : NO];
|
||||
[NextButton setEnabled:canFwdAtStart ? YES : NO];
|
||||
[CancelButton setEnabled:canCancel ? YES : NO];
|
||||
[TabView selectTabViewItemWithIdentifier:pageId];
|
||||
if (shouldBlock == NO)
|
||||
[self fireCustomEvent:CUSTOMEVENT_RUNQUEUE data1:0 data2:0 atStart:NO];
|
||||
else
|
||||
{
|
||||
[NSApp run];
|
||||
assert(clickValue < CLICK_NONE);
|
||||
} // else
|
||||
return (int) clickValue;
|
||||
} // doPage
|
||||
|
||||
- (int)doReadme:(const char *)title text:(NSString *)text canBack:(boolean)canBack canFwd:(boolean)canFwd
|
||||
{
|
||||
NSRange range = {0, 1}; // reset scrolling to start of text.
|
||||
[ReadmeText setString:text];
|
||||
[ReadmeText scrollRangeToVisible:range];
|
||||
return [self doPage:@"Readme" title:title canBack:canBack canFwd:canFwd canCancel:true canFwdAtStart:canFwd shouldBlock:YES];
|
||||
} // doReadme
|
||||
|
||||
- (void)setOptionTreeSensitivity:(MojoGuiSetupOptions *)opts enabled:(boolean)val
|
||||
{
|
||||
if (opts != nil)
|
||||
{
|
||||
[((id) opts->guiopaque) setEnabled:(val ? YES : NO)];
|
||||
[self setOptionTreeSensitivity:opts->next_sibling enabled:val];
|
||||
[self setOptionTreeSensitivity:opts->child enabled:(val && opts->value)];
|
||||
} // if
|
||||
} // setOptionTreeSensitivity
|
||||
|
||||
- (MojoGuiSetupOptions *)findMojoOption:(id)obj opt:(MojoGuiSetupOptions *)opt
|
||||
{
|
||||
// !!! FIXME: this is not ideal. How can we attach this pointer to
|
||||
// !!! FIXME: the objects themselves so we don't have to walk a tree
|
||||
// !!! FIXME: to find it on each action? The objects are controls
|
||||
// !!! FIXME: and cells (distinct classes), and I don't control the
|
||||
// !!! FIXME: creation of all of them (radio buttons).
|
||||
// !!! FIXME: Alternately, let's just hold a hashtable to map
|
||||
// !!! FIXME: objects to options without walking this tree.
|
||||
if (opt == nil)
|
||||
return nil;
|
||||
|
||||
MojoGuiSetupOptions *i;
|
||||
for (i = opt; i != nil; i = i->next_sibling)
|
||||
{
|
||||
if (i->guiopaque == ((void *) obj))
|
||||
return i;
|
||||
MojoGuiSetupOptions *rc = [self findMojoOption:obj opt:i->child];
|
||||
if (rc != nil)
|
||||
return rc;
|
||||
} // for
|
||||
|
||||
return [self findMojoOption:obj opt:opt->child];
|
||||
} // findMojoOption
|
||||
|
||||
- (void)optionToggled:(id)toggle
|
||||
{
|
||||
MojoGuiSetupOptions *opts = [self findMojoOption:toggle opt:mojoOpts];
|
||||
assert(opts != nil);
|
||||
// !!! FIXME: cast is wrong. use a selector?
|
||||
const boolean enabled = ([((NSControl*)toggle) isEnabled] == YES);
|
||||
opts->value = enabled;
|
||||
[self setOptionTreeSensitivity:opts->child enabled:enabled];
|
||||
} // optionToggled
|
||||
|
||||
- (NSView *)newOptionLevel:(NSView *)box
|
||||
{
|
||||
NSRect frame = NSMakeRect(10, 10, 10, 10);
|
||||
NSView *widget = [[NSView alloc] initWithFrame:frame];
|
||||
[box addSubview:widget positioned:NSWindowBelow relativeTo:nil];
|
||||
[widget release]; // (box) owns it now.
|
||||
return widget;
|
||||
} // newOptionLevel
|
||||
|
||||
// !!! FIXME: most of this mess is cut, pasted, and Cocoaized from the
|
||||
// !!! FIXME: GTK+ GUI. Can we abstract this in the high level and just
|
||||
// !!! FIXME: implement the target-specific bits in the plugins?
|
||||
- (void)buildOptions:(MojoGuiSetupOptions *)opts view:(NSView *)box sensitive:(boolean)sensitive
|
||||
{
|
||||
NSRect frame = NSMakeRect(10, 10, 10, 10);
|
||||
if (opts != nil)
|
||||
{
|
||||
if (opts->is_group_parent)
|
||||
{
|
||||
MojoGuiSetupOptions *kids = opts->child;
|
||||
NSView *childbox = nil;
|
||||
//GtkWidget *alignment = gtk_alignment_new(0.0, 0.5, 0, 0);
|
||||
//gtk_widget_show(alignment);
|
||||
|
||||
// !!! FIXME: disable line wrap?
|
||||
// !!! FIXME: resize on superview resize?
|
||||
NSTextField *widget = [[NSTextField alloc] initWithFrame:frame];
|
||||
[widget setStringValue:[NSString stringWithUTF8String:opts->description]];
|
||||
[widget setEnabled:(sensitive ? YES : NO)];
|
||||
[widget setEditable:NO];
|
||||
[widget setSelectable:NO];
|
||||
[widget setBordered:NO];
|
||||
[widget setBezeled:NO];
|
||||
[widget setAlignment:NSLeftTextAlignment];
|
||||
[widget sizeToFit];
|
||||
if (opts->tooltip != nil)
|
||||
[widget setToolTip:[NSString stringWithUTF8String:opts->tooltip]];
|
||||
[box addSubview:widget positioned:NSWindowBelow relativeTo:nil];
|
||||
[widget release]; // (box) owns it now.
|
||||
//!!! FIXME[box sizeToFit];
|
||||
|
||||
childbox = [self newOptionLevel:box];
|
||||
NSButtonCell *prototype = [[NSButtonCell alloc] init];
|
||||
[prototype setButtonType:NSRadioButton];
|
||||
[prototype setAllowsMixedState:NO];
|
||||
NSMatrix *matrix = [[NSMatrix alloc] initWithFrame:frame mode:NSRadioModeMatrix prototype:(NSCell *)prototype numberOfRows:0 numberOfColumns:1];
|
||||
int row = 0;
|
||||
while (kids)
|
||||
{
|
||||
[matrix addRow];
|
||||
NSButtonCell *cell = (NSButtonCell *) [matrix cellAtRow:row column:0];
|
||||
kids->guiopaque = cell;
|
||||
[cell setTitle:[NSString stringWithUTF8String:kids->description]];
|
||||
[matrix setState:(kids->value ? NSOnState : NSOffState) atRow:row column:0];
|
||||
[cell setEnabled:(kids->value ? YES : NO)];
|
||||
[cell setTarget:self];
|
||||
[cell setAction:@selector(optionToggled:)];
|
||||
|
||||
if (kids->tooltip != nil)
|
||||
[matrix setToolTip:[NSString stringWithUTF8String:kids->tooltip] forCell:cell];
|
||||
|
||||
if (kids->child != nil)
|
||||
[self buildOptions:kids->child view:[self newOptionLevel:childbox] sensitive:sensitive];
|
||||
|
||||
kids = kids->next_sibling;
|
||||
row++;
|
||||
} // while
|
||||
|
||||
[matrix sizeToCells];
|
||||
[childbox addSubview:matrix positioned:NSWindowBelow relativeTo:nil];
|
||||
[matrix release]; // childbox owns it now.
|
||||
//!!! FIXME: [childbox sizeToFit];
|
||||
//!!! FIXME: [[childbox superview] sizeToFit];
|
||||
} // if
|
||||
|
||||
else
|
||||
{
|
||||
NSButton *widget = [[NSButton alloc] initWithFrame:frame];
|
||||
opts->guiopaque = widget;
|
||||
[widget setAllowsMixedState:NO];
|
||||
[widget setTitle:[NSString stringWithUTF8String:opts->description]];
|
||||
[widget setState:(opts->value ? NSOnState : NSOffState)];
|
||||
[widget setEnabled:(sensitive ? YES : NO)];
|
||||
[widget setTarget:self];
|
||||
[widget setAction:@selector(optionToggled:)];
|
||||
[box addSubview:widget positioned:NSWindowBelow relativeTo:nil];
|
||||
[widget release]; // (box) owns it now.
|
||||
//!!!FIXME:[box sizeToFit];
|
||||
|
||||
if (opts->tooltip != nil)
|
||||
[widget setToolTip:[NSString stringWithUTF8String:opts->tooltip]];
|
||||
|
||||
if (opts->child != nil)
|
||||
[self buildOptions:opts->child view:[self newOptionLevel:box] sensitive:((sensitive) && (opts->value))];
|
||||
} // else
|
||||
|
||||
[self buildOptions:opts->next_sibling view:box sensitive:sensitive];
|
||||
} // if
|
||||
|
||||
//!!! FIXME:[box sizeToFit];
|
||||
} // buildOptions
|
||||
|
||||
- (int)doOptions:(MojoGuiSetupOptions *)opts canBack:(boolean)canBack canFwd:(boolean)canFwd
|
||||
{
|
||||
// add all the option widgets to the page's view.
|
||||
[self buildOptions:opts view:OptionsView sensitive:true];
|
||||
|
||||
// run the page.
|
||||
mojoOpts = opts;
|
||||
int retval = [self doPage:@"Options" title:_("Options") canBack:canBack canFwd:canFwd canCancel:true canFwdAtStart:canFwd shouldBlock:YES];
|
||||
mojoOpts = nil;
|
||||
|
||||
// we're done, so nuke everything from the view.
|
||||
NSArray *array = [[OptionsView subviews] copy];
|
||||
NSEnumerator *enumerator = [array objectEnumerator];
|
||||
NSView *obj;
|
||||
while ((obj = (NSView *) [enumerator nextObject]) != nil)
|
||||
[obj removeFromSuperviewWithoutNeedingDisplay];
|
||||
[OptionsView setNeedsDisplay:YES];
|
||||
[enumerator release];
|
||||
[array release];
|
||||
|
||||
return retval;
|
||||
} // doOptions
|
||||
|
||||
- (char *)doDestination:(const char **)recommends recnum:(int)recnum command:(int *)command canBack:(boolean)canBack canFwd:(boolean)canFwd
|
||||
{
|
||||
const boolean fwdAtStart = ( (recnum > 0) && (*(recommends[0])) );
|
||||
int i;
|
||||
|
||||
[DestinationCombo removeAllItems];
|
||||
for (i = 0; i < recnum; i++)
|
||||
[DestinationCombo addItemWithObjectValue:[NSString stringWithUTF8String:recommends[i]]];
|
||||
|
||||
if (recnum > 0)
|
||||
[DestinationCombo setStringValue:[NSString stringWithUTF8String:recommends[0]]];
|
||||
else
|
||||
[DestinationCombo setStringValue:@""];
|
||||
|
||||
*command = [self doPage:@"Destination" title:_("Destination") canBack:canBack canFwd:canFwd canCancel:true canFwdAtStart:fwdAtStart shouldBlock:YES];
|
||||
char *retval = xstrdup([[DestinationCombo stringValue] UTF8String]);
|
||||
[DestinationCombo removeAllItems];
|
||||
[DestinationCombo setStringValue:@""];
|
||||
return retval;
|
||||
} // doDestination
|
||||
|
||||
- (int)doProductKey:(const char *)desc fmt:(const char *)fmt buf:(char *)buf buflen:(const int)buflen canBack:(boolean)canBack canFwd:(boolean)canFwd
|
||||
{
|
||||
// !!! FIXME: write me!
|
||||
return [self doPage:@"ProductKey" title:desc canBack:canBack canFwd:canFwd canCancel:true canFwdAtStart:canFwd shouldBlock:YES];
|
||||
} // doProductKey
|
||||
|
||||
- (int)doProgress:(const char *)type component:(const char *)component percent:(int)percent item:(const char *)item canCancel:(boolean)canCancel
|
||||
{
|
||||
const BOOL indeterminate = (percent < 0) ? YES : NO;
|
||||
[ProgressComponentLabel setStringValue:[NSString stringWithUTF8String:component]];
|
||||
[ProgressItemLabel setStringValue:[NSString stringWithUTF8String:item]];
|
||||
[ProgressBar setIndeterminate:indeterminate];
|
||||
if (!indeterminate)
|
||||
[ProgressBar setDoubleValue:(double)percent];
|
||||
return [self doPage:@"Progress" title:type canBack:false canFwd:false canCancel:canCancel canFwdAtStart:false shouldBlock:NO];
|
||||
} // doProgress
|
||||
|
||||
- (void)doFinal:(const char *)msg
|
||||
{
|
||||
finalPage = true;
|
||||
[FinalText setStringValue:[NSString stringWithUTF8String:msg]];
|
||||
[NextButton setTitle:[NSString stringWithUTF8String:_("Finish")]];
|
||||
[self doPage:@"Final" title:_("Finish") canBack:false canFwd:true canCancel:false canFwdAtStart:true shouldBlock:YES];
|
||||
} // doFinal
|
||||
@end // implementation MojoSetupController
|
||||
|
||||
// Override [NSApplication sendEvent], so we can catch custom events.
|
||||
@interface MojoSetupApplication : NSApplication
|
||||
{
|
||||
}
|
||||
- (void)sendEvent:(NSEvent *)event;
|
||||
@end // interface MojoSetupApplication
|
||||
|
||||
@implementation MojoSetupApplication
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
if ([event type] == NSApplicationDefined)
|
||||
[((MojoSetupController *)[self delegate]) doCustomEvent:event];
|
||||
[super sendEvent:event];
|
||||
} // sendEvent
|
||||
@end // implementation MojoSetupApplication
|
||||
|
||||
|
||||
static uint8 MojoGui_cocoa_priority(boolean istty)
|
||||
{
|
||||
// obviously this is the thing you want on Mac OS X.
|
||||
return MOJOGUI_PRIORITY_TRY_FIRST;
|
||||
} // MojoGui_cocoa_priority
|
||||
|
||||
|
||||
static boolean MojoGui_cocoa_init(void)
|
||||
{
|
||||
// This lets a stdio app become a GUI app. Otherwise, you won't get
|
||||
// GUI events from the system and other things will fail to work.
|
||||
// Putting the app in an application bundle does the same thing.
|
||||
// TransformProcessType() is a 10.3+ API. SetFrontProcess() is 10.0+.
|
||||
if (TransformProcessType != NULL) // check it as a weak symbol.
|
||||
{
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
} // if
|
||||
|
||||
GAutoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// !!! FIXME: make sure we have access to the desktop...may be ssh'd in
|
||||
// !!! FIXME: as another user that doesn't have the Finder loaded or
|
||||
// !!! FIXME: something.
|
||||
|
||||
// For NSApp to be our subclass, instead of default NSApplication.
|
||||
[MojoSetupApplication sharedApplication];
|
||||
if ([NSBundle loadNibNamed:@"MojoSetup" owner:NSApp] == NO)
|
||||
return false;
|
||||
|
||||
// Force NSApp initialization stuff. MojoSetupController is set, in the
|
||||
// .nib, to be NSApp's delegate. Its applicationDidFinishLaunching calls
|
||||
// [NSApp stop] to break event loop right away so we can continue.
|
||||
[NSApp run];
|
||||
|
||||
return true; // always succeeds.
|
||||
} // MojoGui_cocoa_init
|
||||
|
||||
|
||||
static void MojoGui_cocoa_deinit(void)
|
||||
{
|
||||
[GAutoreleasePool release];
|
||||
GAutoreleasePool = nil;
|
||||
// !!! FIXME: destroy nib and NSApp?
|
||||
} // MojoGui_cocoa_deinit
|
||||
|
||||
|
||||
static void MojoGui_cocoa_msgbox(const char *title, const char *text)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[NSApp delegate] fireCustomEvent:CUSTOMEVENT_MSGBOX data1:(NSInteger)title data2:(NSInteger)text atStart:YES];
|
||||
[pool release];
|
||||
} // MojoGui_cocoa_msgbox
|
||||
|
||||
|
||||
static boolean MojoGui_cocoa_promptyn(const char *title, const char *text,
|
||||
boolean defval)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[NSApp delegate] fireCustomEvent:CUSTOMEVENT_PROMPTYN data1:(NSInteger)title data2:(NSInteger)text atStart:YES];
|
||||
const MojoGuiYNAN ynan = [[NSApp delegate] getAnswerYNAN];
|
||||
[pool release];
|
||||
assert((ynan == MOJOGUI_YES) || (ynan == MOJOGUI_NO));
|
||||
return (ynan == MOJOGUI_YES);
|
||||
} // MojoGui_cocoa_promptyn
|
||||
|
||||
|
||||
static MojoGuiYNAN MojoGui_cocoa_promptynan(const char *title,
|
||||
const char *text,
|
||||
boolean defval)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[NSApp delegate] fireCustomEvent:CUSTOMEVENT_PROMPTYNAN data1:(NSInteger)title data2:(NSInteger)text atStart:YES];
|
||||
const MojoGuiYNAN retval = [[NSApp delegate] getAnswerYNAN];
|
||||
[pool release];
|
||||
return retval;
|
||||
} // MojoGui_cocoa_promptynan
|
||||
|
||||
|
||||
static boolean MojoGui_cocoa_start(const char *title,
|
||||
const MojoGuiSplash *splash)
|
||||
{
|
||||
printf("start\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
// !!! FIXME: deal with (splash).
|
||||
[[NSApp delegate] prepareWidgets:title];
|
||||
[pool release];
|
||||
return true;
|
||||
} // MojoGui_cocoa_start
|
||||
|
||||
|
||||
static void MojoGui_cocoa_stop(void)
|
||||
{
|
||||
printf("stop\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[NSApp delegate] unprepareWidgets];
|
||||
[pool release];
|
||||
} // MojoGui_cocoa_stop
|
||||
|
||||
|
||||
static int MojoGui_cocoa_readme(const char *name, const uint8 *data,
|
||||
size_t len, boolean can_back,
|
||||
boolean can_fwd)
|
||||
{
|
||||
printf("readme\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *str = [[[NSString alloc] initWithBytes:data length:len encoding:NSUTF8StringEncoding] autorelease];
|
||||
const int retval = [[NSApp delegate] doReadme:name text:str canBack:can_back canFwd:can_fwd];
|
||||
[pool release];
|
||||
return retval;
|
||||
} // MojoGui_cocoa_readme
|
||||
|
||||
|
||||
static int MojoGui_cocoa_options(MojoGuiSetupOptions *opts,
|
||||
boolean can_back, boolean can_fwd)
|
||||
{
|
||||
printf("options\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
const int retval = [[NSApp delegate] doOptions:opts canBack:can_back canFwd:can_fwd];
|
||||
[pool release];
|
||||
return retval;
|
||||
} // MojoGui_cocoa_options
|
||||
|
||||
|
||||
static char *MojoGui_cocoa_destination(const char **recommends, int recnum,
|
||||
int *command, boolean can_back,
|
||||
boolean can_fwd)
|
||||
{
|
||||
printf("destination\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
char *retval = [[NSApp delegate] doDestination:recommends recnum:recnum command:command canBack:can_back canFwd:can_fwd];
|
||||
[pool release];
|
||||
return retval;
|
||||
} // MojoGui_cocoa_destination
|
||||
|
||||
|
||||
static int MojoGui_cocoa_productkey(const char *desc, const char *fmt,
|
||||
char *buf, const int buflen,
|
||||
boolean can_back, boolean can_fwd)
|
||||
{
|
||||
printf("productkey\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
const int retval = [[NSApp delegate] doProductKey:desc fmt:fmt buf:buf buflen:buflen canBack:can_back canFwd:can_fwd];
|
||||
[pool release];
|
||||
return retval;
|
||||
} // MojoGui_cocoa_productkey
|
||||
|
||||
|
||||
static boolean MojoGui_cocoa_insertmedia(const char *medianame)
|
||||
{
|
||||
printf("insertmedia\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[NSApp delegate] fireCustomEvent:CUSTOMEVENT_INSERTMEDIA data1:(NSInteger)medianame data2:0 atStart:YES];
|
||||
const MojoGuiYNAN ynan = [[NSApp delegate] getAnswerYNAN];
|
||||
assert((ynan == MOJOGUI_YES) || (ynan == MOJOGUI_NO));
|
||||
[pool release];
|
||||
return (ynan == MOJOGUI_YES);
|
||||
} // MojoGui_cocoa_insertmedia
|
||||
|
||||
|
||||
static void MojoGui_cocoa_progressitem(void)
|
||||
{
|
||||
printf("progressitem\n");
|
||||
// no-op in this UI target.
|
||||
} // MojoGui_cocoa_progressitem
|
||||
|
||||
|
||||
static int MojoGui_cocoa_progress(const char *type, const char *component,
|
||||
int percent, const char *item,
|
||||
boolean can_cancel)
|
||||
{
|
||||
printf("progress\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
const int retval = [[NSApp delegate] doProgress:type component:component percent:percent item:item canCancel:can_cancel];
|
||||
[pool release];
|
||||
return retval;
|
||||
} // MojoGui_cocoa_progress
|
||||
|
||||
|
||||
static void MojoGui_cocoa_final(const char *msg)
|
||||
{
|
||||
printf("final\n");
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[NSApp delegate] doFinal:msg];
|
||||
[pool release];
|
||||
} // MojoGui_cocoa_final
|
||||
|
||||
// end of gui_cocoa.m ...
|
||||
|
|
@ -1,938 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*
|
||||
*/
|
||||
|
||||
// Not only does GTK+ 2.x _look_ better than 1.x, it offers a lot of basic
|
||||
// functionality, like message boxes, that you'd expect to exist in a GUI
|
||||
// toolkit. In GTK+v1, you'd have to roll all that on your own!
|
||||
//
|
||||
// It's easier to implement in that regard, and produces a smaller DLL, but
|
||||
// it has a million dependencies, so you might need to use a GTK+v1 plugin,
|
||||
// too, in case they break backwards compatibility.
|
||||
|
||||
#if !SUPPORT_GUI_GTKPLUS2
|
||||
#error Something is wrong in the build system.
|
||||
#endif
|
||||
|
||||
#define BUILDING_EXTERNAL_PLUGIN 1
|
||||
#include "gui.h"
|
||||
|
||||
MOJOGUI_PLUGIN(gtkplus2)
|
||||
|
||||
#if !GUI_STATIC_LINK_GTKPLUS2
|
||||
CREATE_MOJOGUI_ENTRY_POINT(gtkplus2)
|
||||
#endif
|
||||
|
||||
#undef format
|
||||
#include <gtk/gtk.h>
|
||||
#define format entry->format
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PAGE_INTRO,
|
||||
PAGE_README,
|
||||
PAGE_OPTIONS,
|
||||
PAGE_DEST,
|
||||
PAGE_PRODUCTKEY,
|
||||
PAGE_PROGRESS,
|
||||
PAGE_FINAL
|
||||
} WizardPages;
|
||||
|
||||
static WizardPages currentpage = PAGE_INTRO;
|
||||
static gboolean canfwd = TRUE;
|
||||
static GtkWidget *gtkwindow = NULL;
|
||||
static GtkWidget *pagetitle = NULL;
|
||||
static GtkWidget *notebook = NULL;
|
||||
static GtkWidget *readme = NULL;
|
||||
static GtkWidget *cancel = NULL;
|
||||
static GtkWidget *back = NULL;
|
||||
static GtkWidget *next = NULL;
|
||||
static GtkWidget *finish = NULL;
|
||||
static GtkWidget *msgbox = NULL;
|
||||
static GtkWidget *destination = NULL;
|
||||
static GtkWidget *productkey = NULL;
|
||||
static GtkWidget *progressbar = NULL;
|
||||
static GtkWidget *progresslabel = NULL;
|
||||
static GtkWidget *finallabel = NULL;
|
||||
static GtkWidget *browse = NULL;
|
||||
static GtkWidget *splash = NULL;
|
||||
|
||||
static volatile enum
|
||||
{
|
||||
CLICK_BACK=-1,
|
||||
CLICK_CANCEL,
|
||||
CLICK_NEXT,
|
||||
CLICK_NONE
|
||||
} click_value = CLICK_NONE;
|
||||
|
||||
|
||||
static void prepare_wizard(const char *name, WizardPages page,
|
||||
boolean can_back, boolean can_fwd,
|
||||
boolean can_cancel, boolean fwd_at_start)
|
||||
{
|
||||
char *markup = g_markup_printf_escaped(
|
||||
"<span size='large' weight='bold'>%s</span>",
|
||||
name);
|
||||
|
||||
currentpage = page;
|
||||
canfwd = can_fwd;
|
||||
|
||||
gtk_label_set_markup(GTK_LABEL(pagetitle), markup);
|
||||
g_free(markup);
|
||||
|
||||
gtk_widget_set_sensitive(back, can_back);
|
||||
gtk_widget_set_sensitive(next, fwd_at_start);
|
||||
gtk_widget_set_sensitive(cancel, can_cancel);
|
||||
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), (gint) page);
|
||||
|
||||
assert(click_value == CLICK_NONE);
|
||||
assert(gtkwindow != NULL);
|
||||
assert(msgbox == NULL);
|
||||
} // prepare_wizard
|
||||
|
||||
|
||||
static int wait_event(void)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
// signals fired under gtk_main_iteration can change click_value.
|
||||
gtk_main_iteration();
|
||||
if (click_value == CLICK_CANCEL)
|
||||
{
|
||||
char *title = xstrdup(_("Cancel installation"));
|
||||
char *text = xstrdup(_("Are you sure you want to cancel installation?"));
|
||||
if (!MojoGui_gtkplus2_promptyn(title, text, false))
|
||||
click_value = CLICK_NONE;
|
||||
free(title);
|
||||
free(text);
|
||||
} // if
|
||||
|
||||
assert(click_value <= CLICK_NONE);
|
||||
retval = (int) click_value;
|
||||
click_value = CLICK_NONE;
|
||||
return retval;
|
||||
} // wait_event
|
||||
|
||||
|
||||
static int pump_events(void)
|
||||
{
|
||||
int retval = (int) CLICK_NONE;
|
||||
while ( (retval == ((int) CLICK_NONE)) && (gtk_events_pending()) )
|
||||
retval = wait_event();
|
||||
return retval;
|
||||
} // pump_events
|
||||
|
||||
|
||||
static int run_wizard(const char *name, WizardPages page,
|
||||
boolean can_back, boolean can_fwd, boolean can_cancel,
|
||||
boolean fwd_at_start)
|
||||
{
|
||||
int retval = CLICK_NONE;
|
||||
prepare_wizard(name, page, can_back, can_fwd, can_cancel, fwd_at_start);
|
||||
while (retval == ((int) CLICK_NONE))
|
||||
retval = wait_event();
|
||||
|
||||
assert(retval < ((int) CLICK_NONE));
|
||||
return retval;
|
||||
} // run_wizard
|
||||
|
||||
|
||||
static gboolean signal_delete(GtkWidget *w, GdkEvent *evt, gpointer data)
|
||||
{
|
||||
click_value = CLICK_CANCEL;
|
||||
return TRUE; /* eat event: default handler destroys window! */
|
||||
} // signal_delete
|
||||
|
||||
|
||||
static void signal_clicked(GtkButton *_button, gpointer data)
|
||||
{
|
||||
GtkWidget *button = GTK_WIDGET(_button);
|
||||
if (button == back)
|
||||
click_value = CLICK_BACK;
|
||||
else if (button == cancel)
|
||||
click_value = CLICK_CANCEL;
|
||||
else if ((button == next) || (button == finish))
|
||||
click_value = CLICK_NEXT;
|
||||
else
|
||||
{
|
||||
assert(0 && "Unknown click event.");
|
||||
} // else
|
||||
} // signal_clicked
|
||||
|
||||
|
||||
static void signal_browse_clicked(GtkButton *_button, gpointer data)
|
||||
{
|
||||
GtkWidget *dialog = gtk_file_chooser_dialog_new (
|
||||
_("Destination"),
|
||||
NULL,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
|
||||
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
|
||||
gtk_combo_box_get_active_text(GTK_COMBO_BOX(destination)));
|
||||
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||
gchar *filename;
|
||||
gchar *utfname;
|
||||
|
||||
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
||||
|
||||
utfname = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
|
||||
gtk_combo_box_prepend_text(GTK_COMBO_BOX(destination), utfname);
|
||||
gtk_combo_box_set_active(GTK_COMBO_BOX(destination), 0);
|
||||
|
||||
g_free(utfname);
|
||||
g_free(filename);
|
||||
}
|
||||
|
||||
// !!! FIXME: should append the package name to the directory they chose?
|
||||
// !!! FIXME: This is annoying, they might have created the folder
|
||||
// !!! FIXME: themselves in the dialog.
|
||||
// !!! FIXME: Could warn when the target directory already contains files?
|
||||
|
||||
gtk_widget_destroy(dialog);
|
||||
} // signal_browse_clicked
|
||||
|
||||
|
||||
static void signal_dest_changed(GtkComboBox *combo, gpointer user_data)
|
||||
{
|
||||
// Disable the forward button when the destination entry is blank.
|
||||
if ((currentpage == PAGE_DEST) && (canfwd))
|
||||
{
|
||||
gchar *str = gtk_combo_box_get_active_text(combo);
|
||||
const gboolean filled_in = ((str != NULL) && (*str != '\0'));
|
||||
g_free(str);
|
||||
gtk_widget_set_sensitive(next, filled_in);
|
||||
} // if
|
||||
} // signal_dest_changed
|
||||
|
||||
|
||||
static void signal_productkey_changed(GtkEditable *edit, gpointer user_data)
|
||||
{
|
||||
// Disable the forward button when the entry is blank.
|
||||
if ((currentpage == PAGE_PRODUCTKEY) && (canfwd))
|
||||
{
|
||||
const char *fmt = (const char *) user_data;
|
||||
char *key = (char *) gtk_editable_get_chars(edit, 0, -1);
|
||||
const gboolean okay = isValidProductKey(fmt, key);
|
||||
g_free(key);
|
||||
gtk_widget_set_sensitive(next, okay);
|
||||
} // if
|
||||
} // signal_productkey_changed
|
||||
|
||||
|
||||
static uint8 MojoGui_gtkplus2_priority(boolean istty)
|
||||
{
|
||||
// gnome-session exports this environment variable since 2002.
|
||||
if (getenv("GNOME_DESKTOP_SESSION_ID") != NULL)
|
||||
return MOJOGUI_PRIORITY_TRY_FIRST;
|
||||
|
||||
return MOJOGUI_PRIORITY_TRY_NORMAL;
|
||||
} // MojoGui_gtkplus2_priority
|
||||
|
||||
|
||||
static boolean MojoGui_gtkplus2_init(void)
|
||||
{
|
||||
int tmpargc = 0;
|
||||
char *args[] = { NULL, NULL };
|
||||
char **tmpargv = args;
|
||||
if (!gtk_init_check(&tmpargc, &tmpargv))
|
||||
{
|
||||
logInfo("gtkplus2: gtk_init_check() failed, use another UI.");
|
||||
return false;
|
||||
} // if
|
||||
return true;
|
||||
} // MojoGui_gtkplus2_init
|
||||
|
||||
|
||||
static void MojoGui_gtkplus2_deinit(void)
|
||||
{
|
||||
// !!! FIXME: GTK+ doesn't have a deinit function...it installs a crappy
|
||||
// !!! FIXME: atexit() function!
|
||||
} // MojoGui_gtkplus2_deinit
|
||||
|
||||
/**
|
||||
*
|
||||
* @param defbutton The response ID to use when enter is pressed, or 0
|
||||
* to leave it up to GTK+.
|
||||
*/
|
||||
static gint do_msgbox(const char *title, const char *text,
|
||||
GtkMessageType mtype, GtkButtonsType btype,
|
||||
GtkResponseType defbutton,
|
||||
void (*addButtonCallback)(GtkWidget *_msgbox))
|
||||
{
|
||||
gint retval = 0;
|
||||
|
||||
// Modal dialog, this will never be called recursively.
|
||||
assert(msgbox == NULL);
|
||||
|
||||
msgbox = gtk_message_dialog_new(GTK_WINDOW(gtkwindow), GTK_DIALOG_MODAL,
|
||||
mtype, btype, "%s", title);
|
||||
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msgbox),
|
||||
"%s", text);
|
||||
|
||||
if (defbutton)
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(msgbox), defbutton);
|
||||
|
||||
if (addButtonCallback != NULL)
|
||||
addButtonCallback(msgbox);
|
||||
|
||||
retval = gtk_dialog_run(GTK_DIALOG(msgbox));
|
||||
gtk_widget_destroy(msgbox);
|
||||
msgbox = NULL;
|
||||
|
||||
return retval;
|
||||
} // do_msgbox
|
||||
|
||||
|
||||
static void MojoGui_gtkplus2_msgbox(const char *title, const char *text)
|
||||
{
|
||||
do_msgbox(title, text, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, 0, NULL);
|
||||
} // MojoGui_gtkplus2_msgbox
|
||||
|
||||
|
||||
static boolean MojoGui_gtkplus2_promptyn(const char *title, const char *text,
|
||||
boolean defval)
|
||||
{
|
||||
gint rc = do_msgbox(title, text, GTK_MESSAGE_QUESTION,
|
||||
GTK_BUTTONS_YES_NO,
|
||||
defval ? GTK_RESPONSE_YES : GTK_RESPONSE_NO,
|
||||
NULL);
|
||||
|
||||
return (rc == GTK_RESPONSE_YES);
|
||||
} // MojoGui_gtkplus2_promptyn
|
||||
|
||||
|
||||
static void promptynanButtonCallback(GtkWidget *_msgbox)
|
||||
{
|
||||
char *always = xstrdup(_("_Always"));
|
||||
char *never = xstrdup(_("N_ever"));
|
||||
gtk_dialog_add_buttons(GTK_DIALOG(_msgbox),
|
||||
GTK_STOCK_YES, GTK_RESPONSE_YES,
|
||||
GTK_STOCK_NO, GTK_RESPONSE_NO,
|
||||
always, 1,
|
||||
never, 0,
|
||||
NULL);
|
||||
|
||||
free(always);
|
||||
free(never);
|
||||
} // promptynanButtonCallback
|
||||
|
||||
|
||||
static MojoGuiYNAN MojoGui_gtkplus2_promptynan(const char *title,
|
||||
const char *text,
|
||||
boolean defval)
|
||||
{
|
||||
const gint rc = do_msgbox(title, text, GTK_MESSAGE_QUESTION,
|
||||
GTK_BUTTONS_NONE,
|
||||
defval ? GTK_RESPONSE_YES : GTK_RESPONSE_NO,
|
||||
promptynanButtonCallback);
|
||||
switch (rc)
|
||||
{
|
||||
case GTK_RESPONSE_YES: return MOJOGUI_YES;
|
||||
case GTK_RESPONSE_NO: return MOJOGUI_NO;
|
||||
case 1: return MOJOGUI_ALWAYS;
|
||||
case 0: return MOJOGUI_NEVER;
|
||||
} // switch
|
||||
|
||||
assert(false && "BUG: unhandled case in switch statement");
|
||||
return MOJOGUI_NO; // just in case.
|
||||
} // MojoGui_gtkplus2_promptynan
|
||||
|
||||
|
||||
static GtkWidget *create_button(GtkWidget *box, const char *iconname,
|
||||
const char *text,
|
||||
void (*signal_callback)
|
||||
(GtkButton *button, gpointer data))
|
||||
{
|
||||
GtkWidget *button = gtk_button_new_with_mnemonic(text);
|
||||
GtkWidget *image = gtk_image_new_from_stock(iconname, GTK_ICON_SIZE_BUTTON);
|
||||
gtk_button_set_image (GTK_BUTTON(button), image);
|
||||
gtk_widget_show(button);
|
||||
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
|
||||
gtk_signal_connect(GTK_OBJECT(button), "clicked",
|
||||
GTK_SIGNAL_FUNC(signal_callback), NULL);
|
||||
return button;
|
||||
} // create_button
|
||||
|
||||
|
||||
static void free_splash(guchar *pixels, gpointer data)
|
||||
{
|
||||
free(pixels);
|
||||
} // free_splash
|
||||
|
||||
|
||||
static GtkWidget *build_splash(const MojoGuiSplash *splash)
|
||||
{
|
||||
GtkWidget *retval = NULL;
|
||||
GdkPixbuf *pixbuf = NULL;
|
||||
guchar *rgba = NULL;
|
||||
const uint32 splashlen = splash->w * splash->h * 4;
|
||||
|
||||
if (splash->position == MOJOGUI_SPLASH_NONE)
|
||||
return NULL;
|
||||
|
||||
if ((splash->rgba == NULL) || (splashlen == 0))
|
||||
return NULL;
|
||||
|
||||
rgba = (guchar *) xmalloc(splashlen);
|
||||
memcpy(rgba, splash->rgba, splashlen);
|
||||
pixbuf = gdk_pixbuf_new_from_data(rgba, GDK_COLORSPACE_RGB, TRUE, 8,
|
||||
splash->w, splash->h, splash->w * 4,
|
||||
free_splash, NULL);
|
||||
if (pixbuf == NULL)
|
||||
free(rgba);
|
||||
else
|
||||
{
|
||||
retval = gtk_image_new_from_pixbuf(pixbuf);
|
||||
g_object_unref(pixbuf); // retval adds a ref to pixbuf, so lose our's.
|
||||
if (retval != NULL)
|
||||
gtk_widget_show(retval);
|
||||
} // else
|
||||
|
||||
return retval;
|
||||
} // build_splash
|
||||
|
||||
|
||||
static GtkWidget *create_gtkwindow(const char *title,
|
||||
const MojoGuiSplash *_splash)
|
||||
{
|
||||
GtkWidget *splashbox = NULL;
|
||||
GtkWidget *window;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *box;
|
||||
GtkWidget *alignment;
|
||||
GtkWidget *hbox;
|
||||
|
||||
currentpage = PAGE_INTRO;
|
||||
canfwd = TRUE;
|
||||
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
|
||||
gtk_window_set_title(GTK_WINDOW(window), title);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(window), 8);
|
||||
|
||||
GdkPixbuf *icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
|
||||
"system-software-installer",
|
||||
48, 0, NULL);
|
||||
if (icon)
|
||||
gtk_window_set_icon(GTK_WINDOW(window), icon);
|
||||
|
||||
assert(splash == NULL);
|
||||
splash = build_splash(_splash);
|
||||
if (splash != NULL)
|
||||
{
|
||||
// !!! FIXME: MOJOGUI_SPLASH_BACKGROUND?
|
||||
const MojoGuiSplashPos pos = _splash->position;
|
||||
if ((pos == MOJOGUI_SPLASH_LEFT) || (pos == MOJOGUI_SPLASH_RIGHT))
|
||||
{
|
||||
splashbox = gtk_hbox_new(FALSE, 6);
|
||||
gtk_widget_show(splashbox);
|
||||
gtk_container_add(GTK_CONTAINER(window), splashbox);
|
||||
if (pos == MOJOGUI_SPLASH_LEFT)
|
||||
gtk_box_pack_start(GTK_BOX(splashbox), splash, FALSE, FALSE, 6);
|
||||
else
|
||||
gtk_box_pack_end(GTK_BOX(splashbox), splash, FALSE, FALSE, 6);
|
||||
} // if
|
||||
|
||||
else if ((pos == MOJOGUI_SPLASH_TOP) || (pos == MOJOGUI_SPLASH_BOTTOM))
|
||||
{
|
||||
splashbox = gtk_vbox_new(FALSE, 6);
|
||||
gtk_widget_show(splashbox);
|
||||
gtk_container_add(GTK_CONTAINER(window), splashbox);
|
||||
if (pos == MOJOGUI_SPLASH_TOP)
|
||||
gtk_box_pack_start(GTK_BOX(splashbox), splash, FALSE, FALSE, 6);
|
||||
else
|
||||
gtk_box_pack_end(GTK_BOX(splashbox), splash, FALSE, FALSE, 6);
|
||||
} // else if
|
||||
} // if
|
||||
|
||||
if (splashbox == NULL) // no splash, use the window for the top container.
|
||||
splashbox = window;
|
||||
|
||||
box = gtk_vbox_new(FALSE, 6);
|
||||
gtk_widget_show(box);
|
||||
gtk_container_add(GTK_CONTAINER(splashbox), box);
|
||||
|
||||
pagetitle = gtk_label_new("");
|
||||
gtk_widget_show(pagetitle);
|
||||
gtk_box_pack_start(GTK_BOX(box), pagetitle, FALSE, TRUE, 16);
|
||||
|
||||
notebook = gtk_notebook_new();
|
||||
gtk_widget_show(notebook);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(notebook), 0);
|
||||
gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0);
|
||||
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
|
||||
gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
|
||||
gtk_widget_set_size_request(notebook,
|
||||
(gint) (((float) gdk_screen_width()) * 0.4),
|
||||
(gint) (((float) gdk_screen_height()) * 0.4));
|
||||
|
||||
widget = gtk_hbutton_box_new();
|
||||
gtk_widget_show(widget);
|
||||
gtk_box_pack_start(GTK_BOX(box), widget, FALSE, FALSE, 0);
|
||||
gtk_button_box_set_layout(GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_END);
|
||||
gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX (widget), 6, 0);
|
||||
gtk_button_box_set_spacing(GTK_BUTTON_BOX (widget), 6);
|
||||
|
||||
box = widget;
|
||||
cancel = create_button(box, "gtk-cancel", _("Cancel"), signal_clicked);
|
||||
back = create_button(box, "gtk-go-back", _("Back"), signal_clicked);
|
||||
next = create_button(box, "gtk-go-forward", _("Next"), signal_clicked);
|
||||
finish = create_button(box, "gtk-goto-last", _("Finish"), signal_clicked);
|
||||
gtk_widget_hide(finish);
|
||||
|
||||
// !!! FIXME: intro page.
|
||||
widget = gtk_vbox_new(FALSE, 0);
|
||||
gtk_widget_show(widget);
|
||||
gtk_container_add(GTK_CONTAINER(notebook), widget);
|
||||
|
||||
// README/EULA page.
|
||||
widget = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_scrolled_window_set_policy(
|
||||
GTK_SCROLLED_WINDOW(widget),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
|
||||
gtk_scrolled_window_set_shadow_type(
|
||||
GTK_SCROLLED_WINDOW(widget),
|
||||
GTK_SHADOW_IN);
|
||||
gtk_widget_show(widget);
|
||||
gtk_container_add(GTK_CONTAINER(notebook), widget);
|
||||
|
||||
readme = gtk_text_view_new();
|
||||
gtk_widget_show(readme);
|
||||
gtk_container_add(GTK_CONTAINER(widget), readme);
|
||||
gtk_text_view_set_editable(GTK_TEXT_VIEW(readme), FALSE);
|
||||
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(readme), GTK_WRAP_NONE);
|
||||
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(readme), FALSE);
|
||||
gtk_text_view_set_left_margin(GTK_TEXT_VIEW(readme), 4);
|
||||
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(readme), 4);
|
||||
|
||||
// !!! FIXME: options page.
|
||||
box = gtk_vbox_new(FALSE, 0);
|
||||
gtk_widget_show(box);
|
||||
gtk_container_add(GTK_CONTAINER(notebook), box);
|
||||
|
||||
// Destination page
|
||||
box = gtk_vbox_new(FALSE, 0);
|
||||
gtk_widget_show(box);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 6);
|
||||
widget = gtk_label_new(_("Folder:"));
|
||||
gtk_widget_show(widget);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
|
||||
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
|
||||
gtk_label_set_line_wrap(GTK_LABEL(widget), FALSE);
|
||||
alignment = gtk_alignment_new(0.5, 0.5, 1, 0);
|
||||
destination = gtk_combo_box_entry_new_text();
|
||||
gtk_signal_connect(GTK_OBJECT(destination), "changed",
|
||||
GTK_SIGNAL_FUNC(signal_dest_changed), NULL);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), destination);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), alignment, TRUE, TRUE, 0);
|
||||
browse = create_button(hbox, "gtk-open",
|
||||
_("B_rowse..."), signal_browse_clicked);
|
||||
gtk_widget_show_all (hbox);
|
||||
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
|
||||
gtk_container_add(GTK_CONTAINER(notebook), box);
|
||||
|
||||
// Product key page
|
||||
box = gtk_vbox_new(FALSE, 0);
|
||||
gtk_widget_show(box);
|
||||
|
||||
widget = gtk_label_new(_("Please enter your product key"));
|
||||
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_CENTER);
|
||||
gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE);
|
||||
gtk_widget_show(widget);
|
||||
gtk_box_pack_start(GTK_BOX(box), widget, FALSE, TRUE, 0);
|
||||
|
||||
hbox = gtk_hbox_new(FALSE, 0);
|
||||
gtk_widget_show(hbox);
|
||||
productkey = gtk_entry_new();
|
||||
gtk_entry_set_editable(GTK_ENTRY(productkey), TRUE);
|
||||
gtk_entry_set_visibility(GTK_ENTRY(productkey), TRUE);
|
||||
gtk_widget_show(productkey);
|
||||
gtk_box_pack_start(GTK_BOX(hbox), productkey, TRUE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(notebook), box);
|
||||
|
||||
// Progress page
|
||||
box = gtk_vbox_new(FALSE, 6);
|
||||
gtk_widget_show(box);
|
||||
alignment = gtk_alignment_new(0.5, 0.5, 1, 0);
|
||||
gtk_widget_show(alignment);
|
||||
progressbar = gtk_progress_bar_new();
|
||||
gtk_widget_show(progressbar);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), progressbar);
|
||||
gtk_box_pack_start(GTK_BOX(box), alignment, FALSE, TRUE, 0);
|
||||
progresslabel = gtk_label_new("");
|
||||
gtk_widget_show(progresslabel);
|
||||
gtk_box_pack_start(GTK_BOX(box), progresslabel, FALSE, TRUE, 0);
|
||||
gtk_label_set_justify(GTK_LABEL(progresslabel), GTK_JUSTIFY_LEFT);
|
||||
gtk_label_set_line_wrap(GTK_LABEL(progresslabel), FALSE);
|
||||
gtk_container_add(GTK_CONTAINER(notebook), box);
|
||||
|
||||
// !!! FIXME: final page.
|
||||
widget = gtk_vbox_new(FALSE, 0);
|
||||
gtk_widget_show(widget);
|
||||
gtk_container_add(GTK_CONTAINER(notebook), widget);
|
||||
finallabel = gtk_label_new("");
|
||||
gtk_widget_show(finallabel);
|
||||
gtk_box_pack_start(GTK_BOX(widget), finallabel, FALSE, TRUE, 0);
|
||||
gtk_label_set_justify(GTK_LABEL(finallabel), GTK_JUSTIFY_LEFT);
|
||||
gtk_label_set_line_wrap(GTK_LABEL(finallabel), TRUE);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(window), "delete-event",
|
||||
GTK_SIGNAL_FUNC(signal_delete), NULL);
|
||||
|
||||
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
|
||||
gtk_widget_show(window);
|
||||
|
||||
gtk_widget_grab_focus(next);
|
||||
|
||||
return window;
|
||||
} // create_gtkwindow
|
||||
|
||||
|
||||
static boolean MojoGui_gtkplus2_start(const char *title,
|
||||
const MojoGuiSplash *splash)
|
||||
{
|
||||
gtkwindow = create_gtkwindow(title, splash);
|
||||
return (gtkwindow != NULL);
|
||||
} // MojoGui_gtkplus2_start
|
||||
|
||||
|
||||
static void MojoGui_gtkplus2_stop(void)
|
||||
{
|
||||
assert(msgbox == NULL);
|
||||
if (gtkwindow != NULL)
|
||||
gtk_widget_destroy(gtkwindow);
|
||||
|
||||
gtkwindow = NULL;
|
||||
pagetitle = NULL;
|
||||
finallabel = NULL;
|
||||
progresslabel = NULL;
|
||||
progressbar = NULL;
|
||||
destination = NULL;
|
||||
productkey = NULL;
|
||||
notebook = NULL;
|
||||
readme = NULL;
|
||||
cancel = NULL;
|
||||
back = NULL;
|
||||
next = NULL;
|
||||
finish = NULL;
|
||||
splash = NULL;
|
||||
} // MojoGui_gtkplus2_stop
|
||||
|
||||
|
||||
static int MojoGui_gtkplus2_readme(const char *name, const uint8 *data,
|
||||
size_t datalen, boolean can_back,
|
||||
boolean can_fwd)
|
||||
{
|
||||
GtkTextBuffer *textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(readme));
|
||||
gtk_text_buffer_set_text(textbuf, (const gchar *) data, datalen);
|
||||
return run_wizard(name, PAGE_README, can_back, can_fwd, true, can_fwd);
|
||||
} // MojoGui_gtkplus2_readme
|
||||
|
||||
|
||||
static void set_option_tree_sensitivity(MojoGuiSetupOptions *opts, boolean val)
|
||||
{
|
||||
if (opts != NULL)
|
||||
{
|
||||
gtk_widget_set_sensitive((GtkWidget *) opts->guiopaque, val);
|
||||
set_option_tree_sensitivity(opts->next_sibling, val);
|
||||
set_option_tree_sensitivity(opts->child, val && opts->value);
|
||||
} // if
|
||||
} // set_option_tree_sensitivity
|
||||
|
||||
|
||||
static void signal_option_toggled(GtkToggleButton *toggle, gpointer data)
|
||||
{
|
||||
MojoGuiSetupOptions *opts = (MojoGuiSetupOptions *) data;
|
||||
const boolean enabled = gtk_toggle_button_get_active(toggle);
|
||||
opts->value = enabled;
|
||||
set_option_tree_sensitivity(opts->child, enabled);
|
||||
} // signal_option_toggled
|
||||
|
||||
|
||||
static GtkWidget *new_option_level(GtkWidget *box)
|
||||
{
|
||||
GtkWidget *alignment = gtk_alignment_new(0.0, 0.5, 0, 0);
|
||||
GtkWidget *retval = gtk_vbox_new(FALSE, 0);
|
||||
gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 15, 0);
|
||||
gtk_widget_show(alignment);
|
||||
gtk_widget_show(retval);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), retval);
|
||||
gtk_box_pack_start(GTK_BOX(box), alignment, TRUE, TRUE, 0);
|
||||
return retval;
|
||||
} // new_option_level
|
||||
|
||||
|
||||
// use this to generate a tooltip only as needed.
|
||||
static GtkTooltips *get_tip(GtkTooltips **_tip)
|
||||
{
|
||||
if (*_tip == NULL)
|
||||
{
|
||||
GtkTooltips *tip = gtk_tooltips_new();
|
||||
gtk_tooltips_enable(tip);
|
||||
*_tip = tip;
|
||||
} // if
|
||||
|
||||
return *_tip;
|
||||
} // get_tip
|
||||
|
||||
|
||||
static void build_options(MojoGuiSetupOptions *opts, GtkWidget *box,
|
||||
gboolean sensitive)
|
||||
{
|
||||
if (opts != NULL)
|
||||
{
|
||||
GtkTooltips *tip = NULL;
|
||||
GtkWidget *widget = NULL;
|
||||
|
||||
if (opts->is_group_parent)
|
||||
{
|
||||
MojoGuiSetupOptions *kids = opts->child;
|
||||
GtkWidget *childbox = NULL;
|
||||
GtkWidget *alignment = gtk_alignment_new(0.0, 0.5, 0, 0);
|
||||
gtk_widget_show(alignment);
|
||||
widget = gtk_label_new(opts->description);
|
||||
opts->guiopaque = widget;
|
||||
gtk_widget_set_sensitive(widget, sensitive);
|
||||
gtk_widget_show(widget);
|
||||
gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
|
||||
gtk_label_set_line_wrap(GTK_LABEL(widget), FALSE);
|
||||
gtk_container_add(GTK_CONTAINER(alignment), widget);
|
||||
gtk_box_pack_start(GTK_BOX(box), alignment, FALSE, TRUE, 0);
|
||||
|
||||
if (opts->tooltip != NULL)
|
||||
gtk_tooltips_set_tip(get_tip(&tip), widget, opts->tooltip, 0);
|
||||
|
||||
widget = NULL;
|
||||
childbox = new_option_level(box);
|
||||
while (kids)
|
||||
{
|
||||
widget = gtk_radio_button_new_with_label_from_widget(
|
||||
GTK_RADIO_BUTTON(widget),
|
||||
kids->description);
|
||||
kids->guiopaque = widget;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
|
||||
kids->value);
|
||||
gtk_widget_set_sensitive(widget, sensitive);
|
||||
gtk_widget_show(widget);
|
||||
gtk_box_pack_start(GTK_BOX(childbox), widget, FALSE, TRUE, 0);
|
||||
gtk_signal_connect(GTK_OBJECT(widget), "toggled",
|
||||
GTK_SIGNAL_FUNC(signal_option_toggled), kids);
|
||||
|
||||
if (kids->tooltip != NULL)
|
||||
gtk_tooltips_set_tip(get_tip(&tip),widget,kids->tooltip,0);
|
||||
|
||||
if (kids->child != NULL)
|
||||
{
|
||||
build_options(kids->child, new_option_level(childbox),
|
||||
sensitive);
|
||||
} // if
|
||||
kids = kids->next_sibling;
|
||||
} // while
|
||||
} // if
|
||||
|
||||
else
|
||||
{
|
||||
widget = gtk_check_button_new_with_label(opts->description);
|
||||
opts->guiopaque = widget;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
|
||||
opts->value);
|
||||
gtk_widget_set_sensitive(widget, sensitive);
|
||||
gtk_widget_show(widget);
|
||||
gtk_box_pack_start(GTK_BOX(box), widget, FALSE, TRUE, 0);
|
||||
gtk_signal_connect(GTK_OBJECT(widget), "toggled",
|
||||
GTK_SIGNAL_FUNC(signal_option_toggled), opts);
|
||||
|
||||
if (opts->tooltip != NULL)
|
||||
gtk_tooltips_set_tip(get_tip(&tip), widget, opts->tooltip, 0);
|
||||
|
||||
if (opts->child != NULL)
|
||||
{
|
||||
build_options(opts->child, new_option_level(box),
|
||||
((sensitive) && (opts->value)) );
|
||||
} // if
|
||||
} // else
|
||||
|
||||
build_options(opts->next_sibling, box, sensitive);
|
||||
} // if
|
||||
} // build_options
|
||||
|
||||
|
||||
static int MojoGui_gtkplus2_options(MojoGuiSetupOptions *opts,
|
||||
boolean can_back, boolean can_fwd)
|
||||
{
|
||||
int retval;
|
||||
GtkWidget *box;
|
||||
GtkWidget *page; // this is a vbox.
|
||||
|
||||
page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), PAGE_OPTIONS);
|
||||
box = gtk_vbox_new(FALSE, 0);
|
||||
gtk_widget_show(box);
|
||||
gtk_box_pack_start(GTK_BOX(page), box, FALSE, FALSE, 0);
|
||||
|
||||
build_options(opts, box, TRUE);
|
||||
retval = run_wizard(_("Options"), PAGE_OPTIONS,
|
||||
can_back, can_fwd, true, can_fwd);
|
||||
gtk_widget_destroy(box);
|
||||
return retval;
|
||||
} // MojoGui_gtkplus2_options
|
||||
|
||||
|
||||
static char *MojoGui_gtkplus2_destination(const char **recommends, int recnum,
|
||||
int *command, boolean can_back,
|
||||
boolean can_fwd)
|
||||
{
|
||||
GtkComboBox *combo = GTK_COMBO_BOX(destination);
|
||||
const boolean fwd_at_start = ( (recnum > 0) && (*(recommends[0])) );
|
||||
gchar *str = NULL;
|
||||
char *retval = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < recnum; i++)
|
||||
gtk_combo_box_append_text(combo, recommends[i]);
|
||||
gtk_combo_box_set_active (combo, 0);
|
||||
|
||||
*command = run_wizard(_("Destination"), PAGE_DEST,
|
||||
can_back, can_fwd, true, fwd_at_start);
|
||||
|
||||
str = gtk_combo_box_get_active_text(combo);
|
||||
|
||||
// shouldn't ever be empty ("next" should be disabled in that case).
|
||||
assert( (*command <= 0) || ((str != NULL) && (*str != '\0')) );
|
||||
|
||||
retval = xstrdup(str);
|
||||
g_free(str);
|
||||
|
||||
for (i = recnum-1; i >= 0; i--)
|
||||
gtk_combo_box_remove_text(combo, i);
|
||||
|
||||
return retval;
|
||||
} // MojoGui_gtkplus2_destination
|
||||
|
||||
|
||||
static int MojoGui_gtkplus2_productkey(const char *desc, const char *fmt,
|
||||
char *buf, const int buflen,
|
||||
boolean can_back, boolean can_fwd)
|
||||
{
|
||||
gchar *str = NULL;
|
||||
int retval = 0;
|
||||
const boolean fwd_at_start = isValidProductKey(fmt, buf);
|
||||
|
||||
gtk_entry_set_max_length(GTK_ENTRY(productkey), buflen - 1);
|
||||
gtk_entry_set_width_chars(GTK_ENTRY(productkey), buflen - 1);
|
||||
gtk_entry_set_text(GTK_ENTRY(productkey), (gchar *) buf);
|
||||
|
||||
const guint connid = gtk_signal_connect(GTK_OBJECT(productkey), "changed",
|
||||
GTK_SIGNAL_FUNC(signal_productkey_changed),
|
||||
(void *) fmt);
|
||||
retval = run_wizard(desc, PAGE_PRODUCTKEY,
|
||||
can_back, can_fwd, true, fwd_at_start);
|
||||
gtk_signal_disconnect(GTK_OBJECT(productkey), connid);
|
||||
|
||||
str = gtk_editable_get_chars(GTK_EDITABLE(productkey), 0, -1);
|
||||
// should never be invalid ("next" should be disabled in that case).
|
||||
assert( (retval <= 0) || ((str) && (isValidProductKey(fmt, str))) );
|
||||
assert(strlen(str) < buflen);
|
||||
strcpy(buf, (char *) str);
|
||||
g_free(str);
|
||||
gtk_entry_set_text(GTK_ENTRY(productkey), "");
|
||||
|
||||
return retval;
|
||||
} // MojoGui_gtkplus2_productkey
|
||||
|
||||
|
||||
static boolean MojoGui_gtkplus2_insertmedia(const char *medianame)
|
||||
{
|
||||
gint rc = 0;
|
||||
// !!! FIXME: Use stock GTK icon for "media"?
|
||||
// !!! FIXME: better text.
|
||||
const char *title = xstrdup(_("Media change"));
|
||||
// !!! FIXME: better text.
|
||||
const char *fmt = xstrdup(_("Please insert '%0'"));
|
||||
const char *text = format(fmt, medianame);
|
||||
rc = do_msgbox(title, text, GTK_MESSAGE_WARNING,
|
||||
GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, NULL);
|
||||
free((void *) text);
|
||||
free((void *) fmt);
|
||||
free((void *) title);
|
||||
return (rc == GTK_RESPONSE_OK);
|
||||
} // MojoGui_gtkplus2_insertmedia
|
||||
|
||||
|
||||
static void MojoGui_gtkplus2_progressitem(void)
|
||||
{
|
||||
// no-op in this UI target.
|
||||
} // MojoGui_gtkplus2_progressitem
|
||||
|
||||
|
||||
static boolean MojoGui_gtkplus2_progress(const char *type, const char *component,
|
||||
int percent, const char *item,
|
||||
boolean can_cancel)
|
||||
{
|
||||
static uint32 lastTicks = 0;
|
||||
const uint32 ticks = ticks();
|
||||
int rc;
|
||||
|
||||
if ((ticks - lastTicks) > 200) // just not to spam this...
|
||||
{
|
||||
GtkProgressBar *progress = GTK_PROGRESS_BAR(progressbar);
|
||||
if (percent < 0)
|
||||
gtk_progress_bar_pulse(progress);
|
||||
else
|
||||
gtk_progress_bar_set_fraction(progress, ((gdouble) percent) / 100.0);
|
||||
|
||||
gtk_progress_bar_set_text(progress, component);
|
||||
gtk_label_set_text(GTK_LABEL(progresslabel), item);
|
||||
lastTicks = ticks;
|
||||
} // if
|
||||
|
||||
prepare_wizard(type, PAGE_PROGRESS, false, false, can_cancel, false);
|
||||
rc = pump_events();
|
||||
assert( (rc == ((int) CLICK_CANCEL)) || (rc == ((int) CLICK_NONE)) );
|
||||
return (rc != CLICK_CANCEL);
|
||||
} // MojoGui_gtkplus2_progress
|
||||
|
||||
|
||||
static void MojoGui_gtkplus2_final(const char *msg)
|
||||
{
|
||||
gtk_widget_hide(next);
|
||||
gtk_widget_show(finish);
|
||||
gtk_label_set_text(GTK_LABEL(finallabel), msg);
|
||||
run_wizard(_("Finish"), PAGE_FINAL, false, true, false, true);
|
||||
} // MojoGui_gtkplus2_final
|
||||
|
||||
// end of gui_gtkplus2.c ...
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,655 +0,0 @@
|
|||
/**
|
||||
* MojoSetup; a portable, flexible installation application.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
*/
|
||||
|
||||
#if !SUPPORT_GUI_STDIO
|
||||
#error Something is wrong in the build system.
|
||||
#endif
|
||||
|
||||
#define BUILDING_EXTERNAL_PLUGIN 1
|
||||
#include "gui.h"
|
||||
|
||||
MOJOGUI_PLUGIN(stdio)
|
||||
|
||||
#if !GUI_STATIC_LINK_STDIO
|
||||
CREATE_MOJOGUI_ENTRY_POINT(stdio)
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static char *lastProgressType = NULL;
|
||||
static char *lastComponent = NULL;
|
||||
static uint32 percentTicks = 0;
|
||||
|
||||
static int read_stdin(char *buf, int len)
|
||||
{
|
||||
if (fgets(buf, len, stdin) == NULL)
|
||||
return -1;
|
||||
|
||||
len = strlen(buf) - 1;
|
||||
while ( (len >= 0) && ((buf[len] == '\n') || (buf[len] == '\r')) )
|
||||
buf[len--] = '\0';
|
||||
|
||||
return len+1;
|
||||
} // read_stdin
|
||||
|
||||
|
||||
static int readstr(const char *prompt, char *buf, int len,
|
||||
boolean back, boolean fwd)
|
||||
{
|
||||
// !!! FIXME: if read_stdin() returns -1, we return 0, which makes it
|
||||
// !!! FIXME: indistinguishable from "user hit enter" ... maybe we should
|
||||
// !!! FIXME: abort in read_stdin() if i/o fails?
|
||||
|
||||
int retval = 0;
|
||||
char *backstr = (back) ? xstrdup(_("back")) : NULL;
|
||||
|
||||
if (prompt != NULL)
|
||||
printf("%s\n", prompt);
|
||||
|
||||
if (back)
|
||||
{
|
||||
char *fmt = xstrdup(_("Type '%0' to go back."));
|
||||
char *msg = format(fmt, backstr);
|
||||
printf("%s\n", msg);
|
||||
free(msg);
|
||||
free(fmt);
|
||||
} // if
|
||||
|
||||
if (fwd)
|
||||
{
|
||||
printf("%s", _("Press enter to continue."));
|
||||
printf("\n");
|
||||
} // if
|
||||
|
||||
printf("%s",_("> "));
|
||||
fflush(stdout);
|
||||
|
||||
if ((retval = read_stdin(buf, len)) >= 0)
|
||||
{
|
||||
if ((back) && (strcmp(buf, backstr) == 0)) // !!! FIXME: utf8casecmp?
|
||||
retval = -1;
|
||||
} // if
|
||||
|
||||
free(backstr);
|
||||
return retval;
|
||||
} // readstr
|
||||
|
||||
|
||||
static uint8 MojoGui_stdio_priority(boolean istty)
|
||||
{
|
||||
// if not a tty and no other GUI plugins worked out, let the base
|
||||
// application try to spawn a terminal and try again. If it can't do so,
|
||||
// it will panic() and thus end the process, so we don't end up blocking
|
||||
// on some prompt the user can't see.
|
||||
|
||||
if (!istty)
|
||||
return MOJOGUI_PRIORITY_NEVER_TRY;
|
||||
|
||||
return MOJOGUI_PRIORITY_TRY_ABSOLUTELY_LAST; // always a last resort.
|
||||
} // MojoGui_stdio_priority
|
||||
|
||||
|
||||
static boolean MojoGui_stdio_init(void)
|
||||
{
|
||||
percentTicks = 0;
|
||||
return true; // always succeeds.
|
||||
} // MojoGui_stdio_init
|
||||
|
||||
|
||||
static void MojoGui_stdio_deinit(void)
|
||||
{
|
||||
free(lastProgressType);
|
||||
free(lastComponent);
|
||||
lastProgressType = NULL;
|
||||
lastComponent = NULL;
|
||||
} // MojoGui_stdio_deinit
|
||||
|
||||
|
||||
static void MojoGui_stdio_msgbox(const char *title, const char *text)
|
||||
{
|
||||
char buf[128];
|
||||
char *fmt = xstrdup(_("NOTICE: %0\n[hit enter]"));
|
||||
char *msg = format(fmt, text);
|
||||
printf("%s\n", msg);
|
||||
free(msg);
|
||||
free(fmt);
|
||||
fflush(stdout);
|
||||
read_stdin(buf, sizeof (buf));
|
||||
} // MojoGui_stdio_msgbox
|
||||
|
||||
|
||||
static boolean MojoGui_stdio_promptyn(const char *title, const char *text,
|
||||
boolean defval)
|
||||
{
|
||||
boolean retval = false;
|
||||
if (!feof(stdin))
|
||||
{
|
||||
const char *_fmt = ((defval) ? _("%0 [Y/n]: ") : _("%0 [y/N]: "));
|
||||
char *fmt = xstrdup(_fmt);
|
||||
char *msg = format(fmt, text);
|
||||
char *localized_no = xstrdup(_("N"));
|
||||
char *localized_yes = xstrdup(_("Y"));
|
||||
boolean getout = false;
|
||||
char buf[128];
|
||||
|
||||
while (!getout)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
getout = true; // we may reset this later.
|
||||
printf("%s", msg);
|
||||
fflush(stdout);
|
||||
rc = read_stdin(buf, sizeof (buf));
|
||||
|
||||
if (rc < 0)
|
||||
retval = false;
|
||||
else if (rc == 0)
|
||||
retval = defval;
|
||||
else if (strcasecmp(buf, localized_no) == 0)
|
||||
retval = false;
|
||||
else if (strcasecmp(buf, localized_yes) == 0)
|
||||
retval = true;
|
||||
else
|
||||
getout = false; // try again.
|
||||
} // while
|
||||
|
||||
free(localized_yes);
|
||||
free(localized_no);
|
||||
free(msg);
|
||||
free(fmt);
|
||||
} // if
|
||||
|
||||
return retval;
|
||||
} // MojoGui_stdio_promptyn
|
||||
|
||||
|
||||
static MojoGuiYNAN MojoGui_stdio_promptynan(const char *title, const char *txt,
|
||||
boolean defval)
|
||||
{
|
||||
MojoGuiYNAN retval = MOJOGUI_NO;
|
||||
if (!feof(stdin))
|
||||
{
|
||||
char *fmt = xstrdup(_("%0\n[y/n/Always/Never]: "));
|
||||
char *msg = format(fmt, txt);
|
||||
char *localized_no = xstrdup(_("N"));
|
||||
char *localized_yes = xstrdup(_("Y"));
|
||||
char *localized_always = xstrdup(_("Always"));
|
||||
char *localized_never = xstrdup(_("Never"));
|
||||
boolean getout = false;
|
||||
char buf[128];
|
||||
|
||||
while (!getout)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
getout = true; // we may reset this later.
|
||||
printf("%s\n", msg);
|
||||
fflush(stdout);
|
||||
rc = read_stdin(buf, sizeof (buf));
|
||||
|
||||
if (rc < 0)
|
||||
retval = MOJOGUI_NO;
|
||||
else if (rc == 0)
|
||||
retval = (defval) ? MOJOGUI_YES : MOJOGUI_NO;
|
||||
else if (strcasecmp(buf, localized_no) == 0)
|
||||
retval = MOJOGUI_NO;
|
||||
else if (strcasecmp(buf, localized_yes) == 0)
|
||||
retval = MOJOGUI_YES;
|
||||
else if (strcasecmp(buf, localized_always) == 0)
|
||||
retval = MOJOGUI_ALWAYS;
|
||||
else if (strcasecmp(buf, localized_never) == 0)
|
||||
retval = MOJOGUI_NEVER;
|
||||
else
|
||||
getout = false; // try again.
|
||||
} // while
|
||||
|
||||
free(localized_never);
|
||||
free(localized_always);
|
||||
free(localized_yes);
|
||||
free(localized_no);
|
||||
free(msg);
|
||||
free(fmt);
|
||||
} // if
|
||||
|
||||
return retval;
|
||||
} // MojoGui_stdio_promptynan
|
||||
|
||||
|
||||
static boolean MojoGui_stdio_start(const char *title,
|
||||
const MojoGuiSplash *splash)
|
||||
{
|
||||
printf("%s\n", title);
|
||||
return true;
|
||||
} // MojoGui_stdio_start
|
||||
|
||||
|
||||
static void MojoGui_stdio_stop(void)
|
||||
{
|
||||
// no-op.
|
||||
} // MojoGui_stdio_stop
|
||||
|
||||
|
||||
static void dumb_pager(const char *name, const char *data, size_t datalen)
|
||||
{
|
||||
const int MAX_PAGE_LINES = 21;
|
||||
char *fmt = xstrdup(_("(%0-%1 of %2 lines, see more?)"));
|
||||
int i = 0;
|
||||
int w = 0;
|
||||
int linecount = 0;
|
||||
boolean getout = false;
|
||||
char **lines = splitText(data, 80, &linecount, &w);
|
||||
|
||||
assert(linecount >= 0);
|
||||
|
||||
printf("%s\n", name);
|
||||
|
||||
if (lines == NULL) // failed to parse?!
|
||||
printf("%s\n", data); // just dump it all. Oh well.
|
||||
else
|
||||
{
|
||||
int printed = 0;
|
||||
do
|
||||
{
|
||||
for (i = 0; (i < MAX_PAGE_LINES) && (printed < linecount); i++)
|
||||
printf("%s", lines[printed++]);
|
||||
|
||||
if (printed >= linecount)
|
||||
getout = true;
|
||||
else
|
||||
{
|
||||
char *msg = NULL;
|
||||
printf("\n");
|
||||
msg = format(fmt, numstr((printed-i)+1),
|
||||
numstr(printed), numstr(linecount));
|
||||
getout = !MojoGui_stdio_promptyn("", msg, true);
|
||||
free(msg);
|
||||
printf("\n");
|
||||
} // else
|
||||
} while (!getout);
|
||||
|
||||
for (i = 0; i < linecount; i++)
|
||||
free(lines[i]);
|
||||
free(lines);
|
||||
} // while
|
||||
|
||||
free(fmt);
|
||||
} // dumb_pager
|
||||
|
||||
|
||||
static int MojoGui_stdio_readme(const char *name, const uint8 *_data,
|
||||
size_t datalen, boolean can_back,
|
||||
boolean can_fwd)
|
||||
{
|
||||
const char *data = (const char *) _data;
|
||||
char buf[256];
|
||||
int retval = -1;
|
||||
boolean failed = true;
|
||||
|
||||
// !!! FIXME: popen() isn't reliable.
|
||||
#if 0 //PLATFORM_UNIX
|
||||
const size_t namelen = strlen(name);
|
||||
const char *programs[] = { getenv("PAGER"), "more", "less -M", "less" };
|
||||
int i = 0;
|
||||
|
||||
// flush streams, so output doesn't mingle with the popen()'d process.
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
for (i = 0; i < STATICARRAYLEN(programs); i++)
|
||||
{
|
||||
const char *cmd = programs[i];
|
||||
if (cmd != NULL)
|
||||
{
|
||||
FILE *io = popen(cmd, "w");
|
||||
if (io != NULL)
|
||||
{
|
||||
failed = false;
|
||||
if (!failed) failed = (fwrite("\n", 1, 1, io) != 1);
|
||||
if (!failed) failed = (fwrite(name, namelen, 1, io) != 1);
|
||||
if (!failed) failed = (fwrite("\n", 1, 1, io) != 1);
|
||||
if (!failed) failed = (fwrite(data, datalen, 1, io) != 1);
|
||||
if (!failed) failed = (fwrite("\n", 1, 1, io) != 1);
|
||||
failed |= (pclose(io) != 0); // call whether we failed or not.
|
||||
if (!failed)
|
||||
break; // it worked, we're done!
|
||||
} // if
|
||||
} // if
|
||||
} // for
|
||||
#endif // PLATFORM_UNIX
|
||||
|
||||
if (failed) // We're not Unix, or none of the pagers worked?
|
||||
dumb_pager(name, data, datalen);
|
||||
|
||||
// Put up the "hit enter to continue (or 'back' to go back)" prompt,
|
||||
// but only if there's an choice to be made here.
|
||||
if ((!can_back) || (readstr(NULL, buf, sizeof (buf), can_back, true) >= 0))
|
||||
retval = 1;
|
||||
|
||||
return retval;
|
||||
} // MojoGui_stdio_readme
|
||||
|
||||
|
||||
static void toggle_option(MojoGuiSetupOptions *parent,
|
||||
MojoGuiSetupOptions *opts, int *line, int target)
|
||||
{
|
||||
if ((opts != NULL) && (target > *line))
|
||||
{
|
||||
if (!opts->is_group_parent)
|
||||
{
|
||||
if (++(*line) == target)
|
||||
{
|
||||
const boolean toggled = ((opts->value) ? false : true);
|
||||
|
||||
// "radio buttons" in a group?
|
||||
if ((parent) && (parent->is_group_parent))
|
||||
{
|
||||
if (toggled) // drop unless we weren't the current toggle.
|
||||
{
|
||||
// set all siblings to false...
|
||||
MojoGuiSetupOptions *i = parent->child;
|
||||
while (i != NULL)
|
||||
{
|
||||
i->value = false;
|
||||
i = i->next_sibling;
|
||||
} // while
|
||||
opts->value = true; // reset us to be true.
|
||||
} // if
|
||||
} // if
|
||||
|
||||
else // individual "check box" was chosen.
|
||||
{
|
||||
opts->value = toggled;
|
||||
} // else
|
||||
|
||||
return; // we found it, bail.
|
||||
} // if
|
||||
} // if
|
||||
|
||||
if (opts->value) // if option is toggled on, descend to children.
|
||||
toggle_option(opts, opts->child, line, target);
|
||||
toggle_option(parent, opts->next_sibling, line, target);
|
||||
} // if
|
||||
} // toggle_option
|
||||
|
||||
|
||||
static void print_options(MojoGuiSetupOptions *opts, int *line, int level)
|
||||
{
|
||||
if (opts != NULL)
|
||||
{
|
||||
int i;
|
||||
int spacing = 1;
|
||||
if (opts->is_group_parent)
|
||||
spacing += 6;
|
||||
else
|
||||
{
|
||||
(*line)++;
|
||||
printf("%2d [%c]", *line, opts->value ? 'X' : ' ');
|
||||
} // else
|
||||
|
||||
for (i = 0; i < (level + spacing); i++)
|
||||
putchar(' ');
|
||||
|
||||
printf("%s%s\n", opts->description, opts->is_group_parent ? ":" : "");
|
||||
|
||||
if ((opts->value) || (opts->is_group_parent))
|
||||
print_options(opts->child, line, level+1);
|
||||
print_options(opts->next_sibling, line, level);
|
||||
} // if
|
||||
} // print_options
|
||||
|
||||
|
||||
static int MojoGui_stdio_options(MojoGuiSetupOptions *opts,
|
||||
boolean can_back, boolean can_fwd)
|
||||
{
|
||||
const char *inst_opts_str = xstrdup(_("Options"));
|
||||
const char *prompt = xstrdup(_("Choose number to change."));
|
||||
int retval = -1;
|
||||
boolean getout = false;
|
||||
char buf[128];
|
||||
int len = 0;
|
||||
|
||||
while (!getout)
|
||||
{
|
||||
int line = 0;
|
||||
|
||||
printf("\n\n");
|
||||
printf("%s", inst_opts_str);
|
||||
printf("\n");
|
||||
print_options(opts, &line, 1);
|
||||
printf("\n");
|
||||
|
||||
if ((len = readstr(prompt, buf, sizeof (buf), can_back, true)) < 0)
|
||||
getout = true;
|
||||
else if (len == 0)
|
||||
{
|
||||
getout = true;
|
||||
retval = 1;
|
||||
} // else if
|
||||
else
|
||||
{
|
||||
char *endptr = NULL;
|
||||
int target = (int) strtol(buf, &endptr, 10);
|
||||
if (*endptr == '\0') // complete string was a valid number?
|
||||
{
|
||||
line = 0;
|
||||
toggle_option(NULL, opts, &line, target);
|
||||
} // if
|
||||
} // else
|
||||
} // while
|
||||
|
||||
free((void *) inst_opts_str);
|
||||
free((void *) prompt);
|
||||
|
||||
return retval;
|
||||
} // MojoGui_stdio_options
|
||||
|
||||
|
||||
static char *MojoGui_stdio_destination(const char **recommends, int recnum,
|
||||
int *command, boolean can_back,
|
||||
boolean can_fwd)
|
||||
{
|
||||
const char *instdeststr = xstrdup(_("Destination"));
|
||||
const char *prompt = NULL;
|
||||
char *retval = NULL;
|
||||
boolean getout = false;
|
||||
char buf[128];
|
||||
int len = 0;
|
||||
int i = 0;
|
||||
|
||||
*command = -1;
|
||||
|
||||
if (recnum > 0)
|
||||
prompt = xstrdup(_("Choose install destination by number (hit enter for #1), or enter your own."));
|
||||
else
|
||||
prompt = xstrdup(_("Enter path where files will be installed."));
|
||||
|
||||
while (!getout)
|
||||
{
|
||||
printf("\n\n%s\n", instdeststr);
|
||||
for (i = 0; i < recnum; i++)
|
||||
printf(" %2d %s\n", i+1, recommends[i]);
|
||||
printf("\n");
|
||||
|
||||
if ((len = readstr(prompt, buf, sizeof (buf), can_back, false)) < 0)
|
||||
getout = true;
|
||||
|
||||
else if ((len == 0) && (recnum > 0)) // default to first in list.
|
||||
{
|
||||
retval = xstrdup(recommends[0]);
|
||||
*command = 1;
|
||||
getout = true;
|
||||
} // else if
|
||||
|
||||
else if (len > 0)
|
||||
{
|
||||
char *endptr = NULL;
|
||||
int target = (int) strtol(buf, &endptr, 10);
|
||||
// complete string was a valid number?
|
||||
if ((*endptr == '\0') && (target > 0) && (target <= recnum))
|
||||
retval = xstrdup(recommends[target-1]);
|
||||
else
|
||||
retval = xstrdup(buf);
|
||||
|
||||
*command = 1;
|
||||
getout = true;
|
||||
} // else
|
||||
} // while
|
||||
|
||||
free((void *) prompt);
|
||||
free((void *) instdeststr);
|
||||
|
||||
return retval;
|
||||
} // MojoGui_stdio_destination
|
||||
|
||||
|
||||
static int MojoGui_stdio_productkey(const char *desc, const char *fmt,
|
||||
char *buf, const int buflen,
|
||||
boolean can_back, boolean can_fwd)
|
||||
{
|
||||
const char *prompt = xstrdup(_("Please enter your product key"));
|
||||
char *defval = ((*buf) ? xstrdup(buf) : NULL);
|
||||
boolean getout = false;
|
||||
int retval = -1;
|
||||
char *msg = NULL;
|
||||
|
||||
if (defval != NULL)
|
||||
{
|
||||
char *locfmt = xstrdup(_("(just press enter to use '%0')"));
|
||||
msg = format(locfmt, defval);
|
||||
free(locfmt);
|
||||
} // if
|
||||
|
||||
while (!getout)
|
||||
{
|
||||
int len;
|
||||
printf("\n\n%s\n", desc);
|
||||
if (msg != NULL)
|
||||
printf("%s\n", msg);
|
||||
if ((len = readstr(prompt, buf, buflen, can_back, false)) < 0)
|
||||
getout = true;
|
||||
else
|
||||
{
|
||||
if ((len == 0) && (defval != NULL))
|
||||
strcpy(buf, defval);
|
||||
|
||||
if (isValidProductKey(fmt, buf))
|
||||
{
|
||||
retval = 1;
|
||||
getout = true;
|
||||
} // else if
|
||||
else
|
||||
{
|
||||
// We can't check the input character-by-character, so reuse
|
||||
// the failed-verification localized string.
|
||||
printf("\n%s\n\n",
|
||||
_("That key appears to be invalid. Please try again."));
|
||||
} // else
|
||||
} // else
|
||||
} // while
|
||||
|
||||
free(msg);
|
||||
free(defval);
|
||||
free((void *) prompt);
|
||||
|
||||
return retval;
|
||||
} // MojoGui_stdio_productkey
|
||||
|
||||
|
||||
static boolean MojoGui_stdio_insertmedia(const char *medianame)
|
||||
{
|
||||
char buf[32];
|
||||
char *fmt = xstrdup(_("Please insert '%0'"));
|
||||
char *msg = format(fmt, medianame);
|
||||
printf("%s\n", _("Media change"));
|
||||
printf("%s\n", msg);
|
||||
free(msg);
|
||||
free(fmt);
|
||||
return (readstr(NULL, buf, sizeof (buf), false, true) >= 0);
|
||||
} // MojoGui_stdio_insertmedia
|
||||
|
||||
|
||||
static void MojoGui_stdio_progressitem(void)
|
||||
{
|
||||
// force new line of output on next call to MojoGui_stdio_progress()
|
||||
percentTicks = 0;
|
||||
} // MojoGui_stdio_progressitem
|
||||
|
||||
|
||||
static boolean MojoGui_stdio_progress(const char *type, const char *component,
|
||||
int percent, const char *item,
|
||||
boolean can_cancel)
|
||||
{
|
||||
const uint32 now = ticks();
|
||||
|
||||
if ( (lastComponent == NULL) ||
|
||||
(strcmp(lastComponent, component) != 0) ||
|
||||
(lastProgressType == NULL) ||
|
||||
(strcmp(lastProgressType, type) != 0) )
|
||||
{
|
||||
free(lastProgressType);
|
||||
free(lastComponent);
|
||||
lastProgressType = xstrdup(type);
|
||||
lastComponent = xstrdup(component);
|
||||
printf("%s\n%s\n", type, component);
|
||||
} // if
|
||||
|
||||
// limit update spam... will only write every one second, tops,
|
||||
// on any given filename, but it writes each filename at least once
|
||||
// so it doesn't look like we only installed a few things.
|
||||
if (percentTicks <= now)
|
||||
{
|
||||
char *fmt = NULL;
|
||||
char *msg = NULL;
|
||||
percentTicks = now + 1000;
|
||||
if (percent < 0)
|
||||
printf("%s\n", item);
|
||||
else
|
||||
{
|
||||
fmt = xstrdup(_("%0 (total progress: %1%%)"));
|
||||
msg = format(fmt, item, numstr(percent));
|
||||
printf("%s\n", msg);
|
||||
free(msg);
|
||||
free(fmt);
|
||||
} // else
|
||||
} // if
|
||||
|
||||
return true;
|
||||
} // MojoGui_stdio_progress
|
||||
|
||||
|
||||
static void MojoGui_stdio_final(const char *msg)
|
||||
{
|
||||
printf("%s\n\n", msg);
|
||||
fflush(stdout);
|
||||
} // MojoGui_stdio_final
|
||||
|
||||
// end of gui_stdio.c ...
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,48 +0,0 @@
|
|||
|
||||
This is libfetch, from FreeBSD.
|
||||
|
||||
I grabbed it from CVS, like this:
|
||||
cvs -z9 -dfreebsdanoncvs@anoncvs.FreeBSD.org:/home/ncvs co src/lib/libfetch
|
||||
|
||||
Checkout was from May 5th, 2007, 1pm EST.
|
||||
|
||||
This just has minor modifications to make it play nicely with our build system,
|
||||
and code, and stuff we don't need was trimmed out.
|
||||
|
||||
Changes made for MojoSetup that aren't part of a virgin copy of libfetch are
|
||||
noted with "#if __MOJOSETUP__" sections.
|
||||
|
||||
|
||||
Here is the libfetch copyright from common.c ...
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
--ryan.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,135 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/lib/libfetch/common.h,v 1.28 2004/09/21 18:35:20 des Exp $
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_INCLUDED
|
||||
#define _COMMON_H_INCLUDED
|
||||
|
||||
#define FTP_DEFAULT_PORT 21
|
||||
#define HTTP_DEFAULT_PORT 80
|
||||
#define FTP_DEFAULT_PROXY_PORT 21
|
||||
#define HTTP_DEFAULT_PROXY_PORT 3128
|
||||
|
||||
#ifdef WITH_SSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
/* Connection */
|
||||
typedef struct fetchconn conn_t;
|
||||
struct fetchconn {
|
||||
int sd; /* socket descriptor */
|
||||
char *buf; /* buffer */
|
||||
size_t bufsize; /* buffer size */
|
||||
size_t buflen; /* length of buffer contents */
|
||||
int err; /* last protocol reply code */
|
||||
#ifdef WITH_SSL
|
||||
SSL *ssl; /* SSL handle */
|
||||
SSL_CTX *ssl_ctx; /* SSL context */
|
||||
X509 *ssl_cert; /* server certificate */
|
||||
SSL_METHOD *ssl_meth; /* SSL method */
|
||||
#endif
|
||||
int ref; /* reference count */
|
||||
};
|
||||
|
||||
/* Structure used for error message lists */
|
||||
struct fetcherr {
|
||||
const int num;
|
||||
const int cat;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
/* for _fetch_writev */
|
||||
struct iovec;
|
||||
|
||||
void _fetch_seterr(struct fetcherr *, int);
|
||||
void _fetch_syserr(void);
|
||||
#if __MOJOSETUP__
|
||||
void _fetch_info(const char *fmt, ...) ISPRINTF(1,2);
|
||||
#else
|
||||
void _fetch_info(const char *, ...);
|
||||
#endif
|
||||
int _fetch_default_port(const char *);
|
||||
int _fetch_default_proxy_port(const char *);
|
||||
int _fetch_bind(int, int, const char *);
|
||||
conn_t *_fetch_connect(const char *, int, int, int);
|
||||
conn_t *_fetch_reopen(int);
|
||||
conn_t *_fetch_ref(conn_t *);
|
||||
int _fetch_ssl(conn_t *, int);
|
||||
ssize_t _fetch_read(conn_t *, char *, size_t);
|
||||
int _fetch_getln(conn_t *);
|
||||
ssize_t _fetch_write(conn_t *, const char *, size_t);
|
||||
ssize_t _fetch_writev(conn_t *, struct iovec *, int);
|
||||
int _fetch_putln(conn_t *, const char *, size_t);
|
||||
int _fetch_close(conn_t *);
|
||||
int _fetch_add_entry(struct url_ent **, int *, int *,
|
||||
const char *, struct url_stat *);
|
||||
int _fetch_netrc_auth(struct url *url);
|
||||
|
||||
#define _ftp_seterr(n) _fetch_seterr(_ftp_errlist, n)
|
||||
#define _http_seterr(n) _fetch_seterr(_http_errlist, n)
|
||||
#define _netdb_seterr(n) _fetch_seterr(_netdb_errlist, n)
|
||||
#define _url_seterr(n) _fetch_seterr(_url_errlist, n)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define DEBUG(x) do { if (fetchDebug) { x; } } while (0)
|
||||
#else
|
||||
#define DEBUG(x) do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* I don't really like exporting _http_request() and _ftp_request(),
|
||||
* but the HTTP and FTP code occasionally needs to cross-call
|
||||
* eachother, and this saves me from adding a lot of special-case code
|
||||
* to handle those cases.
|
||||
*
|
||||
* Note that _*_request() free purl, which is way ugly but saves us a
|
||||
* whole lot of trouble.
|
||||
*/
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *_http_request(struct url *, const char *,
|
||||
struct url_stat *, struct url *, const char *);
|
||||
MojoInput *_ftp_request(struct url *, const char *,
|
||||
struct url_stat *, struct url *, const char *);
|
||||
#else
|
||||
FILE *_http_request(struct url *, const char *,
|
||||
struct url_stat *, struct url *, const char *);
|
||||
FILE *_ftp_request(struct url *, const char *,
|
||||
struct url_stat *, struct url *, const char *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check whether a particular flag is set
|
||||
*/
|
||||
#define CHECK_FLAG(x) (flags && strchr(flags, (x)))
|
||||
|
||||
#endif
|
|
@ -1,478 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if __MOJOSETUP__
|
||||
#include "mojosetup_libfetch.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if !sun /* __MOJOSETUP__ Solaris support... */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/lib/libfetch/fetch.c,v 1.38 2004/09/21 18:35:20 des Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fetch.h"
|
||||
#include "common.h"
|
||||
|
||||
auth_t fetchAuthMethod;
|
||||
int fetchLastErrCode;
|
||||
char fetchLastErrString[MAXERRSTRING];
|
||||
int fetchTimeout;
|
||||
int fetchRestartCalls = 1;
|
||||
int fetchDebug;
|
||||
|
||||
|
||||
/*** Local data **************************************************************/
|
||||
|
||||
/*
|
||||
* Error messages for parser errors
|
||||
*/
|
||||
#define URL_MALFORMED 1
|
||||
#define URL_BAD_SCHEME 2
|
||||
#define URL_BAD_PORT 3
|
||||
static struct fetcherr _url_errlist[] = {
|
||||
{ URL_MALFORMED, FETCH_URL, "Malformed URL" },
|
||||
{ URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" },
|
||||
{ URL_BAD_PORT, FETCH_URL, "Invalid server port" },
|
||||
{ -1, FETCH_UNKNOWN, "Unknown parser error" }
|
||||
};
|
||||
|
||||
|
||||
/*** Public API **************************************************************/
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* read-only stream connected to the document referenced by the URL.
|
||||
* Also fill out the struct url_stat.
|
||||
*/
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *
|
||||
#else
|
||||
FILE *
|
||||
#endif
|
||||
fetchXGet(struct url *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
int direct;
|
||||
|
||||
direct = CHECK_FLAG('d');
|
||||
if (us != NULL) {
|
||||
us->size = -1;
|
||||
us->atime = us->mtime = 0;
|
||||
}
|
||||
#if __MOJOSETUP__
|
||||
#if SUPPORT_URL_FTP
|
||||
if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchXGetFTP(URL, us, flags));
|
||||
#endif
|
||||
#if SUPPORT_URL_HTTP
|
||||
if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchXGetHTTP(URL, us, flags));
|
||||
#endif
|
||||
#if SUPPORT_URL_HTTPS
|
||||
if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchXGetHTTP(URL, us, flags));
|
||||
#endif
|
||||
#else
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchXGetFile(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchXGetFTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchXGetHTTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchXGetHTTP(URL, us, flags));
|
||||
#endif
|
||||
_url_seterr(URL_BAD_SCHEME);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* read-only stream connected to the document referenced by the URL.
|
||||
*/
|
||||
#if !__MOJOSETUP__
|
||||
FILE *
|
||||
fetchGet(struct url *URL, const char *flags)
|
||||
{
|
||||
return (fetchXGet(URL, NULL, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* write-only stream connected to the document referenced by the URL.
|
||||
*/
|
||||
FILE *
|
||||
fetchPut(struct url *URL, const char *flags)
|
||||
{
|
||||
int direct;
|
||||
|
||||
direct = CHECK_FLAG('d');
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchPutFile(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchPutFTP(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchPutHTTP(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchPutHTTP(URL, flags));
|
||||
_url_seterr(URL_BAD_SCHEME);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return the
|
||||
* size of the document referenced by the URL if it exists.
|
||||
*/
|
||||
int
|
||||
fetchStat(struct url *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
int direct;
|
||||
|
||||
direct = CHECK_FLAG('d');
|
||||
if (us != NULL) {
|
||||
us->size = -1;
|
||||
us->atime = us->mtime = 0;
|
||||
}
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchStatFile(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchStatFTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchStatHTTP(URL, us, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchStatHTTP(URL, us, flags));
|
||||
_url_seterr(URL_BAD_SCHEME);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the appropriate protocol for the URL scheme, and return a
|
||||
* list of files in the directory pointed to by the URL.
|
||||
*/
|
||||
struct url_ent *
|
||||
fetchList(struct url *URL, const char *flags)
|
||||
{
|
||||
int direct;
|
||||
|
||||
direct = CHECK_FLAG('d');
|
||||
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
|
||||
return (fetchListFile(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
|
||||
return (fetchListFTP(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0)
|
||||
return (fetchListHTTP(URL, flags));
|
||||
else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0)
|
||||
return (fetchListHTTP(URL, flags));
|
||||
_url_seterr(URL_BAD_SCHEME);
|
||||
return (NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchXGet().
|
||||
*/
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *
|
||||
#else
|
||||
FILE *
|
||||
#endif
|
||||
fetchXGetURL(const char *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *f = NULL;
|
||||
#else
|
||||
FILE *f;
|
||||
#endif
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
f = fetchXGet(u, us, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchGet().
|
||||
*/
|
||||
#if !__MOJOSETUP__
|
||||
FILE *
|
||||
fetchGetURL(const char *URL, const char *flags)
|
||||
{
|
||||
return (fetchXGetURL(URL, NULL, flags));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchPut().
|
||||
*/
|
||||
FILE *
|
||||
fetchPutURL(const char *URL, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
FILE *f;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
f = fetchPut(u, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchStat().
|
||||
*/
|
||||
int
|
||||
fetchStatURL(const char *URL, struct url_stat *us, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
int s;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
s = fetchStat(u, us, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to parse the given URL; if successful, call fetchList().
|
||||
*/
|
||||
struct url_ent *
|
||||
fetchListURL(const char *URL, const char *flags)
|
||||
{
|
||||
struct url *u;
|
||||
struct url_ent *ue;
|
||||
|
||||
if ((u = fetchParseURL(URL)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
ue = fetchList(u, flags);
|
||||
|
||||
fetchFreeURL(u);
|
||||
return (ue);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make a URL
|
||||
*/
|
||||
struct url *
|
||||
fetchMakeURL(const char *scheme, const char *host, int port, const char *doc,
|
||||
const char *user, const char *pwd)
|
||||
{
|
||||
struct url *u;
|
||||
|
||||
if (!scheme || (!host && !doc)) {
|
||||
_url_seterr(URL_MALFORMED);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (port < 0 || port > 65535) {
|
||||
_url_seterr(URL_BAD_PORT);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* allocate struct url */
|
||||
if ((u = calloc(1, sizeof(*u))) == NULL) {
|
||||
_fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((u->doc = strdup(doc ? doc : "/")) == NULL) {
|
||||
_fetch_syserr();
|
||||
free(u);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#define seturl(x) snprintf(u->x, sizeof(u->x), "%s", x)
|
||||
seturl(scheme);
|
||||
seturl(host);
|
||||
seturl(user);
|
||||
seturl(pwd);
|
||||
#undef seturl
|
||||
u->port = port;
|
||||
|
||||
return (u);
|
||||
}
|
||||
|
||||
/*
|
||||
* Split an URL into components. URL syntax is:
|
||||
* [method:/][/[user[:pwd]@]host[:port]/][document]
|
||||
* This almost, but not quite, RFC1738 URL syntax.
|
||||
*/
|
||||
struct url *
|
||||
fetchParseURL(const char *URL)
|
||||
{
|
||||
char *doc;
|
||||
const char *p, *q;
|
||||
struct url *u;
|
||||
int i;
|
||||
|
||||
/* allocate struct url */
|
||||
if ((u = calloc(1, sizeof(*u))) == NULL) {
|
||||
_fetch_syserr();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* scheme name */
|
||||
if ((p = strstr(URL, ":/"))) {
|
||||
snprintf(u->scheme, URL_SCHEMELEN+1,
|
||||
"%.*s", (int)(p - URL), URL);
|
||||
URL = ++p;
|
||||
/*
|
||||
* Only one slash: no host, leave slash as part of document
|
||||
* Two slashes: host follows, strip slashes
|
||||
*/
|
||||
if (URL[1] == '/')
|
||||
URL = (p += 2);
|
||||
} else {
|
||||
p = URL;
|
||||
}
|
||||
if (!*URL || *URL == '/' || *URL == '.' ||
|
||||
(u->scheme[0] == '\0' &&
|
||||
strchr(URL, '/') == NULL && strchr(URL, ':') == NULL))
|
||||
goto nohost;
|
||||
|
||||
p = strpbrk(URL, "/@");
|
||||
if (p && *p == '@') {
|
||||
/* username */
|
||||
for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++)
|
||||
if (i < URL_USERLEN)
|
||||
u->user[i++] = *q;
|
||||
|
||||
/* password */
|
||||
if (*q == ':')
|
||||
for (q++, i = 0; (*q != ':') && (*q != '@'); q++)
|
||||
if (i < URL_PWDLEN)
|
||||
u->pwd[i++] = *q;
|
||||
|
||||
p++;
|
||||
} else {
|
||||
p = URL;
|
||||
}
|
||||
|
||||
/* hostname */
|
||||
#ifdef INET6
|
||||
if (*p == '[' && (q = strchr(p + 1, ']')) != NULL &&
|
||||
(*++q == '\0' || *q == '/' || *q == ':')) {
|
||||
if ((i = q - p - 2) > MAXHOSTNAMELEN)
|
||||
i = MAXHOSTNAMELEN;
|
||||
strncpy(u->host, ++p, i);
|
||||
p = q;
|
||||
} else
|
||||
#endif
|
||||
for (i = 0; *p && (*p != '/') && (*p != ':'); p++)
|
||||
if (i < MAXHOSTNAMELEN)
|
||||
u->host[i++] = *p;
|
||||
|
||||
/* port */
|
||||
if (*p == ':') {
|
||||
for (q = ++p; *q && (*q != '/'); q++)
|
||||
if (isdigit(*q))
|
||||
u->port = u->port * 10 + (*q - '0');
|
||||
else {
|
||||
/* invalid port */
|
||||
_url_seterr(URL_BAD_PORT);
|
||||
goto ouch;
|
||||
}
|
||||
p = q;
|
||||
}
|
||||
|
||||
nohost:
|
||||
/* document */
|
||||
if (!*p)
|
||||
p = "/";
|
||||
|
||||
if (strcasecmp(u->scheme, SCHEME_HTTP) == 0 ||
|
||||
strcasecmp(u->scheme, SCHEME_HTTPS) == 0) {
|
||||
const char hexnums[] = "0123456789abcdef";
|
||||
|
||||
/* percent-escape whitespace. */
|
||||
if ((doc = malloc(strlen(p) * 3 + 1)) == NULL) {
|
||||
_fetch_syserr();
|
||||
goto ouch;
|
||||
}
|
||||
u->doc = doc;
|
||||
while (*p != '\0') {
|
||||
if (!isspace(*p)) {
|
||||
*doc++ = *p++;
|
||||
} else {
|
||||
*doc++ = '%';
|
||||
*doc++ = hexnums[((unsigned int)*p) >> 4];
|
||||
*doc++ = hexnums[((unsigned int)*p) & 0xf];
|
||||
p++;
|
||||
}
|
||||
}
|
||||
*doc = '\0';
|
||||
} else if ((u->doc = strdup(p)) == NULL) {
|
||||
_fetch_syserr();
|
||||
goto ouch;
|
||||
}
|
||||
|
||||
DEBUG(fprintf(stderr,
|
||||
"scheme: [%s]\n"
|
||||
"user: [%s]\n"
|
||||
"password: [%s]\n"
|
||||
"host: [%s]\n"
|
||||
"port: [%d]\n"
|
||||
"document: [%s]\n",
|
||||
u->scheme, u->user, u->pwd,
|
||||
u->host, u->port, u->doc));
|
||||
|
||||
return (u);
|
||||
|
||||
ouch:
|
||||
free(u);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a URL
|
||||
*/
|
||||
void
|
||||
fetchFreeURL(struct url *u)
|
||||
{
|
||||
free(u->doc);
|
||||
free(u);
|
||||
}
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/lib/libfetch/fetch.h,v 1.26 2004/09/21 18:35:20 des Exp $
|
||||
*/
|
||||
|
||||
#ifndef _FETCH_H_INCLUDED
|
||||
#define _FETCH_H_INCLUDED
|
||||
|
||||
#if __MOJOSETUP__
|
||||
#define _LIBFETCH_VER3(ver) "libfetch/2.0 (MojoSetup " #ver ")"
|
||||
#define _LIBFETCH_VER2(ver) _LIBFETCH_VER3(ver)
|
||||
#define _LIBFETCH_VER _LIBFETCH_VER2(APPREV)
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
#ifndef __BEGIN_DECLS
|
||||
#define __BEGIN_DECLS
|
||||
#endif
|
||||
#ifndef __END_DECLS
|
||||
#define __END_DECLS
|
||||
#endif
|
||||
#else
|
||||
#define _LIBFETCH_VER "libfetch/2.0"
|
||||
#endif
|
||||
|
||||
#define URL_SCHEMELEN 16
|
||||
#define URL_USERLEN 256
|
||||
#define URL_PWDLEN 256
|
||||
|
||||
struct url {
|
||||
char scheme[URL_SCHEMELEN+1];
|
||||
char user[URL_USERLEN+1];
|
||||
char pwd[URL_PWDLEN+1];
|
||||
char host[MAXHOSTNAMELEN+1];
|
||||
int port;
|
||||
char *doc;
|
||||
off_t offset;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct url_stat {
|
||||
off_t size;
|
||||
time_t atime;
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
struct url_ent {
|
||||
char name[PATH_MAX];
|
||||
struct url_stat stat;
|
||||
};
|
||||
|
||||
/* Recognized schemes */
|
||||
#define SCHEME_FTP "ftp"
|
||||
#define SCHEME_HTTP "http"
|
||||
#define SCHEME_HTTPS "https"
|
||||
#define SCHEME_FILE "file"
|
||||
|
||||
/* Error codes */
|
||||
#define FETCH_ABORT 1
|
||||
#define FETCH_AUTH 2
|
||||
#define FETCH_DOWN 3
|
||||
#define FETCH_EXISTS 4
|
||||
#define FETCH_FULL 5
|
||||
#define FETCH_INFO 6
|
||||
#define FETCH_MEMORY 7
|
||||
#define FETCH_MOVED 8
|
||||
#define FETCH_NETWORK 9
|
||||
#define FETCH_OK 10
|
||||
#define FETCH_PROTO 11
|
||||
#define FETCH_RESOLV 12
|
||||
#define FETCH_SERVER 13
|
||||
#define FETCH_TEMP 14
|
||||
#define FETCH_TIMEOUT 15
|
||||
#define FETCH_UNAVAIL 16
|
||||
#define FETCH_UNKNOWN 17
|
||||
#define FETCH_URL 18
|
||||
#define FETCH_VERBOSE 19
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* FILE-specific functions */
|
||||
#if !__MOJOSETUP__
|
||||
FILE *fetchXGetFile(struct url *, struct url_stat *, const char *);
|
||||
FILE *fetchGetFile(struct url *, const char *);
|
||||
FILE *fetchPutFile(struct url *, const char *);
|
||||
int fetchStatFile(struct url *, struct url_stat *, const char *);
|
||||
struct url_ent *fetchListFile(struct url *, const char *);
|
||||
#endif
|
||||
|
||||
/* HTTP-specific functions */
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *fetchXGetHTTP(struct url *, struct url_stat *, const char *);
|
||||
#else
|
||||
FILE *fetchXGetHTTP(struct url *, struct url_stat *, const char *);
|
||||
FILE *fetchGetHTTP(struct url *, const char *);
|
||||
FILE *fetchPutHTTP(struct url *, const char *);
|
||||
int fetchStatHTTP(struct url *, struct url_stat *, const char *);
|
||||
struct url_ent *fetchListHTTP(struct url *, const char *);
|
||||
#endif
|
||||
|
||||
/* FTP-specific functions */
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *fetchXGetFTP(struct url *, struct url_stat *, const char *);
|
||||
#else
|
||||
FILE *fetchXGetFTP(struct url *, struct url_stat *, const char *);
|
||||
FILE *fetchGetFTP(struct url *, const char *);
|
||||
FILE *fetchPutFTP(struct url *, const char *);
|
||||
int fetchStatFTP(struct url *, struct url_stat *, const char *);
|
||||
struct url_ent *fetchListFTP(struct url *, const char *);
|
||||
#endif
|
||||
|
||||
/* Generic functions */
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *fetchXGetURL(const char *, struct url_stat *, const char *);
|
||||
#else
|
||||
FILE *fetchXGetURL(const char *, struct url_stat *, const char *);
|
||||
FILE *fetchGetURL(const char *, const char *);
|
||||
FILE *fetchPutURL(const char *, const char *);
|
||||
int fetchStatURL(const char *, struct url_stat *, const char *);
|
||||
struct url_ent *fetchListURL(const char *, const char *);
|
||||
#endif
|
||||
|
||||
#if __MOJOSETUP__
|
||||
MojoInput *fetchXGet(struct url *, struct url_stat *, const char *);
|
||||
#else
|
||||
FILE *fetchXGet(struct url *, struct url_stat *, const char *);
|
||||
FILE *fetchGet(struct url *, const char *);
|
||||
FILE *fetchPut(struct url *, const char *);
|
||||
int fetchStat(struct url *, struct url_stat *, const char *);
|
||||
struct url_ent *fetchList(struct url *, const char *);
|
||||
#endif
|
||||
|
||||
/* URL parsing */
|
||||
struct url *fetchMakeURL(const char *, const char *, int,
|
||||
const char *, const char *, const char *);
|
||||
struct url *fetchParseURL(const char *);
|
||||
void fetchFreeURL(struct url *);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/* Authentication */
|
||||
typedef int (*auth_t)(struct url *);
|
||||
extern auth_t fetchAuthMethod;
|
||||
|
||||
/* Last error code */
|
||||
extern int fetchLastErrCode;
|
||||
#define MAXERRSTRING 256
|
||||
extern char fetchLastErrString[MAXERRSTRING];
|
||||
|
||||
/* I/O timeout */
|
||||
extern int fetchTimeout;
|
||||
|
||||
/* Restart interrupted syscalls */
|
||||
extern int fetchRestartCalls;
|
||||
|
||||
/* Extra verbosity */
|
||||
extern int fetchDebug;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,47 +0,0 @@
|
|||
# $FreeBSD: src/lib/libfetch/ftp.errors,v 1.6 2002/10/30 06:06:16 des Exp $
|
||||
#
|
||||
# This list is taken from RFC 959.
|
||||
# It probably needs a going over.
|
||||
#
|
||||
110 OK Restart marker reply
|
||||
120 TEMP Service ready in a few minutes
|
||||
125 OK Data connection already open; transfer starting
|
||||
150 OK File status okay; about to open data connection
|
||||
200 OK Command okay
|
||||
202 PROTO Command not implemented, superfluous at this site
|
||||
211 INFO System status, or system help reply
|
||||
212 INFO Directory status
|
||||
213 INFO File status
|
||||
214 INFO Help message
|
||||
215 INFO Set system type
|
||||
220 OK Service ready for new user
|
||||
221 OK Service closing control connection
|
||||
225 OK Data connection open; no transfer in progress
|
||||
226 OK Requested file action successful
|
||||
227 OK Entering Passive Mode
|
||||
229 OK Entering Extended Passive Mode
|
||||
230 OK User logged in, proceed
|
||||
250 OK Requested file action okay, completed
|
||||
257 OK File/directory created
|
||||
331 AUTH User name okay, need password
|
||||
332 AUTH Need account for login
|
||||
350 OK Requested file action pending further information
|
||||
421 DOWN Service not available, closing control connection
|
||||
425 NETWORK Can't open data connection
|
||||
426 ABORT Connection closed; transfer aborted
|
||||
450 UNAVAIL File unavailable (e.g., file busy)
|
||||
451 SERVER Requested action aborted: local error in processing
|
||||
452 FULL Insufficient storage space in system
|
||||
500 PROTO Syntax error, command unrecognized
|
||||
501 PROTO Syntax error in parameters or arguments
|
||||
502 PROTO Command not implemented
|
||||
503 PROTO Bad sequence of commands
|
||||
504 PROTO Command not implemented for that parameter
|
||||
530 AUTH Not logged in
|
||||
532 AUTH Need account for storing files
|
||||
535 PROTO Bug in MediaHawk Video Kernel FTP server
|
||||
550 UNAVAIL File unavailable (e.g., file not found, no access)
|
||||
551 PROTO Requested action aborted. Page type unknown
|
||||
552 FULL Exceeded storage allocation
|
||||
553 EXISTS File name not allowed
|
||||
999 PROTO Protocol error
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*/
|
||||
|
||||
static struct fetcherr _ftp_errlist[] = {
|
||||
{ 110, FETCH_OK, "Restart marker reply" },
|
||||
{ 120, FETCH_TEMP, "Service ready in a few minutes" },
|
||||
{ 125, FETCH_OK, "Data connection already open; transfer starting" },
|
||||
{ 150, FETCH_OK, "File status okay; about to open data connection" },
|
||||
{ 200, FETCH_OK, "Command okay" },
|
||||
{ 202, FETCH_PROTO, "Command not implemented, superfluous at this site" },
|
||||
{ 211, FETCH_INFO, "System status, or system help reply" },
|
||||
{ 212, FETCH_INFO, "Directory status" },
|
||||
{ 213, FETCH_INFO, "File status" },
|
||||
{ 214, FETCH_INFO, "Help message" },
|
||||
{ 215, FETCH_INFO, "Set system type" },
|
||||
{ 220, FETCH_OK, "Service ready for new user" },
|
||||
{ 221, FETCH_OK, "Service closing control connection" },
|
||||
{ 225, FETCH_OK, "Data connection open; no transfer in progress" },
|
||||
{ 226, FETCH_OK, "Requested file action successful" },
|
||||
{ 227, FETCH_OK, "Entering Passive Mode" },
|
||||
{ 229, FETCH_OK, "Entering Extended Passive Mode" },
|
||||
{ 230, FETCH_OK, "User logged in, proceed" },
|
||||
{ 250, FETCH_OK, "Requested file action okay, completed" },
|
||||
{ 257, FETCH_OK, "File/directory created" },
|
||||
{ 331, FETCH_AUTH, "User name okay, need password" },
|
||||
{ 332, FETCH_AUTH, "Need account for login" },
|
||||
{ 350, FETCH_OK, "Requested file action pending further information" },
|
||||
{ 421, FETCH_DOWN, "Service not available, closing control connection" },
|
||||
{ 425, FETCH_NETWORK, "Can't open data connection" },
|
||||
{ 426, FETCH_ABORT, "Connection closed; transfer aborted" },
|
||||
{ 450, FETCH_UNAVAIL, "File unavailable (e.g., file busy)" },
|
||||
{ 451, FETCH_SERVER, "Requested action aborted: local error in processing" },
|
||||
{ 452, FETCH_FULL, "Insufficient storage space in system" },
|
||||
{ 500, FETCH_PROTO, "Syntax error, command unrecognized" },
|
||||
{ 501, FETCH_PROTO, "Syntax error in parameters or arguments" },
|
||||
{ 502, FETCH_PROTO, "Command not implemented" },
|
||||
{ 503, FETCH_PROTO, "Bad sequence of commands" },
|
||||
{ 504, FETCH_PROTO, "Command not implemented for that parameter" },
|
||||
{ 530, FETCH_AUTH, "Not logged in" },
|
||||
{ 532, FETCH_AUTH, "Need account for storing files" },
|
||||
{ 535, FETCH_PROTO, "Bug in MediaHawk Video Kernel FTP server" },
|
||||
{ 550, FETCH_UNAVAIL, "File unavailable (e.g., file not found, no access)" },
|
||||
{ 551, FETCH_PROTO, "Requested action aborted. Page type unknown" },
|
||||
{ 552, FETCH_FULL, "Exceeded storage allocation" },
|
||||
{ 553, FETCH_EXISTS, "File name not allowed" },
|
||||
{ 999, FETCH_PROTO, "Protocol error" },
|
||||
{ -1, FETCH_UNKNOWN, "Unknown FTP error" }
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,45 +0,0 @@
|
|||
# $FreeBSD: src/lib/libfetch/http.errors,v 1.5 2001/05/23 18:52:02 des Exp $
|
||||
#
|
||||
# This list is taken from RFC 2068.
|
||||
#
|
||||
100 OK Continue
|
||||
101 OK Switching Protocols
|
||||
200 OK OK
|
||||
201 OK Created
|
||||
202 OK Accepted
|
||||
203 INFO Non-Authoritative Information
|
||||
204 OK No Content
|
||||
205 OK Reset Content
|
||||
206 OK Partial Content
|
||||
300 MOVED Multiple Choices
|
||||
301 MOVED Moved Permanently
|
||||
302 MOVED Moved Temporarily
|
||||
303 MOVED See Other
|
||||
304 OK Not Modified
|
||||
305 INFO Use Proxy
|
||||
307 MOVED Temporary Redirect
|
||||
400 PROTO Bad Request
|
||||
401 AUTH Unauthorized
|
||||
402 AUTH Payment Required
|
||||
403 AUTH Forbidden
|
||||
404 UNAVAIL Not Found
|
||||
405 PROTO Method Not Allowed
|
||||
406 PROTO Not Acceptable
|
||||
407 AUTH Proxy Authentication Required
|
||||
408 TIMEOUT Request Time-out
|
||||
409 EXISTS Conflict
|
||||
410 UNAVAIL Gone
|
||||
411 PROTO Length Required
|
||||
412 SERVER Precondition Failed
|
||||
413 PROTO Request Entity Too Large
|
||||
414 PROTO Request-URI Too Large
|
||||
415 PROTO Unsupported Media Type
|
||||
416 UNAVAIL Requested Range Not Satisfiable
|
||||
417 SERVER Expectation Failed
|
||||
500 SERVER Internal Server Error
|
||||
501 PROTO Not Implemented
|
||||
502 SERVER Bad Gateway
|
||||
503 TEMP Service Unavailable
|
||||
504 TIMEOUT Gateway Time-out
|
||||
505 PROTO HTTP Version not supported
|
||||
999 PROTO Protocol error
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*/
|
||||
|
||||
static struct fetcherr _http_errlist[] = {
|
||||
{ 100, FETCH_OK, "Continue" },
|
||||
{ 101, FETCH_OK, "Switching Protocols" },
|
||||
{ 200, FETCH_OK, "OK" },
|
||||
{ 201, FETCH_OK, "Created" },
|
||||
{ 202, FETCH_OK, "Accepted" },
|
||||
{ 203, FETCH_INFO, "Non-Authoritative Information" },
|
||||
{ 204, FETCH_OK, "No Content" },
|
||||
{ 205, FETCH_OK, "Reset Content" },
|
||||
{ 206, FETCH_OK, "Partial Content" },
|
||||
{ 300, FETCH_MOVED, "Multiple Choices" },
|
||||
{ 301, FETCH_MOVED, "Moved Permanently" },
|
||||
{ 302, FETCH_MOVED, "Moved Temporarily" },
|
||||
{ 303, FETCH_MOVED, "See Other" },
|
||||
{ 304, FETCH_OK, "Not Modified" },
|
||||
{ 305, FETCH_INFO, "Use Proxy" },
|
||||
{ 307, FETCH_MOVED, "Temporary Redirect" },
|
||||
{ 400, FETCH_PROTO, "Bad Request" },
|
||||
{ 401, FETCH_AUTH, "Unauthorized" },
|
||||
{ 402, FETCH_AUTH, "Payment Required" },
|
||||
{ 403, FETCH_AUTH, "Forbidden" },
|
||||
{ 404, FETCH_UNAVAIL, "Not Found" },
|
||||
{ 405, FETCH_PROTO, "Method Not Allowed" },
|
||||
{ 406, FETCH_PROTO, "Not Acceptable" },
|
||||
{ 407, FETCH_AUTH, "Proxy Authentication Required" },
|
||||
{ 408, FETCH_TIMEOUT, "Request Time-out" },
|
||||
{ 409, FETCH_EXISTS, "Conflict" },
|
||||
{ 410, FETCH_UNAVAIL, "Gone" },
|
||||
{ 411, FETCH_PROTO, "Length Required" },
|
||||
{ 412, FETCH_SERVER, "Precondition Failed" },
|
||||
{ 413, FETCH_PROTO, "Request Entity Too Large" },
|
||||
{ 414, FETCH_PROTO, "Request-URI Too Large" },
|
||||
{ 415, FETCH_PROTO, "Unsupported Media Type" },
|
||||
{ 416, FETCH_UNAVAIL, "Requested Range Not Satisfiable" },
|
||||
{ 417, FETCH_SERVER, "Expectation Failed" },
|
||||
{ 500, FETCH_SERVER, "Internal Server Error" },
|
||||
{ 501, FETCH_PROTO, "Not Implemented" },
|
||||
{ 502, FETCH_SERVER, "Bad Gateway" },
|
||||
{ 503, FETCH_TEMP, "Service Unavailable" },
|
||||
{ 504, FETCH_TIMEOUT, "Gateway Time-out" },
|
||||
{ 505, FETCH_PROTO, "HTTP Version not supported" },
|
||||
{ 999, FETCH_PROTO, "Protocol error" },
|
||||
{ -1, FETCH_UNKNOWN, "Unknown HTTP error" }
|
||||
};
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2006-2010 Ryan C. Gordon and others.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
*/
|
||||
|
||||
#ifndef _INCL_MOJOSETUP_LIBFETCH_H_
|
||||
#define _INCL_MOJOSETUP_LIBFETCH_H_
|
||||
|
||||
#include "../universal.h"
|
||||
#include "../platform.h"
|
||||
#include "../fileio.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if sun
|
||||
#ifdef u_int32_t
|
||||
#undef u_int32_t
|
||||
#endif
|
||||
#define u_int32_t uint32_t
|
||||
#endif
|
||||
|
||||
int MOJOSETUP_vasprintf(char **strp, const char *fmt, va_list ap);
|
||||
#define vasprintf MOJOSETUP_vasprintf
|
||||
int MOJOSETUP_asprintf(char **strp, const char *fmt, ...) ISPRINTF(2,3);
|
||||
#define asprintf MOJOSETUP_asprintf
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||
#ifndef FREEBSD
|
||||
#define FREEBSD 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Things FreeBSD defines elsewhere...
|
||||
|
||||
#ifndef __FBSDID
|
||||
#define __FBSDID(x)
|
||||
#endif
|
||||
|
||||
#ifndef __DECONST
|
||||
#define __DECONST(type, var) ((type) var)
|
||||
#endif
|
||||
|
||||
#ifndef __unused
|
||||
#define __unused
|
||||
#endif
|
||||
|
||||
// apparently this is 17 in FreeBSD.
|
||||
#ifndef MAXLOGNAME
|
||||
#define MAXLOGNAME (17)
|
||||
#endif
|
||||
|
||||
#undef calloc
|
||||
#define calloc(x, y) xmalloc(x * y)
|
||||
|
||||
#undef malloc
|
||||
#define malloc(x) xmalloc(x)
|
||||
|
||||
#undef realloc
|
||||
#define realloc(x, y) xrealloc(x, y)
|
||||
|
||||
#undef strdup
|
||||
#define strdup(x) xstrdup(x)
|
||||
|
||||
#undef strncpy
|
||||
#define strncpy(x, y, z) xstrncpy(x, y, z)
|
||||
|
||||
#if !FREEBSD
|
||||
#ifndef TCP_NOPUSH
|
||||
#define TCP_NOPUSH TCP_CORK
|
||||
#endif
|
||||
#define EAUTH EPERM
|
||||
boolean ishexnumber(char ch);
|
||||
// Linux has had this since glibc 4.6.8, but doesn't expose it in the headers
|
||||
// without _XOPEN_SOURCE or _GNU_SOURCE, which breaks other things.
|
||||
// ...just force a declaration here, then.
|
||||
#ifdef __linux__
|
||||
char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
time_t timegm_portable(struct tm *tm);
|
||||
#ifdef timegm
|
||||
#undef timegm
|
||||
#endif
|
||||
#define timegm timegm_portable
|
||||
|
||||
#endif
|
||||
|
||||
// end of mojosetup_libfetch.h ...
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
This is the source code to liblzma from XZ Utils:
|
||||
|
||||
http://tukaani.org/xz/
|
||||
|
||||
This is a snapshot of the xz-5.0.3 release. Changes I've made to it are
|
||||
wrapped in #if __MOJOSETUP__ blocks. I've tried to agressively delete files
|
||||
we don't use at all, too.
|
||||
|
||||
The source code in this directory is public domain.
|
||||
|
||||
--ryan.
|
||||
|
|
@ -1,318 +0,0 @@
|
|||
/**
|
||||
* \file api/lzma.h
|
||||
* \brief The public API of liblzma data compression library
|
||||
*
|
||||
* liblzma is a public domain general-purpose data compression library with
|
||||
* a zlib-like API. The native file format is .xz, but also the old .lzma
|
||||
* format and raw (no headers) streams are supported. Multiple compression
|
||||
* algorithms (filters) are supported. Currently LZMA2 is the primary filter.
|
||||
*
|
||||
* liblzma is part of XZ Utils <http://tukaani.org/xz/>. XZ Utils includes
|
||||
* a gzip-like command line tool named xz and some other tools. XZ Utils
|
||||
* is developed and maintained by Lasse Collin.
|
||||
*
|
||||
* Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK
|
||||
* <http://7-zip.org/sdk.html>.
|
||||
*
|
||||
* The SHA-256 implementation is based on the public domain code found from
|
||||
* 7-Zip <http://7-zip.org/>, which has a modified version of the public
|
||||
* domain SHA-256 code found from Crypto++ <http://www.cryptopp.com/>.
|
||||
* The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai.
|
||||
*/
|
||||
|
||||
/*
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* This file has been put into the public domain.
|
||||
* You can do whatever you want with this file.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_H
|
||||
#define LZMA_H
|
||||
|
||||
/*****************************
|
||||
* Required standard headers *
|
||||
*****************************/
|
||||
|
||||
/*
|
||||
* liblzma API headers need some standard types and macros. To allow
|
||||
* including lzma.h without requiring the application to include other
|
||||
* headers first, lzma.h includes the required standard headers unless
|
||||
* they already seem to be included already or if LZMA_MANUAL_HEADERS
|
||||
* has been defined.
|
||||
*
|
||||
* Here's what types and macros are needed and from which headers:
|
||||
* - stddef.h: size_t, NULL
|
||||
* - stdint.h: uint8_t, uint32_t, uint64_t, UINT32_C(n), uint64_C(n),
|
||||
* UINT32_MAX, UINT64_MAX
|
||||
*
|
||||
* However, inttypes.h is a little more portable than stdint.h, although
|
||||
* inttypes.h declares some unneeded things compared to plain stdint.h.
|
||||
*
|
||||
* The hacks below aren't perfect, specifically they assume that inttypes.h
|
||||
* exists and that it typedefs at least uint8_t, uint32_t, and uint64_t,
|
||||
* and that, in case of incomplete inttypes.h, unsigned int is 32-bit.
|
||||
* If the application already takes care of setting up all the types and
|
||||
* macros properly (for example by using gnulib's stdint.h or inttypes.h),
|
||||
* we try to detect that the macros are already defined and don't include
|
||||
* inttypes.h here again. However, you may define LZMA_MANUAL_HEADERS to
|
||||
* force this file to never include any system headers.
|
||||
*
|
||||
* Some could argue that liblzma API should provide all the required types,
|
||||
* for example lzma_uint64, LZMA_UINT64_C(n), and LZMA_UINT64_MAX. This was
|
||||
* seen as an unnecessary mess, since most systems already provide all the
|
||||
* necessary types and macros in the standard headers.
|
||||
*
|
||||
* Note that liblzma API still has lzma_bool, because using stdbool.h would
|
||||
* break C89 and C++ programs on many systems. sizeof(bool) in C99 isn't
|
||||
* necessarily the same as sizeof(bool) in C++.
|
||||
*/
|
||||
|
||||
#ifndef LZMA_MANUAL_HEADERS
|
||||
/*
|
||||
* I suppose this works portably also in C++. Note that in C++,
|
||||
* we need to get size_t into the global namespace.
|
||||
*/
|
||||
# include <stddef.h>
|
||||
|
||||
/*
|
||||
* Skip inttypes.h if we already have all the required macros. If we
|
||||
* have the macros, we assume that we have the matching typedefs too.
|
||||
*/
|
||||
# if !defined(UINT32_C) || !defined(UINT64_C) \
|
||||
|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
|
||||
/*
|
||||
* MSVC has no C99 support, and thus it cannot be used to
|
||||
* compile liblzma. The liblzma API has to still be usable
|
||||
* from MSVC, so we need to define the required standard
|
||||
* integer types here.
|
||||
*/
|
||||
# if defined(_WIN32) && defined(_MSC_VER)
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# else
|
||||
/* Use the standard inttypes.h. */
|
||||
# ifdef __cplusplus
|
||||
/*
|
||||
* C99 sections 7.18.2 and 7.18.4 specify
|
||||
* that C++ implementations define the limit
|
||||
* and constant macros only if specifically
|
||||
* requested. Note that if you want the
|
||||
* format macros (PRIu64 etc.) too, you need
|
||||
* to define __STDC_FORMAT_MACROS before
|
||||
* including lzma.h, since re-including
|
||||
* inttypes.h with __STDC_FORMAT_MACROS
|
||||
* defined doesn't necessarily work.
|
||||
*/
|
||||
# ifndef __STDC_LIMIT_MACROS
|
||||
# define __STDC_LIMIT_MACROS 1
|
||||
# endif
|
||||
# ifndef __STDC_CONSTANT_MACROS
|
||||
# define __STDC_CONSTANT_MACROS 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# include <inttypes.h>
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Some old systems have only the typedefs in inttypes.h, and
|
||||
* lack all the macros. For those systems, we need a few more
|
||||
* hacks. We assume that unsigned int is 32-bit and unsigned
|
||||
* long is either 32-bit or 64-bit. If these hacks aren't
|
||||
* enough, the application has to setup the types manually
|
||||
* before including lzma.h.
|
||||
*/
|
||||
# ifndef UINT32_C
|
||||
# if defined(_WIN32) && defined(_MSC_VER)
|
||||
# define UINT32_C(n) n ## UI32
|
||||
# else
|
||||
# define UINT32_C(n) n ## U
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef UINT64_C
|
||||
# if defined(_WIN32) && defined(_MSC_VER)
|
||||
# define UINT64_C(n) n ## UI64
|
||||
# else
|
||||
/* Get ULONG_MAX. */
|
||||
# include <limits.h>
|
||||
# if ULONG_MAX == 4294967295UL
|
||||
# define UINT64_C(n) n ## ULL
|
||||
# else
|
||||
# define UINT64_C(n) n ## UL
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef UINT32_MAX
|
||||
# define UINT32_MAX (UINT32_C(4294967295))
|
||||
# endif
|
||||
|
||||
# ifndef UINT64_MAX
|
||||
# define UINT64_MAX (UINT64_C(18446744073709551615))
|
||||
# endif
|
||||
# endif
|
||||
#endif /* ifdef LZMA_MANUAL_HEADERS */
|
||||
|
||||
|
||||
/******************
|
||||
* LZMA_API macro *
|
||||
******************/
|
||||
|
||||
/*
|
||||
* Some systems require that the functions and function pointers are
|
||||
* declared specially in the headers. LZMA_API_IMPORT is for importing
|
||||
* symbols and LZMA_API_CALL is to specify the calling convention.
|
||||
*
|
||||
* By default it is assumed that the application will link dynamically
|
||||
* against liblzma. #define LZMA_API_STATIC in your application if you
|
||||
* want to link against static liblzma. If you don't care about portability
|
||||
* to operating systems like Windows, or at least don't care about linking
|
||||
* against static liblzma on them, don't worry about LZMA_API_STATIC. That
|
||||
* is, most developers will never need to use LZMA_API_STATIC.
|
||||
*
|
||||
* The GCC variants are a special case on Windows (Cygwin and MinGW).
|
||||
* We rely on GCC doing the right thing with its auto-import feature,
|
||||
* and thus don't use __declspec(dllimport). This way developers don't
|
||||
* need to worry about LZMA_API_STATIC. Also the calling convention is
|
||||
* omitted on Cygwin but not on MinGW.
|
||||
*/
|
||||
#ifndef LZMA_API_IMPORT
|
||||
# if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
|
||||
# define LZMA_API_IMPORT __declspec(dllimport)
|
||||
# else
|
||||
# define LZMA_API_IMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef LZMA_API_CALL
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
# define LZMA_API_CALL __cdecl
|
||||
# else
|
||||
# define LZMA_API_CALL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef LZMA_API
|
||||
# define LZMA_API(type) LZMA_API_IMPORT type LZMA_API_CALL
|
||||
#endif
|
||||
|
||||
|
||||
/***********
|
||||
* nothrow *
|
||||
***********/
|
||||
|
||||
/*
|
||||
* None of the functions in liblzma may throw an exception. Even
|
||||
* the functions that use callback functions won't throw exceptions,
|
||||
* because liblzma would break if a callback function threw an exception.
|
||||
*/
|
||||
#ifndef lzma_nothrow
|
||||
# if defined(__cplusplus)
|
||||
# define lzma_nothrow throw()
|
||||
# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
|
||||
# define lzma_nothrow __attribute__((__nothrow__))
|
||||
# else
|
||||
# define lzma_nothrow
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/********************
|
||||
* GNU C extensions *
|
||||
********************/
|
||||
|
||||
/*
|
||||
* GNU C extensions are used conditionally in the public API. It doesn't
|
||||
* break anything if these are sometimes enabled and sometimes not, only
|
||||
* affects warnings and optimizations.
|
||||
*/
|
||||
#if __GNUC__ >= 3
|
||||
# ifndef lzma_attribute
|
||||
# define lzma_attribute(attr) __attribute__(attr)
|
||||
# endif
|
||||
|
||||
/* warn_unused_result was added in GCC 3.4. */
|
||||
# ifndef lzma_attr_warn_unused_result
|
||||
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
|
||||
# define lzma_attr_warn_unused_result
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#else
|
||||
# ifndef lzma_attribute
|
||||
# define lzma_attribute(attr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef lzma_attr_pure
|
||||
# define lzma_attr_pure lzma_attribute((__pure__))
|
||||
#endif
|
||||
|
||||
#ifndef lzma_attr_const
|
||||
# define lzma_attr_const lzma_attribute((__const__))
|
||||
#endif
|
||||
|
||||
#ifndef lzma_attr_warn_unused_result
|
||||
# define lzma_attr_warn_unused_result \
|
||||
lzma_attribute((__warn_unused_result__))
|
||||
#endif
|
||||
|
||||
|
||||
/**************
|
||||
* Subheaders *
|
||||
**************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Subheaders check that this is defined. It is to prevent including
|
||||
* them directly from applications.
|
||||
*/
|
||||
#define LZMA_H_INTERNAL 1
|
||||
|
||||
/* Basic features */
|
||||
#include "lzma/version.h"
|
||||
#include "lzma/base.h"
|
||||
#include "lzma/vli.h"
|
||||
#include "lzma/check.h"
|
||||
|
||||
/* Filters */
|
||||
#include "lzma/filter.h"
|
||||
#include "lzma/bcj.h"
|
||||
#include "lzma/delta.h"
|
||||
#include "lzma/lzma.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"
|
||||
|
||||
/* Hardware information */
|
||||
#include "lzma/hardware.h"
|
||||
|
||||
/*
|
||||
* All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
|
||||
* re-including the subheaders.
|
||||
*/
|
||||
#undef LZMA_H_INTERNAL
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef LZMA_H */
|
|
@ -1,606 +0,0 @@
|
|||
/**
|
||||
* \file lzma/base.h
|
||||
* \brief Data types and functions used in many places in liblzma API
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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 Boolean
|
||||
*
|
||||
* This is here because C89 doesn't have stdbool.h. To set a value for
|
||||
* variables having type lzma_bool, you can use
|
||||
* - C99's `true' and `false' from stdbool.h;
|
||||
* - C++'s internal `true' and `false'; or
|
||||
* - integers one (true) and zero (false).
|
||||
*/
|
||||
typedef unsigned char lzma_bool;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Type of reserved enumeration variable in structures
|
||||
*
|
||||
* To avoid breaking library ABI when new features are added, several
|
||||
* structures contain extra variables that may be used in future. Since
|
||||
* sizeof(enum) can be different than sizeof(int), and sizeof(enum) may
|
||||
* even vary depending on the range of enumeration constants, we specify
|
||||
* a separate type to be used for reserved enumeration variables. All
|
||||
* enumeration constants in liblzma API will be non-negative and less
|
||||
* than 128, which should guarantee that the ABI won't break even when
|
||||
* new constants are added to existing enumerations.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_RESERVED_ENUM = 0
|
||||
} lzma_reserved_enum;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Return values used by several functions in liblzma
|
||||
*
|
||||
* Check the descriptions of specific functions to find out which return
|
||||
* values they can return. With some functions the return values may have
|
||||
* more specific meanings than described here; those differences are
|
||||
* described per-function basis.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_OK = 0,
|
||||
/**<
|
||||
* \brief Operation completed successfully
|
||||
*/
|
||||
|
||||
LZMA_STREAM_END = 1,
|
||||
/**<
|
||||
* \brief End of stream was reached
|
||||
*
|
||||
* In encoder, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or
|
||||
* LZMA_FINISH was finished. In decoder, this indicates
|
||||
* that all the data was successfully decoded.
|
||||
*
|
||||
* In all cases, when LZMA_STREAM_END is returned, the last
|
||||
* output bytes should be picked from strm->next_out.
|
||||
*/
|
||||
|
||||
LZMA_NO_CHECK = 2,
|
||||
/**<
|
||||
* \brief Input stream has no integrity check
|
||||
*
|
||||
* This return value can be returned only if the
|
||||
* LZMA_TELL_NO_CHECK flag was used when initializing
|
||||
* the decoder. LZMA_NO_CHECK is just a warning, and
|
||||
* the decoding can be continued normally.
|
||||
*
|
||||
* It is possible to call lzma_get_check() immediately after
|
||||
* lzma_code has returned LZMA_NO_CHECK. The result will
|
||||
* naturally be LZMA_CHECK_NONE, but the possibility to call
|
||||
* lzma_get_check() may be convenient in some applications.
|
||||
*/
|
||||
|
||||
LZMA_UNSUPPORTED_CHECK = 3,
|
||||
/**<
|
||||
* \brief Cannot calculate the integrity check
|
||||
*
|
||||
* The usage of this return value is different in encoders
|
||||
* and decoders.
|
||||
*
|
||||
* Encoders can return this value only from the initialization
|
||||
* function. If initialization fails with this value, the
|
||||
* encoding cannot be done, because there's no way to produce
|
||||
* output with the correct integrity check.
|
||||
*
|
||||
* Decoders can return this value only from lzma_code() and
|
||||
* only if the LZMA_TELL_UNSUPPORTED_CHECK flag was used when
|
||||
* initializing the decoder. The decoding can still be
|
||||
* continued normally even if the check type is unsupported,
|
||||
* but naturally the check will not be validated, and possible
|
||||
* errors may go undetected.
|
||||
*
|
||||
* With decoder, it is possible to call lzma_get_check()
|
||||
* immediately after lzma_code() has returned
|
||||
* LZMA_UNSUPPORTED_CHECK. This way it is possible to find
|
||||
* out what the unsupported Check ID was.
|
||||
*/
|
||||
|
||||
LZMA_GET_CHECK = 4,
|
||||
/**<
|
||||
* \brief Integrity check type is now available
|
||||
*
|
||||
* This value can be returned only by the lzma_code() function
|
||||
* and only if the decoder was initialized with the
|
||||
* LZMA_TELL_ANY_CHECK flag. LZMA_GET_CHECK tells the
|
||||
* application that it may now call lzma_get_check() to find
|
||||
* out the Check ID. This can be used, for example, to
|
||||
* implement a decoder that accepts only files that have
|
||||
* strong enough integrity check.
|
||||
*/
|
||||
|
||||
LZMA_MEM_ERROR = 5,
|
||||
/**<
|
||||
* \brief Cannot allocate memory
|
||||
*
|
||||
* Memory allocation failed, or the size of the allocation
|
||||
* would be greater than SIZE_MAX.
|
||||
*
|
||||
* Due to internal implementation reasons, the coding cannot
|
||||
* be continued even if more memory were made available after
|
||||
* LZMA_MEM_ERROR.
|
||||
*/
|
||||
|
||||
LZMA_MEMLIMIT_ERROR = 6,
|
||||
/**
|
||||
* \brief Memory usage limit was reached
|
||||
*
|
||||
* Decoder would need more memory than allowed by the
|
||||
* specified memory usage limit. To continue decoding,
|
||||
* the memory usage limit has to be increased with
|
||||
* lzma_memlimit_set().
|
||||
*/
|
||||
|
||||
LZMA_FORMAT_ERROR = 7,
|
||||
/**<
|
||||
* \brief File format not recognized
|
||||
*
|
||||
* The decoder did not recognize the input as supported file
|
||||
* format. This error can occur, for example, when trying to
|
||||
* decode .lzma format file with lzma_stream_decoder,
|
||||
* because lzma_stream_decoder accepts only the .xz format.
|
||||
*/
|
||||
|
||||
LZMA_OPTIONS_ERROR = 8,
|
||||
/**<
|
||||
* \brief Invalid or unsupported options
|
||||
*
|
||||
* Invalid or unsupported options, for example
|
||||
* - unsupported filter(s) or filter options; or
|
||||
* - reserved bits set in headers (decoder only).
|
||||
*
|
||||
* Rebuilding liblzma with more features enabled, or
|
||||
* upgrading to a newer version of liblzma may help.
|
||||
*/
|
||||
|
||||
LZMA_DATA_ERROR = 9,
|
||||
/**<
|
||||
* \brief Data is corrupt
|
||||
*
|
||||
* The usage of this return value is different in encoders
|
||||
* and decoders. In both encoder and decoder, the coding
|
||||
* cannot continue after this error.
|
||||
*
|
||||
* Encoders return this if size limits of the target file
|
||||
* format would be exceeded. These limits are huge, thus
|
||||
* getting this error from an encoder is mostly theoretical.
|
||||
* For example, the maximum compressed and uncompressed
|
||||
* size of a .xz Stream is roughly 8 EiB (2^63 bytes).
|
||||
*
|
||||
* Decoders return this error if the input data is corrupt.
|
||||
* This can mean, for example, invalid CRC32 in headers
|
||||
* or invalid check of uncompressed data.
|
||||
*/
|
||||
|
||||
LZMA_BUF_ERROR = 10,
|
||||
/**<
|
||||
* \brief No progress is possible
|
||||
*
|
||||
* This error code is returned when the coder cannot consume
|
||||
* any new input and produce any new output. The most common
|
||||
* reason for this error is that the input stream being
|
||||
* decoded is truncated or corrupt.
|
||||
*
|
||||
* This error is not fatal. Coding can be continued normally
|
||||
* by providing more input and/or more output space, if
|
||||
* possible.
|
||||
*
|
||||
* Typically the first call to lzma_code() that can do no
|
||||
* progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only
|
||||
* the second consecutive call doing no progress will return
|
||||
* LZMA_BUF_ERROR. This is intentional.
|
||||
*
|
||||
* With zlib, Z_BUF_ERROR may be returned even if the
|
||||
* application is doing nothing wrong, so apps will need
|
||||
* to handle Z_BUF_ERROR specially. The above hack
|
||||
* guarantees that liblzma never returns LZMA_BUF_ERROR
|
||||
* to properly written applications unless the input file
|
||||
* is truncated or corrupt. This should simplify the
|
||||
* applications a little.
|
||||
*/
|
||||
|
||||
LZMA_PROG_ERROR = 11,
|
||||
/**<
|
||||
* \brief Programming error
|
||||
*
|
||||
* This indicates that the arguments given to the function are
|
||||
* invalid or the internal state of the decoder is corrupt.
|
||||
* - Function arguments are invalid or the structures
|
||||
* pointed by the argument pointers are invalid
|
||||
* e.g. if strm->next_out has been set to NULL and
|
||||
* strm->avail_out > 0 when calling lzma_code().
|
||||
* - lzma_* functions have been called in wrong order
|
||||
* e.g. lzma_code() was called right after lzma_end().
|
||||
* - If errors occur randomly, the reason might be flaky
|
||||
* hardware.
|
||||
*
|
||||
* If you think that your code is correct, this error code
|
||||
* can be a sign of a bug in liblzma. See the documentation
|
||||
* how to report bugs.
|
||||
*/
|
||||
} lzma_ret;
|
||||
|
||||
|
||||
/**
|
||||
* \brief The `action' argument for lzma_code()
|
||||
*
|
||||
* After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH,
|
||||
* the same `action' must is used until lzma_code() returns LZMA_STREAM_END.
|
||||
* Also, the amount of input (that is, strm->avail_in) must not be modified
|
||||
* by the application until lzma_code() returns LZMA_STREAM_END. Changing the
|
||||
* `action' or modifying the amount of input will make lzma_code() return
|
||||
* LZMA_PROG_ERROR.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_RUN = 0,
|
||||
/**<
|
||||
* \brief Continue coding
|
||||
*
|
||||
* Encoder: Encode as much input as possible. Some internal
|
||||
* buffering will probably be done (depends on the filter
|
||||
* chain in use), which causes latency: the input used won't
|
||||
* usually be decodeable from the output of the same
|
||||
* lzma_code() call.
|
||||
*
|
||||
* Decoder: Decode as much input as possible and produce as
|
||||
* much output as possible.
|
||||
*/
|
||||
|
||||
LZMA_SYNC_FLUSH = 1,
|
||||
/**<
|
||||
* \brief Make all the input available at output
|
||||
*
|
||||
* Normally the encoder introduces some latency.
|
||||
* LZMA_SYNC_FLUSH forces all the buffered data to be
|
||||
* available at output without resetting the internal
|
||||
* state of the encoder. This way it is possible to use
|
||||
* compressed stream for example for communication over
|
||||
* network.
|
||||
*
|
||||
* Only some filters support LZMA_SYNC_FLUSH. Trying to use
|
||||
* LZMA_SYNC_FLUSH with filters that don't support it will
|
||||
* make lzma_code() return LZMA_OPTIONS_ERROR. For example,
|
||||
* LZMA1 doesn't support LZMA_SYNC_FLUSH but LZMA2 does.
|
||||
*
|
||||
* Using LZMA_SYNC_FLUSH very often can dramatically reduce
|
||||
* the compression ratio. With some filters (for example,
|
||||
* LZMA2), fine-tuning the compression options may help
|
||||
* mitigate this problem significantly (for example,
|
||||
* match finder with LZMA2).
|
||||
*
|
||||
* Decoders don't support LZMA_SYNC_FLUSH.
|
||||
*/
|
||||
|
||||
LZMA_FULL_FLUSH = 2,
|
||||
/**<
|
||||
* \brief Finish encoding of the current Block
|
||||
*
|
||||
* All the input data going to the current Block must have
|
||||
* been given to the encoder (the last bytes can still be
|
||||
* pending in* next_in). Call lzma_code() with LZMA_FULL_FLUSH
|
||||
* until it returns LZMA_STREAM_END. Then continue normally
|
||||
* with LZMA_RUN or finish the Stream with LZMA_FINISH.
|
||||
*
|
||||
* This action is currently supported only by Stream encoder
|
||||
* and easy encoder (which uses Stream encoder). If there is
|
||||
* no unfinished Block, no empty Block is created.
|
||||
*/
|
||||
|
||||
LZMA_FINISH = 3
|
||||
/**<
|
||||
* \brief Finish the coding operation
|
||||
*
|
||||
* All the input data must have been given to the encoder
|
||||
* (the last bytes can still be pending in next_in).
|
||||
* Call lzma_code() with LZMA_FINISH until it returns
|
||||
* LZMA_STREAM_END. Once LZMA_FINISH has been used,
|
||||
* the amount of input must no longer be changed by
|
||||
* the application.
|
||||
*
|
||||
* When decoding, using LZMA_FINISH is optional unless the
|
||||
* LZMA_CONCATENATED flag was used when the decoder was
|
||||
* initialized. When LZMA_CONCATENATED was not used, the only
|
||||
* effect of LZMA_FINISH is that the amount of input must not
|
||||
* be changed just like in the encoder.
|
||||
*/
|
||||
} lzma_action;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Custom functions for memory handling
|
||||
*
|
||||
* A pointer to lzma_allocator may be passed via lzma_stream structure
|
||||
* to liblzma, and some advanced functions take a pointer to lzma_allocator
|
||||
* as a separate function argument. The library will use the functions
|
||||
* specified in lzma_allocator for memory handling instead of the default
|
||||
* malloc() and free(). C++ users should note that the custom memory
|
||||
* handling functions must not throw exceptions.
|
||||
*
|
||||
* liblzma doesn't make an internal copy of lzma_allocator. Thus, it is
|
||||
* OK to change these function pointers in the middle of the coding
|
||||
* process, but obviously it must be done carefully to make sure that the
|
||||
* replacement `free' can deallocate memory allocated by the earlier
|
||||
* `alloc' function(s).
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to a custom memory allocation function
|
||||
*
|
||||
* If you don't want a custom allocator, but still want
|
||||
* custom free(), set this to NULL and liblzma will use
|
||||
* the standard malloc().
|
||||
*
|
||||
* \param opaque lzma_allocator.opaque (see below)
|
||||
* \param nmemb Number of elements like in calloc(). liblzma
|
||||
* will always set nmemb to 1, so it is safe to
|
||||
* ignore nmemb in a custom allocator if you like.
|
||||
* The nmemb argument exists only for
|
||||
* compatibility with zlib and libbzip2.
|
||||
* \param size Size of an element in bytes.
|
||||
* liblzma never sets this to zero.
|
||||
*
|
||||
* \return Pointer to the beginning of a memory block of
|
||||
* `size' bytes, or NULL if allocation fails
|
||||
* for some reason. When allocation fails, functions
|
||||
* of liblzma return LZMA_MEM_ERROR.
|
||||
*
|
||||
* The allocator should not waste time zeroing the allocated buffers.
|
||||
* This is not only about speed, but also memory usage, since the
|
||||
* operating system kernel doesn't necessarily allocate the requested
|
||||
* memory in physical memory until it is actually used. With small
|
||||
* input files, liblzma may actually need only a fraction of the
|
||||
* memory that it requested for allocation.
|
||||
*
|
||||
* \note LZMA_MEM_ERROR is also used when the size of the
|
||||
* allocation would be greater than SIZE_MAX. Thus,
|
||||
* don't assume that the custom allocator must have
|
||||
* returned NULL if some function from liblzma
|
||||
* returns LZMA_MEM_ERROR.
|
||||
*/
|
||||
void *(LZMA_API_CALL *alloc)(void *opaque, size_t nmemb, size_t size);
|
||||
|
||||
/**
|
||||
* \brief Pointer to a custom memory freeing function
|
||||
*
|
||||
* If you don't want a custom freeing function, but still
|
||||
* want a custom allocator, set this to NULL and liblzma
|
||||
* will use the standard free().
|
||||
*
|
||||
* \param opaque lzma_allocator.opaque (see below)
|
||||
* \param ptr Pointer returned by lzma_allocator.alloc(),
|
||||
* or when it is set to NULL, a pointer returned
|
||||
* by the standard malloc().
|
||||
*/
|
||||
void (LZMA_API_CALL *free)(void *opaque, void *ptr);
|
||||
|
||||
/**
|
||||
* \brief Pointer passed to .alloc() and .free()
|
||||
*
|
||||
* opaque is passed as the first argument to lzma_allocator.alloc()
|
||||
* and lzma_allocator.free(). This intended to ease implementing
|
||||
* custom memory allocation functions for use with liblzma.
|
||||
*
|
||||
* If you don't need this, you should set this to NULL.
|
||||
*/
|
||||
void *opaque;
|
||||
|
||||
} lzma_allocator;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Internal data structure
|
||||
*
|
||||
* The contents of this structure is not visible outside the library.
|
||||
*/
|
||||
typedef struct lzma_internal_s lzma_internal;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Passing data to and from liblzma
|
||||
*
|
||||
* The lzma_stream structure is used for
|
||||
* - passing pointers to input and output buffers to liblzma;
|
||||
* - defining custom memory hander functions; and
|
||||
* - holding a pointer to coder-specific internal data structures.
|
||||
*
|
||||
* Typical usage:
|
||||
*
|
||||
* - After allocating lzma_stream (on stack or with malloc()), it must be
|
||||
* initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details).
|
||||
*
|
||||
* - Initialize a coder to the lzma_stream, for example by using
|
||||
* lzma_easy_encoder() or lzma_auto_decoder(). Some notes:
|
||||
* - In contrast to zlib, strm->next_in and strm->next_out are
|
||||
* ignored by all initialization functions, thus it is safe
|
||||
* to not initialize them yet.
|
||||
* - The initialization functions always set strm->total_in and
|
||||
* strm->total_out to zero.
|
||||
* - If the initialization function fails, no memory is left allocated
|
||||
* that would require freeing with lzma_end() even if some memory was
|
||||
* associated with the lzma_stream structure when the initialization
|
||||
* function was called.
|
||||
*
|
||||
* - Use lzma_code() to do the actual work.
|
||||
*
|
||||
* - Once the coding has been finished, the existing lzma_stream can be
|
||||
* reused. It is OK to reuse lzma_stream with different initialization
|
||||
* function without calling lzma_end() first. Old allocations are
|
||||
* automatically freed.
|
||||
*
|
||||
* - Finally, use lzma_end() to free the allocated memory. lzma_end() never
|
||||
* frees the lzma_stream structure itself.
|
||||
*
|
||||
* Application may modify the values of total_in and total_out as it wants.
|
||||
* They are updated by liblzma to match the amount of data read and
|
||||
* written, but aren't used for anything else.
|
||||
*/
|
||||
typedef struct {
|
||||
const uint8_t *next_in; /**< Pointer to the next input byte. */
|
||||
size_t avail_in; /**< Number of available input bytes in next_in. */
|
||||
uint64_t total_in; /**< Total number of bytes read by liblzma. */
|
||||
|
||||
uint8_t *next_out; /**< Pointer to the next output position. */
|
||||
size_t avail_out; /**< Amount of free space in next_out. */
|
||||
uint64_t total_out; /**< Total number of bytes written by liblzma. */
|
||||
|
||||
/**
|
||||
* \brief Custom memory allocation functions
|
||||
*
|
||||
* In most cases this is NULL which makes liblzma use
|
||||
* the standard malloc() and free().
|
||||
*/
|
||||
lzma_allocator *allocator;
|
||||
|
||||
/** Internal state is not visible to applications. */
|
||||
lzma_internal *internal;
|
||||
|
||||
/*
|
||||
* Reserved space to allow possible future extensions without
|
||||
* breaking the ABI. Excluding the initialization of this structure,
|
||||
* you should not touch these, because the names of these variables
|
||||
* may change.
|
||||
*/
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
void *reserved_ptr3;
|
||||
void *reserved_ptr4;
|
||||
uint64_t reserved_int1;
|
||||
uint64_t reserved_int2;
|
||||
size_t reserved_int3;
|
||||
size_t reserved_int4;
|
||||
lzma_reserved_enum reserved_enum1;
|
||||
lzma_reserved_enum reserved_enum2;
|
||||
|
||||
} lzma_stream;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialization for lzma_stream
|
||||
*
|
||||
* When you declare an instance of lzma_stream, you can immediately
|
||||
* initialize it so that initialization functions know that no memory
|
||||
* has been allocated yet:
|
||||
*
|
||||
* lzma_stream strm = LZMA_STREAM_INIT;
|
||||
*
|
||||
* If you need to initialize a dynamically allocated lzma_stream, you can use
|
||||
* memset(strm_pointer, 0, sizeof(lzma_stream)). Strictly speaking, this
|
||||
* violates the C standard since NULL may have different internal
|
||||
* representation than zero, but it should be portable enough in practice.
|
||||
* Anyway, for maximum portability, you can use something like this:
|
||||
*
|
||||
* lzma_stream tmp = LZMA_STREAM_INIT;
|
||||
* *strm = tmp;
|
||||
*/
|
||||
#define LZMA_STREAM_INIT \
|
||||
{ NULL, 0, 0, NULL, 0, 0, NULL, NULL, \
|
||||
NULL, NULL, NULL, NULL, 0, 0, 0, 0, \
|
||||
LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode or decode data
|
||||
*
|
||||
* Once the lzma_stream has been successfully initialized (e.g. with
|
||||
* lzma_stream_encoder()), the actual encoding or decoding is done
|
||||
* using this function. The application has to update strm->next_in,
|
||||
* strm->avail_in, strm->next_out, and strm->avail_out to pass input
|
||||
* to and get output from liblzma.
|
||||
*
|
||||
* See the description of the coder-specific initialization function to find
|
||||
* out what `action' values are supported by the coder.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Free memory allocated for the coder data structures
|
||||
*
|
||||
* \param strm Pointer to lzma_stream that is at least initialized
|
||||
* with LZMA_STREAM_INIT.
|
||||
*
|
||||
* After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
|
||||
* members of the lzma_stream structure are touched.
|
||||
*
|
||||
* \note zlib indicates an error if application end()s unfinished
|
||||
* stream structure. liblzma doesn't do this, and assumes that
|
||||
* application knows what it is doing.
|
||||
*/
|
||||
extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the memory usage of decoder filter chain
|
||||
*
|
||||
* This function is currently supported only when *strm has been initialized
|
||||
* with a function that takes a memlimit argument. With other functions, you
|
||||
* should use e.g. lzma_raw_encoder_memusage() or lzma_raw_decoder_memusage()
|
||||
* to estimate the memory requirements.
|
||||
*
|
||||
* This function is useful e.g. after LZMA_MEMLIMIT_ERROR to find out how big
|
||||
* the memory usage limit should have been to decode the input. Note that
|
||||
* this may give misleading information if decoding .xz Streams that have
|
||||
* multiple Blocks, because each Block can have different memory requirements.
|
||||
*
|
||||
* \return How much memory is currently allocated for the filter
|
||||
* decoders. If no filter chain is currently allocated,
|
||||
* some non-zero value is still returned, which is less than
|
||||
* or equal to what any filter chain would indicate as its
|
||||
* memory requirement.
|
||||
*
|
||||
* If this function isn't supported by *strm or some other error
|
||||
* occurs, zero is returned.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_memusage(const lzma_stream *strm)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the current memory usage limit
|
||||
*
|
||||
* This function is supported only when *strm has been initialized with
|
||||
* a function that takes a memlimit argument.
|
||||
*
|
||||
* \return On success, the current memory usage limit is returned
|
||||
* (always non-zero). On error, zero is returned.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set the memory usage limit
|
||||
*
|
||||
* This function is supported only when *strm has been initialized with
|
||||
* a function that takes a memlimit argument.
|
||||
*
|
||||
* \return - LZMA_OK: New memory usage limit successfully set.
|
||||
* - LZMA_MEMLIMIT_ERROR: The new limit is too small.
|
||||
* The limit was not changed.
|
||||
* - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
|
||||
* support memory usage limit or memlimit was zero.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_memlimit_set(
|
||||
lzma_stream *strm, uint64_t memlimit) lzma_nothrow;
|
|
@ -1,95 +0,0 @@
|
|||
/**
|
||||
* \file lzma/bcj.h
|
||||
* \brief Branch/Call/Jump conversion filters
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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,535 +0,0 @@
|
|||
/**
|
||||
* \file lzma/block.h
|
||||
* \brief .xz Block handling
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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 if new features are needed in
|
||||
* the Block field, 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, most Block related functions will
|
||||
* return LZMA_OPTIONS_ERROR.
|
||||
*
|
||||
* 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;
|
||||
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;
|
||||
|
||||
} 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 be set to the highest value supported by the
|
||||
* application; currently the only possible version is zero. This function
|
||||
* will set version to the lowest value that still supports all the features
|
||||
* required by the Block Header.
|
||||
*
|
||||
* The size of the Block Header must have already been decoded with
|
||||
* lzma_block_header_size_decode() macro and stored to block->header_size.
|
||||
*
|
||||
* 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,
|
||||
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, 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 .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, 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,155 +0,0 @@
|
|||
/**
|
||||
* \file lzma/check.h
|
||||
* \brief Integrity checks
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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 Type of the integrity check (Check ID)
|
||||
*
|
||||
* The .xz format supports multiple types of checks that are calculated
|
||||
* from the uncompressed data. They vary in both speed and ability to
|
||||
* detect errors.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_CHECK_NONE = 0,
|
||||
/**<
|
||||
* No Check is calculated.
|
||||
*
|
||||
* Size of the Check field: 0 bytes
|
||||
*/
|
||||
|
||||
LZMA_CHECK_CRC32 = 1,
|
||||
/**<
|
||||
* CRC32 using the polynomial from the IEEE 802.3 standard
|
||||
*
|
||||
* Size of the Check field: 4 bytes
|
||||
*/
|
||||
|
||||
LZMA_CHECK_CRC64 = 4,
|
||||
/**<
|
||||
* CRC64 using the polynomial from the ECMA-182 standard
|
||||
*
|
||||
* Size of the Check field: 8 bytes
|
||||
*/
|
||||
|
||||
LZMA_CHECK_SHA256 = 10
|
||||
/**<
|
||||
* SHA-256
|
||||
*
|
||||
* Size of the Check field: 32 bytes
|
||||
*/
|
||||
} lzma_check;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Maximum valid Check ID
|
||||
*
|
||||
* The .xz file format specification specifies 16 Check IDs (0-15). Some
|
||||
* of them are only reserved, that is, no actual Check algorithm has been
|
||||
* assigned. When decoding, liblzma still accepts unknown Check IDs for
|
||||
* future compatibility. If a valid but unsupported Check ID is detected,
|
||||
* liblzma can indicate a warning; see the flags LZMA_TELL_NO_CHECK,
|
||||
* LZMA_TELL_UNSUPPORTED_CHECK, and LZMA_TELL_ANY_CHECK in container.h.
|
||||
*/
|
||||
#define LZMA_CHECK_ID_MAX 15
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if the given Check ID is supported
|
||||
*
|
||||
* Return true if the given Check ID is supported by this liblzma build.
|
||||
* Otherwise false is returned. It is safe to call this with a value that
|
||||
* is not in the range [0, 15]; in that case the return value is always false.
|
||||
*
|
||||
* You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always
|
||||
* supported (even if liblzma is built with limited features).
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Check field with the given Check ID
|
||||
*
|
||||
* Although not all Check IDs have a check algorithm associated, the size of
|
||||
* every Check is already frozen. This function returns the size (in bytes) of
|
||||
* the Check field with the specified Check ID. The values are:
|
||||
* { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
|
||||
*
|
||||
* If the argument is not in the range [0, 15], UINT32_MAX is returned.
|
||||
*/
|
||||
extern LZMA_API(uint32_t) lzma_check_size(lzma_check check)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Maximum size of a Check field
|
||||
*/
|
||||
#define LZMA_CHECK_SIZE_MAX 64
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate CRC32
|
||||
*
|
||||
* Calculate CRC32 using the polynomial from the IEEE 802.3 standard.
|
||||
*
|
||||
* \param buf Pointer to the input buffer
|
||||
* \param size Size of the input buffer
|
||||
* \param crc Previously returned CRC value. This is used to
|
||||
* calculate the CRC of a big buffer in smaller chunks.
|
||||
* Set to zero when starting a new calculation.
|
||||
*
|
||||
* \return Updated CRC value, which can be passed to this function
|
||||
* again to continue CRC calculation.
|
||||
*/
|
||||
extern LZMA_API(uint32_t) lzma_crc32(
|
||||
const uint8_t *buf, size_t size, uint32_t crc)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate CRC64
|
||||
*
|
||||
* Calculate CRC64 using the polynomial from the ECMA-182 standard.
|
||||
*
|
||||
* This function is used similarly to lzma_crc32(). See its documentation.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_crc64(
|
||||
const uint8_t *buf, size_t size, uint64_t crc)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/*
|
||||
* SHA-256 functions are currently not exported to public API.
|
||||
* Contact Lasse Collin if you think it should be.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the type of the integrity check
|
||||
*
|
||||
* This function can be called only immediately after lzma_code() has
|
||||
* returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
|
||||
* Calling this function in any other situation has undefined behavior.
|
||||
*/
|
||||
extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm)
|
||||
lzma_nothrow;
|
|
@ -1,429 +0,0 @@
|
|||
/**
|
||||
* \file lzma/container.h
|
||||
* \brief File formats
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
||||
/************
|
||||
* Encoding *
|
||||
************/
|
||||
|
||||
/**
|
||||
* \brief Default compression preset
|
||||
*
|
||||
* It's not straightforward to recommend a default preset, because in some
|
||||
* cases keeping the resource usage relatively low is more important that
|
||||
* getting the maximum compression ratio.
|
||||
*/
|
||||
#define LZMA_PRESET_DEFAULT UINT32_C(6)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Mask for preset level
|
||||
*
|
||||
* This is useful only if you need to extract the level from the preset
|
||||
* variable. That should be rare.
|
||||
*/
|
||||
#define LZMA_PRESET_LEVEL_MASK UINT32_C(0x1F)
|
||||
|
||||
|
||||
/*
|
||||
* Preset flags
|
||||
*
|
||||
* Currently only one flag is defined.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Extreme compression preset
|
||||
*
|
||||
* This flag modifies the preset to make the encoding significantly slower
|
||||
* while improving the compression ratio only marginally. This is useful
|
||||
* when you don't mind wasting time to get as small result as possible.
|
||||
*
|
||||
* This flag doesn't affect the memory usage requirements of the decoder (at
|
||||
* least not significantly). The memory usage of the encoder may be increased
|
||||
* a little but only at the lowest preset levels (0-3).
|
||||
*/
|
||||
#define LZMA_PRESET_EXTREME (UINT32_C(1) << 31)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate approximate memory usage of easy encoder
|
||||
*
|
||||
* This function is a wrapper for lzma_raw_encoder_memusage().
|
||||
*
|
||||
* \param preset Compression preset (level and possible flags)
|
||||
*
|
||||
* \return Number of bytes of memory required for the given
|
||||
* preset when encoding. If an error occurs, for example
|
||||
* due to unsupported preset, UINT64_MAX is returned.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate approximate decoder memory usage of a preset
|
||||
*
|
||||
* This function is a wrapper for lzma_raw_decoder_memusage().
|
||||
*
|
||||
* \param preset Compression preset (level and possible flags)
|
||||
*
|
||||
* \return Number of bytes of memory required to decompress a file
|
||||
* that was compressed using the given preset. If an error
|
||||
* occurs, for example due to unsupported preset, UINT64_MAX
|
||||
* is returned.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Stream encoder using a preset number
|
||||
*
|
||||
* This function is intended for those who just want to use the basic features
|
||||
* if liblzma (that is, most developers out there).
|
||||
*
|
||||
* \param strm Pointer to lzma_stream that is at least initialized
|
||||
* with LZMA_STREAM_INIT.
|
||||
* \param preset Compression preset to use. A preset consist of level
|
||||
* number and zero or more flags. Usually flags aren't
|
||||
* used, so preset is simply a number [0, 9] which match
|
||||
* the options -0 ... -9 of the xz command line tool.
|
||||
* Additional flags can be be set using bitwise-or with
|
||||
* the preset level number, e.g. 6 | LZMA_PRESET_EXTREME.
|
||||
* \param check Integrity check type to use. See check.h for available
|
||||
* checks. The xz command line tool defaults to
|
||||
* LZMA_CHECK_CRC64, which is a good choice if you are
|
||||
* unsure. LZMA_CHECK_CRC32 is good too as long as the
|
||||
* uncompressed file is not many gigabytes.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization succeeded. Use lzma_code() to
|
||||
* encode your data.
|
||||
* - LZMA_MEM_ERROR: Memory allocation failed.
|
||||
* - LZMA_OPTIONS_ERROR: The given compression preset is not
|
||||
* supported by this build of liblzma.
|
||||
* - LZMA_UNSUPPORTED_CHECK: The given check type is not
|
||||
* supported by this liblzma build.
|
||||
* - LZMA_PROG_ERROR: One or more of the parameters have values
|
||||
* that will never be valid. For example, strm == NULL.
|
||||
*
|
||||
* If initialization fails (return value is not LZMA_OK), all the memory
|
||||
* allocated for *strm by liblzma is always freed. Thus, there is no need
|
||||
* to call lzma_end() after failed initialization.
|
||||
*
|
||||
* If initialization succeeds, use lzma_code() to do the actual encoding.
|
||||
* Valid values for `action' (the second argument of lzma_code()) are
|
||||
* LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
|
||||
* there may be compression levels or flags that don't support LZMA_SYNC_FLUSH.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_easy_encoder(
|
||||
lzma_stream *strm, uint32_t preset, lzma_check check)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Stream encoding using a preset number
|
||||
*
|
||||
* The maximum required output buffer size can be calculated with
|
||||
* lzma_stream_buffer_bound().
|
||||
*
|
||||
* \param preset Compression preset to use. See the description
|
||||
* in lzma_easy_encoder().
|
||||
* \param check Type of the integrity check to calculate from
|
||||
* uncompressed data.
|
||||
* \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_easy_buffer_encode(
|
||||
uint32_t preset, lzma_check check,
|
||||
lzma_allocator *allocator, const uint8_t *in, size_t in_size,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Stream encoder using a custom filter chain
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param filters Array of filters. This must be terminated with
|
||||
* filters[n].id = LZMA_VLI_UNKNOWN. See filter.h for
|
||||
* more information.
|
||||
* \param check Type of the integrity check to calculate from
|
||||
* uncompressed data.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_UNSUPPORTED_CHECK
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_encoder(lzma_stream *strm,
|
||||
const lzma_filter *filters, lzma_check check)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .lzma encoder (legacy file format)
|
||||
*
|
||||
* The .lzma format is sometimes called the LZMA_Alone format, which is the
|
||||
* reason for the name of this function. The .lzma format supports only the
|
||||
* LZMA1 filter. There is no support for integrity checks like CRC32.
|
||||
*
|
||||
* Use this function if and only if you need to create files readable by
|
||||
* legacy LZMA tools such as LZMA Utils 4.32.x. Moving to the .xz format
|
||||
* is strongly recommended.
|
||||
*
|
||||
* The valid action values for lzma_code() are LZMA_RUN and LZMA_FINISH.
|
||||
* No kind of flushing is supported, because the file format doesn't make
|
||||
* it possible.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_alone_encoder(
|
||||
lzma_stream *strm, const lzma_options_lzma *options)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate output buffer size for single-call Stream encoder
|
||||
*
|
||||
* When trying to compress uncompressible data, the encoded size will be
|
||||
* slightly bigger than the input data. This function calculates how much
|
||||
* output buffer space is required to be sure that lzma_stream_buffer_encode()
|
||||
* doesn't return LZMA_BUF_ERROR.
|
||||
*
|
||||
* The calculated value is not exact, but it is guaranteed to be big enough.
|
||||
* The actual maximum output space required may be slightly smaller (up to
|
||||
* about 100 bytes). This should not be a problem in practice.
|
||||
*
|
||||
* If the calculated maximum size doesn't fit into size_t or would make the
|
||||
* Stream grow past LZMA_VLI_MAX (which should never happen in practice),
|
||||
* zero is returned to indicate the error.
|
||||
*
|
||||
* \note The limit calculated by this function applies only to
|
||||
* single-call encoding. Multi-call encoding may (and probably
|
||||
* will) have larger maximum expansion when encoding
|
||||
* uncompressible data. Currently there is no function to
|
||||
* calculate the maximum expansion of multi-call encoding.
|
||||
*/
|
||||
extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Stream encoder
|
||||
*
|
||||
* \param filters Array of filters. This must be terminated with
|
||||
* filters[n].id = LZMA_VLI_UNKNOWN. See filter.h
|
||||
* for more information.
|
||||
* \param check Type of the integrity check to calculate from
|
||||
* uncompressed data.
|
||||
* \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_stream_buffer_encode(
|
||||
lzma_filter *filters, lzma_check check,
|
||||
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;
|
||||
|
||||
|
||||
/************
|
||||
* Decoding *
|
||||
************/
|
||||
|
||||
/**
|
||||
* This flag makes lzma_code() return LZMA_NO_CHECK if the input stream
|
||||
* being decoded has no integrity check. Note that when used with
|
||||
* lzma_auto_decoder(), all .lzma files will trigger LZMA_NO_CHECK
|
||||
* if LZMA_TELL_NO_CHECK is used.
|
||||
*/
|
||||
#define LZMA_TELL_NO_CHECK UINT32_C(0x01)
|
||||
|
||||
|
||||
/**
|
||||
* This flag makes lzma_code() return LZMA_UNSUPPORTED_CHECK if the input
|
||||
* stream has an integrity check, but the type of the integrity check is not
|
||||
* supported by this liblzma version or build. Such files can still be
|
||||
* decoded, but the integrity check cannot be verified.
|
||||
*/
|
||||
#define LZMA_TELL_UNSUPPORTED_CHECK UINT32_C(0x02)
|
||||
|
||||
|
||||
/**
|
||||
* This flag makes lzma_code() return LZMA_GET_CHECK as soon as the type
|
||||
* of the integrity check is known. The type can then be got with
|
||||
* lzma_get_check().
|
||||
*/
|
||||
#define LZMA_TELL_ANY_CHECK UINT32_C(0x04)
|
||||
|
||||
|
||||
/**
|
||||
* This flag enables decoding of concatenated files with file formats that
|
||||
* allow concatenating compressed files as is. From the formats currently
|
||||
* supported by liblzma, only the .xz format allows concatenated files.
|
||||
* Concatenated files are not allowed with the legacy .lzma format.
|
||||
*
|
||||
* This flag also affects the usage of the `action' argument for lzma_code().
|
||||
* When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
|
||||
* unless LZMA_FINISH is used as `action'. Thus, the application has to set
|
||||
* LZMA_FINISH in the same way as it does when encoding.
|
||||
*
|
||||
* If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH
|
||||
* as `action' for lzma_code(), but the usage of LZMA_FINISH isn't required.
|
||||
*/
|
||||
#define LZMA_CONCATENATED UINT32_C(0x08)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .xz Stream decoder
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
|
||||
* to effectively disable the limiter.
|
||||
* \param flags Bitwise-or of zero or more of the decoder flags:
|
||||
* LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
|
||||
* LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported flags
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_decoder(
|
||||
lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode .xz Streams and .lzma files with autodetection
|
||||
*
|
||||
* This decoder autodetects between the .xz and .lzma file formats, and
|
||||
* calls lzma_stream_decoder() or lzma_alone_decoder() once the type
|
||||
* of the input file has been detected.
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param memlimit Memory usage limit as bytes. Use UINT64_MAX
|
||||
* to effectively disable the limiter.
|
||||
* \param flags Bitwise-or of flags, or zero for no flags.
|
||||
*
|
||||
* \return - LZMA_OK: Initialization was successful.
|
||||
* - LZMA_MEM_ERROR: Cannot allocate memory.
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported flags
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_auto_decoder(
|
||||
lzma_stream *strm, uint64_t memlimit, uint32_t flags)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize .lzma decoder (legacy file format)
|
||||
*
|
||||
* Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
|
||||
* There is no need to use LZMA_FINISH, but allowing it may simplify
|
||||
* certain types of applications.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_alone_decoder(
|
||||
lzma_stream *strm, uint64_t memlimit)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call .xz Stream decoder
|
||||
*
|
||||
* \param memlimit Pointer to how much memory the decoder is allowed
|
||||
* to allocate. The value pointed by this pointer is
|
||||
* modified if and only if LZMA_MEMLIMIT_ERROR is
|
||||
* returned.
|
||||
* \param flags Bitwise-or of zero or more of the decoder flags:
|
||||
* LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
|
||||
* LZMA_CONCATENATED. Note that LZMA_TELL_ANY_CHECK
|
||||
* is not allowed and will return LZMA_PROG_ERROR.
|
||||
* \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 decoding 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_FORMAT_ERROR
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_DATA_ERROR
|
||||
* - LZMA_NO_CHECK: This can be returned only if using
|
||||
* the LZMA_TELL_NO_CHECK flag.
|
||||
* - LZMA_UNSUPPORTED_CHECK: This can be returned only if using
|
||||
* the LZMA_TELL_UNSUPPORTED_CHECK flag.
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
|
||||
* The minimum required memlimit value was stored to *memlimit.
|
||||
* - LZMA_BUF_ERROR: Output buffer was too small.
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
|
||||
uint64_t *memlimit, uint32_t flags, 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 lzma_attr_warn_unused_result;
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
* \file lzma/delta.h
|
||||
* \brief Delta filter
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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,429 +0,0 @@
|
|||
/**
|
||||
* \file lzma/filter.h
|
||||
* \brief Common filter related types and functions
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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 Maximum number of filters in a chain
|
||||
*
|
||||
* A filter chain can have 1-4 filters, of which three are allowed to change
|
||||
* the size of the data. Usually only one or two filters are needed.
|
||||
*/
|
||||
#define LZMA_FILTERS_MAX 4
|
||||
|
||||
|
||||
/**
|
||||
* \brief Filter options
|
||||
*
|
||||
* This structure is used to pass Filter ID and a pointer filter's
|
||||
* options to liblzma. A few functions work with a single lzma_filter
|
||||
* structure, while most functions expect a filter chain.
|
||||
*
|
||||
* A filter chain is indicated with an array of lzma_filter structures.
|
||||
* The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter
|
||||
* array must have LZMA_FILTERS_MAX + 1 elements (that is, five) to
|
||||
* be able to hold any arbitrary filter chain. This is important when
|
||||
* using lzma_block_header_decode() from block.h, because too small
|
||||
* array would make liblzma write past the end of the filters array.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Filter ID
|
||||
*
|
||||
* Use constants whose name begin with `LZMA_FILTER_' to specify
|
||||
* different filters. In an array of lzma_filter structures, use
|
||||
* LZMA_VLI_UNKNOWN to indicate end of filters.
|
||||
*
|
||||
* \note This is not an enum, because on some systems enums
|
||||
* cannot be 64-bit.
|
||||
*/
|
||||
lzma_vli id;
|
||||
|
||||
/**
|
||||
* \brief Pointer to filter-specific options structure
|
||||
*
|
||||
* If the filter doesn't need options, set this to NULL. If id is
|
||||
* set to LZMA_VLI_UNKNOWN, options is ignored, and thus
|
||||
* doesn't need be initialized.
|
||||
*/
|
||||
void *options;
|
||||
|
||||
} lzma_filter;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if the given Filter ID is supported for encoding
|
||||
*
|
||||
* Return true if the give Filter ID is supported for encoding by this
|
||||
* liblzma build. Otherwise false is returned.
|
||||
*
|
||||
* There is no way to list which filters are available in this particular
|
||||
* liblzma version and build. It would be useless, because the application
|
||||
* couldn't know what kind of options the filter would need.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if the given Filter ID is supported for decoding
|
||||
*
|
||||
* Return true if the give Filter ID is supported for decoding by this
|
||||
* liblzma build. Otherwise false is returned.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Copy the filters array
|
||||
*
|
||||
* Copy the Filter IDs and filter-specific options from src to dest.
|
||||
* Up to LZMA_FILTERS_MAX filters are copied, plus the terminating
|
||||
* .id == LZMA_VLI_UNKNOWN. Thus, dest should have at least
|
||||
* LZMA_FILTERS_MAX + 1 elements space unless the caller knows that
|
||||
* src is smaller than that.
|
||||
*
|
||||
* Unless the filter-specific options is NULL, the Filter ID has to be
|
||||
* supported by liblzma, because liblzma needs to know the size of every
|
||||
* filter-specific options structure. The filter-specific options are not
|
||||
* validated. If options is NULL, any unsupported Filter IDs are copied
|
||||
* without returning an error.
|
||||
*
|
||||
* Old filter-specific options in dest are not freed, so dest doesn't
|
||||
* need to be initialized by the caller in any way.
|
||||
*
|
||||
* If an error occurs, memory possibly already allocated by this function
|
||||
* is always freed.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_OPTIONS_ERROR: Unsupported Filter ID and its options
|
||||
* is not NULL.
|
||||
* - LZMA_PROG_ERROR: src or dest is NULL.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_filters_copy(const lzma_filter *src,
|
||||
lzma_filter *dest, lzma_allocator *allocator) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate approximate memory requirements for raw encoder
|
||||
*
|
||||
* This function can be used to calculate the memory requirements for
|
||||
* Block and Stream encoders too because Block and Stream encoders don't
|
||||
* need significantly more memory than raw encoder.
|
||||
*
|
||||
* \param filters Array of filters terminated with
|
||||
* .id == LZMA_VLI_UNKNOWN.
|
||||
*
|
||||
* \return Number of bytes of memory required for the given
|
||||
* filter chain when encoding. If an error occurs,
|
||||
* for example due to unsupported filter chain,
|
||||
* UINT64_MAX is returned.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate approximate memory requirements for raw decoder
|
||||
*
|
||||
* This function can be used to calculate the memory requirements for
|
||||
* Block and Stream decoders too because Block and Stream decoders don't
|
||||
* need significantly more memory than raw decoder.
|
||||
*
|
||||
* \param filters Array of filters terminated with
|
||||
* .id == LZMA_VLI_UNKNOWN.
|
||||
*
|
||||
* \return Number of bytes of memory required for the given
|
||||
* filter chain when decoding. If an error occurs,
|
||||
* for example due to unsupported filter chain,
|
||||
* UINT64_MAX is returned.
|
||||
*/
|
||||
extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters)
|
||||
lzma_nothrow lzma_attr_pure;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize raw encoder
|
||||
*
|
||||
* This function may be useful when implementing custom file formats.
|
||||
*
|
||||
* \param strm Pointer to properly prepared lzma_stream
|
||||
* \param filters Array of lzma_filter structures. The end of the
|
||||
* array must be marked with .id = LZMA_VLI_UNKNOWN.
|
||||
*
|
||||
* The `action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the
|
||||
* filter chain supports it), or LZMA_FINISH.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_raw_encoder(
|
||||
lzma_stream *strm, const lzma_filter *filters)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Initialize raw decoder
|
||||
*
|
||||
* The initialization of raw decoder goes similarly to raw encoder.
|
||||
*
|
||||
* The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
|
||||
* LZMA_FINISH is not required, it is supported just for convenience.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_raw_decoder(
|
||||
lzma_stream *strm, const lzma_filter *filters)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Update the filter chain in the encoder
|
||||
*
|
||||
* This function is for advanced users only. This function has two slightly
|
||||
* different purposes:
|
||||
*
|
||||
* - After LZMA_FULL_FLUSH when using Stream encoder: Set a new filter
|
||||
* chain, which will be used starting from the next Block.
|
||||
*
|
||||
* - After LZMA_SYNC_FLUSH using Raw, Block, or Stream encoder: Change
|
||||
* the filter-specific options in the middle of encoding. The actual
|
||||
* filters in the chain (Filter IDs) cannot be changed. In the future,
|
||||
* it might become possible to change the filter options without
|
||||
* using LZMA_SYNC_FLUSH.
|
||||
*
|
||||
* While rarely useful, this function may be called also when no data has
|
||||
* been compressed yet. In that case, this function will behave as if
|
||||
* LZMA_FULL_FLUSH (Stream encoder) or LZMA_SYNC_FLUSH (Raw or Block
|
||||
* encoder) had been used right before calling this function.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_MEMLIMIT_ERROR
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_filters_update(
|
||||
lzma_stream *strm, const lzma_filter *filters) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call raw encoder
|
||||
*
|
||||
* \param filters Array of lzma_filter structures. The end of the
|
||||
* array must be marked with .id = LZMA_VLI_UNKNOWN.
|
||||
* \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_OPTIONS_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_DATA_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note There is no function to calculate how big output buffer
|
||||
* would surely be big enough. (lzma_stream_buffer_bound()
|
||||
* works only for lzma_stream_buffer_encode(); raw encoder
|
||||
* won't necessarily meet that bound.)
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
|
||||
const lzma_filter *filters, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t in_size, uint8_t *out,
|
||||
size_t *out_pos, size_t out_size) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Single-call raw decoder
|
||||
*
|
||||
* \param filters Array of lzma_filter structures. The end of the
|
||||
* array must be marked with .id = LZMA_VLI_UNKNOWN.
|
||||
* \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].
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
|
||||
const lzma_filter *filters, 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;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the size of the Filter Properties field
|
||||
*
|
||||
* This function may be useful when implementing custom file formats
|
||||
* using the raw encoder and decoder.
|
||||
*
|
||||
* \param size Pointer to uint32_t to hold the size of the properties
|
||||
* \param filter Filter ID and options (the size of the properties may
|
||||
* vary depending on the options)
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note This function validates the Filter ID, but does not
|
||||
* necessarily validate the options. Thus, it is possible
|
||||
* that this returns LZMA_OK while the following call to
|
||||
* lzma_properties_encode() returns LZMA_OPTIONS_ERROR.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_properties_size(
|
||||
uint32_t *size, const lzma_filter *filter) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode the Filter Properties field
|
||||
*
|
||||
* \param filter Filter ID and options
|
||||
* \param props Buffer to hold the encoded options. The size of
|
||||
* buffer must have been already determined with
|
||||
* lzma_properties_size().
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*
|
||||
* \note Even this function won't validate more options than actually
|
||||
* necessary. Thus, it is possible that encoding the properties
|
||||
* succeeds but using the same options to initialize the encoder
|
||||
* will fail.
|
||||
*
|
||||
* \note If lzma_properties_size() indicated that the size
|
||||
* of the Filter Properties field is zero, calling
|
||||
* lzma_properties_encode() is not required, but it
|
||||
* won't do any harm either.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_properties_encode(
|
||||
const lzma_filter *filter, uint8_t *props) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode the Filter Properties field
|
||||
*
|
||||
* \param filter filter->id must have been set to the correct
|
||||
* Filter ID. filter->options doesn't need to be
|
||||
* initialized (it's not freed by this function). The
|
||||
* decoded options will be stored to filter->options.
|
||||
* filter->options is set to NULL if there are no
|
||||
* properties or if an error occurs.
|
||||
* \param allocator Custom memory allocator used to allocate the
|
||||
* options. Set to NULL to use the default malloc(),
|
||||
* and in case of an error, also free().
|
||||
* \param props Input buffer containing the properties.
|
||||
* \param props_size Size of the properties. This must be the exact
|
||||
* size; giving too much or too little input will
|
||||
* return LZMA_OPTIONS_ERROR.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_properties_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
const uint8_t *props, size_t props_size) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Calculate encoded size of a Filter Flags field
|
||||
*
|
||||
* Knowing the size of Filter Flags is useful to know when allocating
|
||||
* memory to hold the encoded Filter Flags.
|
||||
*
|
||||
* \param size Pointer to integer to hold the calculated size
|
||||
* \param filter Filter ID and associated options whose encoded
|
||||
* size is to be calculated
|
||||
*
|
||||
* \return - LZMA_OK: *size set successfully. Note that this doesn't
|
||||
* guarantee that filter->options is valid, thus
|
||||
* lzma_filter_flags_encode() may still fail.
|
||||
* - LZMA_OPTIONS_ERROR: Unknown Filter ID or unsupported options.
|
||||
* - LZMA_PROG_ERROR: Invalid options
|
||||
*
|
||||
* \note If you need to calculate size of List of Filter Flags,
|
||||
* you need to loop over every lzma_filter entry.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_filter_flags_size(
|
||||
uint32_t *size, const lzma_filter *filter)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode Filter Flags into given buffer
|
||||
*
|
||||
* In contrast to some functions, this doesn't allocate the needed buffer.
|
||||
* This is due to how this function is used internally by liblzma.
|
||||
*
|
||||
* \param filter Filter ID and options to be encoded
|
||||
* \param out Beginning of the output buffer
|
||||
* \param out_pos out[*out_pos] is the next write position. This
|
||||
* is updated by the encoder.
|
||||
* \param out_size out[out_size] is the first byte to not write.
|
||||
*
|
||||
* \return - LZMA_OK: Encoding was successful.
|
||||
* - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
|
||||
* - LZMA_PROG_ERROR: Invalid options or not enough output
|
||||
* buffer space (you should have checked it with
|
||||
* lzma_filter_flags_size()).
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filter,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode Filter Flags from given buffer
|
||||
*
|
||||
* The decoded result is stored into *filter. The old value of
|
||||
* filter->options is not free()d.
|
||||
*
|
||||
* \return - LZMA_OK
|
||||
* - LZMA_OPTIONS_ERROR
|
||||
* - LZMA_MEM_ERROR
|
||||
* - LZMA_PROG_ERROR
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
|
||||
lzma_filter *filter, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_nothrow lzma_attr_warn_unused_result;
|
|
@ -1,55 +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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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;
|
|
@ -1,687 +0,0 @@
|
|||
/**
|
||||
* \file lzma/index.h
|
||||
* \brief Handling of .xz Index and related information
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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(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, 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, 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, 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, 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, lzma_allocator *allocator,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_nothrow;
|
|
@ -1,112 +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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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, 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, lzma_allocator *allocator)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add a new Record to an Index hash
|
||||
*
|
||||
* \param index 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,425 +0,0 @@
|
|||
/**
|
||||
* \file lzma/lzma.h
|
||||
* \brief LZMA1 and LZMA2 filters
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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 LZMA1 Filter ID
|
||||
*
|
||||
* LZMA1 is the very same thing as what was called just LZMA in LZMA Utils,
|
||||
* 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from
|
||||
* accidentally using LZMA when they actually want LZMA2.
|
||||
*
|
||||
* LZMA1 shouldn't be used for new applications unless you _really_ know
|
||||
* what you are doing. LZMA2 is almost always a better choice.
|
||||
*/
|
||||
#define LZMA_FILTER_LZMA1 LZMA_VLI_C(0x4000000000000001)
|
||||
|
||||
/**
|
||||
* \brief LZMA2 Filter ID
|
||||
*
|
||||
* Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds
|
||||
* support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion
|
||||
* when trying to compress uncompressible data), possibility to change
|
||||
* lc/lp/pb in the middle of encoding, and some other internal improvements.
|
||||
*/
|
||||
#define LZMA_FILTER_LZMA2 LZMA_VLI_C(0x21)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Match finders
|
||||
*
|
||||
* Match finder has major effect on both speed and compression ratio.
|
||||
* Usually hash chains are faster than binary trees.
|
||||
*
|
||||
* If you will use LZMA_SYNC_FLUSH often, the hash chains may be a better
|
||||
* choice, because binary trees get much higher compression ratio penalty
|
||||
* with LZMA_SYNC_FLUSH.
|
||||
*
|
||||
* The memory usage formulas are only rough estimates, which are closest to
|
||||
* reality when dict_size is a power of two. The formulas are more complex
|
||||
* in reality, and can also change a little between liblzma versions. Use
|
||||
* lzma_raw_encoder_memusage() to get more accurate estimate of memory usage.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_MF_HC3 = 0x03,
|
||||
/**<
|
||||
* \brief Hash Chain with 2- and 3-byte hashing
|
||||
*
|
||||
* Minimum nice_len: 3
|
||||
*
|
||||
* Memory usage:
|
||||
* - dict_size <= 16 MiB: dict_size * 7.5
|
||||
* - dict_size > 16 MiB: dict_size * 5.5 + 64 MiB
|
||||
*/
|
||||
|
||||
LZMA_MF_HC4 = 0x04,
|
||||
/**<
|
||||
* \brief Hash Chain with 2-, 3-, and 4-byte hashing
|
||||
*
|
||||
* Minimum nice_len: 4
|
||||
*
|
||||
* Memory usage:
|
||||
* - dict_size <= 32 MiB: dict_size * 7.5
|
||||
* - dict_size > 32 MiB: dict_size * 6.5
|
||||
*/
|
||||
|
||||
LZMA_MF_BT2 = 0x12,
|
||||
/**<
|
||||
* \brief Binary Tree with 2-byte hashing
|
||||
*
|
||||
* Minimum nice_len: 2
|
||||
*
|
||||
* Memory usage: dict_size * 9.5
|
||||
*/
|
||||
|
||||
LZMA_MF_BT3 = 0x13,
|
||||
/**<
|
||||
* \brief Binary Tree with 2- and 3-byte hashing
|
||||
*
|
||||
* Minimum nice_len: 3
|
||||
*
|
||||
* Memory usage:
|
||||
* - dict_size <= 16 MiB: dict_size * 11.5
|
||||
* - dict_size > 16 MiB: dict_size * 9.5 + 64 MiB
|
||||
*/
|
||||
|
||||
LZMA_MF_BT4 = 0x14
|
||||
/**<
|
||||
* \brief Binary Tree with 2-, 3-, and 4-byte hashing
|
||||
*
|
||||
* Minimum nice_len: 4
|
||||
*
|
||||
* Memory usage:
|
||||
* - dict_size <= 32 MiB: dict_size * 11.5
|
||||
* - dict_size > 32 MiB: dict_size * 10.5
|
||||
*/
|
||||
} lzma_match_finder;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if given match finder is supported
|
||||
*
|
||||
* Return true if the given match finder is supported by this liblzma build.
|
||||
* Otherwise false is returned. It is safe to call this with a value that
|
||||
* isn't listed in lzma_match_finder enumeration; the return value will be
|
||||
* false.
|
||||
*
|
||||
* There is no way to list which match finders are available in this
|
||||
* particular liblzma version and build. It would be useless, because
|
||||
* a new match finder, which the application developer wasn't aware,
|
||||
* could require giving additional options to the encoder that the older
|
||||
* match finders don't need.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_mf_is_supported(lzma_match_finder match_finder)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compression modes
|
||||
*
|
||||
* This selects the function used to analyze the data produced by the match
|
||||
* finder.
|
||||
*/
|
||||
typedef enum {
|
||||
LZMA_MODE_FAST = 1,
|
||||
/**<
|
||||
* \brief Fast compression
|
||||
*
|
||||
* Fast mode is usually at its best when combined with
|
||||
* a hash chain match finder.
|
||||
*/
|
||||
|
||||
LZMA_MODE_NORMAL = 2
|
||||
/**<
|
||||
* \brief Normal compression
|
||||
*
|
||||
* This is usually notably slower than fast mode. Use this
|
||||
* together with binary tree match finders to expose the
|
||||
* full potential of the LZMA1 or LZMA2 encoder.
|
||||
*/
|
||||
} lzma_mode;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Test if given compression mode is supported
|
||||
*
|
||||
* Return true if the given compression mode is supported by this liblzma
|
||||
* build. Otherwise false is returned. It is safe to call this with a value
|
||||
* that isn't listed in lzma_mode enumeration; the return value will be false.
|
||||
*
|
||||
* There is no way to list which modes are available in this particular
|
||||
* liblzma version and build. It would be useless, because a new compression
|
||||
* mode, which the application developer wasn't aware, could require giving
|
||||
* additional options to the encoder that the older modes don't need.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_mode_is_supported(lzma_mode mode)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Options specific to the LZMA1 and LZMA2 filters
|
||||
*
|
||||
* Since LZMA1 and LZMA2 share most of the code, it's simplest to share
|
||||
* the options structure too. For encoding, all but the reserved variables
|
||||
* need to be initialized unless specifically mentioned otherwise.
|
||||
* lzma_lzma_preset() can be used to get a good starting point.
|
||||
*
|
||||
* For raw decoding, both LZMA1 and LZMA2 need dict_size, preset_dict, and
|
||||
* preset_dict_size (if preset_dict != NULL). LZMA1 needs also lc, lp, and pb.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Dictionary size in bytes
|
||||
*
|
||||
* Dictionary size indicates how many bytes of the recently processed
|
||||
* uncompressed data is kept in memory. One method to reduce size of
|
||||
* the uncompressed data is to store distance-length pairs, which
|
||||
* indicate what data to repeat from the dictionary buffer. Thus,
|
||||
* the bigger the dictionary, the better the compression ratio
|
||||
* usually is.
|
||||
*
|
||||
* Maximum size of the dictionary depends on multiple things:
|
||||
* - Memory usage limit
|
||||
* - Available address space (not a problem on 64-bit systems)
|
||||
* - Selected match finder (encoder only)
|
||||
*
|
||||
* Currently the maximum dictionary size for encoding is 1.5 GiB
|
||||
* (i.e. (UINT32_C(1) << 30) + (UINT32_C(1) << 29)) even on 64-bit
|
||||
* systems for certain match finder implementation reasons. In the
|
||||
* future, there may be match finders that support bigger
|
||||
* dictionaries.
|
||||
*
|
||||
* Decoder already supports dictionaries up to 4 GiB - 1 B (i.e.
|
||||
* UINT32_MAX), so increasing the maximum dictionary size of the
|
||||
* encoder won't cause problems for old decoders.
|
||||
*
|
||||
* Because extremely small dictionaries sizes would have unneeded
|
||||
* overhead in the decoder, the minimum dictionary size is 4096 bytes.
|
||||
*
|
||||
* \note When decoding, too big dictionary does no other harm
|
||||
* than wasting memory.
|
||||
*/
|
||||
uint32_t dict_size;
|
||||
# define LZMA_DICT_SIZE_MIN UINT32_C(4096)
|
||||
# define LZMA_DICT_SIZE_DEFAULT (UINT32_C(1) << 23)
|
||||
|
||||
/**
|
||||
* \brief Pointer to an initial dictionary
|
||||
*
|
||||
* It is possible to initialize the LZ77 history window using
|
||||
* a preset dictionary. It is useful when compressing many
|
||||
* similar, relatively small chunks of data independently from
|
||||
* each other. The preset dictionary should contain typical
|
||||
* strings that occur in the files being compressed. The most
|
||||
* probable strings should be near the end of the preset dictionary.
|
||||
*
|
||||
* This feature should be used only in special situations. For
|
||||
* now, it works correctly only with raw encoding and decoding.
|
||||
* Currently none of the container formats supported by
|
||||
* liblzma allow preset dictionary when decoding, thus if
|
||||
* you create a .xz or .lzma file with preset dictionary, it
|
||||
* cannot be decoded with the regular decoder functions. In the
|
||||
* future, the .xz format will likely get support for preset
|
||||
* dictionary though.
|
||||
*/
|
||||
const uint8_t *preset_dict;
|
||||
|
||||
/**
|
||||
* \brief Size of the preset dictionary
|
||||
*
|
||||
* Specifies the size of the preset dictionary. If the size is
|
||||
* bigger than dict_size, only the last dict_size bytes are
|
||||
* processed.
|
||||
*
|
||||
* This variable is read only when preset_dict is not NULL.
|
||||
* If preset_dict is not NULL but preset_dict_size is zero,
|
||||
* no preset dictionary is used (identical to only setting
|
||||
* preset_dict to NULL).
|
||||
*/
|
||||
uint32_t preset_dict_size;
|
||||
|
||||
/**
|
||||
* \brief Number of literal context bits
|
||||
*
|
||||
* How many of the highest bits of the previous uncompressed
|
||||
* eight-bit byte (also known as `literal') are taken into
|
||||
* account when predicting the bits of the next literal.
|
||||
*
|
||||
* E.g. in typical English text, an upper-case letter is
|
||||
* often followed by a lower-case letter, and a lower-case
|
||||
* letter is usually followed by another lower-case letter.
|
||||
* In the US-ASCII character set, the highest three bits are 010
|
||||
* for upper-case letters and 011 for lower-case letters.
|
||||
* When lc is at least 3, the literal coding can take advantage of
|
||||
* this property in the uncompressed data.
|
||||
*
|
||||
* There is a limit that applies to literal context bits and literal
|
||||
* position bits together: lc + lp <= 4. Without this limit the
|
||||
* decoding could become very slow, which could have security related
|
||||
* results in some cases like email servers doing virus scanning.
|
||||
* This limit also simplifies the internal implementation in liblzma.
|
||||
*
|
||||
* There may be LZMA1 streams that have lc + lp > 4 (maximum possible
|
||||
* lc would be 8). It is not possible to decode such streams with
|
||||
* liblzma.
|
||||
*/
|
||||
uint32_t lc;
|
||||
# define LZMA_LCLP_MIN 0
|
||||
# define LZMA_LCLP_MAX 4
|
||||
# define LZMA_LC_DEFAULT 3
|
||||
|
||||
/**
|
||||
* \brief Number of literal position bits
|
||||
*
|
||||
* lp affects what kind of alignment in the uncompressed data is
|
||||
* assumed when encoding literals. A literal is a single 8-bit byte.
|
||||
* See pb below for more information about alignment.
|
||||
*/
|
||||
uint32_t lp;
|
||||
# define LZMA_LP_DEFAULT 0
|
||||
|
||||
/**
|
||||
* \brief Number of position bits
|
||||
*
|
||||
* pb affects what kind of alignment in the uncompressed data is
|
||||
* assumed in general. The default means four-byte alignment
|
||||
* (2^ pb =2^2=4), which is often a good choice when there's
|
||||
* no better guess.
|
||||
*
|
||||
* When the aligment is known, setting pb accordingly may reduce
|
||||
* the file size a little. E.g. with text files having one-byte
|
||||
* alignment (US-ASCII, ISO-8859-*, UTF-8), setting pb=0 can
|
||||
* improve compression slightly. For UTF-16 text, pb=1 is a good
|
||||
* choice. If the alignment is an odd number like 3 bytes, pb=0
|
||||
* might be the best choice.
|
||||
*
|
||||
* Even though the assumed alignment can be adjusted with pb and
|
||||
* lp, LZMA1 and LZMA2 still slightly favor 16-byte alignment.
|
||||
* It might be worth taking into account when designing file formats
|
||||
* that are likely to be often compressed with LZMA1 or LZMA2.
|
||||
*/
|
||||
uint32_t pb;
|
||||
# define LZMA_PB_MIN 0
|
||||
# define LZMA_PB_MAX 4
|
||||
# define LZMA_PB_DEFAULT 2
|
||||
|
||||
/** Compression mode */
|
||||
lzma_mode mode;
|
||||
|
||||
/**
|
||||
* \brief Nice length of a match
|
||||
*
|
||||
* This determines how many bytes the encoder compares from the match
|
||||
* candidates when looking for the best match. Once a match of at
|
||||
* least nice_len bytes long is found, the encoder stops looking for
|
||||
* better candidates and encodes the match. (Naturally, if the found
|
||||
* match is actually longer than nice_len, the actual length is
|
||||
* encoded; it's not truncated to nice_len.)
|
||||
*
|
||||
* Bigger values usually increase the compression ratio and
|
||||
* compression time. For most files, 32 to 128 is a good value,
|
||||
* which gives very good compression ratio at good speed.
|
||||
*
|
||||
* The exact minimum value depends on the match finder. The maximum
|
||||
* is 273, which is the maximum length of a match that LZMA1 and
|
||||
* LZMA2 can encode.
|
||||
*/
|
||||
uint32_t nice_len;
|
||||
|
||||
/** Match finder ID */
|
||||
lzma_match_finder mf;
|
||||
|
||||
/**
|
||||
* \brief Maximum search depth in the match finder
|
||||
*
|
||||
* For every input byte, match finder searches through the hash chain
|
||||
* or binary tree in a loop, each iteration going one step deeper in
|
||||
* the chain or tree. The searching stops if
|
||||
* - a match of at least nice_len bytes long is found;
|
||||
* - all match candidates from the hash chain or binary tree have
|
||||
* been checked; or
|
||||
* - maximum search depth is reached.
|
||||
*
|
||||
* Maximum search depth is needed to prevent the match finder from
|
||||
* wasting too much time in case there are lots of short match
|
||||
* candidates. On the other hand, stopping the search before all
|
||||
* candidates have been checked can reduce compression ratio.
|
||||
*
|
||||
* Setting depth to zero tells liblzma to use an automatic default
|
||||
* value, that depends on the selected match finder and nice_len.
|
||||
* The default is in the range [4, 200] or so (it may vary between
|
||||
* liblzma versions).
|
||||
*
|
||||
* Using a bigger depth value than the default can increase
|
||||
* compression ratio in some cases. There is no strict maximum value,
|
||||
* but high values (thousands or millions) should be used with care:
|
||||
* the encoder could remain fast enough with typical input, but
|
||||
* malicious input could cause the match finder to slow down
|
||||
* dramatically, possibly creating a denial of service attack.
|
||||
*/
|
||||
uint32_t depth;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
uint32_t reserved_int1;
|
||||
uint32_t reserved_int2;
|
||||
uint32_t reserved_int3;
|
||||
uint32_t reserved_int4;
|
||||
uint32_t reserved_int5;
|
||||
uint32_t reserved_int6;
|
||||
uint32_t reserved_int7;
|
||||
uint32_t reserved_int8;
|
||||
lzma_reserved_enum reserved_enum1;
|
||||
lzma_reserved_enum reserved_enum2;
|
||||
lzma_reserved_enum reserved_enum3;
|
||||
lzma_reserved_enum reserved_enum4;
|
||||
void *reserved_ptr1;
|
||||
void *reserved_ptr2;
|
||||
|
||||
} lzma_options_lzma;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set a compression preset to lzma_options_lzma structure
|
||||
*
|
||||
* 0 is the fastest and 9 is the slowest. These match the switches -0 .. -9
|
||||
* of the xz command line tool. In addition, it is possible to bitwise-or
|
||||
* flags to the preset. Currently only LZMA_PRESET_EXTREME is supported.
|
||||
* The flags are defined in container.h, because the flags are used also
|
||||
* with lzma_easy_encoder().
|
||||
*
|
||||
* The preset values are subject to changes between liblzma versions.
|
||||
*
|
||||
* This function is available only if LZMA1 or LZMA2 encoder has been enabled
|
||||
* when building liblzma.
|
||||
*
|
||||
* \return On success, false is returned. If the preset is not
|
||||
* supported, true is returned.
|
||||
*/
|
||||
extern LZMA_API(lzma_bool) lzma_lzma_preset(
|
||||
lzma_options_lzma *options, uint32_t preset) lzma_nothrow;
|
|
@ -1,228 +0,0 @@
|
|||
/**
|
||||
* \file lzma/stream_flags.h
|
||||
* \brief .xz Stream Header and Stream Footer encoder and decoder
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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;
|
|
@ -1,126 +0,0 @@
|
|||
/**
|
||||
* \file lzma/version.h
|
||||
* \brief Version number
|
||||
*/
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
||||
/*
|
||||
* Version number split into components
|
||||
*/
|
||||
#define LZMA_VERSION_MAJOR 5
|
||||
#define LZMA_VERSION_MINOR 0
|
||||
#define LZMA_VERSION_PATCH 3
|
||||
#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_STABLE
|
||||
|
||||
#ifndef LZMA_VERSION_COMMIT
|
||||
# define LZMA_VERSION_COMMIT ""
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Map symbolic stability levels to integers.
|
||||
*/
|
||||
#define LZMA_VERSION_STABILITY_ALPHA 0
|
||||
#define LZMA_VERSION_STABILITY_BETA 1
|
||||
#define LZMA_VERSION_STABILITY_STABLE 2
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compile-time version number
|
||||
*
|
||||
* The version number is of format xyyyzzzs where
|
||||
* - x = major
|
||||
* - yyy = minor
|
||||
* - zzz = revision
|
||||
* - s indicates stability: 0 = alpha, 1 = beta, 2 = stable
|
||||
*
|
||||
* The same xyyyzzz triplet is never reused with different stability levels.
|
||||
* For example, if 5.1.0alpha has been released, there will never be 5.1.0beta
|
||||
* or 5.1.0 stable.
|
||||
*
|
||||
* \note The version number of liblzma has nothing to with
|
||||
* the version number of Igor Pavlov's LZMA SDK.
|
||||
*/
|
||||
#define LZMA_VERSION (LZMA_VERSION_MAJOR * UINT32_C(10000000) \
|
||||
+ LZMA_VERSION_MINOR * UINT32_C(10000) \
|
||||
+ LZMA_VERSION_PATCH * UINT32_C(10) \
|
||||
+ LZMA_VERSION_STABILITY)
|
||||
|
||||
|
||||
/*
|
||||
* Macros to construct the compile-time version string
|
||||
*/
|
||||
#if LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_ALPHA
|
||||
# define LZMA_VERSION_STABILITY_STRING "alpha"
|
||||
#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_BETA
|
||||
# define LZMA_VERSION_STABILITY_STRING "beta"
|
||||
#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_STABLE
|
||||
# define LZMA_VERSION_STABILITY_STRING ""
|
||||
#else
|
||||
# error Incorrect LZMA_VERSION_STABILITY
|
||||
#endif
|
||||
|
||||
#define LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit) \
|
||||
#major "." #minor "." #patch stability commit
|
||||
|
||||
#define LZMA_VERSION_STRING_C(major, minor, patch, stability, commit) \
|
||||
LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compile-time version as a string
|
||||
*
|
||||
* This can be for example "4.999.5alpha", "4.999.8beta", or "5.0.0" (stable
|
||||
* versions don't have any "stable" suffix). In future, a snapshot built
|
||||
* from source code repository may include an additional suffix, for example
|
||||
* "4.999.8beta-21-g1d92". The commit ID won't be available in numeric form
|
||||
* in LZMA_VERSION macro.
|
||||
*/
|
||||
#define LZMA_VERSION_STRING LZMA_VERSION_STRING_C( \
|
||||
LZMA_VERSION_MAJOR, LZMA_VERSION_MINOR, \
|
||||
LZMA_VERSION_PATCH, LZMA_VERSION_STABILITY_STRING, \
|
||||
LZMA_VERSION_COMMIT)
|
||||
|
||||
|
||||
/* #ifndef is needed for use with windres (MinGW or Cygwin). */
|
||||
#ifndef LZMA_H_INTERNAL_RC
|
||||
|
||||
/**
|
||||
* \brief Run-time version number as an integer
|
||||
*
|
||||
* Return the value of LZMA_VERSION macro at the compile time of liblzma.
|
||||
* This allows the application to compare if it was built against the same,
|
||||
* older, or newer version of liblzma that is currently running.
|
||||
*/
|
||||
extern LZMA_API(uint32_t) lzma_version_number(void)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Run-time version as a string
|
||||
*
|
||||
* This function may be useful if you want to display which version of
|
||||
* liblzma your application is currently using.
|
||||
*/
|
||||
extern LZMA_API(const char *) lzma_version_string(void)
|
||||
lzma_nothrow lzma_attr_const;
|
||||
|
||||
#endif
|
|
@ -1,171 +0,0 @@
|
|||
/**
|
||||
* \file lzma/vli.h
|
||||
* \brief Variable-length integer handling
|
||||
*
|
||||
* In the .xz format, most integers are encoded in a variable-length
|
||||
* representation, which is sometimes called little endian base-128 encoding.
|
||||
* This saves space when smaller values are more likely than bigger values.
|
||||
*
|
||||
* The encoding scheme encodes seven bits to every byte, using minimum
|
||||
* number of bytes required to represent the given value. Encodings that use
|
||||
* non-minimum number of bytes are invalid, thus every integer has exactly
|
||||
* one encoded representation. The maximum number of bits in a VLI is 63,
|
||||
* thus the vli argument must be less than or equal to UINT64_MAX / 2. You
|
||||
* should use LZMA_VLI_MAX for clarity.
|
||||
*/
|
||||
|
||||
/*
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Igor Pavlov
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
* 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 Maximum supported value of a variable-length integer
|
||||
*/
|
||||
#define LZMA_VLI_MAX (UINT64_MAX / 2)
|
||||
|
||||
/**
|
||||
* \brief VLI value to denote that the value is unknown
|
||||
*/
|
||||
#define LZMA_VLI_UNKNOWN UINT64_MAX
|
||||
|
||||
/**
|
||||
* \brief Maximum supported encoded length of variable length integers
|
||||
*/
|
||||
#define LZMA_VLI_BYTES_MAX 9
|
||||
|
||||
/**
|
||||
* \brief VLI constant suffix
|
||||
*/
|
||||
#define LZMA_VLI_C(n) UINT64_C(n)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Variable-length integer type
|
||||
*
|
||||
* Valid VLI values are in the range [0, LZMA_VLI_MAX]. Unknown value is
|
||||
* indicated with LZMA_VLI_UNKNOWN, which is the maximum value of the
|
||||
* underlaying integer type.
|
||||
*
|
||||
* lzma_vli will be uint64_t for the foreseeable future. If a bigger size
|
||||
* is needed in the future, it is guaranteed that 2 * LZMA_VLI_MAX will
|
||||
* not overflow lzma_vli. This simplifies integer overflow detection.
|
||||
*/
|
||||
typedef uint64_t lzma_vli;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Validate a variable-length integer
|
||||
*
|
||||
* This is useful to test that application has given acceptable values
|
||||
* for example in the uncompressed_size and compressed_size variables.
|
||||
*
|
||||
* \return True if the integer is representable as VLI or if it
|
||||
* indicates unknown value.
|
||||
*/
|
||||
#define lzma_vli_is_valid(vli) \
|
||||
((vli) <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN)
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode a variable-length integer
|
||||
*
|
||||
* This function has two modes: single-call and multi-call. Single-call mode
|
||||
* encodes the whole integer at once; it is an error if the output buffer is
|
||||
* too small. Multi-call mode saves the position in *vli_pos, and thus it is
|
||||
* possible to continue encoding if the buffer becomes full before the whole
|
||||
* integer has been encoded.
|
||||
*
|
||||
* \param vli Integer to be encoded
|
||||
* \param vli_pos How many VLI-encoded bytes have already been written
|
||||
* out. When starting to encode a new integer in
|
||||
* multi-call mode, *vli_pos must be set to zero.
|
||||
* To use single-call encoding, set vli_pos to NULL.
|
||||
* \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].
|
||||
*
|
||||
* \return Slightly different return values are used in multi-call and
|
||||
* single-call modes.
|
||||
*
|
||||
* Single-call (vli_pos == NULL):
|
||||
* - LZMA_OK: Integer successfully encoded.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane. This can be due
|
||||
* to too little output space; single-call mode doesn't use
|
||||
* LZMA_BUF_ERROR, since the application should have checked
|
||||
* the encoded size with lzma_vli_size().
|
||||
*
|
||||
* Multi-call (vli_pos != NULL):
|
||||
* - LZMA_OK: So far all OK, but the integer is not
|
||||
* completely written out yet.
|
||||
* - LZMA_STREAM_END: Integer successfully encoded.
|
||||
* - LZMA_BUF_ERROR: No output space was provided.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
|
||||
uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Decode a variable-length integer
|
||||
*
|
||||
* Like lzma_vli_encode(), this function has single-call and multi-call modes.
|
||||
*
|
||||
* \param vli Pointer to decoded integer. The decoder will
|
||||
* initialize it to zero when *vli_pos == 0, so
|
||||
* application isn't required to initialize *vli.
|
||||
* \param vli_pos How many bytes have already been decoded. When
|
||||
* starting to decode a new integer in multi-call
|
||||
* mode, *vli_pos must be initialized to zero. To
|
||||
* use single-call decoding, set vli_pos to NULL.
|
||||
* \param in Beginning of the input buffer
|
||||
* \param in_pos The next byte will be read from in[*in_pos].
|
||||
* \param in_size Size of the input buffer; the first byte that
|
||||
* won't be read is in[in_size].
|
||||
*
|
||||
* \return Slightly different return values are used in multi-call and
|
||||
* single-call modes.
|
||||
*
|
||||
* Single-call (vli_pos == NULL):
|
||||
* - LZMA_OK: Integer successfully decoded.
|
||||
* - LZMA_DATA_ERROR: Integer is corrupt. This includes hitting
|
||||
* the end of the input buffer before the whole integer was
|
||||
* decoded; providing no input at all will use LZMA_DATA_ERROR.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane.
|
||||
*
|
||||
* Multi-call (vli_pos != NULL):
|
||||
* - LZMA_OK: So far all OK, but the integer is not
|
||||
* completely decoded yet.
|
||||
* - LZMA_STREAM_END: Integer successfully decoded.
|
||||
* - LZMA_DATA_ERROR: Integer is corrupt.
|
||||
* - LZMA_BUF_ERROR: No input was provided.
|
||||
* - LZMA_PROG_ERROR: Arguments are not sane.
|
||||
*/
|
||||
extern LZMA_API(lzma_ret) lzma_vli_decode(lzma_vli *vli, size_t *vli_pos,
|
||||
const uint8_t *in, size_t *in_pos, size_t in_size)
|
||||
lzma_nothrow;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Get the number of bytes required to encode a VLI
|
||||
*
|
||||
* \return Number of bytes on success (1-9). If vli isn't valid,
|
||||
* zero is returned.
|
||||
*/
|
||||
extern LZMA_API(uint32_t) lzma_vli_size(lzma_vli vli)
|
||||
lzma_nothrow lzma_attr_pure;
|
|
@ -1,190 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file check.c
|
||||
/// \brief Single API to access different integrity checks
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "check.h"
|
||||
|
||||
#if __MOJOSETUP__ // use our crc32 to keep size down.
|
||||
void MojoCrc32_append(uint32_t *_crc, const uint8_t *buf, uint32_t len);
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
|
||||
{
|
||||
crc ^= 0xFFFFFFFF;
|
||||
MojoCrc32_append(&crc, buf, (uint32_t) size);
|
||||
return crc ^ 0xFFFFFFFF;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern LZMA_API(lzma_bool)
|
||||
lzma_check_is_supported(lzma_check type)
|
||||
{
|
||||
if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
|
||||
return false;
|
||||
|
||||
static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
|
||||
true, // LZMA_CHECK_NONE
|
||||
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
false, // Reserved
|
||||
};
|
||||
|
||||
return available_checks[(unsigned int)(type)];
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_check_size(lzma_check type)
|
||||
{
|
||||
if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
|
||||
return UINT32_MAX;
|
||||
|
||||
// See file-format.txt section 2.1.1.2.
|
||||
static const uint8_t check_sizes[LZMA_CHECK_ID_MAX + 1] = {
|
||||
0,
|
||||
4, 4, 4,
|
||||
8, 8, 8,
|
||||
16, 16, 16,
|
||||
32, 32, 32,
|
||||
64, 64, 64
|
||||
};
|
||||
|
||||
return check_sizes[(unsigned int)(type)];
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_check_init(lzma_check_state *check, lzma_check type)
|
||||
{
|
||||
switch (type) {
|
||||
case LZMA_CHECK_NONE:
|
||||
break;
|
||||
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
case LZMA_CHECK_CRC32:
|
||||
check->state.crc32 = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
case LZMA_CHECK_CRC64:
|
||||
check->state.crc64 = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
case LZMA_CHECK_SHA256:
|
||||
lzma_sha256_init(check);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_check_update(lzma_check_state *check, lzma_check type,
|
||||
const uint8_t *buf, size_t size)
|
||||
{
|
||||
switch (type) {
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
case LZMA_CHECK_CRC32:
|
||||
check->state.crc32 = lzma_crc32(buf, size, check->state.crc32);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
case LZMA_CHECK_CRC64:
|
||||
check->state.crc64 = lzma_crc64(buf, size, check->state.crc64);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
case LZMA_CHECK_SHA256:
|
||||
lzma_sha256_update(buf, size, check);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_check_finish(lzma_check_state *check, lzma_check type)
|
||||
{
|
||||
switch (type) {
|
||||
#ifdef HAVE_CHECK_CRC32
|
||||
case LZMA_CHECK_CRC32:
|
||||
check->buffer.u32[0] = conv32le(check->state.crc32);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_CRC64
|
||||
case LZMA_CHECK_CRC64:
|
||||
check->buffer.u64[0] = conv64le(check->state.crc64);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHECK_SHA256
|
||||
case LZMA_CHECK_SHA256:
|
||||
lzma_sha256_finish(check);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file check.h
|
||||
/// \brief Internal API to different integrity check functions
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_CHECK_H
|
||||
#define LZMA_CHECK_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if __MOJOSETUP__
|
||||
#define HAVE_CHECK_CRC32 1
|
||||
#endif
|
||||
|
||||
// Index hashing needs the best possible hash function (preferably
|
||||
// a cryptographic hash) for maximum reliability.
|
||||
#if defined(HAVE_CHECK_SHA256)
|
||||
# define LZMA_CHECK_BEST LZMA_CHECK_SHA256
|
||||
#elif defined(HAVE_CHECK_CRC64)
|
||||
# define LZMA_CHECK_BEST LZMA_CHECK_CRC64
|
||||
#else
|
||||
# define LZMA_CHECK_BEST LZMA_CHECK_CRC32
|
||||
#endif
|
||||
|
||||
|
||||
/// \brief Structure to hold internal state of the check being calculated
|
||||
///
|
||||
/// \note This is not in the public API because this structure may
|
||||
/// change in future if new integrity check algorithms are added.
|
||||
typedef struct {
|
||||
/// Buffer to hold the final result and a temporary buffer for SHA256.
|
||||
union {
|
||||
uint8_t u8[64];
|
||||
uint32_t u32[16];
|
||||
uint64_t u64[8];
|
||||
} buffer;
|
||||
|
||||
/// Check-specific data
|
||||
union {
|
||||
uint32_t crc32;
|
||||
uint64_t crc64;
|
||||
|
||||
struct {
|
||||
/// Internal state
|
||||
uint32_t state[8];
|
||||
|
||||
/// Size of the message excluding padding
|
||||
uint64_t size;
|
||||
} sha256;
|
||||
} state;
|
||||
|
||||
} lzma_check_state;
|
||||
|
||||
|
||||
/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
|
||||
/// the array two-dimensional.
|
||||
#ifdef HAVE_SMALL
|
||||
extern uint32_t lzma_crc32_table[1][256];
|
||||
extern void lzma_crc32_init(void);
|
||||
#else
|
||||
extern const uint32_t lzma_crc32_table[8][256];
|
||||
extern const uint64_t lzma_crc64_table[4][256];
|
||||
#endif
|
||||
|
||||
|
||||
/// \brief Initialize *check depending on type
|
||||
///
|
||||
/// \return LZMA_OK on success. LZMA_UNSUPPORTED_CHECK if the type is not
|
||||
/// supported by the current version or build of liblzma.
|
||||
/// LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX.
|
||||
extern void lzma_check_init(lzma_check_state *check, lzma_check type);
|
||||
|
||||
/// Update the check state
|
||||
extern void lzma_check_update(lzma_check_state *check, lzma_check type,
|
||||
const uint8_t *buf, size_t size);
|
||||
|
||||
/// Finish the check calculation and store the result to check->buffer.u8.
|
||||
extern void lzma_check_finish(lzma_check_state *check, lzma_check type);
|
||||
|
||||
|
||||
/// Prepare SHA-256 state for new input.
|
||||
extern void lzma_sha256_init(lzma_check_state *check);
|
||||
|
||||
/// Update the SHA-256 hash state
|
||||
extern void lzma_sha256_update(
|
||||
const uint8_t *buf, size_t size, lzma_check_state *check);
|
||||
|
||||
/// Finish the SHA-256 calculation and store the result to check->buffer.u8.
|
||||
extern void lzma_sha256_finish(lzma_check_state *check);
|
||||
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file crc_macros.h
|
||||
/// \brief Some endian-dependent macros for CRC32 and CRC64
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define A(x) ((x) >> 24)
|
||||
# define B(x) (((x) >> 16) & 0xFF)
|
||||
# define C(x) (((x) >> 8) & 0xFF)
|
||||
# define D(x) ((x) & 0xFF)
|
||||
|
||||
# define S8(x) ((x) << 8)
|
||||
# define S32(x) ((x) << 32)
|
||||
|
||||
#else
|
||||
# define A(x) ((x) & 0xFF)
|
||||
# define B(x) (((x) >> 8) & 0xFF)
|
||||
# define C(x) (((x) >> 16) & 0xFF)
|
||||
# define D(x) ((x) >> 24)
|
||||
|
||||
# define S8(x) ((x) >> 8)
|
||||
# define S32(x) ((x) >> 32)
|
||||
#endif
|
|
@ -1,237 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file alone_decoder.c
|
||||
/// \brief Decoder for LZMA_Alone files
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "alone_decoder.h"
|
||||
#include "lzma_decoder.h"
|
||||
#include "lz_decoder.h"
|
||||
|
||||
|
||||
struct lzma_coder_s {
|
||||
lzma_next_coder next;
|
||||
|
||||
enum {
|
||||
SEQ_PROPERTIES,
|
||||
SEQ_DICTIONARY_SIZE,
|
||||
SEQ_UNCOMPRESSED_SIZE,
|
||||
SEQ_CODER_INIT,
|
||||
SEQ_CODE,
|
||||
} sequence;
|
||||
|
||||
/// Position in the header fields
|
||||
size_t pos;
|
||||
|
||||
/// Uncompressed size decoded from the header
|
||||
lzma_vli uncompressed_size;
|
||||
|
||||
/// Memory usage limit
|
||||
uint64_t memlimit;
|
||||
|
||||
/// Amount of memory actually needed (only an estimate)
|
||||
uint64_t memusage;
|
||||
|
||||
/// Options decoded from the header needed to initialize
|
||||
/// the LZMA decoder
|
||||
lzma_options_lzma options;
|
||||
};
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_decode(lzma_coder *coder,
|
||||
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)
|
||||
{
|
||||
while (*out_pos < out_size
|
||||
&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
|
||||
switch (coder->sequence) {
|
||||
case SEQ_PROPERTIES:
|
||||
if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
|
||||
return LZMA_FORMAT_ERROR;
|
||||
|
||||
coder->sequence = SEQ_DICTIONARY_SIZE;
|
||||
++*in_pos;
|
||||
break;
|
||||
|
||||
case SEQ_DICTIONARY_SIZE:
|
||||
coder->options.dict_size
|
||||
|= (size_t)(in[*in_pos]) << (coder->pos * 8);
|
||||
|
||||
if (++coder->pos == 4) {
|
||||
if (coder->options.dict_size != UINT32_MAX) {
|
||||
// A hack to ditch tons of false positives:
|
||||
// We allow only dictionary sizes that are
|
||||
// 2^n or 2^n + 2^(n-1). LZMA_Alone created
|
||||
// only files with 2^n, but accepts any
|
||||
// dictionary size. If someone complains, this
|
||||
// will be reconsidered.
|
||||
uint32_t d = coder->options.dict_size - 1;
|
||||
d |= d >> 2;
|
||||
d |= d >> 3;
|
||||
d |= d >> 4;
|
||||
d |= d >> 8;
|
||||
d |= d >> 16;
|
||||
++d;
|
||||
|
||||
if (d != coder->options.dict_size)
|
||||
return LZMA_FORMAT_ERROR;
|
||||
}
|
||||
|
||||
coder->pos = 0;
|
||||
coder->sequence = SEQ_UNCOMPRESSED_SIZE;
|
||||
}
|
||||
|
||||
++*in_pos;
|
||||
break;
|
||||
|
||||
case SEQ_UNCOMPRESSED_SIZE:
|
||||
coder->uncompressed_size
|
||||
|= (lzma_vli)(in[*in_pos]) << (coder->pos * 8);
|
||||
++*in_pos;
|
||||
if (++coder->pos < 8)
|
||||
break;
|
||||
|
||||
// Another hack to ditch false positives: Assume that
|
||||
// if the uncompressed size is known, it must be less
|
||||
// than 256 GiB. Again, if someone complains, this
|
||||
// will be reconsidered.
|
||||
if (coder->uncompressed_size != LZMA_VLI_UNKNOWN
|
||||
&& coder->uncompressed_size
|
||||
>= (LZMA_VLI_C(1) << 38))
|
||||
return LZMA_FORMAT_ERROR;
|
||||
|
||||
// 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;
|
||||
|
||||
// Fall through
|
||||
|
||||
case SEQ_CODER_INIT: {
|
||||
if (coder->memusage > coder->memlimit)
|
||||
return LZMA_MEMLIMIT_ERROR;
|
||||
|
||||
lzma_filter_info filters[2] = {
|
||||
{
|
||||
.init = &lzma_lzma_decoder_init,
|
||||
.options = &coder->options,
|
||||
}, {
|
||||
.init = NULL,
|
||||
}
|
||||
};
|
||||
|
||||
const lzma_ret ret = lzma_next_filter_init(&coder->next,
|
||||
allocator, filters);
|
||||
if (ret != LZMA_OK)
|
||||
return ret;
|
||||
|
||||
// Use a hack to set the uncompressed size.
|
||||
lzma_lz_decoder_uncompressed(coder->next.coder,
|
||||
coder->uncompressed_size);
|
||||
|
||||
coder->sequence = SEQ_CODE;
|
||||
break;
|
||||
}
|
||||
|
||||
case SEQ_CODE: {
|
||||
return coder->next.code(coder->next.coder,
|
||||
allocator, in, in_pos, in_size,
|
||||
out, out_pos, out_size, action);
|
||||
}
|
||||
|
||||
default:
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
|
||||
{
|
||||
lzma_next_end(&coder->next, allocator);
|
||||
lzma_free(coder, allocator);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static lzma_ret
|
||||
alone_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_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
uint64_t memlimit)
|
||||
{
|
||||
lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator);
|
||||
|
||||
if (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 = &alone_decode;
|
||||
next->end = &alone_decoder_end;
|
||||
next->memconfig = &alone_decoder_memconfig;
|
||||
next->coder->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
next->coder->sequence = SEQ_PROPERTIES;
|
||||
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;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
|
||||
{
|
||||
lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit);
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = true;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = true;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file alone_decoder.h
|
||||
/// \brief Decoder for LZMA_Alone files
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_ALONE_DECODER_H
|
||||
#define LZMA_ALONE_DECODER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
extern lzma_ret lzma_alone_decoder_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, uint64_t memlimit);
|
||||
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_buffer_decoder.c
|
||||
/// \brief Single-call .xz Block decoder
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
|
||||
// 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, 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,247 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_decoder.c
|
||||
/// \brief Decodes .xz Blocks
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
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, 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;
|
||||
|
||||
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;
|
||||
|
||||
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 (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, 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, 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);
|
||||
|
||||
// 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,27 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_decoder.h
|
||||
/// \brief Decodes .xz Blocks
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,
|
||||
lzma_allocator *allocator, lzma_block *block);
|
||||
|
||||
#endif
|
|
@ -1,135 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_header_decoder.c
|
||||
/// \brief Decodes Block Header from .xz files
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, 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.
|
||||
#if __MOJOSETUP__
|
||||
size_t i;
|
||||
for (i = 0; i < LZMA_FILTERS_MAX; ++i) {
|
||||
#else
|
||||
for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
|
||||
#endif
|
||||
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,
|
||||
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.
|
||||
#if __MOJOSETUP__
|
||||
size_t i;
|
||||
for (i = 0; i <= LZMA_FILTERS_MAX; ++i) {
|
||||
#else
|
||||
for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
|
||||
#endif
|
||||
block->filters[i].id = LZMA_VLI_UNKNOWN;
|
||||
block->filters[i].options = NULL;
|
||||
}
|
||||
|
||||
// Always zero for now.
|
||||
block->version = 0;
|
||||
|
||||
// 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;
|
||||
#if __MOJOSETUP__
|
||||
for (i = 0; i < filter_count; ++i) {
|
||||
#else
|
||||
for (size_t i = 0; i < filter_count; ++i) {
|
||||
#endif
|
||||
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,95 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file block_header.c
|
||||
/// \brief Utility functions to handle lzma_block
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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 != 0
|
||||
|| 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;
|
||||
}
|
|
@ -1,393 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file common.h
|
||||
/// \brief Common functions needed in many places in liblzma
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/////////////
|
||||
// Version //
|
||||
/////////////
|
||||
|
||||
extern LZMA_API(uint32_t)
|
||||
lzma_version_number(void)
|
||||
{
|
||||
return LZMA_VERSION;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(const char *)
|
||||
lzma_version_string(void)
|
||||
{
|
||||
return LZMA_VERSION_STRING;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////
|
||||
// Memory allocation //
|
||||
///////////////////////
|
||||
|
||||
extern void * lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
|
||||
lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
{
|
||||
// Some malloc() variants return NULL if called with size == 0.
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
|
||||
void *ptr;
|
||||
|
||||
if (allocator != NULL && allocator->alloc != NULL)
|
||||
ptr = allocator->alloc(allocator->opaque, 1, size);
|
||||
else
|
||||
ptr = malloc(size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_free(void *ptr, lzma_allocator *allocator)
|
||||
{
|
||||
if (allocator != NULL && allocator->free != NULL)
|
||||
allocator->free(allocator->opaque, ptr);
|
||||
else
|
||||
free(ptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//////////
|
||||
// Misc //
|
||||
//////////
|
||||
|
||||
extern size_t
|
||||
lzma_bufcpy(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)
|
||||
{
|
||||
const size_t in_avail = in_size - *in_pos;
|
||||
const size_t out_avail = out_size - *out_pos;
|
||||
const size_t copy_size = my_min(in_avail, out_avail);
|
||||
|
||||
memcpy(out + *out_pos, in + *in_pos, copy_size);
|
||||
|
||||
*in_pos += copy_size;
|
||||
*out_pos += copy_size;
|
||||
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters)
|
||||
{
|
||||
lzma_next_coder_init(filters[0].init, next, allocator);
|
||||
next->id = filters[0].id;
|
||||
return filters[0].init == NULL
|
||||
? LZMA_OK : filters[0].init(next, allocator, filters);
|
||||
}
|
||||
|
||||
|
||||
extern lzma_ret
|
||||
lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *reversed_filters)
|
||||
{
|
||||
// Check that the application isn't trying to change the Filter ID.
|
||||
// End of filters is indicated with LZMA_VLI_UNKNOWN in both
|
||||
// reversed_filters[0].id and next->id.
|
||||
if (reversed_filters[0].id != next->id)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (reversed_filters[0].id == LZMA_VLI_UNKNOWN)
|
||||
return LZMA_OK;
|
||||
|
||||
assert(next->update != NULL);
|
||||
return next->update(next->coder, allocator, NULL, reversed_filters);
|
||||
}
|
||||
|
||||
|
||||
extern void
|
||||
lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
|
||||
{
|
||||
if (next->init != (uintptr_t)(NULL)) {
|
||||
// To avoid tiny end functions that simply call
|
||||
// lzma_free(coder, allocator), we allow leaving next->end
|
||||
// NULL and call lzma_free() here.
|
||||
if (next->end != NULL)
|
||||
next->end(next->coder, allocator);
|
||||
else
|
||||
lzma_free(next->coder, allocator);
|
||||
|
||||
// Reset the variables so the we don't accidentally think
|
||||
// that it is an already initialized coder.
|
||||
*next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// External to internal API wrapper //
|
||||
//////////////////////////////////////
|
||||
|
||||
extern lzma_ret
|
||||
lzma_strm_init(lzma_stream *strm)
|
||||
{
|
||||
if (strm == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (strm->internal == NULL) {
|
||||
strm->internal = lzma_alloc(sizeof(lzma_internal),
|
||||
strm->allocator);
|
||||
if (strm->internal == NULL)
|
||||
return LZMA_MEM_ERROR;
|
||||
|
||||
strm->internal->next = LZMA_NEXT_CODER_INIT;
|
||||
}
|
||||
|
||||
strm->internal->supported_actions[LZMA_RUN] = false;
|
||||
strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false;
|
||||
strm->internal->supported_actions[LZMA_FULL_FLUSH] = false;
|
||||
strm->internal->supported_actions[LZMA_FINISH] = false;
|
||||
strm->internal->sequence = ISEQ_RUN;
|
||||
strm->internal->allow_buf_error = false;
|
||||
|
||||
strm->total_in = 0;
|
||||
strm->total_out = 0;
|
||||
|
||||
return LZMA_OK;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_code(lzma_stream *strm, lzma_action action)
|
||||
{
|
||||
// Sanity checks
|
||||
if ((strm->next_in == NULL && strm->avail_in != 0)
|
||||
|| (strm->next_out == NULL && strm->avail_out != 0)
|
||||
|| strm->internal == NULL
|
||||
|| strm->internal->next.code == NULL
|
||||
|| (unsigned int)(action) > LZMA_FINISH
|
||||
|| !strm->internal->supported_actions[action])
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
// Check if unsupported members have been set to non-zero or non-NULL,
|
||||
// which would indicate that some new feature is wanted.
|
||||
if (strm->reserved_ptr1 != NULL
|
||||
|| strm->reserved_ptr2 != NULL
|
||||
|| strm->reserved_ptr3 != NULL
|
||||
|| strm->reserved_ptr4 != NULL
|
||||
|| strm->reserved_int1 != 0
|
||||
|| strm->reserved_int2 != 0
|
||||
|| strm->reserved_int3 != 0
|
||||
|| strm->reserved_int4 != 0
|
||||
|| strm->reserved_enum1 != LZMA_RESERVED_ENUM
|
||||
|| strm->reserved_enum2 != LZMA_RESERVED_ENUM)
|
||||
return LZMA_OPTIONS_ERROR;
|
||||
|
||||
switch (strm->internal->sequence) {
|
||||
case ISEQ_RUN:
|
||||
switch (action) {
|
||||
case LZMA_RUN:
|
||||
break;
|
||||
|
||||
case LZMA_SYNC_FLUSH:
|
||||
strm->internal->sequence = ISEQ_SYNC_FLUSH;
|
||||
break;
|
||||
|
||||
case LZMA_FULL_FLUSH:
|
||||
strm->internal->sequence = ISEQ_FULL_FLUSH;
|
||||
break;
|
||||
|
||||
case LZMA_FINISH:
|
||||
strm->internal->sequence = ISEQ_FINISH;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ISEQ_SYNC_FLUSH:
|
||||
// The same action must be used until we return
|
||||
// LZMA_STREAM_END, and the amount of input must not change.
|
||||
if (action != LZMA_SYNC_FLUSH
|
||||
|| strm->internal->avail_in != strm->avail_in)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
case ISEQ_FULL_FLUSH:
|
||||
if (action != LZMA_FULL_FLUSH
|
||||
|| strm->internal->avail_in != strm->avail_in)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
case ISEQ_FINISH:
|
||||
if (action != LZMA_FINISH
|
||||
|| strm->internal->avail_in != strm->avail_in)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
break;
|
||||
|
||||
case ISEQ_END:
|
||||
return LZMA_STREAM_END;
|
||||
|
||||
case ISEQ_ERROR:
|
||||
default:
|
||||
return LZMA_PROG_ERROR;
|
||||
}
|
||||
|
||||
size_t in_pos = 0;
|
||||
size_t out_pos = 0;
|
||||
lzma_ret ret = strm->internal->next.code(
|
||||
strm->internal->next.coder, strm->allocator,
|
||||
strm->next_in, &in_pos, strm->avail_in,
|
||||
strm->next_out, &out_pos, strm->avail_out, action);
|
||||
|
||||
strm->next_in += in_pos;
|
||||
strm->avail_in -= in_pos;
|
||||
strm->total_in += in_pos;
|
||||
|
||||
strm->next_out += out_pos;
|
||||
strm->avail_out -= out_pos;
|
||||
strm->total_out += out_pos;
|
||||
|
||||
strm->internal->avail_in = strm->avail_in;
|
||||
|
||||
switch (ret) {
|
||||
case LZMA_OK:
|
||||
// Don't return LZMA_BUF_ERROR when it happens the first time.
|
||||
// This is to avoid returning LZMA_BUF_ERROR when avail_out
|
||||
// was zero but still there was no more data left to written
|
||||
// to next_out.
|
||||
if (out_pos == 0 && in_pos == 0) {
|
||||
if (strm->internal->allow_buf_error)
|
||||
ret = LZMA_BUF_ERROR;
|
||||
else
|
||||
strm->internal->allow_buf_error = true;
|
||||
} else {
|
||||
strm->internal->allow_buf_error = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case LZMA_STREAM_END:
|
||||
if (strm->internal->sequence == ISEQ_SYNC_FLUSH
|
||||
|| strm->internal->sequence == ISEQ_FULL_FLUSH)
|
||||
strm->internal->sequence = ISEQ_RUN;
|
||||
else
|
||||
strm->internal->sequence = ISEQ_END;
|
||||
|
||||
// Fall through
|
||||
|
||||
case LZMA_NO_CHECK:
|
||||
case LZMA_UNSUPPORTED_CHECK:
|
||||
case LZMA_GET_CHECK:
|
||||
case LZMA_MEMLIMIT_ERROR:
|
||||
// Something else than LZMA_OK, but not a fatal error,
|
||||
// that is, coding may be continued (except if ISEQ_END).
|
||||
strm->internal->allow_buf_error = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
// All the other errors are fatal; coding cannot be continued.
|
||||
assert(ret != LZMA_BUF_ERROR);
|
||||
strm->internal->sequence = ISEQ_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(void)
|
||||
lzma_end(lzma_stream *strm)
|
||||
{
|
||||
if (strm != NULL && strm->internal != NULL) {
|
||||
lzma_next_end(&strm->internal->next, strm->allocator);
|
||||
lzma_free(strm->internal, strm->allocator);
|
||||
strm->internal = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_check)
|
||||
lzma_get_check(const lzma_stream *strm)
|
||||
{
|
||||
// Return LZMA_CHECK_NONE if we cannot know the check type.
|
||||
// It's a bug in the application if this happens.
|
||||
if (strm->internal->next.get_check == NULL)
|
||||
return LZMA_CHECK_NONE;
|
||||
|
||||
return strm->internal->next.get_check(strm->internal->next.coder);
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_memusage(const lzma_stream *strm)
|
||||
{
|
||||
uint64_t memusage;
|
||||
uint64_t old_memlimit;
|
||||
|
||||
if (strm == NULL || strm->internal == NULL
|
||||
|| strm->internal->next.memconfig == NULL
|
||||
|| strm->internal->next.memconfig(
|
||||
strm->internal->next.coder,
|
||||
&memusage, &old_memlimit, 0) != LZMA_OK)
|
||||
return 0;
|
||||
|
||||
return memusage;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(uint64_t)
|
||||
lzma_memlimit_get(const lzma_stream *strm)
|
||||
{
|
||||
uint64_t old_memlimit;
|
||||
uint64_t memusage;
|
||||
|
||||
if (strm == NULL || strm->internal == NULL
|
||||
|| strm->internal->next.memconfig == NULL
|
||||
|| strm->internal->next.memconfig(
|
||||
strm->internal->next.coder,
|
||||
&memusage, &old_memlimit, 0) != LZMA_OK)
|
||||
return 0;
|
||||
|
||||
return old_memlimit;
|
||||
}
|
||||
|
||||
|
||||
extern LZMA_API(lzma_ret)
|
||||
lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
|
||||
{
|
||||
// Dummy variables to simplify memconfig functions
|
||||
uint64_t old_memlimit;
|
||||
uint64_t memusage;
|
||||
|
||||
if (strm == NULL || strm->internal == NULL
|
||||
|| strm->internal->next.memconfig == NULL)
|
||||
return LZMA_PROG_ERROR;
|
||||
|
||||
if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
|
||||
return LZMA_MEMLIMIT_ERROR;
|
||||
|
||||
return strm->internal->next.memconfig(strm->internal->next.coder,
|
||||
&memusage, &old_memlimit, new_memlimit);
|
||||
}
|
|
@ -1,301 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file common.h
|
||||
/// \brief Definitions common to the whole liblzma library
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_COMMON_H
|
||||
#define LZMA_COMMON_H
|
||||
|
||||
#if __MOJOSETUP__
|
||||
#define HAVE_DECODER_LZMA1 1
|
||||
#define HAVE_DECODER_LZMA2 1
|
||||
#define HAVE_DECODER_X86 1
|
||||
#define HAVE_DECODER_POWERPC 1
|
||||
#define HAVE_DECODER_IA64 1
|
||||
#define HAVE_DECODER_ARM 1
|
||||
#define HAVE_DECODER_ARMTHUMB 1
|
||||
#define HAVE_DECODER_SPARC 1
|
||||
#define HAVE_DECODER_DELTA 1
|
||||
#endif
|
||||
|
||||
#include "sysdefs.h"
|
||||
#include "mythread.h"
|
||||
#include "tuklib_integer.h"
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# ifdef DLL_EXPORT
|
||||
# define LZMA_API_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define LZMA_API_EXPORT
|
||||
# endif
|
||||
// Don't use ifdef or defined() below.
|
||||
#elif HAVE_VISIBILITY
|
||||
# define LZMA_API_EXPORT __attribute__((__visibility__("default")))
|
||||
#else
|
||||
# define LZMA_API_EXPORT
|
||||
#endif
|
||||
|
||||
#define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
|
||||
|
||||
#include "lzma.h"
|
||||
|
||||
// These allow helping the compiler in some often-executed branches, whose
|
||||
// result is almost always the same.
|
||||
#ifdef __GNUC__
|
||||
# define likely(expr) __builtin_expect(expr, true)
|
||||
# define unlikely(expr) __builtin_expect(expr, false)
|
||||
#else
|
||||
# define likely(expr) (expr)
|
||||
# define unlikely(expr) (expr)
|
||||
#endif
|
||||
|
||||
|
||||
/// Size of temporary buffers needed in some filters
|
||||
#define LZMA_BUFFER_SIZE 4096
|
||||
|
||||
|
||||
/// Starting value for memory usage estimates. Instead of calculating size
|
||||
/// of _every_ structure and taking into account malloc() overhead etc., we
|
||||
/// add a base size to all memory usage estimates. It's not very accurate
|
||||
/// but should be easily good enough.
|
||||
#define LZMA_MEMUSAGE_BASE (UINT64_C(1) << 15)
|
||||
|
||||
/// Start of internal Filter ID space. These IDs must never be used
|
||||
/// in Streams.
|
||||
#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
|
||||
|
||||
|
||||
/// Supported flags that can be passed to lzma_stream_decoder()
|
||||
/// or lzma_auto_decoder().
|
||||
#define LZMA_SUPPORTED_FLAGS \
|
||||
( LZMA_TELL_NO_CHECK \
|
||||
| LZMA_TELL_UNSUPPORTED_CHECK \
|
||||
| LZMA_TELL_ANY_CHECK \
|
||||
| LZMA_CONCATENATED )
|
||||
|
||||
|
||||
/// 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;
|
||||
|
||||
|
||||
/// Type of a function used to initialize a filter encoder or decoder
|
||||
typedef lzma_ret (*lzma_init_function)(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter_info *filters);
|
||||
|
||||
/// Type of a function to do some kind of coding work (filters, Stream,
|
||||
/// Block encoders/decoders etc.). Some special coders use don't use both
|
||||
/// input and output buffers, but for simplicity they still use this same
|
||||
/// function prototype.
|
||||
typedef lzma_ret (*lzma_code_function)(
|
||||
lzma_coder *coder, 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);
|
||||
|
||||
/// Type of a function to free the memory allocated for the coder
|
||||
typedef void (*lzma_end_function)(
|
||||
lzma_coder *coder, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Raw coder validates and converts an array of lzma_filter structures to
|
||||
/// an array of lzma_filter_info structures. This array is used with
|
||||
/// lzma_next_filter_init to initialize the filter chain.
|
||||
struct lzma_filter_info_s {
|
||||
/// Filter ID. This is used only by the encoder
|
||||
/// with lzma_filters_update().
|
||||
lzma_vli id;
|
||||
|
||||
/// Pointer to function used to initialize the filter.
|
||||
/// This is NULL to indicate end of array.
|
||||
lzma_init_function init;
|
||||
|
||||
/// Pointer to filter's options structure
|
||||
void *options;
|
||||
};
|
||||
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
|
||||
/// point to a filter coder.
|
||||
lzma_vli id;
|
||||
|
||||
/// "Pointer" to init function. This is never called here.
|
||||
/// We need only to detect if we are initializing a coder
|
||||
/// that was allocated earlier. See lzma_next_coder_init and
|
||||
/// lzma_next_strm_init macros in this file.
|
||||
uintptr_t init;
|
||||
|
||||
/// Pointer to function to do the actual coding
|
||||
lzma_code_function code;
|
||||
|
||||
/// Pointer to function to free lzma_next_coder.coder. This can
|
||||
/// be NULL; in that case, lzma_free is called to free
|
||||
/// lzma_next_coder.coder.
|
||||
lzma_end_function end;
|
||||
|
||||
/// 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);
|
||||
|
||||
/// 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,
|
||||
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, lzma_allocator *allocator,
|
||||
const lzma_filter *filters,
|
||||
const lzma_filter *reversed_filters);
|
||||
};
|
||||
|
||||
|
||||
/// Macro to initialize lzma_next_coder structure
|
||||
#define LZMA_NEXT_CODER_INIT \
|
||||
(lzma_next_coder){ \
|
||||
.coder = NULL, \
|
||||
.init = (uintptr_t)(NULL), \
|
||||
.id = LZMA_VLI_UNKNOWN, \
|
||||
.code = NULL, \
|
||||
.end = NULL, \
|
||||
.get_check = NULL, \
|
||||
.memconfig = NULL, \
|
||||
.update = NULL, \
|
||||
}
|
||||
|
||||
|
||||
/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to
|
||||
/// this is stored in lzma_stream.
|
||||
struct lzma_internal_s {
|
||||
/// The actual coder that should do something useful
|
||||
lzma_next_coder next;
|
||||
|
||||
/// Track the state of the coder. This is used to validate arguments
|
||||
/// so that the actual coders can rely on e.g. that LZMA_SYNC_FLUSH
|
||||
/// is used on every call to lzma_code until next.code has returned
|
||||
/// LZMA_STREAM_END.
|
||||
enum {
|
||||
ISEQ_RUN,
|
||||
ISEQ_SYNC_FLUSH,
|
||||
ISEQ_FULL_FLUSH,
|
||||
ISEQ_FINISH,
|
||||
ISEQ_END,
|
||||
ISEQ_ERROR,
|
||||
} sequence;
|
||||
|
||||
/// A copy of lzma_stream avail_in. This is used to verify that the
|
||||
/// amount of input doesn't change once e.g. LZMA_FINISH has been
|
||||
/// used.
|
||||
size_t avail_in;
|
||||
|
||||
/// Indicates which lzma_action values are allowed by next.code.
|
||||
bool supported_actions[4];
|
||||
|
||||
/// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
|
||||
/// made (no input consumed and no output produced by next.code).
|
||||
bool allow_buf_error;
|
||||
};
|
||||
|
||||
|
||||
/// Allocates memory
|
||||
extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
|
||||
lzma_attribute((__malloc__)) lzma_attr_alloc_size(1);
|
||||
|
||||
/// Frees memory
|
||||
extern void lzma_free(void *ptr, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Allocates strm->internal if it is NULL, and initializes *strm and
|
||||
/// strm->internal. This function is only called via lzma_next_strm_init macro.
|
||||
extern lzma_ret lzma_strm_init(lzma_stream *strm);
|
||||
|
||||
/// Initializes the next filter in the chain, if any. This takes care of
|
||||
/// freeing the memory of previously initialized filter if it is different
|
||||
/// than the filter being initialized now. This way the actual filter
|
||||
/// initialization functions don't need to use lzma_next_coder_init macro.
|
||||
extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
|
||||
lzma_allocator *allocator, const lzma_filter_info *filters);
|
||||
|
||||
/// Update the next filter in the chain, if any. This checks that
|
||||
/// the application is not trying to change the Filter IDs.
|
||||
extern lzma_ret lzma_next_filter_update(
|
||||
lzma_next_coder *next, lzma_allocator *allocator,
|
||||
const lzma_filter *reversed_filters);
|
||||
|
||||
/// Frees the memory allocated for next->coder either using next->end or,
|
||||
/// if next->end is NULL, using lzma_free.
|
||||
extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
|
||||
|
||||
|
||||
/// Copy as much data as possible from in[] to out[] and update *in_pos
|
||||
/// and *out_pos accordingly. Returns the number of bytes copied.
|
||||
extern size_t lzma_bufcpy(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);
|
||||
|
||||
|
||||
/// \brief Return if expression doesn't evaluate to LZMA_OK
|
||||
///
|
||||
/// There are several situations where we want to return immediately
|
||||
/// with the value of expr if it isn't LZMA_OK. This macro shortens
|
||||
/// the code a little.
|
||||
#define return_if_error(expr) \
|
||||
do { \
|
||||
const lzma_ret ret_ = (expr); \
|
||||
if (ret_ != LZMA_OK) \
|
||||
return ret_; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/// If next isn't already initialized, free the previous coder. Then mark
|
||||
/// that next is _possibly_ initialized for the coder using this macro.
|
||||
/// "Possibly" means that if e.g. allocation of next->coder fails, the
|
||||
/// structure isn't actually initialized for this coder, but leaving
|
||||
/// next->init to func is still OK.
|
||||
#define lzma_next_coder_init(func, next, allocator) \
|
||||
do { \
|
||||
if ((uintptr_t)(func) != (next)->init) \
|
||||
lzma_next_end(next, allocator); \
|
||||
(next)->init = (uintptr_t)(func); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/// Initializes lzma_strm and calls func() to initialize strm->internal->next.
|
||||
/// (The function being called will use lzma_next_coder_init()). If
|
||||
/// initialization fails, memory that wasn't freed by func() is freed
|
||||
/// along strm->internal.
|
||||
#define lzma_next_strm_init(func, strm, ...) \
|
||||
do { \
|
||||
return_if_error(lzma_strm_init(strm)); \
|
||||
const lzma_ret ret_ = func(&(strm)->internal->next, \
|
||||
(strm)->allocator, __VA_ARGS__); \
|
||||
if (ret_ != LZMA_OK) { \
|
||||
lzma_end(strm); \
|
||||
return ret_; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_decoder_memusage.c
|
||||
/// \brief Decoder memory usage calculation to match easy encoder presets
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,32 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_preset.c
|
||||
/// \brief Preset handling for easy encoder and decoder
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,37 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file easy_preset.h
|
||||
/// \brief Preset handling for easy encoder and decoder
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,92 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_buffer_decoder.c
|
||||
/// \brief Single-call raw decoding
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, 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,354 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_common.c
|
||||
/// \brief Filter-specific stuff common for both encoder and decoder
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,
|
||||
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, 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 __MOJOSETUP__
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
if (is_encoder) {
|
||||
#if __MOJOSETUP__
|
||||
for (i = 0; i < count; ++i) {
|
||||
#else
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
#endif
|
||||
// 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 {
|
||||
#if __MOJOSETUP__
|
||||
for (i = 0; i < count; ++i) {
|
||||
#else
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
#endif
|
||||
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,53 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_common.c
|
||||
/// \brief Filter-specific stuff common for both encoder and decoder
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, 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,193 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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"
|
||||
#include "lzma2_decoder.h"
|
||||
#include "simple_decoder.h"
|
||||
#include "delta_decoder.h"
|
||||
|
||||
|
||||
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, 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)
|
||||
{
|
||||
#if __MOJOSETUP__
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAY_SIZE(decoders); ++i)
|
||||
#else
|
||||
for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
|
||||
#endif
|
||||
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, 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, 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,28 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_decoder.c
|
||||
/// \brief Filter ID mapping to filter-specific functions
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, lzma_allocator *allocator,
|
||||
const lzma_filter *options);
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file filter_flags_decoder.c
|
||||
/// \brief Decodes a Filter Flags field
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, 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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,78 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index.h
|
||||
/// \brief Handling of Index
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_INDEX_H
|
||||
#define LZMA_INDEX_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/// Minimum Unpadded Size
|
||||
#define UNPADDED_SIZE_MIN LZMA_VLI_C(5)
|
||||
|
||||
/// Maximum Unpadded Size
|
||||
#define UNPADDED_SIZE_MAX (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
|
||||
|
||||
|
||||
/// Get the size of the Index Padding field. This is needed by Index encoder
|
||||
/// and decoder, but applications should have no use for this.
|
||||
extern uint32_t lzma_index_padding_size(const lzma_index *i);
|
||||
|
||||
|
||||
/// Set for how many Records to allocate memory the next time
|
||||
/// lzma_index_append() needs to allocate space for a new Record.
|
||||
/// This is used only by the Index decoder.
|
||||
extern void lzma_index_prealloc(lzma_index *i, lzma_vli records);
|
||||
|
||||
|
||||
/// Round the variable-length integer to the next multiple of four.
|
||||
static inline lzma_vli
|
||||
vli_ceil4(lzma_vli vli)
|
||||
{
|
||||
assert(vli <= LZMA_VLI_MAX);
|
||||
return (vli + 3) & ~LZMA_VLI_C(3);
|
||||
}
|
||||
|
||||
|
||||
/// Calculate the size of the Index field excluding Index Padding
|
||||
static inline lzma_vli
|
||||
index_size_unpadded(lzma_vli count, lzma_vli index_list_size)
|
||||
{
|
||||
// Index Indicator + Number of Records + List of Records + CRC32
|
||||
return 1 + lzma_vli_size(count) + index_list_size + 4;
|
||||
}
|
||||
|
||||
|
||||
/// Calculate the size of the Index field including Index Padding
|
||||
static inline lzma_vli
|
||||
index_size(lzma_vli count, lzma_vli index_list_size)
|
||||
{
|
||||
return vli_ceil4(index_size_unpadded(count, index_list_size));
|
||||
}
|
||||
|
||||
|
||||
/// Calculate the total size of the Stream
|
||||
static inline lzma_vli
|
||||
index_stream_size(lzma_vli blocks_size,
|
||||
lzma_vli count, lzma_vli index_list_size)
|
||||
{
|
||||
return LZMA_STREAM_HEADER_SIZE + blocks_size
|
||||
+ index_size(count, index_list_size)
|
||||
+ LZMA_STREAM_HEADER_SIZE;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,350 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index_decoder.c
|
||||
/// \brief Decodes the Index field
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, 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, 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, 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, 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, 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,337 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file index_hash.c
|
||||
/// \brief Validates Index by using a hash function
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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, 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, 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,47 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file mythread.h
|
||||
/// \brief Wrappers for threads
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "sysdefs.h"
|
||||
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
# include <pthread.h>
|
||||
|
||||
# define mythread_once(func) \
|
||||
do { \
|
||||
static pthread_once_t once_ = PTHREAD_ONCE_INIT; \
|
||||
pthread_once(&once_, &func); \
|
||||
} while (0)
|
||||
|
||||
# define mythread_sigmask(how, set, oset) \
|
||||
pthread_sigmask(how, set, oset)
|
||||
|
||||
#else
|
||||
|
||||
# define mythread_once(func) \
|
||||
do { \
|
||||
static bool once_ = false; \
|
||||
if (!once_) { \
|
||||
func(); \
|
||||
once_ = true; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
# define mythread_sigmask(how, set, oset) \
|
||||
sigprocmask(how, set, oset)
|
||||
|
||||
#endif
|
|
@ -1,463 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_decoder.c
|
||||
/// \brief Decodes .xz Streams
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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 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, 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, 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 0 is currently the only possible version.
|
||||
coder->block_options.version = 0;
|
||||
|
||||
// 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));
|
||||
|
||||
// Check the memory usage limit.
|
||||
const uint64_t memusage = lzma_raw_decoder_memusage(filters);
|
||||
lzma_ret ret;
|
||||
#if __MOJOSETUP__
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
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.
|
||||
#if __MOJOSETUP__
|
||||
for (i = 0; i < LZMA_FILTERS_MAX; ++i)
|
||||
#else
|
||||
for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
|
||||
#endif
|
||||
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, 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, 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->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,26 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_decoder.h
|
||||
/// \brief Decodes .xz Streams
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,
|
||||
lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
|
||||
|
||||
#endif
|
|
@ -1,52 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_common.c
|
||||
/// \brief Common stuff for Stream flags coders
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,38 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_common.h
|
||||
/// \brief Common stuff for Stream flags coders
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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,87 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file stream_flags_decoder.c
|
||||
/// \brief Decodes Stream Header and Stream Footer from .xz files
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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,204 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file sysdefs.h
|
||||
/// \brief Common includes, definitions, system-specific things etc.
|
||||
///
|
||||
/// This file is used also by the lzma command line tool, that's why this
|
||||
/// file is separate from common.h.
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LZMA_SYSDEFS_H
|
||||
#define LZMA_SYSDEFS_H
|
||||
|
||||
#if __MOJOSETUP__
|
||||
#ifndef _MSC_VER
|
||||
#define HAVE_STDINT_H 1
|
||||
#endif
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_STDBOOL_H 1
|
||||
#endif
|
||||
|
||||
//////////////
|
||||
// Includes //
|
||||
//////////////
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
// Get standard-compliant stdio functions under MinGW and MinGW-w64.
|
||||
#ifdef __MINGW32__
|
||||
# define __USE_MINGW_ANSI_STDIO 1
|
||||
#endif
|
||||
|
||||
// size_t and NULL
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
// C99 says that inttypes.h always includes stdint.h, but some systems
|
||||
// don't do that, and require including stdint.h separately.
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The
|
||||
// limits are also used to figure out some macros missing from pre-C99 systems.
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
// Be more compatible with systems that have non-conforming inttypes.h.
|
||||
// We assume that int is 32-bit and that long is either 32-bit or 64-bit.
|
||||
// Full Autoconf test could be more correct, but this should work well enough.
|
||||
// Note that this duplicates some code from lzma.h, but this is better since
|
||||
// we can work without inttypes.h thanks to Autoconf tests.
|
||||
#ifndef UINT32_C
|
||||
# if UINT_MAX != 4294967295U
|
||||
# error UINT32_C is not defined and unsigned int is not 32-bit.
|
||||
# endif
|
||||
# define UINT32_C(n) n ## U
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
# define UINT32_MAX UINT32_C(4294967295)
|
||||
#endif
|
||||
#ifndef PRIu32
|
||||
# define PRIu32 "u"
|
||||
#endif
|
||||
#ifndef PRIx32
|
||||
# define PRIx32 "x"
|
||||
#endif
|
||||
#ifndef PRIX32
|
||||
# define PRIX32 "X"
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX == 4294967295UL
|
||||
# ifndef UINT64_C
|
||||
# define UINT64_C(n) n ## ULL
|
||||
# endif
|
||||
# ifndef PRIu64
|
||||
# define PRIu64 "llu"
|
||||
# endif
|
||||
# ifndef PRIx64
|
||||
# define PRIx64 "llx"
|
||||
# endif
|
||||
# ifndef PRIX64
|
||||
# define PRIX64 "llX"
|
||||
# endif
|
||||
#else
|
||||
# ifndef UINT64_C
|
||||
# define UINT64_C(n) n ## UL
|
||||
# endif
|
||||
# ifndef PRIu64
|
||||
# define PRIu64 "lu"
|
||||
# endif
|
||||
# ifndef PRIx64
|
||||
# define PRIx64 "lx"
|
||||
# endif
|
||||
# ifndef PRIX64
|
||||
# define PRIX64 "lX"
|
||||
# endif
|
||||
#endif
|
||||
#ifndef UINT64_MAX
|
||||
# define UINT64_MAX UINT64_C(18446744073709551615)
|
||||
#endif
|
||||
|
||||
// Interix has broken header files, which typedef size_t to unsigned long,
|
||||
// but a few lines later define SIZE_MAX to INT32_MAX.
|
||||
#ifdef __INTERIX
|
||||
# undef SIZE_MAX
|
||||
#endif
|
||||
|
||||
// The code currently assumes that size_t is either 32-bit or 64-bit.
|
||||
#ifndef SIZE_MAX
|
||||
# if SIZEOF_SIZE_T == 4
|
||||
# define SIZE_MAX UINT32_MAX
|
||||
# elif SIZEOF_SIZE_T == 8
|
||||
# define SIZE_MAX UINT64_MAX
|
||||
# else
|
||||
# error size_t is not 32-bit or 64-bit
|
||||
# endif
|
||||
#endif
|
||||
#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX
|
||||
# error size_t is not 32-bit or 64-bit
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
// Pre-C99 systems lack stdbool.h. All the code in LZMA Utils must be written
|
||||
// so that it works with fake bool type, for example:
|
||||
//
|
||||
// bool foo = (flags & 0x100) != 0;
|
||||
// bool bar = !!(flags & 0x100);
|
||||
//
|
||||
// This works with the real C99 bool but breaks with fake bool:
|
||||
//
|
||||
// bool baz = (flags & 0x100);
|
||||
//
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# if ! HAVE__BOOL
|
||||
typedef unsigned char _Bool;
|
||||
# endif
|
||||
# define bool _Bool
|
||||
# define false 0
|
||||
# define true 1
|
||||
# define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
// string.h should be enough but let's include strings.h and memory.h too if
|
||||
// they exists, since that shouldn't do any harm, but may improve portability.
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MEMORY_H
|
||||
# include <memory.h>
|
||||
#endif
|
||||
|
||||
|
||||
////////////
|
||||
// Macros //
|
||||
////////////
|
||||
|
||||
#undef memzero
|
||||
#define memzero(s, n) memset(s, 0, n)
|
||||
|
||||
// NOTE: Avoid using MIN() and MAX(), because even conditionally defining
|
||||
// those macros can cause some portability trouble, since on some systems
|
||||
// the system headers insist defining their own versions.
|
||||
#define my_min(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define my_max(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
|
||||
# define lzma_attr_alloc_size(x) __attribute__((__alloc_size__(x)))
|
||||
#else
|
||||
# define lzma_attr_alloc_size(x)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,76 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_common.h
|
||||
/// \brief Common definitions for tuklib modules
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Author: Lasse Collin
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_COMMON_H
|
||||
#define TUKLIB_COMMON_H
|
||||
|
||||
// The config file may be replaced by a package-specific file.
|
||||
// It should include at least stddef.h, inttypes.h, and limits.h.
|
||||
#include "tuklib_config.h"
|
||||
|
||||
// TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by
|
||||
// the tuklib modules. If you use a tuklib module in a library,
|
||||
// you should use TUKLIB_SYMBOL_PREFIX to make sure that there
|
||||
// are no symbol conflicts in case someone links your library
|
||||
// into application that also uses the same tuklib module.
|
||||
#ifndef TUKLIB_SYMBOL_PREFIX
|
||||
# define TUKLIB_SYMBOL_PREFIX
|
||||
#endif
|
||||
|
||||
#define TUKLIB_CAT_X(a, b) a ## b
|
||||
#define TUKLIB_CAT(a, b) TUKLIB_CAT_X(a, b)
|
||||
|
||||
#ifndef TUKLIB_SYMBOL
|
||||
# define TUKLIB_SYMBOL(sym) TUKLIB_CAT(TUKLIB_SYMBOL_PREFIX, sym)
|
||||
#endif
|
||||
|
||||
#ifndef TUKLIB_DECLS_BEGIN
|
||||
# ifdef __cplusplus
|
||||
# define TUKLIB_DECLS_BEGIN extern "C" {
|
||||
# else
|
||||
# define TUKLIB_DECLS_BEGIN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef TUKLIB_DECLS_END
|
||||
# ifdef __cplusplus
|
||||
# define TUKLIB_DECLS_END }
|
||||
# else
|
||||
# define TUKLIB_DECLS_END
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define TUKLIB_GNUC_REQ(major, minor) \
|
||||
((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \
|
||||
|| __GNUC__ > (major))
|
||||
#else
|
||||
# define TUKLIB_GNUC_REQ(major, minor) 0
|
||||
#endif
|
||||
|
||||
#if TUKLIB_GNUC_REQ(2, 5)
|
||||
# define tuklib_attr_noreturn __attribute__((__noreturn__))
|
||||
#else
|
||||
# define tuklib_attr_noreturn
|
||||
#endif
|
||||
|
||||
#if (defined(_WIN32) && !defined(__CYGWIN__)) \
|
||||
|| defined(__OS2__) || defined(__MSDOS__)
|
||||
# define TUKLIB_DOSLIKE 1
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "sysdefs.h"
|
||||
#else
|
||||
# include <stddef.h>
|
||||
# include <inttypes.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Joachim Henke
|
||||
// Public Domain
|
||||
//
|
|
@ -1,528 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file tuklib_integer.h
|
||||
/// \brief Various integer and bit operations
|
||||
///
|
||||
/// This file provides macros or functions to do some basic integer and bit
|
||||
/// operations.
|
||||
///
|
||||
/// Endianness related integer operations (XX = 16, 32, or 64; Y = b or l):
|
||||
/// - Byte swapping: bswapXX(num)
|
||||
/// - Byte order conversions to/from native: convXXYe(num)
|
||||
/// - Aligned reads: readXXYe(ptr)
|
||||
/// - Aligned writes: writeXXYe(ptr, num)
|
||||
/// - Unaligned reads (16/32-bit only): unaligned_readXXYe(ptr)
|
||||
/// - Unaligned writes (16/32-bit only): unaligned_writeXXYe(ptr, num)
|
||||
///
|
||||
/// Since they can macros, the arguments should have no side effects since
|
||||
/// they may be evaluated more than once.
|
||||
///
|
||||
/// \todo PowerPC and possibly some other architectures support
|
||||
/// byte swapping load and store instructions. This file
|
||||
/// doesn't take advantage of those instructions.
|
||||
///
|
||||
/// Bit scan operations for non-zero 32-bit integers:
|
||||
/// - Bit scan reverse (find highest non-zero bit): bsr32(num)
|
||||
/// - Count leading zeros: clz32(num)
|
||||
/// - Count trailing zeros: ctz32(num)
|
||||
/// - Bit scan forward (simply an alias for ctz32()): bsf32(num)
|
||||
///
|
||||
/// The above bit scan operations return 0-31. If num is zero,
|
||||
/// the result is undefined.
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin and Joachim Henke
|
||||
// Public Domain
|
||||
//
|
||||
|
||||
// Authors: Lasse Collin
|
||||
// Joachim Henke
|
||||
//
|
||||
// This file has been put into the public domain.
|
||||
// You can do whatever you want with this file.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TUKLIB_INTEGER_H
|
||||
#define TUKLIB_INTEGER_H
|
||||
|
||||
#include "tuklib_common.h"
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Operating system specific features //
|
||||
////////////////////////////////////////
|
||||
|
||||
#if defined(HAVE_BYTESWAP_H)
|
||||
// glibc, uClibc, dietlibc
|
||||
# include <byteswap.h>
|
||||
# ifdef HAVE_BSWAP_16
|
||||
# define bswap16(num) bswap_16(num)
|
||||
# endif
|
||||
# ifdef HAVE_BSWAP_32
|
||||
# define bswap32(num) bswap_32(num)
|
||||
# endif
|
||||
# ifdef HAVE_BSWAP_64
|
||||
# define bswap64(num) bswap_64(num)
|
||||
# endif
|
||||
|
||||
#elif defined(HAVE_SYS_ENDIAN_H)
|
||||
// *BSDs and Darwin
|
||||
# include <sys/endian.h>
|
||||
|
||||
#elif defined(HAVE_SYS_BYTEORDER_H)
|
||||
// Solaris
|
||||
# include <sys/byteorder.h>
|
||||
# ifdef BSWAP_16
|
||||
# define bswap16(num) BSWAP_16(num)
|
||||
# endif
|
||||
# ifdef BSWAP_32
|
||||
# define bswap32(num) BSWAP_32(num)
|
||||
# endif
|
||||
# ifdef BSWAP_64
|
||||
# define bswap64(num) BSWAP_64(num)
|
||||
# endif
|
||||
# ifdef BE_16
|
||||
# define conv16be(num) BE_16(num)
|
||||
# endif
|
||||
# ifdef BE_32
|
||||
# define conv32be(num) BE_32(num)
|
||||
# endif
|
||||
# ifdef BE_64
|
||||
# define conv64be(num) BE_64(num)
|
||||
# endif
|
||||
# ifdef LE_16
|
||||
# define conv16le(num) LE_16(num)
|
||||
# endif
|
||||
# ifdef LE_32
|
||||
# define conv32le(num) LE_32(num)
|
||||
# endif
|
||||
# ifdef LE_64
|
||||
# define conv64le(num) LE_64(num)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////
|
||||
// Byte swapping //
|
||||
///////////////////
|
||||
|
||||
#ifndef bswap16
|
||||
# define bswap16(num) \
|
||||
(((uint16_t)(num) << 8) | ((uint16_t)(num) >> 8))
|
||||
#endif
|
||||
|
||||
#ifndef bswap32
|
||||
# define bswap32(num) \
|
||||
( (((uint32_t)(num) << 24) ) \
|
||||
| (((uint32_t)(num) << 8) & UINT32_C(0x00FF0000)) \
|
||||
| (((uint32_t)(num) >> 8) & UINT32_C(0x0000FF00)) \
|
||||
| (((uint32_t)(num) >> 24) ) )
|
||||
#endif
|
||||
|
||||
#ifndef bswap64
|
||||
# define bswap64(num) \
|
||||
( (((uint64_t)(num) << 56) ) \
|
||||
| (((uint64_t)(num) << 40) & UINT64_C(0x00FF000000000000)) \
|
||||
| (((uint64_t)(num) << 24) & UINT64_C(0x0000FF0000000000)) \
|
||||
| (((uint64_t)(num) << 8) & UINT64_C(0x000000FF00000000)) \
|
||||
| (((uint64_t)(num) >> 8) & UINT64_C(0x00000000FF000000)) \
|
||||
| (((uint64_t)(num) >> 24) & UINT64_C(0x0000000000FF0000)) \
|
||||
| (((uint64_t)(num) >> 40) & UINT64_C(0x000000000000FF00)) \
|
||||
| (((uint64_t)(num) >> 56) ) )
|
||||
#endif
|
||||
|
||||
// Define conversion macros using the basic byte swapping macros.
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# ifndef conv16be
|
||||
# define conv16be(num) ((uint16_t)(num))
|
||||
# endif
|
||||
# ifndef conv32be
|
||||
# define conv32be(num) ((uint32_t)(num))
|
||||
# endif
|
||||
# ifndef conv64be
|
||||
# define conv64be(num) ((uint64_t)(num))
|
||||
# endif
|
||||
# ifndef conv16le
|
||||
# define conv16le(num) bswap16(num)
|
||||
# endif
|
||||
# ifndef conv32le
|
||||
# define conv32le(num) bswap32(num)
|
||||
# endif
|
||||
# ifndef conv64le
|
||||
# define conv64le(num) bswap64(num)
|
||||
# endif
|
||||
#else
|
||||
# ifndef conv16be
|
||||
# define conv16be(num) bswap16(num)
|
||||
# endif
|
||||
# ifndef conv32be
|
||||
# define conv32be(num) bswap32(num)
|
||||
# endif
|
||||
# ifndef conv64be
|
||||
# define conv64be(num) bswap64(num)
|
||||
# endif
|
||||
# ifndef conv16le
|
||||
# define conv16le(num) ((uint16_t)(num))
|
||||
# endif
|
||||
# ifndef conv32le
|
||||
# define conv32le(num) ((uint32_t)(num))
|
||||
# endif
|
||||
# ifndef conv64le
|
||||
# define conv64le(num) ((uint64_t)(num))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
// Aligned reads and writes //
|
||||
//////////////////////////////
|
||||
|
||||
static inline uint16_t
|
||||
read16be(const uint8_t *buf)
|
||||
{
|
||||
uint16_t num = *(const uint16_t *)buf;
|
||||
return conv16be(num);
|
||||
}
|
||||
|
||||
|
||||
static inline uint16_t
|
||||
read16le(const uint8_t *buf)
|
||||
{
|
||||
uint16_t num = *(const uint16_t *)buf;
|
||||
return conv16le(num);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
read32be(const uint8_t *buf)
|
||||
{
|
||||
uint32_t num = *(const uint32_t *)buf;
|
||||
return conv32be(num);
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
read32le(const uint8_t *buf)
|
||||
{
|
||||
uint32_t num = *(const uint32_t *)buf;
|
||||
return conv32le(num);
|
||||
}
|
||||
|
||||
|
||||
static inline uint64_t
|
||||
read64be(const uint8_t *buf)
|
||||
{
|
||||
uint64_t num = *(const uint64_t *)buf;
|
||||
return conv64be(num);
|
||||
}
|
||||
|
||||
|
||||
static inline uint64_t
|
||||
read64le(const uint8_t *buf)
|
||||
{
|
||||
uint64_t num = *(const uint64_t *)buf;
|
||||
return conv64le(num);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: Possible byte swapping must be done in a macro to allow GCC
|
||||
// to optimize byte swapping of constants when using glibc's or *BSD's
|
||||
// byte swapping macros. The actual write is done in an inline function
|
||||
// to make type checking of the buf pointer possible similarly to readXXYe()
|
||||
// functions.
|
||||
|
||||
#define write16be(buf, num) write16ne((buf), conv16be(num))
|
||||
#define write16le(buf, num) write16ne((buf), conv16le(num))
|
||||
#define write32be(buf, num) write32ne((buf), conv32be(num))
|
||||
#define write32le(buf, num) write32ne((buf), conv32le(num))
|
||||
#define write64be(buf, num) write64ne((buf), conv64be(num))
|
||||
#define write64le(buf, num) write64ne((buf), conv64le(num))
|
||||
|
||||
|
||||
static inline void
|
||||
write16ne(uint8_t *buf, uint16_t num)
|
||||
{
|
||||
*(uint16_t *)buf = num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write32ne(uint8_t *buf, uint32_t num)
|
||||
{
|
||||
*(uint32_t *)buf = num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write64ne(uint8_t *buf, uint64_t num)
|
||||
{
|
||||
*(uint64_t *)buf = num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// Unaligned reads and writes //
|
||||
////////////////////////////////
|
||||
|
||||
// NOTE: TUKLIB_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and
|
||||
// 32-bit unaligned integer loads and stores. It's possible that 64-bit
|
||||
// unaligned access doesn't work or is slower than byte-by-byte access.
|
||||
// Since unaligned 64-bit is probably not needed as often as 16-bit or
|
||||
// 32-bit, we simply don't support 64-bit unaligned access for now.
|
||||
#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
|
||||
# define unaligned_read16be read16be
|
||||
# define unaligned_read16le read16le
|
||||
# define unaligned_read32be read32be
|
||||
# define unaligned_read32le read32le
|
||||
# define unaligned_write16be write16be
|
||||
# define unaligned_write16le write16le
|
||||
# define unaligned_write32be write32be
|
||||
# define unaligned_write32le write32le
|
||||
|
||||
#else
|
||||
|
||||
static inline uint16_t
|
||||
unaligned_read16be(const uint8_t *buf)
|
||||
{
|
||||
uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1];
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
static inline uint16_t
|
||||
unaligned_read16le(const uint8_t *buf)
|
||||
{
|
||||
uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
unaligned_read32be(const uint8_t *buf)
|
||||
{
|
||||
uint32_t num = (uint32_t)buf[0] << 24;
|
||||
num |= (uint32_t)buf[1] << 16;
|
||||
num |= (uint32_t)buf[2] << 8;
|
||||
num |= (uint32_t)buf[3];
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
unaligned_read32le(const uint8_t *buf)
|
||||
{
|
||||
uint32_t num = (uint32_t)buf[0];
|
||||
num |= (uint32_t)buf[1] << 8;
|
||||
num |= (uint32_t)buf[2] << 16;
|
||||
num |= (uint32_t)buf[3] << 24;
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
unaligned_write16be(uint8_t *buf, uint16_t num)
|
||||
{
|
||||
buf[0] = num >> 8;
|
||||
buf[1] = num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
unaligned_write16le(uint8_t *buf, uint16_t num)
|
||||
{
|
||||
buf[0] = num;
|
||||
buf[1] = num >> 8;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
unaligned_write32be(uint8_t *buf, uint32_t num)
|
||||
{
|
||||
buf[0] = num >> 24;
|
||||
buf[1] = num >> 16;
|
||||
buf[2] = num >> 8;
|
||||
buf[3] = num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
unaligned_write32le(uint8_t *buf, uint32_t num)
|
||||
{
|
||||
buf[0] = num;
|
||||
buf[1] = num >> 8;
|
||||
buf[2] = num >> 16;
|
||||
buf[3] = num >> 24;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
bsr32(uint32_t n)
|
||||
{
|
||||
// Check for ICC first, since it tends to define __GNUC__ too.
|
||||
#if defined(__INTEL_COMPILER)
|
||||
return _bit_scan_reverse(n);
|
||||
|
||||
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
|
||||
// GCC >= 3.4 has __builtin_clz(), which gives good results on
|
||||
// multiple architectures. On x86, __builtin_clz() ^ 31U becomes
|
||||
// either plain BSR (so the XOR gets optimized away) or LZCNT and
|
||||
// XOR (if -march indicates that SSE4a instructions are supported).
|
||||
return __builtin_clz(n) ^ 31U;
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
uint32_t i;
|
||||
__asm__("bsrl %1, %0" : "=r" (i) : "rm" (n));
|
||||
return i;
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
// MSVC isn't supported by tuklib, but since this code exists,
|
||||
// it doesn't hurt to have it here anyway.
|
||||
uint32_t i;
|
||||
_BitScanReverse((DWORD *)&i, n);
|
||||
return i;
|
||||
|
||||
#else
|
||||
uint32_t i = 31;
|
||||
|
||||
if ((n & UINT32_C(0xFFFF0000)) == 0) {
|
||||
n <<= 16;
|
||||
i = 15;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xFF000000)) == 0) {
|
||||
n <<= 8;
|
||||
i -= 8;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xF0000000)) == 0) {
|
||||
n <<= 4;
|
||||
i -= 4;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xC0000000)) == 0) {
|
||||
n <<= 2;
|
||||
i -= 2;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x80000000)) == 0)
|
||||
--i;
|
||||
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
clz32(uint32_t n)
|
||||
{
|
||||
#if defined(__INTEL_COMPILER)
|
||||
return _bit_scan_reverse(n) ^ 31U;
|
||||
|
||||
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
|
||||
return __builtin_clz(n);
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
uint32_t i;
|
||||
__asm__("bsrl %1, %0\n\t"
|
||||
"xorl $31, %0"
|
||||
: "=r" (i) : "rm" (n));
|
||||
return i;
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
uint32_t i;
|
||||
_BitScanReverse((DWORD *)&i, n);
|
||||
return i ^ 31U;
|
||||
|
||||
#else
|
||||
uint32_t i = 0;
|
||||
|
||||
if ((n & UINT32_C(0xFFFF0000)) == 0) {
|
||||
n <<= 16;
|
||||
i = 16;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xFF000000)) == 0) {
|
||||
n <<= 8;
|
||||
i += 8;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xF0000000)) == 0) {
|
||||
n <<= 4;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0xC0000000)) == 0) {
|
||||
n <<= 2;
|
||||
i += 2;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x80000000)) == 0)
|
||||
++i;
|
||||
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t
|
||||
ctz32(uint32_t n)
|
||||
{
|
||||
#if defined(__INTEL_COMPILER)
|
||||
return _bit_scan_forward(n);
|
||||
|
||||
#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX
|
||||
return __builtin_ctz(n);
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
uint32_t i;
|
||||
__asm__("bsfl %1, %0" : "=r" (i) : "rm" (n));
|
||||
return i;
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
uint32_t i;
|
||||
_BitScanForward((DWORD *)&i, n);
|
||||
return i;
|
||||
|
||||
#else
|
||||
uint32_t i = 0;
|
||||
|
||||
if ((n & UINT32_C(0x0000FFFF)) == 0) {
|
||||
n >>= 16;
|
||||
i = 16;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x000000FF)) == 0) {
|
||||
n >>= 8;
|
||||
i += 8;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x0000000F)) == 0) {
|
||||
n >>= 4;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x00000003)) == 0) {
|
||||
n >>= 2;
|
||||
i += 2;
|
||||
}
|
||||
|
||||
if ((n & UINT32_C(0x00000001)) == 0)
|
||||
++i;
|
||||
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define bsf32 ctz32
|
||||
|
||||
#endif
|
|
@ -1,90 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file vli_decoder.c
|
||||
/// \brief Decodes variable-length integers
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
// 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,33 +0,0 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/// \file vli_size.c
|
||||
/// \brief Calculates the encoded size of a variable-length integer
|
||||
//
|
||||
// Copyright 2012 Lasse Collin
|
||||
// Public Domain
|
||||
//
|
||||
// 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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue