mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-15 07:20:31 +02:00
Replace zlib, zstd, libchdr, libzip and libpng with libretro-common
Deflate, zlib and gzip streams go through rinflate and rdeflate, zstd through rzstd, CHD images through rchd, zip archives through rzip_archive and PNG through rpng. The bundled libraries, their build glue and the system-library options are gone; adler32 and uncompress keep zlib's ABI for the prebuilt FFmpeg archives that still call them. libretro-common is one CMake library that the core, the headless tool and the unit tests all link. The reads take shorter paths on the way. CHD decodes straight from the loader's reads and a range of blocks at a time, and a file read at any alignment decodes into place; CSO keeps one inflate stream instead of one per block; a plain ISO serves a file read with one read of its exact bytes; a stored zip member is read in place and a deflated one through restart points rather than a copy of the whole image in memory; zip members decode into the caller's buffer; sequential reads through the frontend's VFS skip the seek, which also keeps its buffering. libretro/test reads one image as ISO, CSO, CHD and zip through the block devices, boots each, and checks the codecs against Python-made vectors; a CI job runs it.
This commit is contained in:
1 parent
6b22f99818
commit
d56b453891
252 files changed
+1751
-91370
No files matched your search
@@ -93,6 +93,36 @@ jobs:
|
||||
shell: msys2 {0}
|
||||
run: make -C libretro -f Makefile -j4 platform=win
|
||||
|
||||
# Reads the same disc image as ISO, CSO (two frame sizes), CHD (every codec and two hunk sizes)
|
||||
# and zipped (stored and deflated) through the core's own block devices and compares every
|
||||
# block, boots each one, and checks the deflate, zstd, PNG and zip code against vectors made by
|
||||
# Python's zlib, zstandard and Pillow.
|
||||
test-libretro-images:
|
||||
runs-on: ubuntu-26.04
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update -y -qq
|
||||
sudo apt-get install -y libgl1-mesa-dev mame-tools genisoimage zip python3-pil python3-zstandard
|
||||
|
||||
- name: Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@f09c25b45002a07be2955cbe52e8cee55643f89d # v1.2.24
|
||||
with:
|
||||
key: test-libretro-images
|
||||
|
||||
- name: Build the core and the checks
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:$PATH"
|
||||
make -C libretro -f Makefile -j4 test-tools
|
||||
|
||||
- name: Run the checks
|
||||
run: libretro/test/run.sh
|
||||
|
||||
build:
|
||||
name: build (${{ matrix.id }})
|
||||
strategy:
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
[submodule "ext/miniupnp"]
|
||||
path = ext/miniupnp
|
||||
url = https://github.com/miniupnp/miniupnp.git
|
||||
[submodule "zstd"]
|
||||
path = ext/zstd
|
||||
url = https://github.com/facebook/zstd.git
|
||||
[submodule "SDL/macOS"]
|
||||
path = SDL/macOS
|
||||
url = https://github.com/hrydgard/ppsspp-mac-sdl
|
||||
@@ -38,9 +35,6 @@
|
||||
[submodule "ext/rcheevos"]
|
||||
path = ext/rcheevos
|
||||
url = https://github.com/RetroAchievements/rcheevos.git
|
||||
[submodule "ext/libchdr"]
|
||||
path = ext/libchdr
|
||||
url = https://github.com/rtissera/libchdr.git
|
||||
[submodule "ext/libadrenotools"]
|
||||
path = ext/libadrenotools
|
||||
url = https://github.com/bylaws/libadrenotools.git
|
||||
|
||||
+42
-268
@@ -199,12 +199,7 @@ option(USE_SYSTEM_SNAPPY "Dynamically link against system snappy" ${USE_SYSTEM_S
|
||||
option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG})
|
||||
option(BUILD_BUNDLED_FFMPEG "Build bundled ffmpeg module" ${BUILD_BUNDLED_FFMPEG})
|
||||
option(USE_SYSTEM_FREETYPE "Dynamically link against system freetype" ${USE_SYSTEM_FREETYPE})
|
||||
option(USE_SYSTEM_LIBCHDR "Dynamically link against system libchdr" ${USE_SYSTEM_LIBCHDR})
|
||||
option(USE_SYSTEM_LIBZIP "Dynamically link against system libzip" ${USE_SYSTEM_LIBZIP})
|
||||
|
||||
option(USE_SYSTEM_LIBPNG "Dynamically link against system libpng" ON)
|
||||
option(USE_SYSTEM_RAPIDJSON "Build using system rapidjson" ${USE_SYSTEM_RAPIDJSON})
|
||||
option(USE_SYSTEM_ZSTD "Dynamically link against system zstd" ${USE_SYSTEM_ZSTD})
|
||||
option(USE_SYSTEM_MINIUPNPC "Dynamically link against system miniUPnPc" ${USE_SYSTEM_MINIUPNPC})
|
||||
option(USE_ASAN "Use address sanitizer" OFF)
|
||||
option(USE_UBSAN "Use undefined behaviour sanitizer" OFF)
|
||||
@@ -228,7 +223,6 @@ endif()
|
||||
if(WEBOS)
|
||||
set(USING_X11_VULKAN OFF)
|
||||
set(USING_GLES2 ON)
|
||||
set(USE_SYSTEM_ZSTD OFF)
|
||||
if(CMAKE_CXX_COMPILER MATCHES "arm")
|
||||
set(ARMV7 ON)
|
||||
endif()
|
||||
@@ -430,9 +424,6 @@ if(ARM64)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
# NEON optimizations in libpng17 seem to cause PNG load errors, see #14485.
|
||||
add_compile_definitions(PNG_ARM_NEON_OPT=0)
|
||||
|
||||
add_compile_options(-Wall -Werror=return-type -Wno-unused-function -Wno-sign-compare -Wno-unused-but-set-variable "$<$<COMPILE_LANGUAGE:CXX>:-Wno-reorder>" -Wno-unknown-pragmas -Wno-unused-value -Wno-unused-variable -Wno-error=incompatible-pointer-types)
|
||||
if(NOT CLANG)
|
||||
# This one is very useful but has many false positives.
|
||||
@@ -573,6 +564,48 @@ macro(setup_target_project TargetName ProjectDir)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# libretro-common, as one library everything links: the VFS, threading and codecs.
|
||||
# The headless test tools link it as well as the core.
|
||||
add_library(libretro-common STATIC
|
||||
libretro/libretro-common/compat/compat_posix_string.c
|
||||
libretro/libretro-common/compat/fopen_utf8.c
|
||||
libretro/libretro-common/compat/compat_strl.c
|
||||
libretro/libretro-common/encodings/encoding_crc32.c
|
||||
libretro/libretro-common/encodings/encoding_deflate.c
|
||||
libretro/libretro-common/encodings/encoding_huffman.c
|
||||
libretro/libretro-common/encodings/encoding_rzstd.c
|
||||
libretro/libretro-common/encodings/encoding_utf.c
|
||||
libretro/libretro-common/features/features_cpu.c
|
||||
libretro/libretro-common/file/file_path.c
|
||||
libretro/libretro-common/file/file_path_io.c
|
||||
libretro/libretro-common/formats/7z/r7z_lzma.c
|
||||
libretro/libretro-common/formats/chd/rchd.c
|
||||
libretro/libretro-common/formats/flac/rflac.c
|
||||
libretro/libretro-common/formats/png/rpng.c
|
||||
libretro/libretro-common/formats/png/rpng_encode.c
|
||||
libretro/libretro-common/formats/zip/rzip_archive.c
|
||||
libretro/libretro-common/queues/retro_spsc.c
|
||||
libretro/libretro-common/queues/retro_waitable_spsc.c
|
||||
libretro/libretro-common/rthreads/retro_asym_eventcount.c
|
||||
libretro/libretro-common/rthreads/retro_eventcount.c
|
||||
libretro/libretro-common/rthreads/retro_procbarrier.c
|
||||
libretro/libretro-common/rthreads/rthreads.c
|
||||
libretro/libretro-common/rthreads/tpool.c
|
||||
libretro/libretro-common/streams/file_stream.c
|
||||
libretro/libretro-common/streams/file_stream_transforms.c
|
||||
libretro/libretro-common/streams/interface_stream.c
|
||||
libretro/libretro-common/streams/memory_stream.c
|
||||
libretro/libretro-common/streams/trans_stream.c
|
||||
libretro/libretro-common/streams/trans_stream_deflate.c
|
||||
libretro/libretro-common/streams/trans_stream_pipe.c
|
||||
libretro/libretro-common/string/rstrtod.c
|
||||
libretro/libretro-common/time/rtime.c
|
||||
libretro/libretro-common/vfs/vfs_implementation.c)
|
||||
target_include_directories(libretro-common PUBLIC libretro/libretro-common/include)
|
||||
target_compile_definitions(libretro-common PUBLIC HAVE_RZSTD HAVE_RFLAC
|
||||
HAVE_RCHD_DEFLATE HAVE_RCHD_LZMA HAVE_RCHD_FLAC HAVE_RCHD_ZSTD)
|
||||
target_link_libraries(libretro-common Threads::Threads)
|
||||
|
||||
add_subdirectory(ext)
|
||||
|
||||
include_directories(ext/OpenXR-SDK/include)
|
||||
@@ -668,249 +701,6 @@ if(USE_FFMPEG)
|
||||
endif()
|
||||
endif(USE_FFMPEG)
|
||||
|
||||
find_package(ZLIB)
|
||||
if(ZLIB_FOUND AND NOT ANDROID)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
add_compile_definitions(SHARED_ZLIB)
|
||||
else()
|
||||
add_library(zlib STATIC
|
||||
ext/zlib/adler32.c
|
||||
ext/zlib/compress.c
|
||||
ext/zlib/crc32.c
|
||||
ext/zlib/crc32.h
|
||||
ext/zlib/deflate.c
|
||||
ext/zlib/deflate.h
|
||||
ext/zlib/gzclose.c
|
||||
ext/zlib/gzguts.h
|
||||
ext/zlib/gzlib.c
|
||||
ext/zlib/gzread.c
|
||||
ext/zlib/gzwrite.c
|
||||
ext/zlib/infback.c
|
||||
ext/zlib/inffast.c
|
||||
ext/zlib/inffast.h
|
||||
ext/zlib/inffixed.h
|
||||
ext/zlib/inflate.c
|
||||
ext/zlib/inflate.h
|
||||
ext/zlib/inftrees.c
|
||||
ext/zlib/inftrees.h
|
||||
ext/zlib/trees.c
|
||||
ext/zlib/trees.h
|
||||
ext/zlib/uncompr.c
|
||||
ext/zlib/zconf.h
|
||||
ext/zlib/zlib.h
|
||||
ext/zlib/zutil.c
|
||||
ext/zlib/zutil.h
|
||||
)
|
||||
include_directories(ext/zlib)
|
||||
set(ZLIB_LIBRARY zlib)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
# These can be fast even for debug.
|
||||
target_compile_options(udis86 PRIVATE "-O2")
|
||||
target_compile_options(cityhash PRIVATE "-O2")
|
||||
if(NOT ZLIB_FOUND)
|
||||
target_compile_options(zlib PRIVATE "-O2")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
find_package(LIBZIP)
|
||||
if(LIBZIP_FOUND AND USE_SYSTEM_LIBZIP)
|
||||
include_directories(${LIBZIP_INCLUDE_DIRS})
|
||||
add_compile_definitions(SHARED_LIBZIP)
|
||||
else()
|
||||
add_library(libzip STATIC
|
||||
ext/libzip/zip_add.c
|
||||
ext/libzip/zip_add_dir.c
|
||||
ext/libzip/zip_add_entry.c
|
||||
ext/libzip/zip_algorithm_deflate.c
|
||||
ext/libzip/zip_buffer.c
|
||||
ext/libzip/zip_close.c
|
||||
ext/libzip/zip_delete.c
|
||||
ext/libzip/zip_dir_add.c
|
||||
ext/libzip/zip_dirent.c
|
||||
ext/libzip/zip_discard.c
|
||||
ext/libzip/zip_entry.c
|
||||
ext/libzip/zip_error.c
|
||||
ext/libzip/zip_error_clear.c
|
||||
ext/libzip/zip_error_get.c
|
||||
ext/libzip/zip_error_get_sys_type.c
|
||||
ext/libzip/zip_error_strerror.c
|
||||
ext/libzip/zip_error_to_str.c
|
||||
ext/libzip/zip_extra_field.c
|
||||
ext/libzip/zip_extra_field_api.c
|
||||
ext/libzip/zip_fclose.c
|
||||
ext/libzip/zip_fdopen.c
|
||||
ext/libzip/zip_file_add.c
|
||||
ext/libzip/zip_file_error_clear.c
|
||||
ext/libzip/zip_file_error_get.c
|
||||
ext/libzip/zip_file_get_comment.c
|
||||
ext/libzip/zip_file_get_external_attributes.c
|
||||
ext/libzip/zip_file_get_offset.c
|
||||
ext/libzip/zip_file_rename.c
|
||||
ext/libzip/zip_file_replace.c
|
||||
ext/libzip/zip_file_set_comment.c
|
||||
ext/libzip/zip_file_set_encryption.c
|
||||
ext/libzip/zip_file_set_external_attributes.c
|
||||
ext/libzip/zip_file_set_mtime.c
|
||||
ext/libzip/zip_file_strerror.c
|
||||
ext/libzip/zip_fopen.c
|
||||
ext/libzip/zip_fopen_encrypted.c
|
||||
ext/libzip/zip_fopen_index.c
|
||||
ext/libzip/zip_fopen_index_encrypted.c
|
||||
ext/libzip/zip_fread.c
|
||||
ext/libzip/zip_fseek.c
|
||||
ext/libzip/zip_ftell.c
|
||||
ext/libzip/zip_get_archive_comment.c
|
||||
ext/libzip/zip_get_archive_flag.c
|
||||
ext/libzip/zip_get_encryption_implementation.c
|
||||
ext/libzip/zip_get_file_comment.c
|
||||
ext/libzip/zip_get_name.c
|
||||
ext/libzip/zip_get_num_entries.c
|
||||
ext/libzip/zip_get_num_files.c
|
||||
ext/libzip/zip_hash.c
|
||||
ext/libzip/zip_io_util.c
|
||||
ext/libzip/zip_libzip_version.c
|
||||
ext/libzip/zip_memdup.c
|
||||
ext/libzip/zip_name_locate.c
|
||||
ext/libzip/zip_new.c
|
||||
ext/libzip/zip_open.c
|
||||
ext/libzip/zip_pkware.c
|
||||
ext/libzip/zip_progress.c
|
||||
ext/libzip/zip_rename.c
|
||||
ext/libzip/zip_replace.c
|
||||
ext/libzip/zip_set_archive_comment.c
|
||||
ext/libzip/zip_set_archive_flag.c
|
||||
ext/libzip/zip_set_default_password.c
|
||||
ext/libzip/zip_set_file_comment.c
|
||||
ext/libzip/zip_set_file_compression.c
|
||||
ext/libzip/zip_set_name.c
|
||||
ext/libzip/zip_source_accept_empty.c
|
||||
ext/libzip/zip_source_begin_write.c
|
||||
ext/libzip/zip_source_begin_write_cloning.c
|
||||
ext/libzip/zip_source_buffer.c
|
||||
ext/libzip/zip_source_call.c
|
||||
ext/libzip/zip_source_close.c
|
||||
ext/libzip/zip_source_commit_write.c
|
||||
ext/libzip/zip_source_compress.c
|
||||
ext/libzip/zip_source_crc.c
|
||||
ext/libzip/zip_source_error.c
|
||||
ext/libzip/zip_source_file_common.c
|
||||
ext/libzip/zip_source_file_stdio.c
|
||||
ext/libzip/zip_source_free.c
|
||||
ext/libzip/zip_source_function.c
|
||||
ext/libzip/zip_source_get_file_attributes.c
|
||||
ext/libzip/zip_source_is_deleted.c
|
||||
ext/libzip/zip_source_layered.c
|
||||
ext/libzip/zip_source_open.c
|
||||
ext/libzip/zip_source_pkware_decode.c
|
||||
ext/libzip/zip_source_pkware_encode.c
|
||||
ext/libzip/zip_source_read.c
|
||||
ext/libzip/zip_source_remove.c
|
||||
ext/libzip/zip_source_rollback_write.c
|
||||
ext/libzip/zip_source_seek.c
|
||||
ext/libzip/zip_source_seek_write.c
|
||||
ext/libzip/zip_source_stat.c
|
||||
ext/libzip/zip_source_supports.c
|
||||
ext/libzip/zip_source_tell.c
|
||||
ext/libzip/zip_source_tell_write.c
|
||||
ext/libzip/zip_source_window.c
|
||||
ext/libzip/zip_source_write.c
|
||||
ext/libzip/zip_source_zip.c
|
||||
ext/libzip/zip_source_zip_new.c
|
||||
ext/libzip/zip_stat.c
|
||||
ext/libzip/zip_stat_index.c
|
||||
ext/libzip/zip_stat_init.c
|
||||
ext/libzip/zip_strerror.c
|
||||
ext/libzip/zip_string.c
|
||||
ext/libzip/zip_unchange.c
|
||||
ext/libzip/zip_unchange_all.c
|
||||
ext/libzip/zip_unchange_archive.c
|
||||
ext/libzip/zip_unchange_data.c
|
||||
ext/libzip/zip_utf-8.c
|
||||
ext/libzip/zip_err_str.c
|
||||
)
|
||||
if(WIN32)
|
||||
target_compile_options(libzip PRIVATE $<$<C_COMPILER_ID:Clang>:-Wno-incompatible-function-pointer-types> $<$<C_COMPILER_ID:GNU>:-Wno-incompatible-pointer-types>)
|
||||
target_sources(libzip PRIVATE
|
||||
ext/libzip/zip_source_file_win32.c
|
||||
ext/libzip/zip_source_file_win32_named.c
|
||||
ext/libzip/zip_source_file_win32_utf16.c
|
||||
ext/libzip/zip_source_file_win32_utf8.c
|
||||
)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
target_sources(libzip PRIVATE ext/libzip/zip_random_uwp.c)
|
||||
else()
|
||||
target_sources(libzip PRIVATE ext/libzip/zip_source_file_win32_ansi.c ext/libzip/zip_random_win32.c)
|
||||
endif()
|
||||
else()
|
||||
target_sources(libzip PRIVATE
|
||||
ext/libzip/zip_mkstempm.c
|
||||
ext/libzip/zip_source_file_stdio_named.c
|
||||
ext/libzip/zip_random_unix.c
|
||||
)
|
||||
endif()
|
||||
target_compile_definitions(libzip PRIVATE HAVE_STDBOOL_H)
|
||||
include_directories(ext/libzip)
|
||||
set(LIBZIP_LIBRARY libzip)
|
||||
endif()
|
||||
|
||||
# Android and iOS require at least libpng17.
|
||||
if(ANDROID OR IOS)
|
||||
set(PNG_REQUIRED_VERSION 1.7)
|
||||
else()
|
||||
set(PNG_REQUIRED_VERSION 1.6)
|
||||
endif()
|
||||
|
||||
if(USE_SYSTEM_LIBPNG)
|
||||
find_package(PNG ${PNG_REQUIRED_VERSION})
|
||||
endif()
|
||||
if(PNG_FOUND)
|
||||
include_directories(${PNG_INCLUDE_DIRS})
|
||||
else()
|
||||
if(ARM)
|
||||
set(PNG_ARM_INCLUDES
|
||||
ext/libpng17/arm/arm_init.c
|
||||
ext/libpng17/arm/filter_neon.S
|
||||
ext/libpng17/arm/filter_neon_intrinsics.c
|
||||
)
|
||||
elseif(ARM64)
|
||||
set(PNG_ARM_INCLUDES
|
||||
ext/libpng17/arm/arm_init.c
|
||||
ext/libpng17/arm/filter_neon_intrinsics.c
|
||||
)
|
||||
endif()
|
||||
add_library(png17 STATIC
|
||||
ext/libpng17/pngconf.h
|
||||
ext/libpng17/pngdebug.h
|
||||
ext/libpng17/png.c
|
||||
ext/libpng17/png.h
|
||||
ext/libpng17/pngerror.c
|
||||
ext/libpng17/pngget.c
|
||||
ext/libpng17/pnginfo.h
|
||||
ext/libpng17/pnglibconf.h
|
||||
ext/libpng17/pngmem.c
|
||||
ext/libpng17/pngpread.c
|
||||
ext/libpng17/pngpriv.h
|
||||
ext/libpng17/pngread.c
|
||||
ext/libpng17/pngrio.c
|
||||
ext/libpng17/pngrtran.c
|
||||
ext/libpng17/pngrutil.c
|
||||
ext/libpng17/pngset.c
|
||||
ext/libpng17/pngstruct.h
|
||||
ext/libpng17/pngtrans.c
|
||||
ext/libpng17/pngwio.c
|
||||
ext/libpng17/pngwrite.c
|
||||
ext/libpng17/pngwtran.c
|
||||
ext/libpng17/pngwutil.c
|
||||
${PNG_ARM_INCLUDES}
|
||||
)
|
||||
set(PNG_LIBRARIES png17)
|
||||
include_directories(ext/libpng17)
|
||||
endif()
|
||||
|
||||
|
||||
set(targetExtra)
|
||||
set(targetExtraLibs)
|
||||
|
||||
@@ -1115,22 +905,6 @@ endif()
|
||||
|
||||
add_subdirectory(Common)
|
||||
|
||||
if(USE_SYSTEM_ZSTD)
|
||||
find_package(ZSTD REQUIRED)
|
||||
else()
|
||||
add_subdirectory(ext/zstd-build)
|
||||
include_directories(ext/zstd/lib)
|
||||
endif()
|
||||
|
||||
if(USE_SYSTEM_LIBCHDR)
|
||||
find_package(PkgConfig)
|
||||
if(PkgConfig_FOUND)
|
||||
pkg_check_modules(libchdr_PKGCONFIG IMPORTED_TARGET libchdr)
|
||||
endif()
|
||||
else()
|
||||
include_directories(ext/libchdr/include)
|
||||
endif()
|
||||
|
||||
add_subdirectory(GPU)
|
||||
add_subdirectory(Core)
|
||||
|
||||
|
||||
+1
-13
@@ -353,10 +353,6 @@ add_library(Common STATIC
|
||||
${CMAKE_SOURCE_DIR}/ext/jpge/jpge.h
|
||||
)
|
||||
|
||||
if(LIBRETRO)
|
||||
target_include_directories(Common PRIVATE ${CMAKE_SOURCE_DIR}/libretro/libretro-common/include)
|
||||
endif()
|
||||
|
||||
setup_target_project(Common Common)
|
||||
|
||||
if(IOS)
|
||||
@@ -389,15 +385,7 @@ if(WIN32)
|
||||
target_link_libraries(Common winmm dsound dxguid d2d1 dwrite d3d11 Version dbghelp)
|
||||
endif()
|
||||
|
||||
target_link_libraries(Common ${LIBZIP_LIBRARY} 7zip ${PNG_LIBRARIES} basis_universal ${ZLIB_LIBRARY} pugixml vma gason udis86 ${RT_LIB} ${ATOMIC_LIB})
|
||||
|
||||
# ZIMLoad.cpp/ZIMSave.cpp, Serializer.cpp, and Render/TextureAtlas.cpp call directly into zstd.
|
||||
if(USE_SYSTEM_ZSTD)
|
||||
target_include_directories(Common PRIVATE ${ZSTD_INCLUDE_DIR})
|
||||
target_link_libraries(Common ${ZSTD_LIBRARY})
|
||||
else()
|
||||
target_link_libraries(Common libzstd_static)
|
||||
endif()
|
||||
target_link_libraries(Common 7zip basis_universal pugixml vma gason udis86 libretro-common ${RT_LIB} ${ATOMIC_LIB})
|
||||
|
||||
# Common/GPU/ShaderTranslation.cpp and Common/GPU/Vulkan/VulkanContext.cpp call directly into
|
||||
# glslang/spirv-cross, so Common needs to declare this dependency itself rather than relying on
|
||||
|
||||
@@ -1,100 +1,113 @@
|
||||
// Little utility functions for data compression.
|
||||
// Taken from http://panthema.net/2007/0328-ZLibString.html
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <encodings/deflate.h>
|
||||
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
#include "Common/Log.h"
|
||||
|
||||
/** Compress a STL string using zlib with given compression level and return
|
||||
* the binary data. */
|
||||
bool compress_string(const std::string& str, std::string *dest, int compressionlevel) {
|
||||
z_stream zs; // z_stream is zlib's control structure
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
int64_t InflateBuffer(void *stream, int windowBits, const uint8_t *in, size_t inLen, uint8_t *out, size_t outLen, size_t *consumed) {
|
||||
rinflate_reset(stream, windowBits);
|
||||
rinflate_set_in(stream, in, inLen);
|
||||
rinflate_set_out(stream, out, outLen);
|
||||
size_t rd = 0, wr = 0;
|
||||
// One call runs until the stream ends or a buffer runs out.
|
||||
const int status = rinflate_process(stream, &rd, &wr);
|
||||
if (consumed)
|
||||
*consumed = rd;
|
||||
return status == RDEFLATE_PROCESS_END ? (int64_t)wr : -1;
|
||||
}
|
||||
|
||||
if (deflateInit(&zs, compressionlevel) != Z_OK) {
|
||||
ERROR_LOG(Log::IO, "deflateInit failed while compressing.");
|
||||
return false;
|
||||
}
|
||||
int64_t InflateBuffer(int windowBits, const uint8_t *in, size_t inLen, uint8_t *out, size_t outLen, size_t *consumed) {
|
||||
void *stream = rinflate_new(windowBits);
|
||||
if (!stream)
|
||||
return -1;
|
||||
const int64_t result = InflateBuffer(stream, windowBits, in, inLen, out, outLen, consumed);
|
||||
rinflate_free(stream);
|
||||
return result;
|
||||
}
|
||||
|
||||
zs.next_in = (Bytef*)str.data();
|
||||
zs.avail_in = (uInt)str.size(); // set the z_stream's input
|
||||
|
||||
int ret;
|
||||
char outbuffer[32768];
|
||||
std::string outstring;
|
||||
|
||||
// retrieve the compressed bytes blockwise
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = sizeof(outbuffer);
|
||||
|
||||
ret = deflate(&zs, Z_FINISH);
|
||||
|
||||
if (outstring.size() < zs.total_out) {
|
||||
// append the block to the output string
|
||||
outstring.append(outbuffer,
|
||||
zs.total_out - outstring.size());
|
||||
uint32_t Adler32(uint32_t adler, const uint8_t *buf, size_t len) {
|
||||
// 5552 is the most bytes that can be summed before the 32-bit sums overflow.
|
||||
uint32_t a = adler & 0xFFFF, b = adler >> 16;
|
||||
while (len > 0) {
|
||||
size_t n = len < 5552 ? len : 5552;
|
||||
len -= n;
|
||||
while (n--) {
|
||||
a += *buf++;
|
||||
b += a;
|
||||
}
|
||||
} while (ret == Z_OK);
|
||||
|
||||
deflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
|
||||
ERROR_LOG(Log::IO, "Exception during zlib compression: (%d): %s", ret, zs.msg);
|
||||
return false;
|
||||
a %= 65521;
|
||||
b %= 65521;
|
||||
}
|
||||
return (b << 16) | a;
|
||||
}
|
||||
|
||||
*dest = outstring;
|
||||
// Runs a stream to its end, growing *dest as output arrives.
|
||||
template <class Process, class SetOut>
|
||||
static bool RunToEnd(void *stream, std::string *dest, size_t initial, Process process, SetOut setOut) {
|
||||
std::string out;
|
||||
out.resize(initial < 4096 ? 4096 : initial);
|
||||
size_t used = 0;
|
||||
for (;;) {
|
||||
setOut(stream, (uint8_t *)&out[used], out.size() - used);
|
||||
size_t rd = 0, wr = 0;
|
||||
const int status = process(stream, &rd, &wr);
|
||||
used += wr;
|
||||
if (status == RDEFLATE_PROCESS_END)
|
||||
break;
|
||||
if (status != RDEFLATE_PROCESS_NEXT)
|
||||
return false;
|
||||
if (used == out.size())
|
||||
out.resize(out.size() * 2);
|
||||
else if (rd == 0 && wr == 0)
|
||||
return false; // input ran out before the end of the stream
|
||||
}
|
||||
out.resize(used);
|
||||
*dest = std::move(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Decompress an STL string using zlib and return the original data. */
|
||||
bool decompress_string(const std::string& str, std::string *dest) {
|
||||
if (!str.size())
|
||||
bool compress_string(const std::string &str, std::string *dest, int compressionlevel, int windowBits) {
|
||||
void *stream = rdeflate_new(compressionlevel, windowBits);
|
||||
if (!stream)
|
||||
return false;
|
||||
|
||||
z_stream zs; // z_stream is zlib's control structure
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
// modification by hrydgard: inflateInit2, 16+MAXWBITS makes it read gzip data too
|
||||
if (inflateInit2(&zs, 32+MAX_WBITS) != Z_OK) {
|
||||
ERROR_LOG(Log::IO, "inflateInit failed while decompressing.");
|
||||
rdeflate_set_in(stream, (const uint8_t *)str.data(), str.size());
|
||||
rdeflate_finish(stream);
|
||||
const bool ok = RunToEnd(stream, dest, str.size() / 2 + 64, rdeflate_process, rdeflate_set_out);
|
||||
rdeflate_free(stream);
|
||||
if (!ok)
|
||||
ERROR_LOG(Log::IO, "deflate failed while compressing.");
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool decompress_string(const std::string &str, std::string *dest) {
|
||||
if (str.empty())
|
||||
return false;
|
||||
}
|
||||
|
||||
zs.next_in = (Bytef*)str.data();
|
||||
zs.avail_in = (uInt)str.size();
|
||||
|
||||
int ret;
|
||||
char outbuffer[32768];
|
||||
std::string outstring;
|
||||
|
||||
// get the decompressed bytes blockwise using repeated calls to inflate
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = sizeof(outbuffer);
|
||||
|
||||
ret = inflate(&zs, 0);
|
||||
|
||||
if (outstring.size() < zs.total_out) {
|
||||
outstring.append(outbuffer,
|
||||
zs.total_out - outstring.size());
|
||||
}
|
||||
|
||||
} while (ret == Z_OK);
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
|
||||
ERROR_LOG(Log::IO, "Exception during zlib decompression: (%i) %s", ret, zs.msg);
|
||||
void *stream = rinflate_new(47);
|
||||
if (!stream)
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = outstring;
|
||||
return true;
|
||||
rinflate_set_in(stream, (const uint8_t *)str.data(), str.size());
|
||||
// rinflate_set_out treats each new window as following the last, so growing works.
|
||||
const bool ok = RunToEnd(stream, dest, str.size() * 4, rinflate_process, rinflate_set_out);
|
||||
rinflate_free(stream);
|
||||
if (!ok)
|
||||
ERROR_LOG(Log::IO, "inflate failed while decompressing.");
|
||||
return ok;
|
||||
}
|
||||
|
||||
// The prebuilt FFmpeg archives were linked against zlib and still call these two
|
||||
// (adler32 in the MOV/MXF demuxers, uncompress for compressed ID3v2 frames).
|
||||
// zlib's own ABI, so those archives resolve against libretro-common's inflate.
|
||||
extern "C" unsigned long adler32(unsigned long adler, const unsigned char *buf, unsigned int len) {
|
||||
if (!buf)
|
||||
return 1;
|
||||
return Adler32((uint32_t)adler, buf, len);
|
||||
}
|
||||
|
||||
extern "C" int uncompress(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen) {
|
||||
const int64_t produced = InflateBuffer(15, source, sourceLen, dest, *destLen);
|
||||
if (produced < 0)
|
||||
return -3; // Z_DATA_ERROR
|
||||
*destLen = (unsigned long)produced;
|
||||
return 0; // Z_OK
|
||||
}
|
||||
@@ -1,7 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// inflate/deflate convenience wrapper. Uses zlib.
|
||||
bool compress_string(const std::string& str, std::string *dest, int compressionlevel = 9);
|
||||
bool decompress_string(const std::string& str, std::string *dest);
|
||||
// zlib-family codecs on libretro-common's rinflate/rdeflate.
|
||||
// windowBits follow zlib: -15 raw deflate, 15 zlib, 31 gzip, 47 zlib or gzip.
|
||||
|
||||
// Decodes one complete stream into out[0..outLen). Returns the bytes produced, or -1
|
||||
// if the stream is bad, truncated, or doesn't fit. *consumed receives the input used.
|
||||
int64_t InflateBuffer(int windowBits, const uint8_t *in, size_t inLen, uint8_t *out, size_t outLen, size_t *consumed = nullptr);
|
||||
|
||||
// The same through a stream from rinflate_new(), reset here; for callers that decode
|
||||
// many small streams and shouldn't allocate for each one.
|
||||
int64_t InflateBuffer(void *stream, int windowBits, const uint8_t *in, size_t inLen, uint8_t *out, size_t outLen, size_t *consumed = nullptr);
|
||||
|
||||
// RFC 1950 Adler-32, zlib's adler32() (start with 1).
|
||||
uint32_t Adler32(uint32_t adler, const uint8_t *buf, size_t len);
|
||||
|
||||
// Whole-string helpers. compress_string writes zlib by default (31 for gzip);
|
||||
// decompress_string accepts zlib or gzip.
|
||||
bool compress_string(const std::string &str, std::string *dest, int compressionlevel = 9, int windowBits = 15);
|
||||
bool decompress_string(const std::string &str, std::string *dest);
|
||||
+86
-169
@@ -2,7 +2,11 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <png.h>
|
||||
|
||||
#include <formats/image.h>
|
||||
#include <formats/rpng.h>
|
||||
#include <libretro.h> // RETRO_VFS_FILE_ACCESS_*
|
||||
#include <streams/interface_stream.h>
|
||||
|
||||
#include "Common/Data/Format/PNGLoad.h"
|
||||
#include "Common/Log.h"
|
||||
@@ -11,136 +15,56 @@
|
||||
// *image_data_ptr should be deleted with free()
|
||||
// return value of 1 == success.
|
||||
int pngLoad(const char *file, int *pwidth, int *pheight, unsigned char **image_data_ptr) {
|
||||
png_image png;
|
||||
memset(&png, 0, sizeof(png));
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
|
||||
png_image_begin_read_from_file(&png, file);
|
||||
|
||||
if (PNG_IMAGE_FAILED(png))
|
||||
{
|
||||
WARN_LOG(Log::IO, "pngLoad: %s (%s)", png.message, file);
|
||||
*image_data_ptr = nullptr;
|
||||
*image_data_ptr = nullptr;
|
||||
std::string data;
|
||||
if (!File::ReadBinaryFileToString(Path(file), &data) || data.empty()) {
|
||||
WARN_LOG(Log::IO, "pngLoad: can't read %s", file);
|
||||
return 0;
|
||||
}
|
||||
*pwidth = png.width;
|
||||
*pheight = png.height;
|
||||
png.format = PNG_FORMAT_RGBA;
|
||||
|
||||
int stride = PNG_IMAGE_ROW_STRIDE(png);
|
||||
*image_data_ptr = (unsigned char *)malloc(PNG_IMAGE_SIZE(png));
|
||||
png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL);
|
||||
return 1;
|
||||
return pngLoadPtr((const unsigned char *)data.data(), data.size(), pwidth, pheight, image_data_ptr);
|
||||
}
|
||||
|
||||
// Custom error handler
|
||||
void pngErrorHandler(png_structp png_ptr, png_const_charp error_msg) {
|
||||
ERROR_LOG(Log::System, "libpng error: %s\n", error_msg);
|
||||
longjmp(png_jmpbuf(png_ptr), 1);
|
||||
}
|
||||
|
||||
void pngWarningHandler(png_structp png_ptr, png_const_charp warning_msg) {
|
||||
DEBUG_LOG(Log::System, "libpng warning: %s\n", warning_msg);
|
||||
}
|
||||
|
||||
struct PngReadContext {
|
||||
const unsigned char *ptr;
|
||||
size_t remaining;
|
||||
};
|
||||
|
||||
|
||||
int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr, int maxWidth, int maxHeight) {
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngErrorHandler, pngWarningHandler);
|
||||
if (!png) {
|
||||
*image_data_ptr = nullptr;
|
||||
if (input_len < sizeof(PNGHeaderPeek))
|
||||
return 0;
|
||||
}
|
||||
if (input_len == 0) {
|
||||
|
||||
// Reject images larger than the caller's limits before anything is allocated,
|
||||
// so attacker-controlled dimensions can't drive a huge allocation.
|
||||
PNGHeaderPeek peek;
|
||||
memcpy(&peek, input_ptr, sizeof(peek));
|
||||
if (!peek.IsValidPNGHeader() || peek.Width() > maxWidth || peek.Height() > maxHeight) {
|
||||
DEBUG_LOG(Log::IO, "PNG rejected: %dx%d (max %dx%d)", peek.Width(), peek.Height(), maxWidth, maxHeight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ignore incorrect sRGB profiles
|
||||
png_set_option(png, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON);
|
||||
png_set_benign_errors(png, PNG_OPTION_ON);
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
png_destroy_read_struct(&png, NULL, NULL);
|
||||
rpng_t *rpng = rpng_alloc();
|
||||
if (!rpng)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
png_destroy_read_struct(&png, &info, NULL);
|
||||
if (*image_data_ptr) {
|
||||
free(*image_data_ptr);
|
||||
*image_data_ptr = NULL;
|
||||
// rpng only reads through this pointer.
|
||||
uint32_t *data = nullptr;
|
||||
unsigned w = 0, h = 0;
|
||||
int ret = IMAGE_PROCESS_ERROR;
|
||||
if (rpng_set_buf_ptr(rpng, (void *)input_ptr, input_len) && rpng_start(rpng)) {
|
||||
while (rpng_iterate_image(rpng)) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
PngReadContext readContext = {input_ptr, input_len};
|
||||
|
||||
png_set_read_fn(png, &readContext, [](png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) {
|
||||
PngReadContext *ctx = (PngReadContext *)png_get_io_ptr(png_ptr);
|
||||
if (byteCountToRead > ctx->remaining) {
|
||||
// This triggers the longjmp to your pngErrorHandler
|
||||
png_error(png_ptr, "Read past end of buffer");
|
||||
return;
|
||||
if (rpng_is_valid(rpng)) {
|
||||
// RGBA byte order, which is what everything here wants.
|
||||
do {
|
||||
ret = rpng_process_image(rpng, (void **)&data, input_len, &w, &h, true);
|
||||
} while (ret == IMAGE_PROCESS_NEXT);
|
||||
}
|
||||
|
||||
memcpy(outBytes, ctx->ptr, byteCountToRead);
|
||||
ctx->ptr += byteCountToRead;
|
||||
ctx->remaining -= byteCountToRead;
|
||||
});
|
||||
|
||||
png_read_info(png, info);
|
||||
|
||||
const int color_type = png_get_color_type(png, info);
|
||||
png_set_strip_16(png);
|
||||
png_set_packing(png);
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY)
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png);
|
||||
} else if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(png);
|
||||
}
|
||||
rpng_free(rpng);
|
||||
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png);
|
||||
// Force 8-bit RGBA format
|
||||
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
||||
png_set_interlace_handling(png);
|
||||
// Ignore the file's gamma correction
|
||||
png_set_gamma(png, 1.0, 1.0);
|
||||
|
||||
png_read_update_info(png, info);
|
||||
|
||||
*pwidth = png_get_image_width(png, info);
|
||||
*pheight = png_get_image_height(png, info);
|
||||
|
||||
// Reject images larger than the caller's limits to avoid decompression
|
||||
// bombs (attacker-controlled dimensions would otherwise drive a huge
|
||||
// allocation here).
|
||||
if (*pwidth > maxWidth || *pheight > maxHeight) {
|
||||
DEBUG_LOG(Log::IO, "PNG too large: %dx%d (max %dx%d)", *pwidth, *pheight, maxWidth, maxHeight);
|
||||
png_destroy_read_struct(&png, &info, NULL);
|
||||
if (ret != IMAGE_PROCESS_END || !data || (int)w != peek.Width() || (int)h != peek.Height()) {
|
||||
free(data);
|
||||
ERROR_LOG(Log::IO, "PNG decode failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t row_bytes = png_get_rowbytes(png, info);
|
||||
*image_data_ptr = (unsigned char *)malloc(row_bytes * (*pheight));
|
||||
if (!*image_data_ptr) {
|
||||
png_destroy_read_struct(&png, &info, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<png_bytep> row_pointers(*pheight);
|
||||
for (int y = 0; y < *pheight; y++) {
|
||||
row_pointers[y] = *image_data_ptr + y * row_bytes;
|
||||
}
|
||||
|
||||
png_read_image(png, row_pointers.data());
|
||||
png_destroy_read_struct(&png, &info, NULL);
|
||||
*pwidth = (int)w;
|
||||
*pheight = (int)h;
|
||||
*image_data_ptr = (unsigned char *)data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -159,64 +83,57 @@ bool PNGHeaderPeek::IsValidPNGHeader() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pngSave(const Path &filename, const void *buffer, int w, int h, int bytesPerPixel) {
|
||||
png_bytepp row_ptrs = nullptr;
|
||||
|
||||
FILE *fp = File::OpenCFile(filename, "wb");
|
||||
if (!fp) {
|
||||
ERROR_LOG(Log::IO, "Unable to open png file for writing: %s", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, pngErrorHandler, pngWarningHandler);
|
||||
if (png_ptr == nullptr) {
|
||||
fclose(fp);
|
||||
ERROR_LOG(Log::IO, "PNG encode failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
png_destroy_write_struct(&png_ptr, nullptr);
|
||||
fclose(fp);
|
||||
ERROR_LOG(Log::IO, "PNG encode failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
if (row_ptrs != nullptr) {
|
||||
png_free(png_ptr, row_ptrs);
|
||||
// rpng's encoder writes to an intfstream; a memory one sized past the worst case
|
||||
// holds the whole file, which then goes out in one write.
|
||||
bool pngEncode(std::vector<uint8_t> *out, const void *buffer, int w, int h, PNGFormat format) {
|
||||
const uint8_t *src = (const uint8_t *)buffer;
|
||||
std::vector<uint8_t> bgr;
|
||||
enum rpng_pixfmt fmt;
|
||||
int bpp;
|
||||
switch (format) {
|
||||
case PNGFormat::RGBA8888: fmt = RPNG_PIXFMT_RGBA32; bpp = 4; break;
|
||||
// ARGB32 as 32-bit words is B, G, R, A in memory on little-endian hosts.
|
||||
case PNGFormat::BGRA8888: fmt = RPNG_PIXFMT_ARGB32; bpp = 4; break;
|
||||
case PNGFormat::RGB888:
|
||||
default:
|
||||
// rpng takes 24-bit pixels as BGR.
|
||||
bgr.resize((size_t)w * h * 3);
|
||||
for (size_t i = 0; i < bgr.size(); i += 3) {
|
||||
bgr[i + 0] = src[i + 2];
|
||||
bgr[i + 1] = src[i + 1];
|
||||
bgr[i + 2] = src[i + 0];
|
||||
}
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
|
||||
// Should we even do this?
|
||||
File::Delete(filename);
|
||||
|
||||
ERROR_LOG(Log::IO, "PNG encode failed.");
|
||||
src = bgr.data();
|
||||
fmt = RPNG_PIXFMT_BGR24;
|
||||
bpp = 3;
|
||||
break;
|
||||
}
|
||||
const size_t raw = (size_t)w * h * bpp;
|
||||
const size_t bound = raw + raw / 16 + (size_t)h * 8 + 4096;
|
||||
out->resize(bound);
|
||||
intfstream_t *stream = intfstream_open_memory(out->data(), RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE, bound);
|
||||
if (!stream) {
|
||||
out->clear();
|
||||
return false;
|
||||
}
|
||||
const bool ok = rpng_save_image_stream_fmt(src, stream, w, h, w * bpp, fmt, nullptr);
|
||||
const int64_t written = intfstream_get_ptr(stream);
|
||||
intfstream_close(stream);
|
||||
free(stream);
|
||||
if (!ok || written <= 0) {
|
||||
out->clear();
|
||||
return false;
|
||||
}
|
||||
out->resize((size_t)written);
|
||||
return true;
|
||||
}
|
||||
|
||||
png_set_write_fn(png_ptr, fp, [](png_structp png_ptr, png_bytep data, png_size_t size) {
|
||||
if (fwrite(data, 1, size, (FILE *)png_get_io_ptr(png_ptr)) < size) {
|
||||
png_error(png_ptr, "Failed to write to file.");
|
||||
}
|
||||
}, [](png_structp png_ptr) {
|
||||
fflush((FILE *)png_get_io_ptr(png_ptr));
|
||||
});
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, w, h, 8, bytesPerPixel == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
row_ptrs = (png_bytepp)png_malloc(png_ptr, (png_alloc_size_t)h * (png_alloc_size_t)sizeof(png_bytep));
|
||||
for (png_alloc_size_t i = 0; i < h; ++i) {
|
||||
row_ptrs[i] = (png_bytep)buffer + (png_alloc_size_t)w * (png_alloc_size_t)bytesPerPixel * i;
|
||||
bool pngSave(const Path &filename, const void *buffer, int w, int h, int bytesPerPixel) {
|
||||
std::vector<uint8_t> png;
|
||||
if (!pngEncode(&png, buffer, w, h, bytesPerPixel == 4 ? PNGFormat::RGBA8888 : PNGFormat::RGB888) ||
|
||||
!File::WriteDataToFile(false, png.data(), png.size(), filename)) {
|
||||
ERROR_LOG(Log::IO, "PNG encode failed: %s", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
png_set_rows(png_ptr, info_ptr, row_ptrs);
|
||||
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
|
||||
|
||||
png_free(png_ptr, row_ptrs);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/BitSet.h"
|
||||
#include "Common/File/Path.h"
|
||||
@@ -34,4 +35,13 @@ struct PNGHeaderPeek {
|
||||
int Height() const { return swap32(be_height); }
|
||||
};
|
||||
|
||||
// bytesPerPixel 4 is RGBA8888, 3 is RGB888.
|
||||
bool pngSave(const Path &filename, const void *buffer, int w, int h, int bytesPerPixel);
|
||||
|
||||
enum class PNGFormat {
|
||||
RGBA8888,
|
||||
BGRA8888,
|
||||
RGB888,
|
||||
};
|
||||
// Tightly packed pixels in, a complete PNG file out.
|
||||
bool pngEncode(std::vector<uint8_t> *out, const void *buffer, int w, int h, PNGFormat format = PNGFormat::RGBA8888);
|
||||
@@ -2,54 +2,15 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <zstd.h>
|
||||
#include <encodings/rzstd.h>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/Data/Format/ZIMLoad.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
|
||||
int ezuncompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen) {
|
||||
z_stream stream;
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != (uLong)nSrcLen) return Z_BUF_ERROR;
|
||||
|
||||
uInt destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
int nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||
err = Z_DATA_ERROR;
|
||||
if (err != Z_BUF_ERROR) {
|
||||
inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
|
||||
*pnDestLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int *flags, uint8_t **image) {
|
||||
if (datasize < 16) {
|
||||
ERROR_LOG(Log::IO, "ZIM file is too small");
|
||||
@@ -139,10 +100,9 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int
|
||||
}
|
||||
|
||||
if (*flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long outlen = (long)total_data_size;
|
||||
int retcode = ezuncompress(*image, &outlen, (unsigned char *)(zim + 16), (long)payload_size);
|
||||
if (Z_OK != retcode) {
|
||||
ERROR_LOG(Log::IO, "ZIM zlib format decompression failed: %d", retcode);
|
||||
const int64_t outlen = InflateBuffer(15, zim + 16, (size_t)payload_size, *image, (size_t)total_data_size);
|
||||
if (outlen < 0) {
|
||||
ERROR_LOG(Log::IO, "ZIM zlib format decompression failed");
|
||||
free(*image);
|
||||
*image = 0;
|
||||
return 0;
|
||||
@@ -152,8 +112,8 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int
|
||||
ERROR_LOG(Log::IO, "Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size);
|
||||
}
|
||||
} else if (*flags & ZIM_ZSTD_COMPRESSED) {
|
||||
size_t outlen = ZSTD_decompress(*image, total_data_size, zim + 16, payload_size);
|
||||
if (outlen != (size_t)total_data_size) {
|
||||
size_t outlen = 0;
|
||||
if (rzstd_decode(*image, total_data_size, zim + 16, payload_size, &outlen) != RZSTD_PROCESS_END || outlen != (size_t)total_data_size) {
|
||||
ERROR_LOG(Log::IO, "ZIM zstd format decompression failed: %lld", (long long)outlen);
|
||||
free(*image);
|
||||
*image = 0;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <zstd.h>
|
||||
#include <string>
|
||||
|
||||
#include "zlib.h"
|
||||
#include <encodings/rzstd.h>
|
||||
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/Data/Format/ZIMLoad.h"
|
||||
@@ -24,48 +26,6 @@ static unsigned int log2i(unsigned int val) {
|
||||
}
|
||||
|
||||
|
||||
int ezcompress(unsigned char* pDest, long* pnDestLen, const unsigned char* pSrc, long nSrcLen, int compressLevel) {
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
int nExtraChunks;
|
||||
uInt destlen;
|
||||
|
||||
stream.next_in = (Bytef*)pSrc;
|
||||
stream.avail_in = (uInt)nSrcLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != nSrcLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
destlen = (uInt)*pnDestLen;
|
||||
if ((uLong)destlen != (uLong)*pnDestLen) return Z_BUF_ERROR;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, compressLevel);
|
||||
if (err != Z_OK) return err;
|
||||
nExtraChunks = 0;
|
||||
do {
|
||||
stream.next_out = pDest;
|
||||
stream.avail_out = destlen;
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END )
|
||||
break;
|
||||
if (err != Z_OK) {
|
||||
deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
nExtraChunks += 1;
|
||||
} while (stream.avail_out == 0);
|
||||
|
||||
*pnDestLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
return nExtraChunks ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
inline int clamp16(int x) { if (x < 0) return 0; if (x > 15) return 15; return x; }
|
||||
inline int clamp32(int x) { if (x < 0) return 0; if (x > 31) return 31; return x; }
|
||||
@@ -194,19 +154,16 @@ void SaveZIM(FILE *f, int width, int height, int pitch, int flags, const uint8_t
|
||||
int data_size;
|
||||
Convert(image_data, width, height, pitch, flags, &data, &data_size);
|
||||
if (flags & ZIM_ZLIB_COMPRESSED) {
|
||||
long dest_len = data_size * 2;
|
||||
uint8_t *dest = new uint8_t[dest_len];
|
||||
if (Z_OK == ezcompress(dest, &dest_len, data, data_size, compressLevel == 0 ? Z_DEFAULT_COMPRESSION : compressLevel)) {
|
||||
fwrite(dest, 1, dest_len, f);
|
||||
std::string dest;
|
||||
if (compress_string(std::string((const char *)data, data_size), &dest, compressLevel == 0 ? 6 : compressLevel)) {
|
||||
fwrite(dest.data(), 1, dest.size(), f);
|
||||
} else {
|
||||
ERROR_LOG(Log::IO, "Zlib compression failed.\n");
|
||||
}
|
||||
delete [] dest;
|
||||
} else if (flags & ZIM_ZSTD_COMPRESSED) {
|
||||
size_t dest_len = ZSTD_compressBound(data_size);
|
||||
size_t dest_len = rzstd_compress_bound(data_size);
|
||||
uint8_t *dest = new uint8_t[dest_len];
|
||||
dest_len = ZSTD_compress(dest, dest_len, data, data_size, compressLevel == 0 ? 22 : compressLevel);
|
||||
if (!ZSTD_isError(dest_len)) {
|
||||
if (rzstd_encode(dest, dest_len, data, data_size, compressLevel == 0 ? 9 : compressLevel, &dest_len) == RZSTD_PROCESS_END) {
|
||||
fwrite(dest, 1, dest_len, f);
|
||||
} else {
|
||||
ERROR_LOG(Log::IO, "Zlib compression failed.\n");
|
||||
|
||||
+250
-213
@@ -3,12 +3,11 @@
|
||||
#include <algorithm> // for sort
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#ifdef SHARED_LIBZIP
|
||||
#include <zip.h>
|
||||
#else
|
||||
#include "ext/libzip/zip.h"
|
||||
#endif
|
||||
#include <encodings/crc32.h>
|
||||
#include <encodings/deflate.h>
|
||||
#include <zip/rzip_archive.h>
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/Log.h"
|
||||
@@ -19,13 +18,55 @@
|
||||
// malicious zip can't drive an implausible (or, near UINT64_MAX, wrapping) allocation.
|
||||
static constexpr uint64_t MAX_ZIP_ENTRY_SIZE = 1ULL << 32; // 4GB, generous for any real asset.
|
||||
|
||||
ZipContainer::ZipContainer() noexcept : sourceData_(nullptr), zip_(nullptr) {}
|
||||
|
||||
ZipContainer::ZipContainer(const Path &path) : sourceData_(new SourceData {path, nullptr}), zip_(nullptr) {
|
||||
zip_source_t *source = zip_source_function_create(SourceCallback, sourceData_, nullptr);
|
||||
if (source != nullptr && (zip_ = zip_open_from_source(source, ZIP_RDONLY, nullptr)) == nullptr) {
|
||||
zip_source_free(source);
|
||||
static std::string AsciiLower(std::string_view s) {
|
||||
std::string out(s);
|
||||
for (char &c : out) {
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Heap-allocated so the context rzip holds survives moves of the container.
|
||||
struct ZipFileSource {
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
ZipContainer::ZipContainer(const Path &path) {
|
||||
FILE *file = File::OpenCFile(path, "rb");
|
||||
if (!file)
|
||||
return;
|
||||
const int64_t size = File::GetFileSize(file);
|
||||
source_ = new ZipFileSource{ file };
|
||||
read_ = &FileRead;
|
||||
userdata_ = source_;
|
||||
if (size > 0)
|
||||
Open((uint64_t)size);
|
||||
if (!zip_)
|
||||
close();
|
||||
}
|
||||
|
||||
ZipContainer::ZipContainer(ReadFunc read, void *userdata, uint64_t size) : read_(read), userdata_(userdata) {
|
||||
Open(size);
|
||||
}
|
||||
|
||||
void ZipContainer::Open(uint64_t size) {
|
||||
rzip_archive_t *zip = nullptr;
|
||||
if (rzip_archive_open(&zip, nullptr, size, read_, userdata_) != RZIP_OK)
|
||||
return;
|
||||
zip_ = zip;
|
||||
// One pass to make name lookups cheap. First of any duplicates wins, like libzip.
|
||||
const uint32_t count = rzip_archive_num_entries(zip_);
|
||||
lowerIndex_.reserve(count);
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
lowerIndex_.emplace(AsciiLower(rzip_archive_entry(zip_, i)->name), (int)i);
|
||||
}
|
||||
|
||||
int64_t ZipContainer::FileRead(void *userdata, uint64_t off, void *dst, size_t len) {
|
||||
FILE *file = ((ZipFileSource *)userdata)->file;
|
||||
if (File::Fseek(file, (int64_t)off, SEEK_SET) != 0)
|
||||
return -1;
|
||||
return (int64_t)fread(dst, 1, len, file);
|
||||
}
|
||||
|
||||
ZipContainer::ZipContainer(ZipContainer &&other) noexcept {
|
||||
@@ -33,10 +74,14 @@ ZipContainer::ZipContainer(ZipContainer &&other) noexcept {
|
||||
}
|
||||
|
||||
ZipContainer &ZipContainer::operator=(ZipContainer &&other) noexcept {
|
||||
sourceData_ = other.sourceData_;
|
||||
zip_ = other.zip_;
|
||||
other.sourceData_ = nullptr;
|
||||
other.zip_ = nullptr;
|
||||
if (this == &other)
|
||||
return *this;
|
||||
close();
|
||||
std::swap(zip_, other.zip_);
|
||||
std::swap(source_, other.source_);
|
||||
std::swap(read_, other.read_);
|
||||
std::swap(userdata_, other.userdata_);
|
||||
lowerIndex_ = std::move(other.lowerIndex_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -45,109 +90,132 @@ ZipContainer::~ZipContainer() {
|
||||
}
|
||||
|
||||
void ZipContainer::close() noexcept {
|
||||
if (zip_ != nullptr) {
|
||||
zip_close(zip_);
|
||||
if (zip_) {
|
||||
rzip_archive_close(zip_);
|
||||
zip_ = nullptr;
|
||||
}
|
||||
delete sourceData_;
|
||||
sourceData_ = nullptr;
|
||||
}
|
||||
|
||||
ZipContainer::operator zip_t *() const noexcept {
|
||||
return zip_;
|
||||
}
|
||||
|
||||
zip_int64_t ZipContainer::SourceCallback(void *userdata, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
SourceData &sourceData = *(SourceData *)userdata;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return zip_source_make_command_bitmap(
|
||||
ZIP_SOURCE_SUPPORTS,
|
||||
ZIP_SOURCE_OPEN,
|
||||
ZIP_SOURCE_READ,
|
||||
ZIP_SOURCE_CLOSE,
|
||||
ZIP_SOURCE_STAT,
|
||||
ZIP_SOURCE_ERROR,
|
||||
ZIP_SOURCE_SEEK,
|
||||
ZIP_SOURCE_TELL,
|
||||
-1);
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
{
|
||||
FILE *newFile = File::OpenCFile(sourceData.path, "rb");
|
||||
if (newFile == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
sourceData.file = newFile;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
{
|
||||
size_t n = fread(data, 1, len, sourceData.file);
|
||||
return ferror(sourceData.file) ? -1 : n;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
fclose(sourceData.file);
|
||||
sourceData.file = nullptr;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT:
|
||||
if (sourceData.file == nullptr) {
|
||||
zip_stat_t *stat = (zip_stat_t *)data;
|
||||
zip_stat_init(stat);
|
||||
stat->valid = 0;
|
||||
} else {
|
||||
int64_t pos = File::Ftell(sourceData.file);
|
||||
if (pos == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (File::Fseek(sourceData.file, 0, SEEK_END) != 0) {
|
||||
return -1;
|
||||
}
|
||||
int64_t size = File::Ftell(sourceData.file);
|
||||
if (size != pos && File::Fseek(sourceData.file, pos, SEEK_SET) != 0) {
|
||||
return -1;
|
||||
}
|
||||
zip_stat_t *stat = (zip_stat_t *)data;
|
||||
zip_stat_init(stat);
|
||||
stat->valid = ZIP_STAT_SIZE;
|
||||
stat->size = size;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return ZIP_ER_INTERNAL;
|
||||
|
||||
case ZIP_SOURCE_SEEK:
|
||||
{
|
||||
zip_source_args_seek_t *args = (zip_source_args_seek_t *)data;
|
||||
if (args == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
return File::Fseek(sourceData.file, args->offset, args->whence) ? -1 : 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
return File::Ftell(sourceData.file);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
if (source_) {
|
||||
fclose(source_->file);
|
||||
delete source_;
|
||||
source_ = nullptr;
|
||||
}
|
||||
read_ = nullptr;
|
||||
userdata_ = nullptr;
|
||||
lowerIndex_.clear();
|
||||
}
|
||||
|
||||
int ZipContainer::NumEntries() const {
|
||||
return zip_ ? (int)rzip_archive_num_entries(zip_) : 0;
|
||||
}
|
||||
|
||||
const char *ZipContainer::Name(int index) const {
|
||||
const rzip_entry_t *e = zip_ ? rzip_archive_entry(zip_, (uint32_t)index) : nullptr;
|
||||
return e ? e->name : nullptr;
|
||||
}
|
||||
|
||||
uint64_t ZipContainer::Size(int index) const {
|
||||
const rzip_entry_t *e = zip_ ? rzip_archive_entry(zip_, (uint32_t)index) : nullptr;
|
||||
return e ? e->size : 0;
|
||||
}
|
||||
|
||||
bool ZipContainer::IsDirectory(int index) const {
|
||||
const rzip_entry_t *e = zip_ ? rzip_archive_entry(zip_, (uint32_t)index) : nullptr;
|
||||
return e && e->is_dir;
|
||||
}
|
||||
|
||||
int ZipContainer::Find(std::string_view name, bool nocase) const {
|
||||
if (!zip_)
|
||||
return -1;
|
||||
auto it = lowerIndex_.find(AsciiLower(name));
|
||||
if (it == lowerIndex_.end())
|
||||
return -1;
|
||||
if (!nocase && name != Name(it->second))
|
||||
return rzip_archive_find(zip_, std::string(name).c_str());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool ZipContainer::ExtractInto(int index, uint8_t *dst, size_t dstSize) const {
|
||||
if (!zip_)
|
||||
return false;
|
||||
size_t len = 0;
|
||||
return rzip_archive_extract_into(zip_, (uint32_t)index, dst, dstSize, &len) == RZIP_OK && len == Size(index);
|
||||
}
|
||||
|
||||
bool ZipContainer::ExtractTo(int index, const std::function<bool(const uint8_t *, size_t)> &sink) const {
|
||||
const rzip_entry_t *e = zip_ ? rzip_archive_entry(zip_, (uint32_t)index) : nullptr;
|
||||
if (!e || (e->method != RZIP_METHOD_STORED && e->method != RZIP_METHOD_DEFLATE))
|
||||
return false;
|
||||
const size_t CHUNK = 256 * 1024;
|
||||
std::vector<uint8_t> in(CHUNK);
|
||||
uint32_t crc = 0;
|
||||
uint64_t total = 0;
|
||||
uint64_t inPos = 0;
|
||||
if (e->method == RZIP_METHOD_STORED) {
|
||||
while (inPos < e->csize) {
|
||||
const size_t n = (size_t)std::min<uint64_t>(CHUNK, e->csize - inPos);
|
||||
if (read_(userdata_, e->data_off + inPos, in.data(), n) != (int64_t)n)
|
||||
return false;
|
||||
inPos += n;
|
||||
crc = encoding_crc32(crc, in.data(), n);
|
||||
total += n;
|
||||
if (!sink(in.data(), n))
|
||||
return false;
|
||||
}
|
||||
return total == e->size && crc == e->crc;
|
||||
}
|
||||
|
||||
void *inf = rinflate_new(-15);
|
||||
if (!inf)
|
||||
return false;
|
||||
std::vector<uint8_t> out(CHUNK);
|
||||
bool done = false, ok = true;
|
||||
while (ok && !done && inPos < e->csize) {
|
||||
const size_t n = (size_t)std::min<uint64_t>(CHUNK, e->csize - inPos);
|
||||
if (read_(userdata_, e->data_off + inPos, in.data(), n) != (int64_t)n) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
inPos += n;
|
||||
rinflate_set_in(inf, in.data(), n);
|
||||
for (;;) {
|
||||
rinflate_set_out(inf, out.data(), CHUNK);
|
||||
size_t rd = 0, wr = 0;
|
||||
const int status = rinflate_process(inf, &rd, &wr);
|
||||
if (wr) {
|
||||
crc = encoding_crc32(crc, out.data(), wr);
|
||||
total += wr;
|
||||
if (!sink(out.data(), wr)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status == RDEFLATE_PROCESS_END) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
if (status != RDEFLATE_PROCESS_NEXT) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
// Room left over means this piece of input is used up.
|
||||
if (wr < CHUNK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
rinflate_free(inf);
|
||||
return ok && done && total == e->size && crc == e->crc;
|
||||
}
|
||||
|
||||
ZipFileReader *ZipFileReader::Create(const Path &zipFile, std::string_view inZipPath, bool logErrors) {
|
||||
// The inZipPath is supposed to be a folder, and internally in this class, we suffix
|
||||
// folder paths with '/', matching how the zip library works.
|
||||
// folder paths with '/', matching how zip files name things.
|
||||
std::string path(inZipPath);
|
||||
if (!path.empty() && path.back() != '/') {
|
||||
path.push_back('/');
|
||||
}
|
||||
|
||||
ZipContainer zip(zipFile);
|
||||
if (zip == nullptr) {
|
||||
if (!zip) {
|
||||
if (logErrors) {
|
||||
ERROR_LOG(Log::IO, "Failed to open %s as a zip file", zipFile.c_str());
|
||||
}
|
||||
@@ -165,32 +233,30 @@ ZipFileReader::~ZipFileReader() {
|
||||
uint8_t *ZipFileReader::ReadFile(std::string_view path, size_t *size) {
|
||||
std::string temp_path = join(inZipPath_, path);
|
||||
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
// Figure out the file size first. TODO: Can this part be done without locking the mutex?
|
||||
struct zip_stat zstat;
|
||||
int retval = zip_stat(zip_file_, temp_path.c_str(), ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat);
|
||||
if (retval != 0) {
|
||||
const int index = zip_file_.Find(temp_path);
|
||||
if (index < 0) {
|
||||
ERROR_LOG(Log::IO, "Error opening %s from ZIP", temp_path.c_str());
|
||||
return 0;
|
||||
}
|
||||
// Sanity check the declared size before trusting it for an allocation - a corrupt
|
||||
// or malicious zip could claim a huge (even ~UINT64_MAX, which would wrap the +1
|
||||
// below to 0) size here.
|
||||
if (zstat.size > MAX_ZIP_ENTRY_SIZE) {
|
||||
ERROR_LOG(Log::IO, "Zip entry %s claims an implausible size (%llu), refusing to read", temp_path.c_str(), (unsigned long long)zstat.size);
|
||||
const uint64_t entrySize = zip_file_.Size(index);
|
||||
// Sanity check the declared size before trusting it for an allocation.
|
||||
if (entrySize > MAX_ZIP_ENTRY_SIZE) {
|
||||
ERROR_LOG(Log::IO, "Zip entry %s claims an implausible size (%llu), refusing to read", temp_path.c_str(), (unsigned long long)entrySize);
|
||||
return 0;
|
||||
}
|
||||
zip_file *file = zip_fopen_index(zip_file_, zstat.index, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED);
|
||||
if (!file) {
|
||||
ERROR_LOG(Log::IO, "Error opening %s from ZIP", temp_path.c_str());
|
||||
uint8_t *contents = new uint8_t[entrySize + 1];
|
||||
bool ok;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
ok = zip_file_.ExtractInto(index, contents, (size_t)entrySize);
|
||||
}
|
||||
if (!ok) {
|
||||
ERROR_LOG(Log::IO, "Error reading %s from ZIP", temp_path.c_str());
|
||||
delete[] contents;
|
||||
return 0;
|
||||
}
|
||||
uint8_t *contents = new uint8_t[zstat.size + 1];
|
||||
zip_fread(file, contents, zstat.size);
|
||||
zip_fclose(file);
|
||||
contents[zstat.size] = 0;
|
||||
|
||||
*size = zstat.size;
|
||||
contents[entrySize] = 0;
|
||||
*size = (size_t)entrySize;
|
||||
return contents;
|
||||
}
|
||||
|
||||
@@ -228,8 +294,6 @@ bool ZipFileReader::GetFileListing(std::string_view orig_path, std::vector<File:
|
||||
|
||||
listing->clear();
|
||||
|
||||
// INFO_LOG(Log::IO, "Zip: Listing '%s'", orig_path);
|
||||
|
||||
const std::string relativePath = path.substr(inZipPath_.size());
|
||||
|
||||
listing->reserve(directories.size() + files.size());
|
||||
@@ -242,7 +306,6 @@ bool ZipFileReader::GetFileListing(std::string_view orig_path, std::vector<File:
|
||||
info.exists = true;
|
||||
info.isWritable = false;
|
||||
info.isDirectory = true;
|
||||
// INFO_LOG(Log::IO, "Found file: %s (%s)", info.name.c_str(), info.fullName.c_str());
|
||||
listing->push_back(info);
|
||||
}
|
||||
|
||||
@@ -259,7 +322,6 @@ bool ZipFileReader::GetFileListing(std::string_view orig_path, std::vector<File:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// INFO_LOG(Log::IO, "Found dir: %s (%s)", info.name.c_str(), info.fullName.c_str());
|
||||
listing->push_back(info);
|
||||
}
|
||||
|
||||
@@ -271,11 +333,11 @@ bool ZipFileReader::GetFileListing(std::string_view orig_path, std::vector<File:
|
||||
bool ZipFileReader::GetZipListings(const std::string &path, std::set<std::string> &files, std::set<std::string> &directories) {
|
||||
_dbg_assert_(path.empty() || path.back() == '/');
|
||||
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
int numFiles = zip_get_num_files(zip_file_);
|
||||
// The directory is parsed at open and never changes, so this needs no lock.
|
||||
const int numFiles = zip_file_.NumEntries();
|
||||
bool anyPrefixMatched = false;
|
||||
for (int i = 0; i < numFiles; i++) {
|
||||
const char* name = zip_get_name(zip_file_, i, 0);
|
||||
const char *name = zip_file_.Name(i);
|
||||
if (!name)
|
||||
continue; // shouldn't happen, I think
|
||||
if (startsWith(name, path)) {
|
||||
@@ -303,7 +365,6 @@ bool ZipFileReader::GetZipListings(const std::string &path, std::set<std::string
|
||||
}
|
||||
|
||||
bool ZipFileReader::GetFileInfo(std::string_view path, File::FileInfo *info) {
|
||||
struct zip_stat zstat;
|
||||
std::string temp_path = join(inZipPath_, path);
|
||||
|
||||
// Clear some things to start.
|
||||
@@ -311,24 +372,17 @@ bool ZipFileReader::GetFileInfo(std::string_view path, File::FileInfo *info) {
|
||||
info->isWritable = false;
|
||||
info->size = 0;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
if (0 != zip_stat(zip_file_, temp_path.c_str(), ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) {
|
||||
// ZIP files do not have real directories, so we'll end up here if we
|
||||
// try to stat one. For now that's fine.
|
||||
info->exists = false;
|
||||
return false;
|
||||
}
|
||||
const int index = zip_file_.Find(temp_path);
|
||||
if (index < 0) {
|
||||
// ZIP files do not have real directories, so we'll end up here if we
|
||||
// try to stat one. For now that's fine.
|
||||
info->exists = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Zips usually don't contain directory entries, but they may.
|
||||
if ((zstat.valid & ZIP_STAT_NAME) != 0 && zstat.name && zstat.name[0] != '\0') {
|
||||
info->isDirectory = zstat.name[strlen(zstat.name) - 1] == '/';
|
||||
}
|
||||
if ((zstat.valid & ZIP_STAT_SIZE) != 0) {
|
||||
info->size = zstat.size;
|
||||
}
|
||||
|
||||
info->isDirectory = zip_file_.IsDirectory(index);
|
||||
info->size = zip_file_.Size(index);
|
||||
info->fullName = Path(path);
|
||||
info->exists = true;
|
||||
return true;
|
||||
@@ -339,19 +393,19 @@ public:
|
||||
int zi;
|
||||
};
|
||||
|
||||
// Members are decoded whole: straight into the caller's buffer when the first
|
||||
// read asks for all of it, which is how files are read here, else into data.
|
||||
class ZipFileReaderOpenFile : public VFSOpenFile {
|
||||
public:
|
||||
~ZipFileReaderOpenFile() {
|
||||
// Needs to be closed properly and unlocked.
|
||||
_dbg_assert_(zf == nullptr);
|
||||
}
|
||||
ZipFileReaderFileReference *reference;
|
||||
zip_file_t *zf = nullptr;
|
||||
size_t size = 0;
|
||||
size_t pos = 0;
|
||||
bool decoded = false;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
||||
VFSFileReference *ZipFileReader::GetFile(std::string_view path) {
|
||||
std::string p(path);
|
||||
int zi = zip_name_locate(zip_file_, p.c_str(), ZIP_FL_NOCASE); // this is EXPENSIVE
|
||||
int zi = zip_file_.Find(path);
|
||||
if (zi < 0) {
|
||||
// Not found.
|
||||
return nullptr;
|
||||
@@ -363,16 +417,9 @@ VFSFileReference *ZipFileReader::GetFile(std::string_view path) {
|
||||
|
||||
bool ZipFileReader::GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) {
|
||||
ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference;
|
||||
// If you crash here, you called this while having the lock held by having the file open.
|
||||
// Don't do that, check the info before you open the file.
|
||||
zip_stat_t zstat;
|
||||
if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0)
|
||||
return false;
|
||||
*fileInfo = File::FileInfo{};
|
||||
fileInfo->size = 0;
|
||||
if (zstat.valid & ZIP_STAT_SIZE)
|
||||
fileInfo->size = zstat.size;
|
||||
return zstat.size;
|
||||
fileInfo->size = zip_file_.Size(reference->zi);
|
||||
return fileInfo->size != 0;
|
||||
}
|
||||
|
||||
void ZipFileReader::ReleaseFile(VFSFileReference *vfsReference) {
|
||||
@@ -383,93 +430,83 @@ void ZipFileReader::ReleaseFile(VFSFileReference *vfsReference) {
|
||||
|
||||
VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference, size_t *size) {
|
||||
ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference;
|
||||
*size = 0;
|
||||
const uint64_t entrySize = zip_file_.Size(reference->zi);
|
||||
if (entrySize > MAX_ZIP_ENTRY_SIZE) {
|
||||
WARN_LOG(Log::G3D, "File with index %d in zip has an implausible size", reference->zi);
|
||||
return nullptr;
|
||||
}
|
||||
ZipFileReaderOpenFile *openFile = new ZipFileReaderOpenFile();
|
||||
openFile->reference = reference;
|
||||
*size = 0;
|
||||
// We only allow one file to be open for read concurrently. It's possible that this can be improved,
|
||||
// especially if we only access by index like this.
|
||||
lock_.lock();
|
||||
zip_stat_t zstat;
|
||||
if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0) {
|
||||
lock_.unlock();
|
||||
delete openFile;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0);
|
||||
if (!openFile->zf) {
|
||||
WARN_LOG(Log::G3D, "File with index %d not found in zip", reference->zi);
|
||||
lock_.unlock();
|
||||
delete openFile;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*size = zstat.size;
|
||||
// Intentionally leaving the mutex locked, will be closed in CloseFile.
|
||||
openFile->size = (size_t)entrySize;
|
||||
*size = openFile->size;
|
||||
return openFile;
|
||||
}
|
||||
|
||||
void ZipFileReader::Rewind(VFSOpenFile *vfsOpenFile) {
|
||||
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
|
||||
_assert_(file);
|
||||
// Unless the zip file is compressed, can't seek directly, so we re-open.
|
||||
// This version of libzip doesn't even have zip_file_is_seekable(), should probably upgrade.
|
||||
zip_fclose(file->zf);
|
||||
file->zf = zip_fopen_index(zip_file_, file->reference->zi, 0);
|
||||
_dbg_assert_(file->zf != nullptr);
|
||||
file->pos = 0;
|
||||
}
|
||||
|
||||
size_t ZipFileReader::Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) {
|
||||
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
|
||||
_assert_(file);
|
||||
_dbg_assert_(file->zf != nullptr);
|
||||
return zip_fread(file->zf, buffer, length);
|
||||
if (file->pos >= file->size)
|
||||
return 0;
|
||||
if (!file->decoded && file->pos == 0 && length >= file->size) {
|
||||
// The whole member in one read: decode it where it's going.
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
if (!zip_file_.ExtractInto(file->reference->zi, (uint8_t *)buffer, file->size))
|
||||
return 0;
|
||||
file->pos = file->size;
|
||||
return file->size;
|
||||
}
|
||||
if (!file->decoded) {
|
||||
file->data.resize(file->size);
|
||||
std::lock_guard<std::mutex> guard(lock_);
|
||||
if (!zip_file_.ExtractInto(file->reference->zi, file->data.data(), file->size))
|
||||
return 0;
|
||||
file->decoded = true;
|
||||
}
|
||||
const size_t n = std::min(length, file->size - file->pos);
|
||||
memcpy(buffer, file->data.data() + file->pos, n);
|
||||
file->pos += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
void ZipFileReader::CloseFile(VFSOpenFile *vfsOpenFile) {
|
||||
ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile;
|
||||
_assert_(file);
|
||||
_dbg_assert_(file->zf != nullptr);
|
||||
zip_fclose(file->zf);
|
||||
file->zf = nullptr;
|
||||
vfsOpenFile = nullptr;
|
||||
lock_.unlock();
|
||||
delete file;
|
||||
}
|
||||
|
||||
bool ReadSingleFileFromZip(Path zipFile, const char *path, std::string *data, std::mutex *mutex) {
|
||||
ZipContainer zip(zipFile);
|
||||
if (zip == nullptr) {
|
||||
if (!zip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct zip_stat zstat;
|
||||
if (zip_stat(zip, path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat) != 0) {
|
||||
const int index = zip.Find(path);
|
||||
if (index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (zstat.size > MAX_ZIP_ENTRY_SIZE) {
|
||||
ERROR_LOG(Log::IO, "Zip entry %s claims an implausible size (%llu), refusing to read", path, (unsigned long long)zstat.size);
|
||||
const uint64_t size = zip.Size(index);
|
||||
if (size > MAX_ZIP_ENTRY_SIZE) {
|
||||
ERROR_LOG(Log::IO, "Zip entry %s claims an implausible size (%llu), refusing to read", path, (unsigned long long)size);
|
||||
return false;
|
||||
}
|
||||
zip_file *file = zip_fopen_index(zip, zstat.index, ZIP_FL_UNCHANGED);
|
||||
if (!file) {
|
||||
std::string contents;
|
||||
contents.resize((size_t)size);
|
||||
if (!zip.ExtractInto(index, (uint8_t *)&contents[0], contents.size())) {
|
||||
return false;
|
||||
}
|
||||
if (mutex) {
|
||||
mutex->lock();
|
||||
}
|
||||
data->resize(zstat.size);
|
||||
if (zip_fread(file, data->data(), zstat.size) != zstat.size) {
|
||||
if (mutex) {
|
||||
mutex->unlock();
|
||||
}
|
||||
data->resize(0);
|
||||
zip_fclose(file);
|
||||
return false;
|
||||
}
|
||||
data->swap(contents);
|
||||
if (mutex) {
|
||||
mutex->unlock();
|
||||
}
|
||||
zip_fclose(file);
|
||||
return true;
|
||||
}
|
||||
@@ -1,40 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SHARED_LIBZIP
|
||||
#include <zip.h>
|
||||
#else
|
||||
#include "ext/libzip/zip.h"
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/File/Path.h"
|
||||
|
||||
struct rzip_archive;
|
||||
struct ZipFileSource;
|
||||
|
||||
// A zip archive read with libretro-common's rzip_archive. The bytes come through
|
||||
// a positioned read: from a file opened here, or from the caller's own source.
|
||||
class ZipContainer {
|
||||
public:
|
||||
ZipContainer() noexcept;
|
||||
ZipContainer(const Path &path);
|
||||
// Positioned read of len bytes at off; returns bytes read, or negative on error.
|
||||
typedef int64_t (*ReadFunc)(void *userdata, uint64_t off, void *dst, size_t len);
|
||||
|
||||
ZipContainer() noexcept {}
|
||||
explicit ZipContainer(const Path &path);
|
||||
ZipContainer(ReadFunc read, void *userdata, uint64_t size);
|
||||
~ZipContainer();
|
||||
ZipContainer(const ZipContainer &) = delete;
|
||||
ZipContainer(ZipContainer &&) noexcept;
|
||||
ZipContainer(ZipContainer &&other) noexcept;
|
||||
ZipContainer &operator=(const ZipContainer &) = delete;
|
||||
ZipContainer &operator=(ZipContainer &&) noexcept;
|
||||
ZipContainer &operator=(ZipContainer &&other) noexcept;
|
||||
void close() noexcept;
|
||||
operator zip_t *() const noexcept;
|
||||
|
||||
explicit operator bool() const noexcept { return zip_ != nullptr; }
|
||||
rzip_archive *Raw() const noexcept { return zip_; }
|
||||
|
||||
int NumEntries() const;
|
||||
const char *Name(int index) const;
|
||||
uint64_t Size(int index) const;
|
||||
bool IsDirectory(int index) const;
|
||||
// Exact match, or ASCII case-insensitive when nocase is set. -1 if absent.
|
||||
int Find(std::string_view name, bool nocase = true) const;
|
||||
// The member decoded straight into dst, which has room for Size(index) bytes.
|
||||
bool ExtractInto(int index, uint8_t *dst, size_t dstSize) const;
|
||||
// The member decoded a piece at a time, each piece handed to sink as it comes out
|
||||
// (sink returns false to stop), for members too big to hold. The CRC is checked.
|
||||
bool ExtractTo(int index, const std::function<bool(const uint8_t *, size_t)> &sink) const;
|
||||
|
||||
private:
|
||||
struct SourceData {
|
||||
Path path;
|
||||
FILE *file;
|
||||
} *sourceData_;
|
||||
zip_t *zip_;
|
||||
void Open(uint64_t size);
|
||||
static int64_t FileRead(void *userdata, uint64_t off, void *dst, size_t len);
|
||||
|
||||
static zip_int64_t SourceCallback(void *userdata, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
|
||||
rzip_archive *zip_ = nullptr;
|
||||
ZipFileSource *source_ = nullptr;
|
||||
ReadFunc read_ = nullptr;
|
||||
void *userdata_ = nullptr;
|
||||
std::unordered_map<std::string, int> lowerIndex_;
|
||||
};
|
||||
|
||||
class ZipFileReader : public VFSBackend {
|
||||
@@ -42,7 +64,7 @@ public:
|
||||
static ZipFileReader *Create(const Path &zipFile, std::string_view inZipPath, bool logErrors = true);
|
||||
~ZipFileReader();
|
||||
|
||||
bool IsValid() const { return zip_file_ != nullptr; }
|
||||
bool IsValid() const { return (bool)zip_file_; }
|
||||
|
||||
// use delete[] on the returned value.
|
||||
uint8_t *ReadFile(std::string_view path, size_t *size) override;
|
||||
@@ -68,7 +90,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
ZipFileReader(ZipContainer &&zip, const Path &zipPath, const std::string &inZipPath) : zip_file_(std::move(zip)), zipPath_(zipPath), inZipPath_(inZipPath) {}
|
||||
ZipFileReader(ZipContainer &&zip, const Path &zipPath, const std::string &inZipPath) : zip_file_(std::move(zip)), inZipPath_(inZipPath), zipPath_(zipPath) {}
|
||||
// Path has to be either an empty string, or a string ending with a /.
|
||||
bool GetZipListings(const std::string &path, std::set<std::string> &files, std::set<std::string> &directories);
|
||||
|
||||
@@ -79,5 +101,5 @@ private:
|
||||
};
|
||||
|
||||
// When you just want a single file from a ZIP, and don't care about accurate error reporting, use this.
|
||||
// The buffer should be free'd with free. Mutex will be locked while updating data, if non-null.
|
||||
// Mutex will be locked while updating data, if non-null.
|
||||
bool ReadSingleFileFromZip(Path zipFile, const char *path, std::string *data, std::mutex *mutex);
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <png.h>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <zstd.h>
|
||||
#include <encodings/rzstd.h>
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/Render/TextureAtlas.h"
|
||||
@@ -39,7 +39,9 @@ public:
|
||||
offset_ += sizeof(uint32_t);
|
||||
|
||||
_dbg_assert_(offset_ + compressed_size <= size_);
|
||||
ZSTD_decompress(t, sizeof(T) * count, data_ + offset_, compressed_size);
|
||||
size_t wrote = 0;
|
||||
if (rzstd_decode((uint8_t *)t, sizeof(T) * count, data_ + offset_, compressed_size, &wrote) != RZSTD_PROCESS_END)
|
||||
memset((void *)t, 0, sizeof(T) * count);
|
||||
offset_ += compressed_size;
|
||||
}
|
||||
return t;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <snappy-c.h>
|
||||
#include <zstd.h>
|
||||
#include <encodings/rzstd.h>
|
||||
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
@@ -433,10 +433,10 @@ CChunkFileReader::Error CChunkFileReader::LoadFile(const Path &filename, std::st
|
||||
auto status = snappy_uncompress((const char *)buffer, sz, (char *)uncomp_buffer, &uncomp_size);
|
||||
success = status == SNAPPY_OK;
|
||||
} else if (SerializeCompressType(header.Compress) == SerializeCompressType::ZSTD) {
|
||||
size_t status = ZSTD_decompress((char *)uncomp_buffer, uncomp_size, (const char *)buffer, sz);
|
||||
success = !ZSTD_isError(status);
|
||||
size_t wrote = 0;
|
||||
success = rzstd_decode(uncomp_buffer, uncomp_size, buffer, sz, &wrote) == RZSTD_PROCESS_END;
|
||||
if (success) {
|
||||
uncomp_size = status;
|
||||
uncomp_size = wrote;
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(Log::SaveState, "ChunkReader: Unexpected compression type %d", header.Compress);
|
||||
@@ -491,7 +491,7 @@ CChunkFileReader::Error CChunkFileReader::SaveFile(const Path &filename, const s
|
||||
write_len = snappy_max_compressed_length(sz);
|
||||
break;
|
||||
case SerializeCompressType::ZSTD:
|
||||
write_len = ZSTD_compressBound(sz);
|
||||
write_len = rzstd_compress_bound(sz);
|
||||
break;
|
||||
}
|
||||
u8 *compressed_buffer = write_len == 0 ? nullptr : (u8 *)malloc(write_len);
|
||||
@@ -512,20 +512,7 @@ CChunkFileReader::Error CChunkFileReader::SaveFile(const Path &filename, const s
|
||||
success = snappy_compress((const char *)buffer, sz, (char *)compressed_buffer, &write_len) == SNAPPY_OK;
|
||||
break;
|
||||
case SerializeCompressType::ZSTD:
|
||||
{
|
||||
auto ctx = ZSTD_createCCtx();
|
||||
if (!ctx) {
|
||||
success = false;
|
||||
} else {
|
||||
// TODO: If free disk space is low, we could max this out to 22?
|
||||
ZSTD_CCtx_setParameter(ctx, ZSTD_c_compressionLevel, ZSTD_CLEVEL_DEFAULT);
|
||||
ZSTD_CCtx_setParameter(ctx, ZSTD_c_checksumFlag, 1);
|
||||
ZSTD_CCtx_setPledgedSrcSize(ctx, sz);
|
||||
write_len = ZSTD_compress2(ctx, compressed_buffer, write_len, buffer, sz);
|
||||
success = !ZSTD_isError(write_len);
|
||||
}
|
||||
ZSTD_freeCCtx(ctx);
|
||||
}
|
||||
success = rzstd_encode(compressed_buffer, write_len, buffer, sz, 3, &write_len) == RZSTD_PROCESS_END;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+1
-7
@@ -721,10 +721,6 @@ if((MACOSX OR IOS) AND NOT LIBRETRO)
|
||||
PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
endif()
|
||||
|
||||
if(LIBRETRO)
|
||||
target_include_directories(Core PRIVATE ${CMAKE_SOURCE_DIR}/libretro/libretro-common/include)
|
||||
endif()
|
||||
|
||||
set(CoreExtraLibs)
|
||||
if(ANDROID)
|
||||
list(APPEND CoreExtraLibs android)
|
||||
@@ -735,7 +731,7 @@ endif()
|
||||
|
||||
list(APPEND CoreExtraLibs armips)
|
||||
|
||||
target_link_libraries(Core GPU Common chdr kirk cityhash sfmt19937 xbrz xxhash rcheevos at3_standalone lua
|
||||
target_link_libraries(Core GPU Common libretro-common kirk cityhash sfmt19937 xbrz xxhash rcheevos at3_standalone lua
|
||||
aemu_postoffice_client ${CoreExtraLibs} ${CMAKE_DL_LIBS})
|
||||
|
||||
# Winsock
|
||||
@@ -762,7 +758,6 @@ if(FFmpeg_FOUND)
|
||||
FFmpeg::avutil
|
||||
FFmpeg::swresample
|
||||
FFmpeg::swscale
|
||||
${ZLIB_LIBRARY}
|
||||
)
|
||||
elseif(BUILD_BUNDLED_FFMPEG)
|
||||
target_compile_definitions(Core PRIVATE USE_FFMPEG=1)
|
||||
@@ -773,7 +768,6 @@ elseif(BUILD_BUNDLED_FFMPEG)
|
||||
avutil
|
||||
swresample
|
||||
swscale
|
||||
${ZLIB_LIBRARY}
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
+25
-93
@@ -34,7 +34,7 @@
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
|
||||
#include "ext/armips/Core/Assembler.h"
|
||||
|
||||
@@ -82,31 +82,32 @@ void SymbolMap::Clear() {
|
||||
bool SymbolMap::LoadSymbolMap(const Path &filename) {
|
||||
Clear();
|
||||
|
||||
// TODO(scoped): Use gzdopen instead.
|
||||
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
gzFile f = gzopen_w(filename.ToWString().c_str(), "r");
|
||||
#else
|
||||
gzFile f = gzopen(filename.c_str(), "r");
|
||||
#endif
|
||||
|
||||
if (f == Z_NULL)
|
||||
// The map may be gzipped (bCompressSymbols) or plain text.
|
||||
std::string contents;
|
||||
if (!File::ReadBinaryFileToString(filename, &contents))
|
||||
return false;
|
||||
|
||||
//char temp[256];
|
||||
//fgets(temp,255,f); //.text section layout
|
||||
//fgets(temp,255,f); // Starting Virtual
|
||||
//fgets(temp,255,f); // address Size address
|
||||
//fgets(temp,255,f); // -----------------------
|
||||
if (contents.size() >= 2 && (u8)contents[0] == 0x1f && (u8)contents[1] == 0x8b) {
|
||||
std::string plain;
|
||||
if (!decompress_string(contents, &plain))
|
||||
return false;
|
||||
contents.swap(plain);
|
||||
}
|
||||
size_t pos = 0;
|
||||
|
||||
bool started = false;
|
||||
bool hasModules = false;
|
||||
|
||||
while (!gzeof(f)) {
|
||||
while (pos < contents.size()) {
|
||||
char line[512], temp[256] = {0};
|
||||
char *p = gzgets(f, line, 512);
|
||||
if (p == NULL)
|
||||
break;
|
||||
size_t end = contents.find('\n', pos);
|
||||
if (end == std::string::npos)
|
||||
end = contents.size();
|
||||
const size_t len = std::min(end - pos, sizeof(line) - 1);
|
||||
memcpy(line, contents.data() + pos, len);
|
||||
line[len] = '\0';
|
||||
pos = end + 1;
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
// Chop any newlines off.
|
||||
for (size_t i = strlen(line) - 1; i > 0; i--) {
|
||||
@@ -205,7 +206,6 @@ bool SymbolMap::LoadSymbolMap(const Path &filename) {
|
||||
}
|
||||
}
|
||||
}
|
||||
gzclose(f);
|
||||
activeNeedUpdate_ = true;
|
||||
SortSymbols();
|
||||
return started;
|
||||
@@ -233,81 +233,13 @@ bool SymbolMap::SaveSymbolMap(const Path &filename) const {
|
||||
|
||||
std::string data;
|
||||
buf.TakeAll(&data);
|
||||
FILE *file = File::OpenCFile(filename, "wb");
|
||||
if (file == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (g_Config.bCompressSymbols) {
|
||||
uInt out_size = 4096;
|
||||
Bytef *out_data = (Bytef *)std::malloc(out_size);
|
||||
if (out_data == nullptr) {
|
||||
fclose(file);
|
||||
std::string compressed;
|
||||
if (!compress_string(data, &compressed, 9, 31))
|
||||
return false;
|
||||
}
|
||||
z_stream strm;
|
||||
strm.zalloc = nullptr;
|
||||
strm.zfree = nullptr;
|
||||
strm.opaque = nullptr;
|
||||
if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
std::free(out_data);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
strm.next_in = (Bytef *)data.data();
|
||||
strm.avail_in = (u32)data.size();
|
||||
strm.next_out = out_data;
|
||||
strm.avail_out = out_size;
|
||||
int flush = Z_NO_FLUSH;
|
||||
for (;;) {
|
||||
int status = deflate(&strm, flush);
|
||||
switch (status) {
|
||||
case Z_OK:
|
||||
case Z_STREAM_END:
|
||||
if (strm.avail_out != out_size) {
|
||||
fwrite(out_data, 1, out_size - strm.avail_out, file);
|
||||
}
|
||||
break;
|
||||
case Z_BUF_ERROR:
|
||||
{
|
||||
std::free(out_data);
|
||||
uInt new_out_size = 2 * out_size;
|
||||
if (new_out_size < out_size) {
|
||||
deflateEnd(&strm);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
out_size = new_out_size;
|
||||
out_data = (Bytef *)std::malloc(out_size);
|
||||
if (out_data == nullptr) {
|
||||
deflateEnd(&strm);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
deflateEnd(&strm);
|
||||
std::free(out_data);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
if (status == Z_STREAM_END) {
|
||||
break;
|
||||
}
|
||||
if (strm.avail_in == 0) {
|
||||
flush = Z_FINISH;
|
||||
}
|
||||
strm.next_out = out_data;
|
||||
strm.avail_out = out_size;
|
||||
}
|
||||
deflateEnd(&strm);
|
||||
std::free(out_data);
|
||||
} else {
|
||||
// Just plain write it.
|
||||
fwrite(data.data(), 1, data.size(), file);
|
||||
data.swap(compressed);
|
||||
}
|
||||
fclose(file);
|
||||
return true;
|
||||
return File::WriteDataToFile(false, data.data(), data.size(), filename);
|
||||
}
|
||||
|
||||
bool SymbolMap::LoadNocashSym(const Path &filename) {
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <algorithm>
|
||||
#include <png.h>
|
||||
#include <zlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Data/Format/PNGLoad.h"
|
||||
#include "Common/Data/Encoding/Base64.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Debugger/WebSocket/GPUBufferSubscriber.h"
|
||||
@@ -61,22 +62,13 @@ static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &bu
|
||||
h = totalPixels / w;
|
||||
}
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_ptr) {
|
||||
req.Fail("Internal error setting up PNG encoder (png_ptr)");
|
||||
std::vector<uint8_t> png;
|
||||
const bool encoded = pngEncode(&png, buffer, w, h, includeAlpha ? PNGFormat::RGBA8888 : PNGFormat::RGB888);
|
||||
delete [] flipbuffer;
|
||||
if (!encoded) {
|
||||
req.Fail("Internal error encoding PNG");
|
||||
return false;
|
||||
}
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_write_struct(&png_ptr, nullptr);
|
||||
req.Fail("Internal error setting up PNG encoder (info_ptr)");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Speed. Wireless N should give 35 KB/ms. For most devices, zlib/filters will cost more.
|
||||
png_set_compression_strategy(png_ptr, Z_RLE);
|
||||
png_set_compression_level(png_ptr, 1);
|
||||
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
|
||||
|
||||
auto &json = req.Respond();
|
||||
json.writeInt("width", w);
|
||||
@@ -88,68 +80,12 @@ static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &bu
|
||||
// Start a value...
|
||||
json.writeRaw("uri", "");
|
||||
req.Flush();
|
||||
// Now we'll write it directly to the stream.
|
||||
// Now we'll write it directly to the stream, in pieces that are a multiple of 3 bytes
|
||||
// so the base64 has no padding until the end.
|
||||
req.ws->AddFragment(false, "\"data:image/png;base64,");
|
||||
|
||||
struct Context {
|
||||
DebuggerRequest *req;
|
||||
uint8_t buf[3];
|
||||
size_t bufSize;
|
||||
};
|
||||
Context ctx = { &req, {}, 0 };
|
||||
|
||||
auto write = [](png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
auto ctx = (Context *)png_get_io_ptr(png_ptr);
|
||||
auto &req = *ctx->req;
|
||||
|
||||
// If we buffered some bytes, fill to 3 bytes for a clean base64 encode.
|
||||
// This way we don't have padding.
|
||||
while (length > 0 && ctx->bufSize > 0 && ctx->bufSize != 3) {
|
||||
ctx->buf[ctx->bufSize++] = data[0];
|
||||
data++;
|
||||
length--;
|
||||
}
|
||||
|
||||
if (ctx->bufSize == 3) {
|
||||
req.ws->AddFragment(false, Base64Encode(ctx->buf, ctx->bufSize));
|
||||
ctx->bufSize = 0;
|
||||
}
|
||||
_assert_(ctx->bufSize == 0 || length == 0);
|
||||
|
||||
// Save bytes that would result in padding for next time.
|
||||
size_t toBuffer = length % 3;
|
||||
for (size_t i = 0; i < toBuffer; ++i) {
|
||||
ctx->buf[i] = data[length - toBuffer + i];
|
||||
ctx->bufSize++;
|
||||
}
|
||||
|
||||
if (length > toBuffer) {
|
||||
req.ws->AddFragment(false, Base64Encode(data, length - toBuffer));
|
||||
}
|
||||
};
|
||||
auto flush = [](png_structp png_ptr) {
|
||||
// Nothing, just here to prevent stdio flush.
|
||||
};
|
||||
|
||||
png_bytep *row_pointers = new png_bytep[h];
|
||||
u32 stride = includeAlpha ? w * 4 : w * 3;
|
||||
for (u32 i = 0; i < h; ++i) {
|
||||
row_pointers[i] = (u8 *)buffer + stride * i;
|
||||
}
|
||||
|
||||
png_set_write_fn(png_ptr, &ctx, write, flush);
|
||||
int colorType = includeAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB;
|
||||
png_set_IHDR(png_ptr, info_ptr, w, h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
png_set_rows(png_ptr, info_ptr, row_pointers);
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
|
||||
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
delete [] row_pointers;
|
||||
delete [] flipbuffer;
|
||||
|
||||
if (ctx.bufSize > 0) {
|
||||
req.ws->AddFragment(false, Base64Encode(ctx.buf, ctx.bufSize));
|
||||
ctx.bufSize = 0;
|
||||
const size_t piece = 3 * 16384;
|
||||
for (size_t pos = 0; pos < png.size(); pos += piece) {
|
||||
req.ws->AddFragment(false, Base64Encode(png.data() + pos, std::min(piece, png.size() - pos)));
|
||||
}
|
||||
|
||||
// End the string.
|
||||
|
||||
@@ -187,8 +187,18 @@ size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void
|
||||
|
||||
#if defined(HAVE_LIBRETRO_VFS)
|
||||
std::lock_guard<std::mutex> guard(readLock_);
|
||||
File::Fseek(file_, absolutePos, SEEK_SET);
|
||||
return fread(data, bytes, count, file_);
|
||||
// The VFS has no positioned read. Only seek when the read isn't sequential:
|
||||
// a seek also throws away whatever the frontend's stream had buffered.
|
||||
if (filePos_ != absolutePos) {
|
||||
if (File::Fseek(file_, absolutePos, SEEK_SET) != 0) {
|
||||
filePos_ = -1;
|
||||
return 0;
|
||||
}
|
||||
filePos_ = absolutePos;
|
||||
}
|
||||
const size_t done = fread(data, 1, bytes * count, file_);
|
||||
filePos_ = done == bytes * count ? filePos_ + (s64)done : -1;
|
||||
return done / bytes;
|
||||
#elif PPSSPP_PLATFORM(SWITCH)
|
||||
// Toolchain has no fancy IO API. We must lock.
|
||||
std::lock_guard<std::mutex> guard(readLock_);
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
private:
|
||||
#ifdef HAVE_LIBRETRO_VFS
|
||||
FILE *file_ = nullptr;
|
||||
s64 filePos_ = -1; // where file_ is; -1 when unknown
|
||||
#elif !defined(_WIN32)
|
||||
void DetectSizeFd();
|
||||
int fd_ = -1;
|
||||
|
||||
@@ -1,69 +1,46 @@
|
||||
#ifdef SHARED_LIBZIP
|
||||
#include <zip.h>
|
||||
#else
|
||||
#include "ext/libzip/zip.h"
|
||||
#endif
|
||||
#include <zip/rzip_archive.h>
|
||||
|
||||
#include "Core/FileLoaders/LocalFileLoader.h"
|
||||
#include "Core/FileLoaders/ZipFileLoader.h"
|
||||
|
||||
int64_t ZipFileLoader::BackendRead(void *userdata, uint64_t off, void *dst, size_t len) {
|
||||
FileLoader *backend = (FileLoader *)userdata;
|
||||
return (int64_t)backend->ReadAt((s64)off, len, dst);
|
||||
}
|
||||
|
||||
ZipFileLoader::ZipFileLoader(FileLoader *sourceLoader)
|
||||
: ProxiedFileLoader(sourceLoader), zipArchive_(nullptr) {
|
||||
: ProxiedFileLoader(sourceLoader) {
|
||||
if (!backend_ || !backend_->Exists() || backend_->IsDirectory()) {
|
||||
return;
|
||||
}
|
||||
|
||||
zip_error_t error{};
|
||||
zip_source_t* zipSource = zip_source_function_create([](void* userdata, void* data, zip_uint64_t len, zip_source_cmd_t cmd) -> zip_int64_t {
|
||||
ZipFileLoader *loader = (ZipFileLoader *)userdata;
|
||||
return loader->ZipSourceCallback(data, len, cmd);
|
||||
}, this, &error);
|
||||
if (!zipSource) {
|
||||
ERROR_LOG(Log::IO, "Failed to create ZIP source: %s", zip_error_strerror(&error));
|
||||
return;
|
||||
}
|
||||
|
||||
zipArchive_ = zip_open_from_source(zipSource, ZIP_RDONLY, &error);
|
||||
if (!zipArchive_) {
|
||||
ERROR_LOG(Log::IO, "Failed to open ZIP archive: %s", zip_error_strerror(&error));
|
||||
zip_source_free(zipSource);
|
||||
// zipArchive_ is already nullptr here.
|
||||
zip_ = ZipContainer(&BackendRead, backend_, (uint64_t)backend_->FileSize());
|
||||
if (!zip_) {
|
||||
ERROR_LOG(Log::IO, "Failed to open ZIP archive: %s", backend_->GetPath().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
ZipFileLoader::~ZipFileLoader() {
|
||||
if (dataFile_) {
|
||||
zip_fclose(dataFile_);
|
||||
}
|
||||
if (zipArchive_) {
|
||||
zip_discard(zipArchive_);
|
||||
}
|
||||
if (data_) {
|
||||
free(data_);
|
||||
if (seek_) {
|
||||
rzip_seek_free(seek_);
|
||||
}
|
||||
}
|
||||
|
||||
bool ZipFileLoader::Initialize(int fileIndex) {
|
||||
_dbg_assert_(!data_);
|
||||
_dbg_assert_(!initialized_);
|
||||
|
||||
if (!zipArchive_) {
|
||||
if (!zip_) {
|
||||
ERROR_LOG(Log::IO, "Cannot initialize: ZIP archive is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct zip_stat zstat;
|
||||
int retval = zip_stat_index(zipArchive_, fileIndex, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat);
|
||||
if (retval < 0) {
|
||||
return false;
|
||||
}
|
||||
const char *name = zip_get_name(zipArchive_, fileIndex, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED);
|
||||
if (!name) {
|
||||
ERROR_LOG(Log::IO, "Failed to get name for file index %d", fileIndex);
|
||||
const rzip_entry_t *entry = rzip_archive_entry(zip_.Raw(), (uint32_t)fileIndex);
|
||||
if (!entry) {
|
||||
ERROR_LOG(Log::IO, "Failed to get file index %d", fileIndex);
|
||||
return false;
|
||||
}
|
||||
// Callers (Identify_File and friends) compare against lowercase extensions, like
|
||||
// Path::GetFileExtension returns. Not using tolower to avoid the Turkish I problem.
|
||||
fileExtension_ = KeepIncludingLast(name, '.');
|
||||
fileExtension_ = KeepIncludingLast(entry->name, '.');
|
||||
for (size_t i = 0; i < fileExtension_.size(); i++) {
|
||||
char c = fileExtension_[i];
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
@@ -71,32 +48,27 @@ bool ZipFileLoader::Initialize(int fileIndex) {
|
||||
}
|
||||
}
|
||||
|
||||
_dbg_assert_(zstat.index == fileIndex);
|
||||
dataFileSize_ = zstat.size;
|
||||
dataFile_ = zip_fopen_index(zipArchive_, zstat.index, ZIP_FL_UNCHANGED);
|
||||
if (!dataFile_) {
|
||||
ERROR_LOG(Log::IO, "Failed to open file index %d from ZIP", fileIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle zero-size files
|
||||
if (dataFileSize_ == 0) {
|
||||
data_ = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
data_ = (u8 *)malloc(dataFileSize_);
|
||||
if (!data_) {
|
||||
ERROR_LOG(Log::IO, "Failed to allocate %lld bytes for ZIP file data", (long long)dataFileSize_);
|
||||
zip_fclose(dataFile_);
|
||||
dataFile_ = nullptr;
|
||||
return false;
|
||||
dataFileSize_ = (s64)entry->size;
|
||||
if (entry->method == RZIP_METHOD_STORED) {
|
||||
if (entry->csize != entry->size) {
|
||||
ERROR_LOG(Log::IO, "Stored ZIP member %d has mismatched sizes", fileIndex);
|
||||
return false;
|
||||
}
|
||||
stored_ = true;
|
||||
dataOffset_ = entry->data_off;
|
||||
} else {
|
||||
seek_ = rzip_seek_new(zip_.Raw(), (uint32_t)fileIndex, 0);
|
||||
if (!seek_) {
|
||||
ERROR_LOG(Log::IO, "Can't read ZIP member %d (method %u)", fileIndex, entry->method);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t ZipFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
if (!dataFile_ || absolutePos < 0 || absolutePos >= dataFileSize_) {
|
||||
if (!initialized_ || absolutePos < 0 || absolutePos >= dataFileSize_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -104,90 +76,24 @@ size_t ZipFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags fl
|
||||
bytes = dataFileSize_ - absolutePos;
|
||||
}
|
||||
|
||||
// Decompress until the requested point, filling up data_ as we go. TODO: Do on thread.
|
||||
while (dataReadPos_ < absolutePos + (s64)bytes) {
|
||||
int remaining = BLOCK_SIZE;
|
||||
if (dataReadPos_ + remaining > dataFileSize_) {
|
||||
remaining = (int)(dataFileSize_ - dataReadPos_);
|
||||
}
|
||||
zip_int64_t retval = zip_fread(dataFile_, data_ + dataReadPos_, remaining);
|
||||
if (retval < 0) {
|
||||
ERROR_LOG(Log::IO, "zip_fread failed with error code %lld", (long long)retval);
|
||||
return 0;
|
||||
}
|
||||
if (retval != remaining) {
|
||||
ERROR_LOG(Log::IO, "zip_fread: expected %d bytes, got %lld", remaining, (long long)retval);
|
||||
return 0;
|
||||
}
|
||||
dataReadPos_ += retval;
|
||||
if (stored_) {
|
||||
return backend_->ReadAt((s64)dataOffset_ + absolutePos, bytes, data, flags);
|
||||
}
|
||||
|
||||
// Perform the read.
|
||||
memcpy(data, data_ + absolutePos, bytes);
|
||||
// Index on until the range is covered, then decode from the nearest point.
|
||||
const uint64_t end = (uint64_t)absolutePos + bytes;
|
||||
while (rzip_seek_covered(seek_) < end) {
|
||||
const int state = rzip_seek_build(seek_, end);
|
||||
if (state < 0) {
|
||||
ERROR_LOG(Log::IO, "ZIP member is corrupt (%d)", state);
|
||||
return 0;
|
||||
}
|
||||
if (state == 1)
|
||||
break;
|
||||
}
|
||||
if (rzip_seek_read(seek_, (uint64_t)absolutePos, (uint8_t *)data, bytes) != RZIP_OK) {
|
||||
ERROR_LOG(Log::IO, "ZIP read failed at %lld", (long long)absolutePos);
|
||||
return 0;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
zip_int64_t ZipFileLoader::ZipSourceCallback(void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
{
|
||||
zipReadPos_ = 0;
|
||||
return 0;
|
||||
}
|
||||
case ZIP_SOURCE_READ:
|
||||
{
|
||||
size_t readBytes = backend_->ReadAt(zipReadPos_, len, data);
|
||||
zipReadPos_ += readBytes;
|
||||
return static_cast<zip_int64_t>(readBytes);
|
||||
}
|
||||
case ZIP_SOURCE_SEEK:
|
||||
{
|
||||
if (len < sizeof(zip_source_args_seek_t)) {
|
||||
return -1;
|
||||
}
|
||||
const zip_source_args_seek_t *seekArgs = (const zip_source_args_seek_t *)data;
|
||||
zip_int64_t new_offset;
|
||||
switch (seekArgs->whence) {
|
||||
case SEEK_SET:
|
||||
new_offset = seekArgs->offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
new_offset = zipReadPos_ + seekArgs->offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
new_offset = backend_->FileSize() + seekArgs->offset;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (new_offset < 0 || new_offset > backend_->FileSize()) {
|
||||
return -1;
|
||||
}
|
||||
zipReadPos_ = new_offset;
|
||||
return 0;
|
||||
}
|
||||
case ZIP_SOURCE_TELL:
|
||||
return zipReadPos_;
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
return 0;
|
||||
case ZIP_SOURCE_STAT:
|
||||
{
|
||||
if (len < sizeof(zip_stat_t)) {
|
||||
return -1;
|
||||
}
|
||||
zip_stat_t* st = static_cast<zip_stat_t*>(data);
|
||||
zip_stat_init(st);
|
||||
st->valid = ZIP_STAT_SIZE;
|
||||
st->size = static_cast<zip_uint64_t>(backend_->FileSize());
|
||||
return sizeof(zip_stat_t);
|
||||
}
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return -1;
|
||||
case ZIP_SOURCE_FREE:
|
||||
return 0;
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return zip_source_make_command_bitmap(ZIP_SOURCE_READ, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_OPEN, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, -1);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#ifdef SHARED_LIBZIP
|
||||
#include <zip.h>
|
||||
#else
|
||||
#include "ext/libzip/zip.h"
|
||||
#endif
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/File/Path.h"
|
||||
#include "Common/File/VFS/ZipFileReader.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Loaders.h"
|
||||
|
||||
struct rzip_seek;
|
||||
|
||||
// Exposes a single (chosen) file from a zip file as another file loader.
|
||||
// Useful in a bunch of possible chains.
|
||||
// A stored member is read straight from the backend at its offset. A deflated one
|
||||
// goes through an rzip_seek index, built as far as reads reach: restart points
|
||||
// every megabyte and a few decoded spans, instead of the whole member in memory.
|
||||
class ZipFileLoader : public ProxiedFileLoader {
|
||||
public:
|
||||
ZipFileLoader(FileLoader *sourceLoader);
|
||||
~ZipFileLoader() override;
|
||||
|
||||
zip_t *GetZip() const {
|
||||
return zipArchive_;
|
||||
const ZipContainer &GetZip() const {
|
||||
return zip_;
|
||||
}
|
||||
|
||||
bool Initialize(int fileIndex);
|
||||
|
||||
bool Exists() override {
|
||||
return dataFile_ != nullptr;
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
bool IsDirectory() override {
|
||||
@@ -53,17 +51,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
zip_int64_t ZipSourceCallback(void* data, zip_uint64_t len, zip_source_cmd_t cmd);
|
||||
static int64_t BackendRead(void *userdata, uint64_t off, void *dst, size_t len);
|
||||
|
||||
enum {
|
||||
BLOCK_SIZE = 65536,
|
||||
};
|
||||
zip_t *zipArchive_ = nullptr;
|
||||
s64 zipReadPos_ = 0;
|
||||
|
||||
zip_file_t *dataFile_ = nullptr;
|
||||
uint8_t *data_ = nullptr; // malloc/free
|
||||
s64 dataReadPos_ = 0;
|
||||
ZipContainer zip_;
|
||||
bool initialized_ = false;
|
||||
bool stored_ = false;
|
||||
u64 dataOffset_ = 0; // stored members: where the bytes start in the zip
|
||||
struct rzip_seek *seek_ = nullptr; // deflated members
|
||||
s64 dataFileSize_ = 0;
|
||||
std::string fileExtension_;
|
||||
};
|
||||
+155
-187
@@ -33,9 +33,11 @@
|
||||
#include "Core/FileSystems/BlockDevices.h"
|
||||
#include "Core/FileSystems/ISOFileSystem.h"
|
||||
#include "Core/Util/PathUtil.h"
|
||||
#include "libchdr/chd.h"
|
||||
#include <formats/rchd.h>
|
||||
|
||||
#include "zlib.h"
|
||||
#include <encodings/deflate.h>
|
||||
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
#include "ext/libkirk/amctrl.h"
|
||||
#include "ext/libkirk/kirk_engine.h"
|
||||
|
||||
@@ -321,6 +323,51 @@ bool FileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockDevice::ReadBytes(u64 offset, size_t len, u8 *out) {
|
||||
const size_t blockSize = GetBlockSize();
|
||||
u32 block = (u32)(offset / blockSize);
|
||||
const size_t skip = (size_t)(offset % blockSize);
|
||||
bool ok = true;
|
||||
if (skip != 0 && len > 0) {
|
||||
u8 sector[2048];
|
||||
const size_t n = std::min(len, blockSize - skip);
|
||||
// A failed read must not hand out uninitialized stack.
|
||||
if (!ReadBlock(block++, sector)) {
|
||||
memset(sector, 0, sizeof(sector));
|
||||
ok = false;
|
||||
}
|
||||
memcpy(out, sector + skip, n);
|
||||
out += n;
|
||||
len -= n;
|
||||
}
|
||||
if (len >= blockSize) {
|
||||
const u32 count = (u32)(len / blockSize);
|
||||
ok = ReadBlocks(block, count, out) && ok;
|
||||
block += count;
|
||||
out += (size_t)count * blockSize;
|
||||
len -= (size_t)count * blockSize;
|
||||
}
|
||||
if (len > 0) {
|
||||
u8 sector[2048];
|
||||
if (!ReadBlock(block, sector)) {
|
||||
memset(sector, 0, sizeof(sector));
|
||||
ok = false;
|
||||
}
|
||||
memcpy(out, sector, len);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool FileBlockDevice::ReadBytes(u64 offset, size_t len, u8 *out) {
|
||||
// A plain image is the bytes themselves: one read, no sector staging.
|
||||
const size_t got = fileLoader_->ReadAt(offset, len, out);
|
||||
if (got < len) {
|
||||
memset(out + got, 0, len - got);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
|
||||
size_t retval = fileLoader_->ReadAt((u64)minBlock * (u64)GetBlockSize(), 2048, count, outPtr);
|
||||
if (retval != (size_t)count) {
|
||||
@@ -608,6 +655,7 @@ CISOFileBlockDevice::CISOFileBlockDevice(FileLoader *fileLoader)
|
||||
readBufferSize = CSO_READ_BUFFER_SIZE;
|
||||
readBuffer = new u8[readBufferSize];
|
||||
zlibBuffer = new u8[frameSize + (1u << indexShift)];
|
||||
inflate_ = rinflate_new(-15);
|
||||
zlibBufferFrame = numFrames;
|
||||
|
||||
const u32 indexSize = (u32)indexSize64;
|
||||
@@ -662,6 +710,8 @@ CISOFileBlockDevice::~CISOFileBlockDevice()
|
||||
delete [] index;
|
||||
delete [] readBuffer;
|
||||
delete [] zlibBuffer;
|
||||
if (inflate_)
|
||||
rinflate_free(inflate_);
|
||||
}
|
||||
|
||||
bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
|
||||
@@ -676,7 +726,6 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
|
||||
const u32 idx = index[frameNumber];
|
||||
const u32 indexPos = idx & 0x7FFFFFFF;
|
||||
const u32 nextIndexPos = index[frameNumber + 1] & 0x7FFFFFFF;
|
||||
z_stream z{};
|
||||
|
||||
const u64 compressedReadPos = (u64)indexPos << indexShift;
|
||||
const u64 compressedReadEnd = (u64)nextIndexPos << indexShift;
|
||||
@@ -700,35 +749,17 @@ bool CISOFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
|
||||
} else {
|
||||
const u32 readSize = (u32)fileLoader_->ReadAt(compressedReadPos, 1, compressedReadSize, readBuffer, flags);
|
||||
|
||||
z.zalloc = Z_NULL;
|
||||
z.zfree = Z_NULL;
|
||||
z.opaque = Z_NULL;
|
||||
if (inflateInit2(&z, -15) != Z_OK) {
|
||||
ERROR_LOG(Log::Loader, "GetBlockSize() ERROR: %s\n", (z.msg) ? z.msg : "?");
|
||||
// A one-block frame inflates straight into the caller's buffer.
|
||||
u8 *dst = frameSize == (u32)GetBlockSize() ? outPtr : zlibBuffer;
|
||||
const int64_t produced = inflate_ ? InflateBuffer(inflate_, -15, readBuffer, readSize, dst, frameSize) : -1;
|
||||
if (produced != (int64_t)frameSize) {
|
||||
ERROR_LOG(Log::Loader, "block %d: inflate failed (%d of %d bytes)", blockNumber, (int)produced, frameSize);
|
||||
NotifyReadError();
|
||||
return false;
|
||||
}
|
||||
z.avail_in = readSize;
|
||||
z.next_out = frameSize == (u32)GetBlockSize() ? outPtr : zlibBuffer;
|
||||
z.avail_out = frameSize;
|
||||
z.next_in = readBuffer;
|
||||
|
||||
int status = inflate(&z, Z_FINISH);
|
||||
if (status != Z_STREAM_END) {
|
||||
ERROR_LOG(Log::Loader, "block %d: inflate : %s[%d]\n", blockNumber, (z.msg) ? z.msg : "error", status);
|
||||
NotifyReadError();
|
||||
inflateEnd(&z);
|
||||
if (dst == zlibBuffer)
|
||||
zlibBufferFrame = numFrames; // partly overwritten
|
||||
memset(outPtr, 0, GetBlockSize());
|
||||
return false;
|
||||
}
|
||||
if (z.total_out != frameSize) {
|
||||
ERROR_LOG(Log::Loader, "block %d: block size error %d != %d\n", blockNumber, (u32)z.total_out, frameSize);
|
||||
NotifyReadError();
|
||||
inflateEnd(&z);
|
||||
memset(outPtr, 0, GetBlockSize());
|
||||
return false;
|
||||
}
|
||||
inflateEnd(&z);
|
||||
|
||||
if (frameSize != (u32)GetBlockSize()) {
|
||||
zlibBufferFrame = frameNumber;
|
||||
@@ -758,9 +789,8 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
|
||||
const u32 afterLastIndexPos = index[lastFrameNumber + 1] & 0x7FFFFFFF;
|
||||
const u64 totalReadEnd = (u64)afterLastIndexPos << indexShift;
|
||||
|
||||
z_stream z{};
|
||||
if (inflateInit2(&z, -15) != Z_OK) {
|
||||
ERROR_LOG(Log::Loader, "Unable to initialize inflate: %s\n", (z.msg) ? z.msg : "?");
|
||||
if (!inflate_) {
|
||||
ERROR_LOG(Log::Loader, "Unable to initialize inflate");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -803,34 +833,26 @@ bool CISOFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
|
||||
if (plain) {
|
||||
memcpy(outPtr, rawBuffer + frameBlockOffset * GetBlockSize(), frameBlocks * GetBlockSize());
|
||||
} else {
|
||||
z.avail_in = frameReadSize;
|
||||
z.next_out = frameBlocks == blocksPerFrame ? outPtr : zlibBuffer;
|
||||
z.avail_out = frameSize;
|
||||
z.next_in = rawBuffer;
|
||||
|
||||
int status = inflate(&z, Z_FINISH);
|
||||
if (status != Z_STREAM_END) {
|
||||
ERROR_LOG(Log::Loader, "Inflate frame %d: failed - %s[%d]\n", frame, (z.msg) ? z.msg : "error", status);
|
||||
NotifyReadError();
|
||||
memset(outPtr, 0, frameBlocks * GetBlockSize());
|
||||
} else if (z.total_out != frameSize) {
|
||||
ERROR_LOG(Log::Loader, "Inflate frame %d: block size error %d != %d\n", frame, (u32)z.total_out, frameSize);
|
||||
// Whole frames inflate straight into the caller's buffer.
|
||||
u8 *dst = frameBlocks == blocksPerFrame ? outPtr : zlibBuffer;
|
||||
const int64_t produced = InflateBuffer(inflate_, -15, rawBuffer, frameReadSize, dst, frameSize);
|
||||
if (produced != (int64_t)frameSize) {
|
||||
ERROR_LOG(Log::Loader, "Inflate frame %d: failed (%d of %d bytes)", frame, (int)produced, frameSize);
|
||||
NotifyReadError();
|
||||
if (dst == zlibBuffer)
|
||||
zlibBufferFrame = numFrames; // partly overwritten
|
||||
memset(outPtr, 0, frameBlocks * GetBlockSize());
|
||||
} else if (frameBlocks != blocksPerFrame) {
|
||||
memcpy(outPtr, zlibBuffer + frameBlockOffset * GetBlockSize(), frameBlocks * GetBlockSize());
|
||||
// In case we end up reusing it in a single read later.
|
||||
zlibBufferFrame = frame;
|
||||
}
|
||||
|
||||
inflateReset(&z);
|
||||
}
|
||||
|
||||
block += frameBlocks;
|
||||
outPtr += frameBlocks * GetBlockSize();
|
||||
}
|
||||
|
||||
inflateEnd(&z);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1051,172 +1073,118 @@ bool NPDRMDemoBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached)
|
||||
return true;
|
||||
}
|
||||
|
||||
struct CHDImpl {
|
||||
chd_file *chd = nullptr;
|
||||
const chd_header *header = nullptr;
|
||||
};
|
||||
// rchd does no I/O: it names the byte ranges it needs and is fed them.
|
||||
// Those ranges go straight from the loader into one scratch buffer the
|
||||
// decoder borrows, so a hunk's compressed bytes are never copied twice.
|
||||
static bool CHDServe(rchd_t *chd, FileLoader *loader, std::vector<u8> &scratch, const rchd_request_t &req, bool borrow) {
|
||||
if (req.source != RCHD_SOURCE_SELF)
|
||||
return false;
|
||||
if (scratch.size() < req.length)
|
||||
scratch.resize(req.length);
|
||||
const size_t got = loader->ReadAt(req.offset, req.length, scratch.data());
|
||||
if (got == 0)
|
||||
return false;
|
||||
if (borrow)
|
||||
return rchd_feed_borrow(chd, req.offset, req.source, scratch.data(), got) == RCHD_OK;
|
||||
return rchd_feed(chd, scratch.data(), got) == RCHD_OK;
|
||||
}
|
||||
|
||||
struct ExtendedCoreFile {
|
||||
core_file core; // Must be the first struct member, for some tricky pointer casts.
|
||||
uint64_t seekPos;
|
||||
};
|
||||
static const char *CHDErrorString(int err) {
|
||||
switch (err) {
|
||||
case RCHD_ERROR_DATA: return "invalid data";
|
||||
case RCHD_ERROR_PARAM: return "invalid parameter";
|
||||
case RCHD_ERROR_MEM: return "out of memory";
|
||||
case RCHD_ERROR_UNSUPPORTED: return "unsupported format";
|
||||
case RCHD_ERROR_CRC: return "checksum mismatch";
|
||||
case RCHD_ERROR_NO_PARENT: return "parent CHD not supported";
|
||||
case RCHD_ERROR_STATE: return "invalid state";
|
||||
default: return "error";
|
||||
}
|
||||
}
|
||||
|
||||
CHDFileBlockDevice::CHDFileBlockDevice(FileLoader *fileLoader)
|
||||
: BlockDevice(fileLoader), impl_(new CHDImpl()) {
|
||||
Path paths[8];
|
||||
paths[0] = fileLoader->GetPath();
|
||||
int depth = 0;
|
||||
|
||||
core_file_ = new ExtendedCoreFile();
|
||||
core_file_->core.argp = fileLoader;
|
||||
core_file_->core.fsize = [](core_file *file) -> uint64_t {
|
||||
FileLoader *loader = (FileLoader *)file->argp;
|
||||
return loader->FileSize();
|
||||
};
|
||||
core_file_->core.fseek = [](core_file *file, int64_t offset, int seekType) -> int {
|
||||
ExtendedCoreFile *coreFile = (ExtendedCoreFile *)file;
|
||||
switch (seekType) {
|
||||
case SEEK_SET:
|
||||
coreFile->seekPos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
coreFile->seekPos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
{
|
||||
FileLoader *loader = (FileLoader *)file->argp;
|
||||
coreFile->seekPos = loader->FileSize() + offset;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
core_file_->core.fread = [](void *out_data, size_t size, size_t count, core_file *file) {
|
||||
ExtendedCoreFile *coreFile = (ExtendedCoreFile *)file;
|
||||
FileLoader *loader = (FileLoader *)file->argp;
|
||||
uint64_t totalSize = size * count;
|
||||
loader->ReadAt(coreFile->seekPos, totalSize, out_data);
|
||||
coreFile->seekPos += totalSize;
|
||||
return size * count;
|
||||
};
|
||||
core_file_->core.fclose = [](core_file *file) {
|
||||
ExtendedCoreFile *coreFile = (ExtendedCoreFile *)file;
|
||||
delete coreFile;
|
||||
return 0;
|
||||
};
|
||||
|
||||
/*
|
||||
// TODO: Support parent/child CHD files.
|
||||
|
||||
// Default, in case of failure
|
||||
numBlocks = 0;
|
||||
|
||||
chd_header childHeader;
|
||||
|
||||
chd_error err = chd_read_header(paths[0].c_str(), &childHeader);
|
||||
if (err != CHDERR_NONE) {
|
||||
ERROR_LOG(Log::Loader, "Error loading CHD header for '%s': %s", paths[0].c_str(), chd_error_string(err));
|
||||
NotifyReadError();
|
||||
: BlockDevice(fileLoader) {
|
||||
chd_ = rchd_new();
|
||||
if (!chd_) {
|
||||
errorString_ = "CHD error: out of memory";
|
||||
return;
|
||||
}
|
||||
|
||||
// static const UINT8 nullsha1[CHD_SHA1_BYTES] = { 0 };
|
||||
if (memcmp(nullsha1, childHeader.parentsha1, sizeof(childHeader.sha1)) != 0) {
|
||||
chd_header parentHeader;
|
||||
|
||||
// Look for parent CHD in current directory
|
||||
Path chdDir = paths[0].NavigateUp();
|
||||
|
||||
std::vector<File::FileInfo> files;
|
||||
if (File::GetFilesInDir(chdDir, &files)) {
|
||||
parentHeader.length = 0;
|
||||
|
||||
for (const auto &file : files) {
|
||||
std::string extension = file.fullName.GetFileExtension();
|
||||
if (extension != ".chd") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chd_read_header(filepath.c_str(), &parentHeader) == CHDERR_NONE &&
|
||||
memcmp(parentHeader.sha1, childHeader.parentsha1, sizeof(parentHeader.sha1)) == 0) {
|
||||
// ERROR_LOG(Log::Loader, "Checking '%s'", filepath.c_str());
|
||||
paths[++depth] = filepath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if parentHeader was opened
|
||||
if (parentHeader.length == 0) {
|
||||
ERROR_LOG(Log::Loader, "Error loading CHD '%s': parents not found", fileLoader->GetPath().c_str());
|
||||
NotifyReadError();
|
||||
return;
|
||||
}
|
||||
memcpy(childHeader.parentsha1, parentHeader.parentsha1, sizeof(childHeader.parentsha1));
|
||||
} while (memcmp(nullsha1, childHeader.parentsha1, sizeof(childHeader.sha1)) != 0);
|
||||
int err;
|
||||
rchd_request_t req;
|
||||
while ((err = rchd_open_step(chd_, &req)) == RCHD_PENDING) {
|
||||
if (!CHDServe(chd_, fileLoader, scratch_, req, false)) {
|
||||
err = req.source == RCHD_SOURCE_SELF ? RCHD_ERROR_DATA : RCHD_ERROR_NO_PARENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
chd_file *file = nullptr;
|
||||
chd_error err = chd_open_core_file(&core_file_->core, CHD_OPEN_READ, NULL, &file);
|
||||
if (err != CHDERR_NONE) {
|
||||
errorString_ = StringFromFormat("CHD error: %s: %s", paths[depth].c_str(), chd_error_string(err));
|
||||
const rchd_info_t *info = err == RCHD_OK ? rchd_info(chd_) : nullptr;
|
||||
if (info && info->has_parent)
|
||||
err = RCHD_ERROR_NO_PARENT;
|
||||
if (!info || err != RCHD_OK || info->unit_bytes != (u32)GetBlockSize()) {
|
||||
if (err == RCHD_OK)
|
||||
err = RCHD_ERROR_UNSUPPORTED;
|
||||
errorString_ = StringFromFormat("CHD error: %s: %s", fileLoader->GetPath().c_str(), CHDErrorString(err));
|
||||
rchd_free(chd_);
|
||||
chd_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
impl_->chd = file;
|
||||
impl_->header = chd_get_header(impl_->chd);
|
||||
|
||||
readBuffer = new u8[impl_->header->hunkbytes];
|
||||
currentHunk = -1;
|
||||
blocksPerHunk = impl_->header->hunkbytes / impl_->header->unitbytes;
|
||||
numBlocks = impl_->header->unitcount;
|
||||
|
||||
numBlocks = (u32)(info->logical_bytes / info->unit_bytes);
|
||||
_dbg_assert_(errorString_.empty());
|
||||
}
|
||||
|
||||
CHDFileBlockDevice::~CHDFileBlockDevice() {
|
||||
if (impl_->chd) {
|
||||
chd_close(impl_->chd);
|
||||
delete[] readBuffer;
|
||||
}
|
||||
rchd_free(chd_);
|
||||
}
|
||||
|
||||
bool CHDFileBlockDevice::ReadBlock(int blockNumber, u8 *outPtr, bool uncached) {
|
||||
if (!impl_->chd) {
|
||||
ERROR_LOG(Log::Loader, "ReadBlock: CHD not open. %s", fileLoader_->GetPath().c_str());
|
||||
return false;
|
||||
}
|
||||
if ((u32)blockNumber >= numBlocks) {
|
||||
memset(outPtr, 0, GetBlockSize());
|
||||
return false;
|
||||
}
|
||||
u32 hunk = blockNumber / blocksPerHunk;
|
||||
u32 blockInHunk = blockNumber % blocksPerHunk;
|
||||
return ReadBlocks((u32)blockNumber, 1, outPtr);
|
||||
}
|
||||
|
||||
if (currentHunk != hunk) {
|
||||
chd_error err = chd_read(impl_->chd, hunk, readBuffer);
|
||||
if (err != CHDERR_NONE) {
|
||||
ERROR_LOG(Log::Loader, "CHD read failed: %d %d %s", blockNumber, hunk, chd_error_string(err));
|
||||
NotifyReadError();
|
||||
bool CHDFileBlockDevice::ReadRange(u64 offset, size_t len, u8 *out) {
|
||||
int err = rchd_read_begin(chd_, offset, out, len);
|
||||
rchd_request_t req;
|
||||
if (err == RCHD_OK) {
|
||||
while ((err = rchd_read_step(chd_, &req)) == RCHD_PENDING) {
|
||||
if (!CHDServe(chd_, fileLoader_, scratch_, req, true)) {
|
||||
err = RCHD_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentHunk = hunk;
|
||||
}
|
||||
memcpy(outPtr, readBuffer + blockInHunk * impl_->header->unitbytes, GetBlockSize());
|
||||
if (err != RCHD_OK) {
|
||||
ERROR_LOG(Log::Loader, "CHD read failed at %llu (%d bytes): %s", (unsigned long long)offset, (int)len, CHDErrorString(err));
|
||||
NotifyReadError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CHDFileBlockDevice::ReadBytes(u64 offset, size_t len, u8 *out) {
|
||||
// rchd addresses bytes, so a file read decodes straight into place.
|
||||
if (!chd_ || offset + len > (u64)numBlocks * GetBlockSize())
|
||||
return BlockDevice::ReadBytes(offset, len, out);
|
||||
return ReadRange(offset, len, out);
|
||||
}
|
||||
|
||||
bool CHDFileBlockDevice::ReadBlocks(u32 minBlock, int count, u8 *outPtr) {
|
||||
if (minBlock >= numBlocks) {
|
||||
memset(outPtr, 0, GetBlockSize() * count);
|
||||
const size_t blockSize = GetBlockSize();
|
||||
if (!chd_) {
|
||||
ERROR_LOG(Log::Loader, "ReadBlocks: CHD not open. %s", fileLoader_->GetPath().c_str());
|
||||
memset(outPtr, 0, blockSize * count);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!ReadBlock(minBlock + i, outPtr + i * GetBlockSize())) {
|
||||
return false;
|
||||
}
|
||||
if (minBlock >= numBlocks || count <= 0) {
|
||||
memset(outPtr, 0, blockSize * std::max(count, 0));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
// The tail past the image reads as zeros, like the other devices.
|
||||
const u32 avail = std::min((u32)count, numBlocks - minBlock);
|
||||
if (avail < (u32)count)
|
||||
memset(outPtr + avail * blockSize, 0, (count - avail) * blockSize);
|
||||
|
||||
if (!ReadRange((u64)minBlock * blockSize, avail * blockSize, outPtr))
|
||||
return false;
|
||||
return avail == (u32)count;
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
@@ -46,6 +47,10 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Bytes [offset, offset + len) of the image, at any alignment. The default reads the
|
||||
// partial blocks at either end through a sector buffer; devices that can address bytes
|
||||
// read straight into out instead.
|
||||
virtual bool ReadBytes(u64 offset, size_t len, u8 *out);
|
||||
int constexpr GetBlockSize() const { return 2048;} // forced, it cannot be changed by subclasses. If a subclass uses bigger blocks internally, it must cache and virtualize.
|
||||
virtual u32 GetNumBlocks() const = 0;
|
||||
virtual u64 GetUncompressedSize() const {
|
||||
@@ -80,6 +85,7 @@ private:
|
||||
size_t readBufferSize = 0;
|
||||
u8 *zlibBuffer = nullptr;
|
||||
u32 zlibBufferFrame = 0;
|
||||
void *inflate_ = nullptr; // one rinflate stream, reset per frame
|
||||
u8 indexShift = 0;
|
||||
u8 blockShift = 0;
|
||||
u32 frameSize = 0;
|
||||
@@ -94,6 +100,7 @@ public:
|
||||
~FileBlockDevice();
|
||||
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
|
||||
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
|
||||
bool ReadBytes(u64 offset, size_t len, u8 *out) override;
|
||||
u32 GetNumBlocks() const override {return (u32)(filesize_ / GetBlockSize());}
|
||||
bool IsDisc() const override { return true; }
|
||||
u64 GetUncompressedSize() const override {
|
||||
@@ -194,9 +201,7 @@ private:
|
||||
KirkState kirk_{};
|
||||
};
|
||||
|
||||
struct CHDImpl;
|
||||
|
||||
struct ExtendedCoreFile;
|
||||
struct rchd;
|
||||
|
||||
class CHDFileBlockDevice : public BlockDevice {
|
||||
public:
|
||||
@@ -204,14 +209,13 @@ public:
|
||||
~CHDFileBlockDevice();
|
||||
bool ReadBlock(int blockNumber, u8 *outPtr, bool uncached = false) override;
|
||||
bool ReadBlocks(u32 minBlock, int count, u8 *outPtr) override;
|
||||
bool ReadBytes(u64 offset, size_t len, u8 *out) override;
|
||||
u32 GetNumBlocks() const override { return numBlocks; }
|
||||
bool IsDisc() const override { return true; }
|
||||
private:
|
||||
struct ExtendedCoreFile *core_file_ = nullptr;
|
||||
std::unique_ptr<CHDImpl> impl_;
|
||||
u8 *readBuffer = nullptr;
|
||||
u32 currentHunk = 0;
|
||||
u32 blocksPerHunk = 0;
|
||||
bool ReadRange(u64 offset, size_t len, u8 *out);
|
||||
struct rchd *chd_ = nullptr;
|
||||
std::vector<u8> scratch_; // compressed bytes, borrowed by the decoder
|
||||
u32 numBlocks = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -520,22 +520,7 @@ int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outd
|
||||
int block = (u16)desc.firstLETableSector;
|
||||
u32 size = Memory::ClampValidSizeAt(outdataPtr, (u32)desc.pathTableLength);
|
||||
u8 *out = Memory::GetPointerWriteRangeOrException(outdataPtr, size);
|
||||
|
||||
int blocks = size / blockDevice->GetBlockSize();
|
||||
blockDevice->ReadBlocks(block, blocks, out);
|
||||
size -= blocks * blockDevice->GetBlockSize();
|
||||
out += blocks * blockDevice->GetBlockSize();
|
||||
|
||||
// The remaining (or, usually, only) partial sector.
|
||||
if (size > 0) {
|
||||
u8 temp[2048];
|
||||
// `blocks` whole sectors starting at `block` were already consumed by
|
||||
// ReadBlocks() above, so the trailing partial sector is the next one.
|
||||
if (!blockDevice->ReadBlock(block + blocks, temp)) {
|
||||
memset(temp, 0, sizeof(temp));
|
||||
}
|
||||
memcpy(out, temp, size);
|
||||
}
|
||||
blockDevice->ReadBytes((u64)block * blockDevice->GetBlockSize(), size, out);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -617,44 +602,10 @@ size_t ISOFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) {
|
||||
}
|
||||
|
||||
// Okay, we have size and position, let's rock.
|
||||
const int firstBlockOffset = positionOnIso & 2047;
|
||||
const int firstBlockSize = firstBlockOffset == 0 ? 0 : (int)std::min(size, 2048LL - firstBlockOffset);
|
||||
const int lastBlockSize = (size - firstBlockSize) & 2047;
|
||||
const s64 middleSize = size - firstBlockSize - lastBlockSize;
|
||||
_dbg_assert_((middleSize & 2047) == 0);
|
||||
|
||||
u32 secNum = (u32)(positionOnIso / 2048);
|
||||
u8 theSector[2048];
|
||||
|
||||
if ((middleSize & 2047) != 0) {
|
||||
ERROR_LOG(Log::FileSystem, "Remaining size should be aligned");
|
||||
}
|
||||
|
||||
const u8 *const start = pointer;
|
||||
if (firstBlockSize > 0) {
|
||||
// theSector is uninitialized stack memory, so on a failed read we must not copy it out -
|
||||
// that would hand host stack contents to the game.
|
||||
if (!blockDevice->ReadBlock(secNum++, theSector)) {
|
||||
memset(theSector, 0, sizeof(theSector));
|
||||
}
|
||||
memcpy(pointer, theSector + firstBlockOffset, firstBlockSize);
|
||||
pointer += firstBlockSize;
|
||||
}
|
||||
if (middleSize > 0) {
|
||||
const u32 middleSectors = (u32)(middleSize / 2048);
|
||||
blockDevice->ReadBlocks(secNum, middleSectors, pointer);
|
||||
secNum += middleSectors;
|
||||
pointer += middleSize;
|
||||
}
|
||||
if (lastBlockSize > 0) {
|
||||
if (!blockDevice->ReadBlock(secNum++, theSector)) {
|
||||
memset(theSector, 0, sizeof(theSector));
|
||||
}
|
||||
memcpy(pointer, theSector, lastBlockSize);
|
||||
pointer += lastBlockSize;
|
||||
}
|
||||
|
||||
size_t totalBytes = pointer - start;
|
||||
blockDevice->ReadBytes(positionOnIso, (size_t)size, pointer);
|
||||
// The sector after the last one touched, for the seek-time estimate.
|
||||
const u32 secNum = (u32)(size > 0 ? (positionOnIso + size + 2047) / 2048 : positionOnIso / 2048);
|
||||
const size_t totalBytes = (size_t)size;
|
||||
if (abs((int)lastReadBlock_ - (int)secNum) > 100) {
|
||||
// This is an estimate, sometimes it takes 1+ seconds, but it definitely takes time.
|
||||
usec = 100000;
|
||||
|
||||
@@ -15,11 +15,7 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#ifdef SHARED_ZLIB
|
||||
#include <zlib.h>
|
||||
#else
|
||||
#include "../ext/zlib/zlib.h"
|
||||
#endif
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
|
||||
#include "sceAdler.h"
|
||||
#include "Common/Log.h"
|
||||
@@ -34,7 +30,7 @@ static u32 sceAdler32(u32 adler, u32 data, u32 datalen) {
|
||||
INFO_LOG(Log::sceMisc, "sceAdler32(adler=%08x, data=%08x, datalen=%08x)", adler, data, datalen);
|
||||
|
||||
u8 *buf = Memory::GetPointerWriteUnchecked(data);
|
||||
u32 ret = adler32(adler, buf, datalen);
|
||||
u32 ret = Adler32(adler, buf, datalen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+18
-25
@@ -15,9 +15,10 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "zlib.h"
|
||||
#include <encodings/crc32.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
#include "Core/Debugger/MemBlockInfo.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
@@ -35,49 +36,41 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength,
|
||||
return hleLogError(Log::HLE, 0, "bad crc32 address");
|
||||
}
|
||||
|
||||
z_stream stream{};
|
||||
u8 *outBufferPtr = Memory::GetPointerWriteOrException(OutBuffer);
|
||||
stream.next_in = (Bytef*)Memory::GetPointerOrException(InBuffer);
|
||||
const u8 *inBufferPtr = Memory::GetPointerOrException(InBuffer);
|
||||
// We don't know the available length, just let it use as much as it wants.
|
||||
stream.avail_in = (uInt)Memory::ClampValidSizeAt(InBuffer, Memory::g_MemorySize);
|
||||
stream.next_out = outBufferPtr;
|
||||
stream.avail_out = (uInt)OutBufferLength;
|
||||
const size_t inAvail = Memory::ClampValidSizeAt(InBuffer, Memory::g_MemorySize);
|
||||
const size_t outAvail = OutBufferLength > 0 ? Memory::ClampValidSizeAt(OutBuffer, (u32)OutBufferLength) : 0;
|
||||
|
||||
int err = inflateInit2(&stream, windowBits);
|
||||
if (err != Z_OK) {
|
||||
return hleLogError(Log::HLE, 0, "inflateInit2 failed %08x", err);
|
||||
}
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
inflateEnd(&stream);
|
||||
|
||||
if (err != Z_STREAM_END) {
|
||||
return hleLogError(Log::HLE, 0, "inflate failed %08x", err);
|
||||
size_t totalIn = 0;
|
||||
const int64_t totalOut = InflateBuffer(windowBits, inBufferPtr, inAvail, outBufferPtr, outAvail, &totalIn);
|
||||
if (totalOut < 0) {
|
||||
return hleLogError(Log::HLE, 0, "inflate failed");
|
||||
}
|
||||
if (crc32Addr.IsValid()) {
|
||||
uLong crc = crc32(0L, Z_NULL, 0);
|
||||
*crc32Addr = crc32(crc, outBufferPtr, stream.total_out);
|
||||
*crc32Addr = encoding_crc32(0, outBufferPtr, (size_t)totalOut);
|
||||
}
|
||||
|
||||
if (MemBlockInfoDetailed(stream.total_in, stream.total_out)) {
|
||||
if (MemBlockInfoDetailed((u32)totalIn, (u32)totalOut)) {
|
||||
char tagData[128];
|
||||
size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "sceDeflt/", InBuffer, stream.total_in);
|
||||
NotifyMemInfo(MemBlockFlags::READ, InBuffer, stream.total_in, tagData, tagSize);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, stream.total_out, tagData, tagSize);
|
||||
size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "sceDeflt/", InBuffer, (u32)totalIn);
|
||||
NotifyMemInfo(MemBlockFlags::READ, InBuffer, (u32)totalIn, tagData, tagSize);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, (u32)totalOut, tagData, tagSize);
|
||||
}
|
||||
|
||||
return hleLogDebug(Log::HLE, stream.total_out);
|
||||
return hleLogDebug(Log::HLE, (int)totalOut);
|
||||
}
|
||||
|
||||
static int sceDeflateDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) {
|
||||
return CommonDecompress(-MAX_WBITS, OutBuffer, OutBufferLength, InBuffer, Crc32Addr);
|
||||
return CommonDecompress(-15, OutBuffer, OutBufferLength, InBuffer, Crc32Addr);
|
||||
}
|
||||
|
||||
static int sceGzipDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) {
|
||||
return CommonDecompress(16 + MAX_WBITS, OutBuffer, OutBufferLength, InBuffer, Crc32Addr);
|
||||
return CommonDecompress(31, OutBuffer, OutBufferLength, InBuffer, Crc32Addr);
|
||||
}
|
||||
|
||||
static int sceZlibDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) {
|
||||
return CommonDecompress(MAX_WBITS, OutBuffer, OutBufferLength, InBuffer, Crc32Addr);
|
||||
return CommonDecompress(15, OutBuffer, OutBufferLength, InBuffer, Crc32Addr);
|
||||
}
|
||||
|
||||
const HLEFunction sceDeflt[] = {
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include "zlib.h"
|
||||
#include <encodings/crc32.h>
|
||||
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
@@ -1051,29 +1053,12 @@ static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr,
|
||||
}
|
||||
|
||||
static int gzipDecompress(u8 *OutBuffer, int OutBufferLength, u8 *InBuffer) {
|
||||
int err;
|
||||
z_stream stream;
|
||||
u8 *outBufferPtr;
|
||||
|
||||
outBufferPtr = OutBuffer;
|
||||
stream.next_in = InBuffer;
|
||||
stream.avail_in = (uInt)OutBufferLength;
|
||||
stream.next_out = outBufferPtr;
|
||||
stream.avail_out = (uInt)OutBufferLength;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
err = inflateInit2(&stream, 16+MAX_WBITS);
|
||||
if (err != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
const int64_t produced = InflateBuffer(31, InBuffer, (size_t)OutBufferLength, OutBuffer, (size_t)OutBufferLength);
|
||||
if (produced < 0) {
|
||||
ERROR_LOG(Log::Loader, "gzipDecompress: Didn't reach the end of the input, output buffer too small?");
|
||||
inflateEnd(&stream);
|
||||
return -2;
|
||||
}
|
||||
inflateEnd(&stream);
|
||||
return stream.total_out;
|
||||
return (int)produced;
|
||||
}
|
||||
|
||||
static void parsePrxLibInfo(const u8* ptr, u32 headerSize) {
|
||||
@@ -1304,7 +1289,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load
|
||||
loadedModules.insert(module->GetUID());
|
||||
memset(&module->nm, 0, sizeof(module->nm));
|
||||
|
||||
module->crc = crc32(0, ptr, (uInt)elfSize);
|
||||
module->crc = encoding_crc32(0, ptr, elfSize);
|
||||
module->nm.modid = module->GetUID();
|
||||
|
||||
bool reportedModule = false;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "zlib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Core/MemMap.h"
|
||||
|
||||
+18
-43
@@ -388,7 +388,7 @@ bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &erro
|
||||
// Close the return value with ZipClose (if non-null, of course).
|
||||
ZipContainer ZipOpenPath(const Path &fileName) {
|
||||
ZipContainer z(fileName);
|
||||
if (z == nullptr) {
|
||||
if (!z) {
|
||||
ERROR_LOG(Log::HLE, "Failed to open ZIP file '%s'", fileName.c_str());
|
||||
}
|
||||
return z;
|
||||
@@ -438,43 +438,23 @@ inline char asciitolower(char in) {
|
||||
// i.e. straight from an untrusted file.
|
||||
static const u64 MAX_ZIP_EXTRACT_TO_MEMORY_SIZE = 16 * 1024 * 1024;
|
||||
|
||||
static bool ZipExtractFileToMemory(struct zip *z, int fileIndex, std::string *data) {
|
||||
zip_stat_t zstat{};
|
||||
if (zip_stat_index(z, fileIndex, 0, &zstat) != 0) {
|
||||
ERROR_LOG(Log::HLE, "zip_stat_index failed for file %d in zip", fileIndex);
|
||||
return false;
|
||||
}
|
||||
if (!(zstat.valid & ZIP_STAT_SIZE)) {
|
||||
ERROR_LOG(Log::HLE, "No size for file %d in zip", fileIndex);
|
||||
return false;
|
||||
}
|
||||
if (zstat.size == 0) {
|
||||
static bool ZipExtractFileToMemory(const ZipContainer &z, int fileIndex, std::string *data) {
|
||||
const u64 size = z.Size(fileIndex);
|
||||
if (size == 0) {
|
||||
data->clear();
|
||||
return true;
|
||||
}
|
||||
if (zstat.size > MAX_ZIP_EXTRACT_TO_MEMORY_SIZE) {
|
||||
ERROR_LOG(Log::HLE, "Refusing to extract file %d from zip: declared size %llu is implausible", fileIndex, (unsigned long long)zstat.size);
|
||||
if (size > MAX_ZIP_EXTRACT_TO_MEMORY_SIZE) {
|
||||
ERROR_LOG(Log::HLE, "Refusing to extract file %d from zip: declared size %llu is implausible", fileIndex, (unsigned long long)size);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t readSize = (size_t)zstat.size;
|
||||
data->resize(readSize);
|
||||
|
||||
zip_file *zf = zip_fopen_index(z, fileIndex, 0);
|
||||
if (!zf) {
|
||||
ERROR_LOG(Log::HLE, "Failed to zip_fopen_index file %d from zip", fileIndex);
|
||||
data->resize((size_t)size);
|
||||
if (!z.ExtractInto(fileIndex, (uint8_t *)&(*data)[0], data->size())) {
|
||||
ERROR_LOG(Log::HLE, "Failed to read %d bytes from zip - archive corrupt?", (int)size);
|
||||
data->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
zip_int64_t retval = zip_fread(zf, data->data(), readSize);
|
||||
zip_fclose(zf);
|
||||
|
||||
if (retval < 0 || retval < (int)readSize) {
|
||||
ERROR_LOG(Log::HLE, "Failed to read %d bytes from zip (%d) - archive corrupt?", (int)readSize, (int)retval);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Make this generic and handle all the things.
|
||||
@@ -495,16 +475,15 @@ bool DetectArchiveContents(VFSInterface *vfs, ZipFileInfo *info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void DetectZipFileContents(zip_t *z, ZipFileInfo *info) {
|
||||
void DetectZipFileContents(const ZipContainer &z, ZipFileInfo *info) {
|
||||
info->archiveType = ArchiveType::ZIP;
|
||||
int numFiles = zip_get_num_files(z);
|
||||
if (numFiles < 0) {
|
||||
if (!z) {
|
||||
// Broken zip archive?
|
||||
ERROR_LOG(Log::HLE, "Failed to get the file count of zip file");
|
||||
info->contents = ZipFileContents::UNKNOWN;
|
||||
return;
|
||||
}
|
||||
_dbg_assert_(numFiles >= 0);
|
||||
const int numFiles = z.NumEntries();
|
||||
|
||||
// Verify that this is a PSP zip file with the correct layout. We also try
|
||||
// to detect simple zipped ISO files, those we'll just "install" to the current
|
||||
@@ -528,11 +507,10 @@ void DetectZipFileContents(zip_t *z, ZipFileInfo *info) {
|
||||
// TODO: It might be cleaner to write separate detection functions, but this big loop doing it all at once
|
||||
// is quite convenient and makes it easy to add shared heuristics.
|
||||
for (int i = 0; i < numFiles; i++) {
|
||||
const char *fn = zip_get_name(z, i, 0);
|
||||
|
||||
zip_stat_t stat{};
|
||||
zip_stat_index(z, i, 0, &stat);
|
||||
totalFileSize += stat.size;
|
||||
const char *fn = z.Name(i);
|
||||
if (!fn)
|
||||
continue;
|
||||
totalFileSize += z.Size(i);
|
||||
|
||||
std::string fileName(fn);
|
||||
if (endsWith(fileName, "/")) {
|
||||
@@ -599,9 +577,6 @@ void DetectZipFileContents(zip_t *z, ZipFileInfo *info) {
|
||||
if (sfo.HasKey("TITLE")) {
|
||||
info->gameTitle = sfo.GetValueString("TITLE");
|
||||
info->savedataTitle = sfo.GetValueString("SAVEDATA_TITLE");
|
||||
char buff[20];
|
||||
strftime(buff, 20, "%Y-%m-%d %H:%M:%S", localtime(&stat.mtime));
|
||||
info->mTime = buff;
|
||||
info->savedataDetails = sfo.GetValueString("SAVEDATA_DETAIL");
|
||||
info->savedataDir = sfo.GetValueString("SAVEDATA_DIRECTORY"); // should also be parsable from the path.
|
||||
hasParamSFO = true;
|
||||
|
||||
+1
-1
@@ -206,5 +206,5 @@ struct ZipFileInfo {
|
||||
ZipContainer ZipOpenPath(const Path &fileName);
|
||||
void ZipClose(ZipContainer &z);
|
||||
|
||||
void DetectZipFileContents(zip_t *z, ZipFileInfo *info);
|
||||
void DetectZipFileContents(const ZipContainer &z, ZipFileInfo *info);
|
||||
bool DetectArchiveContents(VFSInterface *vfs, ZipFileInfo *info);
|
||||
+3
-3
@@ -28,7 +28,7 @@
|
||||
|
||||
// for crc32
|
||||
extern "C" {
|
||||
#include "zlib.h"
|
||||
#include <encodings/crc32.h>
|
||||
}
|
||||
|
||||
#include "Core/Reporting.h"
|
||||
@@ -108,7 +108,7 @@ namespace Reporting
|
||||
static u32 CalculateCRC(BlockDevice *blockDevice, std::atomic<bool> *cancel) {
|
||||
auto ga = GetI18NCategory(I18NCat::GAME);
|
||||
|
||||
u32 crc = crc32(0, Z_NULL, 0);
|
||||
u32 crc = 0;
|
||||
|
||||
u8 block[2048];
|
||||
u32 numBlocks = blockDevice->GetNumBlocks();
|
||||
@@ -122,7 +122,7 @@ namespace Reporting
|
||||
g_OSD.RemoveProgressBar("crc", false, 0.0f);
|
||||
return 0;
|
||||
}
|
||||
crc = crc32(crc, block, 2048);
|
||||
crc = encoding_crc32(crc, block, 2048);
|
||||
g_OSD.SetProgressBar("crc", std::string(ga->T("Calculate CRC")), 0.0f, (float)numBlocks, (float)i, 0.5f);
|
||||
}
|
||||
|
||||
|
||||
+3
-22
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <png.h>
|
||||
#include "ext/jpge/jpge.h"
|
||||
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
@@ -453,30 +452,12 @@ bool Save8888RGBAScreenshot(const Path &filename, const u8 *buffer, int w, int h
|
||||
}
|
||||
|
||||
bool Save8888RGBAScreenshot(std::vector<uint8_t> &bufferPNG, const u8 *bufferRGBA8888, int w, int h) {
|
||||
png_image png{};
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
png.format = PNG_FORMAT_RGBA;
|
||||
png.width = w;
|
||||
png.height = h;
|
||||
|
||||
png_alloc_size_t allocSize = bufferPNG.size();
|
||||
int result = png_image_write_to_memory(&png, allocSize == 0 ? nullptr : bufferPNG.data(), &allocSize, 0, bufferRGBA8888, w * 4, nullptr);
|
||||
bool success = result != 0 && png.warning_or_error <= 1;
|
||||
if (!success && allocSize != bufferPNG.size()) {
|
||||
bufferPNG.resize(allocSize);
|
||||
png.warning_or_error = 0;
|
||||
result = png_image_write_to_memory(&png, bufferPNG.data(), &allocSize, 0, bufferRGBA8888, w * 4, nullptr);
|
||||
success = result != 0 && png.warning_or_error <= 1;
|
||||
}
|
||||
if (success)
|
||||
bufferPNG.resize(allocSize);
|
||||
png_image_free(&png);
|
||||
|
||||
if (!success) {
|
||||
if (!pngEncode(&bufferPNG, bufferRGBA8888, w, h)) {
|
||||
ERROR_LOG(Log::IO, "Buffering screenshot to PNG produced errors.");
|
||||
bufferPNG.clear();
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TakeUserScreenshot() {
|
||||
|
||||
+56
-121
@@ -24,11 +24,6 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#ifdef SHARED_LIBZIP
|
||||
#include <zip.h>
|
||||
#else
|
||||
#include "ext/libzip/zip.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Common/CommonWindows.h"
|
||||
@@ -177,16 +172,15 @@ void GameManager::Update() {
|
||||
}
|
||||
}
|
||||
|
||||
bool ZipCanExtractWithoutOverwrite(struct zip *z, const Path &destination, int stripChars, int maxOkFiles) {
|
||||
int numFiles = zip_get_num_files(z);
|
||||
bool ZipCanExtractWithoutOverwrite(const ZipContainer &z, const Path &destination, int stripChars, int maxOkFiles) {
|
||||
int numFiles = z.NumEntries();
|
||||
if (numFiles > maxOkFiles && maxOkFiles >= 0) {
|
||||
// Ignore the check, just assume we can't.
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < numFiles; i++) {
|
||||
const char *fn = zip_get_name(z, i, 0);
|
||||
const char *fn = z.Name(i);
|
||||
if (!fn) {
|
||||
// zip_get_name() returns NULL on a corrupted central directory entry.
|
||||
continue;
|
||||
}
|
||||
if (endsWith(fn, "/")) {
|
||||
@@ -202,23 +196,12 @@ bool ZipCanExtractWithoutOverwrite(struct zip *z, const Path &destination, int s
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string ZipReadFileByIndex(struct zip *z, int file_index) {
|
||||
struct zip_stat zstat;
|
||||
zip_stat_init(&zstat);
|
||||
if (zip_stat_index(z, file_index, 0, &zstat) != 0) {
|
||||
return {};
|
||||
}
|
||||
static std::string ZipReadFileByIndex(const ZipContainer &z, int file_index) {
|
||||
std::string buffer;
|
||||
buffer.resize(zstat.size);
|
||||
zip_file *zf = zip_fopen_index(z, file_index, 0);
|
||||
if (!zf) {
|
||||
buffer.resize((size_t)z.Size(file_index));
|
||||
if (buffer.empty() || !z.ExtractInto(file_index, (uint8_t *)&buffer[0], buffer.size())) {
|
||||
return {};
|
||||
}
|
||||
if (zip_fread(zf, &buffer[0], buffer.size()) != (zip_int64_t)zstat.size) {
|
||||
zip_fclose(zf);
|
||||
return {};
|
||||
}
|
||||
zip_fclose(zf);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -454,17 +437,15 @@ void GameManager::InstallZipContents(ZipFileTask task) {
|
||||
}
|
||||
}
|
||||
|
||||
bool GameManager::DetectTexturePackDest(struct zip *z, int iniIndex, Path &dest) {
|
||||
bool GameManager::DetectTexturePackDest(const ZipContainer &z, int iniIndex, Path &dest) {
|
||||
auto iz = GetI18NCategory(I18NCat::INSTALLZIP);
|
||||
|
||||
struct zip_stat zstat;
|
||||
zip_stat_init(&zstat);
|
||||
if (zip_stat_index(z, iniIndex, 0, &zstat) != 0) {
|
||||
if (iniIndex < 0 || iniIndex >= z.NumEntries()) {
|
||||
SetInstallError(iz->T("Zip archive corrupt"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (zstat.size >= 32 * 1024 * 1024) {
|
||||
if (z.Size(iniIndex) >= 32 * 1024 * 1024) {
|
||||
SetInstallError(iz->T("Texture pack doesn't support install"));
|
||||
return false;
|
||||
}
|
||||
@@ -590,84 +571,47 @@ std::string GameManager::GetISOGameID(FileLoader *loader) const {
|
||||
return sfo.GetValueString("DISC_ID");
|
||||
}
|
||||
|
||||
bool GameManager::ExtractFile(struct zip *z, int file_index, const Path &outFilename, int64_t *bytesCopied, int64_t allBytes, int64_t maxTotalSize) {
|
||||
struct zip_stat zstat;
|
||||
zip_stat_init(&zstat);
|
||||
if (zip_stat_index(z, file_index, 0, &zstat) != 0) {
|
||||
ERROR_LOG(Log::HLE, "Failed to stat file by index (%d) (%s)", file_index, outFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
size_t size = zstat.size;
|
||||
zip_file *zf = zip_fopen_index(z, file_index, 0);
|
||||
if (!zf) {
|
||||
ERROR_LOG(Log::HLE, "Failed to open file by index (%d) (%s)", file_index, outFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameManager::ExtractFile(const ZipContainer &z, int file_index, const Path &outFilename, int64_t *bytesCopied, int64_t allBytes, int64_t maxTotalSize) {
|
||||
const size_t size = (size_t)z.Size(file_index);
|
||||
FILE *f = File::OpenCFile(outFilename, "wb");
|
||||
if (f) {
|
||||
// Don't spam the log.
|
||||
if (file_index < 10) {
|
||||
INFO_LOG(Log::HLE, "Writing %d bytes to '%s'", (int)size, outFilename.c_str());
|
||||
}
|
||||
size_t pos = 0;
|
||||
const size_t blockSize = 1024 * 128;
|
||||
u8 *buffer = new u8[blockSize];
|
||||
while (pos < size) {
|
||||
size_t readSize = std::min(blockSize, size - pos);
|
||||
// Stop before the total would exceed the limit (zip bomb), even
|
||||
// if the declared sizes in the archive were inaccurate.
|
||||
if (*bytesCopied > maxTotalSize || readSize > maxTotalSize - *bytesCopied) {
|
||||
ERROR_LOG(Log::HLE, "Bailing: zip contents too large, limit %d", (int)maxTotalSize);
|
||||
delete[] buffer;
|
||||
fclose(f);
|
||||
zip_fclose(zf);
|
||||
File::Delete(outFilename);
|
||||
return false;
|
||||
}
|
||||
zip_int64_t retval = zip_fread(zf, buffer, readSize);
|
||||
if (retval < 0 || (size_t)retval < readSize) {
|
||||
ERROR_LOG(Log::HLE, "Failed to read %d bytes from zip (%d) - archive corrupt?", (int)readSize, (int)retval);
|
||||
delete[] buffer;
|
||||
fclose(f);
|
||||
zip_fclose(zf);
|
||||
File::Delete(outFilename);
|
||||
return false;
|
||||
}
|
||||
size_t written = fwrite(buffer, 1, readSize, f);
|
||||
if (written != readSize) {
|
||||
ERROR_LOG(Log::HLE, "Wrote %d bytes out of %d - Disk full?", (int)written, (int)readSize);
|
||||
delete[] buffer;
|
||||
fclose(f);
|
||||
zip_fclose(zf);
|
||||
File::Delete(outFilename);
|
||||
return false;
|
||||
}
|
||||
pos += readSize;
|
||||
|
||||
*bytesCopied += readSize;
|
||||
installProgress_ = (float)*bytesCopied / (float)allBytes;
|
||||
}
|
||||
|
||||
zip_fclose(zf);
|
||||
fclose(f);
|
||||
|
||||
// Copy the mtime, too. May not be possible on Android?
|
||||
if (zstat.mtime) {
|
||||
File::ChangeMTime(outFilename, zstat.mtime);
|
||||
}
|
||||
delete[] buffer;
|
||||
return true;
|
||||
} else {
|
||||
if (!f) {
|
||||
auto iz = GetI18NCategory(I18NCat::INSTALLZIP);
|
||||
g_OSD.Show(OSDType::MESSAGE_ERROR, iz->T("Installation failed"), outFilename.ToVisualString());
|
||||
ERROR_LOG(Log::HLE, "Failed to open file for writing: %s", outFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
// Don't spam the log.
|
||||
if (file_index < 10) {
|
||||
INFO_LOG(Log::HLE, "Writing %d bytes to '%s'", (int)size, outFilename.c_str());
|
||||
}
|
||||
// Each decoded piece goes straight to the file.
|
||||
const bool ok = z.ExtractTo(file_index, [&](const uint8_t *data, size_t len) {
|
||||
// Stop before the total would exceed the limit (zip bomb), even
|
||||
// if the declared sizes in the archive were inaccurate.
|
||||
if (*bytesCopied > maxTotalSize || (int64_t)len > maxTotalSize - *bytesCopied) {
|
||||
ERROR_LOG(Log::HLE, "Bailing: zip contents too large, limit %d", (int)maxTotalSize);
|
||||
return false;
|
||||
}
|
||||
const size_t written = fwrite(data, 1, len, f);
|
||||
if (written != len) {
|
||||
ERROR_LOG(Log::HLE, "Wrote %d bytes out of %d - Disk full?", (int)written, (int)len);
|
||||
return false;
|
||||
}
|
||||
*bytesCopied += len;
|
||||
installProgress_ = (float)*bytesCopied / (float)allBytes;
|
||||
return true;
|
||||
});
|
||||
fclose(f);
|
||||
if (!ok) {
|
||||
ERROR_LOG(Log::HLE, "Failed to extract file by index (%d) (%s) - archive corrupt?", file_index, outFilename.c_str());
|
||||
File::Delete(outFilename);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Doesn't care what it is, just extracts the whole ZIP to the requested location.
|
||||
bool GameManager::ExtractZipContents(struct zip *z, const Path &dest, const ZipFileInfo &info, bool allowRoot, int64_t maxTotalSize) {
|
||||
bool GameManager::ExtractZipContents(const ZipContainer &z, const Path &dest, const ZipFileInfo &info, bool allowRoot, int64_t maxTotalSize) {
|
||||
int64_t allBytes = 0;
|
||||
int64_t bytesCopied = 0;
|
||||
|
||||
@@ -704,9 +648,8 @@ bool GameManager::ExtractZipContents(struct zip *z, const Path &dest, const ZipF
|
||||
std::vector<Path> createdFiles;
|
||||
for (int i = 0; i < info.numFiles; i++) {
|
||||
// Let's count the directories as the first 10%.
|
||||
const char *fn = zip_get_name(z, i, 0);
|
||||
const char *fn = z.Name(i);
|
||||
if (!fn) {
|
||||
// zip_get_name() returns NULL on a corrupted central directory entry.
|
||||
continue;
|
||||
}
|
||||
std::string zippedName = fn;
|
||||
@@ -733,17 +676,15 @@ bool GameManager::ExtractZipContents(struct zip *z, const Path &dest, const ZipF
|
||||
createdDirs.insert(outPath);
|
||||
}
|
||||
if (!isDir && fileAllowed(fn)) {
|
||||
struct zip_stat zstat;
|
||||
if (zip_stat_index(z, i, 0, &zstat) >= 0) {
|
||||
// Guard against zip bombs: the total declared size must not
|
||||
// exceed the limit. Check before adding to avoid overflow.
|
||||
if ((int64_t)zstat.size > maxTotalSize || allBytes > maxTotalSize - (int64_t)zstat.size) {
|
||||
ERROR_LOG(Log::HLE, "Bailing: zip contents too large (%d bytes), limit %d", (int)allBytes, (int)maxTotalSize);
|
||||
SetInstallError(sy->T("Too large"));
|
||||
goto bail;
|
||||
}
|
||||
allBytes += (int64_t)zstat.size;
|
||||
const int64_t entrySize = (int64_t)z.Size(i);
|
||||
// Guard against zip bombs: the total declared size must not
|
||||
// exceed the limit. Check before adding to avoid overflow.
|
||||
if (entrySize > maxTotalSize || allBytes > maxTotalSize - entrySize) {
|
||||
ERROR_LOG(Log::HLE, "Bailing: zip contents too large (%d bytes), limit %d", (int)allBytes, (int)maxTotalSize);
|
||||
SetInstallError(sy->T("Too large"));
|
||||
goto bail;
|
||||
}
|
||||
allBytes += entrySize;
|
||||
}
|
||||
g_OSD.SetProgressBar("install", di->T("Installing..."), 0.0f, info.numFiles, (i + 1) * 0.1f, 0.1f);
|
||||
}
|
||||
@@ -752,9 +693,8 @@ bool GameManager::ExtractZipContents(struct zip *z, const Path &dest, const ZipF
|
||||
|
||||
// Now, loop through again in a second pass, writing files.
|
||||
for (int i = 0; i < info.numFiles; i++) {
|
||||
const char *fn = zip_get_name(z, i, 0);
|
||||
const char *fn = z.Name(i);
|
||||
if (!fn) {
|
||||
// zip_get_name() returns NULL on a corrupted central directory entry.
|
||||
continue;
|
||||
}
|
||||
// Note that we do NOT write files that are not in a directory, to avoid random
|
||||
@@ -845,11 +785,10 @@ bool GameManager::InstallMemstickZip(const Path &zipfile, const Path &dest, cons
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, const Path &destDir) {
|
||||
bool GameManager::InstallZippedISO(const ZipContainer &z, int isoFileIndex, const Path &destDir) {
|
||||
// Let's place the output file in the currently selected Games directory.
|
||||
const char *fnPtr = zip_get_name(z, isoFileIndex, 0);
|
||||
const char *fnPtr = z.Name(isoFileIndex);
|
||||
if (!fnPtr) {
|
||||
// zip_get_name() returns NULL on a corrupted central directory entry.
|
||||
return false;
|
||||
}
|
||||
std::string fn = fnPtr;
|
||||
@@ -859,16 +798,12 @@ bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, const Path &
|
||||
} else {
|
||||
nameOffset++;
|
||||
}
|
||||
size_t allBytes = 1;
|
||||
struct zip_stat zstat;
|
||||
zip_stat_init(&zstat);
|
||||
if (zip_stat_index(z, isoFileIndex, 0, &zstat) >= 0) {
|
||||
allBytes += zstat.size;
|
||||
}
|
||||
const size_t isoSize = (size_t)z.Size(isoFileIndex);
|
||||
size_t allBytes = 1 + isoSize;
|
||||
|
||||
std::string name = fn.substr(nameOffset);
|
||||
|
||||
INFO_LOG(Log::IO, "Name in zip: %s size: %d", name.c_str(), (int)zstat.size);
|
||||
INFO_LOG(Log::IO, "Name in zip: %s size: %d", name.c_str(), (int)isoSize);
|
||||
|
||||
if (startsWith(name, "._")) {
|
||||
// Not sure why Apple seems to add this when zipping file?
|
||||
|
||||
@@ -42,7 +42,7 @@ struct ZipFileTask {
|
||||
bool deleteAfter;
|
||||
};
|
||||
|
||||
struct zip;
|
||||
class ZipContainer;
|
||||
class FileLoader;
|
||||
class Path;
|
||||
struct ZipFileInfo;
|
||||
@@ -94,19 +94,19 @@ public:
|
||||
|
||||
// Extracts the contents of an open zip archive into dest. Exposed for testing.
|
||||
// maxTotalSize limits the total decompressed size (zip bomb protection).
|
||||
bool ExtractZipContents(struct zip *z, const Path &dest, const ZipFileInfo &info, bool allowRoot, int64_t maxTotalSize = 0x100000000ULL);
|
||||
bool ExtractZipContents(const ZipContainer &z, const Path &dest, const ZipFileInfo &info, bool allowRoot, int64_t maxTotalSize = 0x100000000ULL);
|
||||
|
||||
private:
|
||||
void InstallZipContents(ZipFileTask task);
|
||||
void InstallPkgContents(Path pkgPath, bool deleteAfter);
|
||||
bool InstallMemstickZip(const Path &zipFile, const Path &dest, const ZipFileInfo &info);
|
||||
bool InstallZippedISO(struct zip *z, int isoFileIndex, const Path &destDir);
|
||||
bool InstallZippedISO(const ZipContainer &z, int isoFileIndex, const Path &destDir);
|
||||
void UninstallGame(const std::string &name);
|
||||
|
||||
void InstallDone();
|
||||
|
||||
bool ExtractFile(struct zip *z, int file_index, const Path &outFilename, int64_t *bytesCopied, int64_t allBytes, int64_t maxTotalSize = 0x100000000ULL);
|
||||
bool DetectTexturePackDest(struct zip *z, int iniIndex, Path &dest);
|
||||
bool ExtractFile(const ZipContainer &z, int file_index, const Path &outFilename, int64_t *bytesCopied, int64_t allBytes, int64_t maxTotalSize = 0x100000000ULL);
|
||||
bool DetectTexturePackDest(const ZipContainer &z, int iniIndex, Path &dest);
|
||||
void SetInstallError(std::string_view err);
|
||||
|
||||
bool InstallInProgress() const { return installThread_.joinable(); }
|
||||
@@ -126,4 +126,4 @@ private:
|
||||
|
||||
extern GameManager g_GameManager;
|
||||
|
||||
bool ZipCanExtractWithoutOverwrite(struct zip *z, const Path &destination, int stripChars, int maxOkFiles);
|
||||
bool ZipCanExtractWithoutOverwrite(const ZipContainer &z, const Path &destination, int stripChars, int maxOkFiles);
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <map>
|
||||
#include <string_view>
|
||||
|
||||
#include "zlib.h"
|
||||
#include "Common/Data/Encoding/Compression.h"
|
||||
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/File/DirListing.h"
|
||||
@@ -721,10 +721,9 @@ void PSARReader::EnsureContents() {
|
||||
entryCompression_ = DetectCompression(block2_.data(), decoded);
|
||||
if (entryCompression_ == PSARCompression::Zlib) {
|
||||
entryData_.resize(contentExpandedSize_);
|
||||
uLongf destLen = contentExpandedSize_;
|
||||
const int zResult = uncompress(entryData_.data(), &destLen, block2_.data(), decoded);
|
||||
if (zResult != Z_OK || destLen != contentExpandedSize_) {
|
||||
WARN_LOG(Log::Loader, "PSAR: inflate failed for '%s' (%d)", entryName_.c_str(), zResult);
|
||||
const int64_t destLen = InflateBuffer(15, block2_.data(), (size_t)decoded, entryData_.data(), entryData_.size());
|
||||
if (destLen != (int64_t)contentExpandedSize_) {
|
||||
WARN_LOG(Log::Loader, "PSAR: inflate failed for '%s' (%d)", entryName_.c_str(), (int)destLen);
|
||||
entryData_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -199,21 +199,9 @@ set(GPU_SOURCES
|
||||
add_library(GPU OBJECT ${GPU_SOURCES})
|
||||
target_compile_features(GPU PUBLIC cxx_std_17)
|
||||
|
||||
if(LIBRETRO)
|
||||
target_include_directories(GPU PRIVATE ${CMAKE_SOURCE_DIR}/libretro/libretro-common/include)
|
||||
endif()
|
||||
|
||||
setup_target_project(GPU GPU)
|
||||
|
||||
# The only direct external dependencies of GPU/ itself (as opposed to Common/GPU/*, which
|
||||
# already carries its own GL/Vulkan loader abstractions): raw gl*() calls in GPU/GLES, direct
|
||||
# ZSTD_compress/decompress calls in GPU/Debugger/Record.cpp and Playback.cpp, and Playback.cpp
|
||||
# also calls snappy_uncompress() directly.
|
||||
target_link_libraries(GPU PUBLIC ${OPENGL_LIBRARIES} ${X11_LIBRARIES} Ext::Snappy)
|
||||
|
||||
if(USE_SYSTEM_ZSTD)
|
||||
target_include_directories(GPU PRIVATE ${ZSTD_INCLUDE_DIR})
|
||||
target_link_libraries(GPU PUBLIC ${ZSTD_LIBRARY})
|
||||
else()
|
||||
target_link_libraries(GPU PUBLIC libzstd_static)
|
||||
endif()
|
||||
# already carries its own GL/Vulkan loader abstractions): raw gl*() calls in GPU/GLES, rzstd
|
||||
# calls in GPU/Debugger/Record.cpp and Playback.cpp, and snappy_uncompress() in Playback.cpp.
|
||||
target_link_libraries(GPU PUBLIC ${OPENGL_LIBRARIES} ${X11_LIBRARIES} Ext::Snappy libretro-common)
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
|
||||
#include <png.h>
|
||||
|
||||
#include "ext/basis_universal/basisu_transcoder.h"
|
||||
#include "ext/basis_universal/basisu_file_headers.h"
|
||||
@@ -725,48 +724,32 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
|
||||
return LoadLevelResult::CONTINUE;
|
||||
|
||||
} else if (imageType == ReplacedImageType::PNG) {
|
||||
png_image png = {};
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
|
||||
std::string pngdata;
|
||||
pngdata.resize(fileSize);
|
||||
pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize));
|
||||
vfs_->CloseFile(openFile);
|
||||
if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) {
|
||||
ERROR_LOG(Log::TexReplacement, "Could not load texture replacement info: %s - %s (zip)", filename.c_str(), png.message);
|
||||
return LoadLevelResult::LOAD_ERROR;
|
||||
}
|
||||
if (png.width > (uint32_t)level.w || png.height > (uint32_t)level.h) {
|
||||
ERROR_LOG(Log::TexReplacement, "Texture replacement changed since header read: %s", filename.c_str());
|
||||
png_image_free(&png);
|
||||
return LoadLevelResult::LOAD_ERROR;
|
||||
}
|
||||
|
||||
bool checkedAlpha = false;
|
||||
if ((png.format & PNG_FORMAT_FLAG_ALPHA) == 0) {
|
||||
// Well, we know for sure it doesn't have alpha.
|
||||
if (mipLevel == 0) {
|
||||
alphaStatus_ = TextureAlpha::Solid;
|
||||
}
|
||||
checkedAlpha = true;
|
||||
int w = 0, h = 0;
|
||||
unsigned char *image = nullptr;
|
||||
if (!pngLoadPtr((const unsigned char *)pngdata.data(), pngdata.size(), &w, &h, &image, level.w, level.h)) {
|
||||
ERROR_LOG(Log::TexReplacement, "Could not load texture replacement: %s", filename.c_str());
|
||||
return LoadLevelResult::LOAD_ERROR;
|
||||
}
|
||||
png.format = PNG_FORMAT_RGBA;
|
||||
|
||||
std::vector<uint8_t> &out = data_[mipLevel];
|
||||
out.resize(level.w * level.h * 4);
|
||||
if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) {
|
||||
ERROR_LOG(Log::TexReplacement, "Could not load texture replacement: %s - %s", filename.c_str(), png.message);
|
||||
out.resize(0);
|
||||
return LoadLevelResult::LOAD_ERROR;
|
||||
if (w == level.w) {
|
||||
memcpy(&out[0], image, (size_t)w * 4 * h);
|
||||
} else {
|
||||
for (int y = 0; y < h; ++y)
|
||||
memcpy(&out[(size_t)level.w * 4 * y], image + (size_t)w * 4 * y, (size_t)w * 4);
|
||||
}
|
||||
png_image_free(&png);
|
||||
free(image);
|
||||
|
||||
if (!checkedAlpha) {
|
||||
// This will only check the hashed bits.
|
||||
const TextureAlpha res = CheckAlpha32Rect((u32 *)&out[0], level.w, png.width, png.height, 0xFF000000);
|
||||
if (res == TextureAlpha::Any || mipLevel == 0) {
|
||||
alphaStatus_ = res;
|
||||
}
|
||||
// This will only check the hashed bits.
|
||||
const TextureAlpha res = CheckAlpha32Rect((u32 *)&out[0], level.w, w, h, 0xFF000000);
|
||||
if (res == TextureAlpha::Any || mipLevel == 0) {
|
||||
alphaStatus_ = res;
|
||||
}
|
||||
|
||||
levels_.push_back(level);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <png.h>
|
||||
|
||||
#include "ext/basis_universal/basisu_transcoder.h"
|
||||
#include "ext/xxhash.h"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <snappy-c.h>
|
||||
#include <zstd.h>
|
||||
#include <encodings/rzstd.h>
|
||||
|
||||
#include "Common/Profiler/Profiler.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
@@ -1082,8 +1082,8 @@ static bool ReadCompressed(u32 fp, void *dest, size_t sz, uint32_t version) {
|
||||
size_t real_size = sz;
|
||||
if (version < 5)
|
||||
snappy_uncompress((const char *)compressed, compressed_size, (char *)dest, &real_size);
|
||||
else
|
||||
real_size = ZSTD_decompress(dest, real_size, compressed, compressed_size);
|
||||
else if (rzstd_decode((uint8_t *)dest, sz, compressed, compressed_size, &real_size) != RZSTD_PROCESS_END)
|
||||
real_size = 0;
|
||||
delete[] compressed;
|
||||
|
||||
return real_size == sz;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <zstd.h>
|
||||
#include <encodings/rzstd.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
@@ -169,9 +169,10 @@ bool Recorder::BeginRecording() {
|
||||
}
|
||||
|
||||
static void WriteCompressed(FILE *fp, const void *p, size_t sz) {
|
||||
size_t compressed_size = ZSTD_compressBound(sz);
|
||||
size_t compressed_size = rzstd_compress_bound(sz);
|
||||
u8 *compressed = new u8[compressed_size];
|
||||
compressed_size = ZSTD_compress(compressed, compressed_size, p, sz, 6);
|
||||
if (rzstd_encode(compressed, compressed_size, (const u8 *)p, sz, 6, &compressed_size) != RZSTD_PROCESS_END)
|
||||
compressed_size = 0;
|
||||
|
||||
u32 write_size = (u32)compressed_size;
|
||||
fwrite(&write_size, sizeof(write_size), 1, fp);
|
||||
|
||||
@@ -14,9 +14,6 @@ set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "let's not build binaries we don't ne
|
||||
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON CACHE BOOL "let's not use exceptions" FORCE)
|
||||
set(ENABLE_SPVREMAPPER OFF CACHE BOOL "we don't need spvremapper" FORCE)
|
||||
|
||||
# not really needed since we currently bypass the official cmakelists...
|
||||
set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "we don't need zlib examples" FORCE)
|
||||
|
||||
# This is really a workaround for an NDK 20 compiler issue (PPSSPP issue #12105), but shouldn't hurt.
|
||||
if(ANDROID)
|
||||
set(ENABLE_HLSL OFF CACHE BOOL "let's not build HLSL support we don't need" FORCE)
|
||||
@@ -93,10 +90,6 @@ if(USE_DISCORD AND NOT IOS AND NOT LIBRETRO)
|
||||
add_subdirectory(discord-rpc-build)
|
||||
endif()
|
||||
|
||||
if(NOT USE_SYSTEM_LIBCHDR)
|
||||
add_subdirectory(libchdr-build)
|
||||
endif()
|
||||
|
||||
if(BUILD_BUNDLED_FFMPEG)
|
||||
add_subdirectory(ffmpeg-build)
|
||||
endif()
|
||||
|
||||
@@ -19,10 +19,5 @@ add_library(basis_universal STATIC
|
||||
basisu_transcoder_uastc.h
|
||||
)
|
||||
|
||||
# basisu_transcoder.cpp calls ZSTD_decompress()/ZSTD_isError() directly for KTX2 supercompression.
|
||||
if(USE_SYSTEM_ZSTD)
|
||||
target_include_directories(basis_universal PRIVATE ${ZSTD_INCLUDE_DIR})
|
||||
target_link_libraries(basis_universal ${ZSTD_LIBRARY})
|
||||
else()
|
||||
target_link_libraries(basis_universal libzstd_static)
|
||||
endif()
|
||||
# KTX2 supercompression goes through libretro-common's rzstd.
|
||||
target_link_libraries(basis_universal libretro-common)
|
||||
@@ -154,8 +154,8 @@
|
||||
#if BASISD_SUPPORT_KTX2
|
||||
// If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded.
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
// We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError()
|
||||
#include <zstd.h>
|
||||
// Zstd comes from libretro-common's rzstd.
|
||||
#include <encodings/rzstd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -17236,8 +17236,8 @@ namespace basist
|
||||
if (m_header.m_supercompression_scheme == KTX2_SS_ZSTANDARD)
|
||||
{
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
size_t actualUncompSize = ZSTD_decompress(uncomp_data.data(), (size_t)uncomp_size, pComp_data, (size_t)comp_size);
|
||||
if (ZSTD_isError(actualUncompSize))
|
||||
size_t actualUncompSize = 0;
|
||||
if (rzstd_decode(uncomp_data.data(), (size_t)uncomp_size, pComp_data, (size_t)comp_size, &actualUncompSize) != RZSTD_PROCESS_END)
|
||||
{
|
||||
BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Zstd decompression failed, file is invalid or corrupted\n");
|
||||
return false;
|
||||
|
||||
-1
Submodule ext/libchdr deleted from 8bba7745d7.
@@ -1,36 +0,0 @@
|
||||
cmake_minimum_required (VERSION 3.10.0)
|
||||
project (chdr)
|
||||
|
||||
set(LZMA_DIR ../libchdr/deps/lzma-24.05/src)
|
||||
set(SRC_DIR ../libchdr/src)
|
||||
|
||||
include_directories(../libchdr/deps/lzma-24.05/include)
|
||||
include_directories(../libchdr/include)
|
||||
include_directories(../zlib)
|
||||
include_directories(../zstd/lib)
|
||||
|
||||
add_definitions(-DZ7_ST)
|
||||
|
||||
# Hack - CpuArch.c has a workaround that we reuse.
|
||||
add_definitions(-D__SWITCH__)
|
||||
|
||||
set(ALL_SOURCE_FILES
|
||||
${LZMA_DIR}/Alloc.c
|
||||
${LZMA_DIR}/Bra.c
|
||||
${LZMA_DIR}/Bra86.c
|
||||
${LZMA_DIR}/BraIA64.c
|
||||
${LZMA_DIR}/CpuArch.c
|
||||
${LZMA_DIR}/Delta.c
|
||||
${LZMA_DIR}/LzFind.c
|
||||
${LZMA_DIR}/LzmaDec.c
|
||||
${LZMA_DIR}/LzmaEnc.c
|
||||
${LZMA_DIR}/Lzma86Dec.c
|
||||
${LZMA_DIR}/Sort.c
|
||||
${SRC_DIR}/libchdr_bitstream.c
|
||||
${SRC_DIR}/libchdr_cdrom.c
|
||||
${SRC_DIR}/libchdr_chd.c
|
||||
${SRC_DIR}/libchdr_flac.c
|
||||
${SRC_DIR}/libchdr_huffman.c
|
||||
)
|
||||
|
||||
add_library(chdr STATIC ${ALL_SOURCE_FILES})
|
||||
@@ -1,314 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Alloc.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Bra.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Bra86.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\BraIA64.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\CpuArch.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Delta.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\LzFind.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Lzma86Dec.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\LzmaDec.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\LzmaEnc.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Sort.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_bitstream.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_cdrom.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_chd.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_flac.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_huffman.c" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\7zTypes.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\7zWindows.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Alloc.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Bra.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Compiler.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\CpuArch.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Delta.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzFind.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzHash.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Lzma86.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzmaDec.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzmaEnc.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Precomp.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\RotateDefs.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Sort.h" />
|
||||
<ClInclude Include="libchdr\include\dr_libs\dr_flac.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\bitstream.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\cdrom.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\chd.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\chdconfig.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\flac.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\huffman.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{956F1F48-B612-46D8-89EE-96996DCD9383}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>libchdr</RootNamespace>
|
||||
<TargetName>libchdr_static</TargetName>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<OutDir>$(SolutionDir)..\ext\libchdr\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\ext\libchdr\bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\</IntDir>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Windows\fix_2017.props" />
|
||||
</ImportGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>$(IncludePath);$(SolutionDir)..\ext\libchdr\include;$(UniversalCRT_IncludePath);</IncludePath>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>Z7_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<AdditionalIncludeDirectories>libchdr\include;libchdr\deps\lzma-24.05\include;zlib;zstd\lib;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>Z7_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<AdditionalIncludeDirectories>libchdr\include;libchdr\deps\lzma-24.05\include;zlib;zstd\lib;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>Z7_ST;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<AdditionalIncludeDirectories>libchdr\include;libchdr\deps\lzma-24.05\include;zlib;zstd\lib;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>Z7_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
<AdditionalIncludeDirectories>libchdr\include;libchdr\deps\lzma-24.05\include;zlib;zstd\lib;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>Z7_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>libchdr\include;libchdr\deps\lzma-24.05\include;zlib;zstd\lib;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>Z7_ST;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>libchdr\include;libchdr\deps\lzma-24.05\include;zlib;zstd\lib;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libchdr\src\libchdr_bitstream.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_cdrom.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_chd.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_flac.c" />
|
||||
<ClCompile Include="libchdr\src\libchdr_huffman.c" />
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Alloc.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Bra.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Bra86.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\BraIA64.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\CpuArch.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Delta.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\LzFind.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Lzma86Dec.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\LzmaDec.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\LzmaEnc.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="libchdr\deps\lzma-24.05\src\Sort.c">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libchdr\include\dr_libs\dr_flac.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\bitstream.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\cdrom.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\chd.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\chdconfig.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\flac.h" />
|
||||
<ClInclude Include="libchdr\include\libchdr\huffman.h" />
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\7zTypes.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\7zWindows.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Alloc.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Bra.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Compiler.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\CpuArch.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Delta.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzFind.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzHash.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Lzma86.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzmaDec.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\LzmaEnc.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Precomp.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\RotateDefs.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="libchdr\deps\lzma-24.05\include\Sort.h">
|
||||
<Filter>LZMA</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="LZMA">
|
||||
<UniqueIdentifier>{ff31581b-3ff9-4e39-bb96-2f662896cf70}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,43 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
project(libpng17)
|
||||
|
||||
add_library(png17 STATIC
|
||||
pngconf.h
|
||||
pngdebug.h
|
||||
png.c
|
||||
png.h
|
||||
pngerror.c
|
||||
pngget.c
|
||||
pnginfo.h
|
||||
pnglibconf.h
|
||||
pngmem.c
|
||||
pngpread.c
|
||||
pngpriv.h
|
||||
pngread.c
|
||||
pngrio.c
|
||||
pngrtran.c
|
||||
pngrutil.c
|
||||
pngset.c
|
||||
pngstruct.h
|
||||
pngtest.c
|
||||
pngtrans.c
|
||||
pngwio.c
|
||||
pngwrite.c
|
||||
pngwtran.c
|
||||
pngwutil.c
|
||||
)
|
||||
|
||||
# Add arm files for ARM processors
|
||||
if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm(64)?|aarch64")
|
||||
set (ARM_FILES arm/arm_init.c
|
||||
)
|
||||
|
||||
# Check if it's 32 bit
|
||||
if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
|
||||
list(APPEND ARM_FILES arm/filter_neon.S)
|
||||
else()
|
||||
list(APPEND ARM_FILES arm/filter_neon_intrinsics.c)
|
||||
endif()
|
||||
|
||||
target_sources(png17 PRIVATE ${ARM_FILES})
|
||||
endif()
|
||||
@@ -1,135 +0,0 @@
|
||||
|
||||
/* arm_init.c - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2014 Glenn Randers-Pehrson
|
||||
* Written by Mans Rullgard, 2011.
|
||||
* Last changed in libpng 1.6.16 [December 22, 2014]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
|
||||
* called.
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
|
||||
#include "../pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_arm_arm_init
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
|
||||
/* WARNING: it is strongly recommended that you do not build libpng with
|
||||
* run-time checks for CPU features if at all possible. In the case of the ARM
|
||||
* NEON instructions there is no processor-specific way of detecting the
|
||||
* presence of the required support, therefore run-time detection is extremely
|
||||
* OS specific.
|
||||
*
|
||||
* You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
|
||||
* a fragment of C source code which defines the png_have_neon function. There
|
||||
* are a number of implementations in contrib/arm-neon, but the only one that
|
||||
* has partial support is contrib/arm-neon/linux.c - a generic Linux
|
||||
* implementation which reads /proc/cpufino.
|
||||
*/
|
||||
#ifndef PNG_ARM_NEON_FILE
|
||||
# ifdef __linux__
|
||||
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_ARM_NEON_FILE
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
static int png_have_neon(png_structp png_ptr);
|
||||
#include PNG_ARM_NEON_FILE
|
||||
|
||||
#else /* PNG_ARM_NEON_FILE */
|
||||
# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
|
||||
#endif /* PNG_ARM_NEON_FILE */
|
||||
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||
|
||||
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
|
||||
#endif
|
||||
|
||||
void
|
||||
png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
|
||||
{
|
||||
/* The switch statement is compiled in for ARM_NEON_API, the call to
|
||||
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
|
||||
* the check is only performed if the API has not set the NEON option on
|
||||
* or off explicitly. In this case the check controls what happens.
|
||||
*
|
||||
* If the CHECK is not compiled in and the option is UNSET the behavior prior
|
||||
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
|
||||
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
|
||||
* as documented in png.h
|
||||
*/
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
switch ((pp->options >> PNG_ARM_NEON) & 3)
|
||||
{
|
||||
case PNG_OPTION_UNSET:
|
||||
/* Allow the run-time check to execute if it has been enabled -
|
||||
* thus both API and CHECK can be turned on. If it isn't supported
|
||||
* this case will fall through to the 'default' below, which just
|
||||
* returns.
|
||||
*/
|
||||
#endif /* PNG_ARM_NEON_API_SUPPORTED */
|
||||
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||
{
|
||||
static volatile sig_atomic_t no_neon = -1; /* not checked */
|
||||
|
||||
if (no_neon < 0)
|
||||
no_neon = !png_have_neon(pp);
|
||||
|
||||
if (no_neon)
|
||||
return;
|
||||
}
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
break;
|
||||
#endif
|
||||
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
default: /* OFF or INVALID */
|
||||
return;
|
||||
|
||||
case PNG_OPTION_ON:
|
||||
/* Option turned on */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IMPORTANT: any new external functions used here must be declared using
|
||||
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
|
||||
* 'prefix' option to configure works:
|
||||
*
|
||||
* ./configure --with-libpng-prefix=foobar_
|
||||
*
|
||||
* Verify you have got this right by running the above command, doing a build
|
||||
* and examining pngprefix.h; it must contain a #define for every external
|
||||
* function you add. (Notice that this happens automatically for the
|
||||
* initialization function.)
|
||||
*/
|
||||
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
|
||||
|
||||
if (bpp == 3)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth3_neon;
|
||||
}
|
||||
|
||||
else if (bpp == 4)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth4_neon;
|
||||
}
|
||||
}
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* READ */
|
||||
@@ -1,253 +0,0 @@
|
||||
|
||||
/* filter_neon.S - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2014 Glenn Randers-Pehrson
|
||||
* Written by Mans Rullgard, 2011.
|
||||
* Last changed in libpng 1.6.16 [(PENDING RELEASE)]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* This is required to get the symbol renames, which are #defines, and the
|
||||
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
|
||||
*/
|
||||
#define PNG_VERSION_INFO_ONLY
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
|
||||
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
|
||||
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
|
||||
* for the logic which sets PNG_USE_ARM_NEON_ASM:
|
||||
*/
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
|
||||
#ifdef __ELF__
|
||||
# define ELF
|
||||
#else
|
||||
# define ELF @
|
||||
#endif
|
||||
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
.macro func name, export=0
|
||||
.macro endfunc
|
||||
ELF .size \name, . - \name
|
||||
.endfunc
|
||||
.purgem endfunc
|
||||
.endm
|
||||
.text
|
||||
|
||||
/* Explicitly specifying alignment here because some versions of
|
||||
* GAS don't align code correctly. This is harmless in correctly
|
||||
* written versions of GAS.
|
||||
*/
|
||||
.align 2
|
||||
|
||||
.if \export
|
||||
.global \name
|
||||
.endif
|
||||
ELF .type \name, STT_FUNC
|
||||
.func \name
|
||||
\name:
|
||||
.endm
|
||||
|
||||
func png_read_filter_row_sub4_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vadd.u8 d0, d3, d4
|
||||
vadd.u8 d1, d0, d5
|
||||
vadd.u8 d2, d1, d6
|
||||
vadd.u8 d3, d2, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r3, r3, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_sub3_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
mov r0, r1
|
||||
mov r2, #3
|
||||
mov r12, #12
|
||||
vld1.8 {q11}, [r0], r12
|
||||
1:
|
||||
vext.8 d5, d22, d23, #3
|
||||
vadd.u8 d0, d3, d22
|
||||
vext.8 d6, d22, d23, #6
|
||||
vadd.u8 d1, d0, d5
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], r12
|
||||
vst1.32 {d0[0]}, [r1,:32], r2
|
||||
vadd.u8 d2, d1, d6
|
||||
vst1.32 {d1[0]}, [r1], r2
|
||||
vadd.u8 d3, d2, d7
|
||||
vst1.32 {d2[0]}, [r1], r2
|
||||
vst1.32 {d3[0]}, [r1], r2
|
||||
subs r3, r3, #12
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_up_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
1:
|
||||
vld1.8 {q0}, [r1,:128]
|
||||
vld1.8 {q1}, [r2,:128]!
|
||||
vadd.u8 q0, q0, q1
|
||||
vst1.8 {q0}, [r1,:128]!
|
||||
subs r3, r3, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_avg4_neon, export=1
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||
vhadd.u8 d0, d3, d16
|
||||
vadd.u8 d0, d0, d4
|
||||
vhadd.u8 d1, d0, d17
|
||||
vadd.u8 d1, d1, d5
|
||||
vhadd.u8 d2, d1, d18
|
||||
vadd.u8 d2, d2, d6
|
||||
vhadd.u8 d3, d2, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r12, r12, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_avg3_neon, export=1
|
||||
push {r4,lr}
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
mov r0, r1
|
||||
mov r4, #3
|
||||
mov lr, #12
|
||||
vld1.8 {q11}, [r0], lr
|
||||
1:
|
||||
vld1.8 {q10}, [r2], lr
|
||||
vext.8 d5, d22, d23, #3
|
||||
vhadd.u8 d0, d3, d20
|
||||
vext.8 d17, d20, d21, #3
|
||||
vadd.u8 d0, d0, d22
|
||||
vext.8 d6, d22, d23, #6
|
||||
vhadd.u8 d1, d0, d17
|
||||
vext.8 d18, d20, d21, #6
|
||||
vadd.u8 d1, d1, d5
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], lr
|
||||
vst1.32 {d0[0]}, [r1,:32], r4
|
||||
vhadd.u8 d2, d1, d18
|
||||
vst1.32 {d1[0]}, [r1], r4
|
||||
vext.8 d19, d21, d21, #1
|
||||
vadd.u8 d2, d2, d6
|
||||
vhadd.u8 d3, d2, d19
|
||||
vst1.32 {d2[0]}, [r1], r4
|
||||
vadd.u8 d3, d3, d7
|
||||
vst1.32 {d3[0]}, [r1], r4
|
||||
subs r12, r12, #12
|
||||
bgt 1b
|
||||
|
||||
pop {r4,pc}
|
||||
endfunc
|
||||
|
||||
.macro paeth rx, ra, rb, rc
|
||||
vaddl.u8 q12, \ra, \rb @ a + b
|
||||
vaddl.u8 q15, \rc, \rc @ 2*c
|
||||
vabdl.u8 q13, \rb, \rc @ pa
|
||||
vabdl.u8 q14, \ra, \rc @ pb
|
||||
vabd.u16 q15, q12, q15 @ pc
|
||||
vcle.u16 q12, q13, q14 @ pa <= pb
|
||||
vcle.u16 q13, q13, q15 @ pa <= pc
|
||||
vcle.u16 q14, q14, q15 @ pb <= pc
|
||||
vand q12, q12, q13 @ pa <= pb && pa <= pc
|
||||
vmovn.u16 d28, q14
|
||||
vmovn.u16 \rx, q12
|
||||
vbsl d28, \rb, \rc
|
||||
vbsl \rx, \ra, d28
|
||||
.endm
|
||||
|
||||
func png_read_filter_row_paeth4_neon, export=1
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
vmov.i8 d20, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||
paeth d0, d3, d16, d20
|
||||
vadd.u8 d0, d0, d4
|
||||
paeth d1, d0, d17, d16
|
||||
vadd.u8 d1, d1, d5
|
||||
paeth d2, d1, d18, d17
|
||||
vadd.u8 d2, d2, d6
|
||||
paeth d3, d2, d19, d18
|
||||
vmov d20, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r12, r12, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_paeth3_neon, export=1
|
||||
push {r4,lr}
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
vmov.i8 d4, #0
|
||||
mov r0, r1
|
||||
mov r4, #3
|
||||
mov lr, #12
|
||||
vld1.8 {q11}, [r0], lr
|
||||
1:
|
||||
vld1.8 {q10}, [r2], lr
|
||||
paeth d0, d3, d20, d4
|
||||
vext.8 d5, d22, d23, #3
|
||||
vadd.u8 d0, d0, d22
|
||||
vext.8 d17, d20, d21, #3
|
||||
paeth d1, d0, d17, d20
|
||||
vst1.32 {d0[0]}, [r1,:32], r4
|
||||
vext.8 d6, d22, d23, #6
|
||||
vadd.u8 d1, d1, d5
|
||||
vext.8 d18, d20, d21, #6
|
||||
paeth d2, d1, d18, d17
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], lr
|
||||
vst1.32 {d1[0]}, [r1], r4
|
||||
vadd.u8 d2, d2, d6
|
||||
vext.8 d19, d21, d21, #1
|
||||
paeth d3, d2, d19, d18
|
||||
vst1.32 {d2[0]}, [r1], r4
|
||||
vmov d4, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst1.32 {d3[0]}, [r1], r4
|
||||
subs r12, r12, #12
|
||||
bgt 1b
|
||||
|
||||
pop {r4,pc}
|
||||
endfunc
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
|
||||
#endif /* READ */
|
||||
@@ -1,395 +0,0 @@
|
||||
|
||||
/* filter_neon_intrinsics.c - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2014 Glenn Randers-Pehrson
|
||||
* Written by James Yu <james.yu at linaro.org>, October 2013.
|
||||
* Based on filter_neon.S, written by Mans Rullgard, 2011.
|
||||
*
|
||||
* Last changed in libpng 1.6.16 [December 22, 2014]
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#include "../pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_arm_filter_neon_intrinsics
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* This code requires -mfpu=neon on the command line: */
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_ARM64)
|
||||
#include <arm64_neon.h>
|
||||
#else
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
/* libpng row pointers are not necessarily aligned to any particular boundary,
|
||||
* however this code will only work with appropriate alignment. arm/arm_init.c
|
||||
* checks for this (and will not compile unless it is done). This code uses
|
||||
* variants of png_aligncast to avoid compiler warnings.
|
||||
*/
|
||||
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
|
||||
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
|
||||
|
||||
/* The following relies on a variable 'temp_pointer' being declared with type
|
||||
* 'type'. This is written this way just to hide the GCC strict aliasing
|
||||
* warning; note that the code is safe because there never is an alias between
|
||||
* the input and output pointers.
|
||||
*/
|
||||
#define png_ldr(type,pointer)\
|
||||
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
|
||||
void
|
||||
png_read_filter_row_up_neon(png_alloc_size_t rowbytes, unsigned int bpp,
|
||||
png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint8x16_t qrp, qpp;
|
||||
|
||||
qrp = vld1q_u8(rp);
|
||||
qpp = vld1q_u8(pp);
|
||||
qrp = vaddq_u8(qrp, qpp);
|
||||
vst1q_u8(rp, qrp);
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_sub3_neon(png_alloc_size_t rowbytes, unsigned int bpp, png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
|
||||
uint8x16_t vtmp = vld1q_u8(rp);
|
||||
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||
uint8x8x2_t vrp = *vrpt;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
for (; rp < rp_stop;)
|
||||
{
|
||||
uint8x8_t vtmp1, vtmp2;
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||
vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
|
||||
vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_row)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_sub4_neon(png_alloc_size_t rowbytes, unsigned int bpp,
|
||||
png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
for (; rp < rp_stop; rp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
uint8x8x4_t vrp = *vrpt;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
|
||||
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_row)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_avg3_neon(png_alloc_size_t rowbytes, unsigned int bpp,
|
||||
png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
|
||||
uint8x16_t vtmp;
|
||||
uint8x8x2_t *vrpt;
|
||||
uint8x8x2_t vrp;
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
vtmp = vld1q_u8(rp);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
for (; rp < rp_stop; pp += 12)
|
||||
{
|
||||
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||
|
||||
uint8x8x2_t *vppt;
|
||||
uint8x8x2_t vpp;
|
||||
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp = vld1q_u8(pp);
|
||||
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||
vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||
|
||||
vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_avg4_neon(png_alloc_size_t rowbytes, unsigned int bpp,
|
||||
png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp;
|
||||
uint8x8x4_t *vrpt, *vppt;
|
||||
uint8x8x4_t vrp, vpp;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
|
||||
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||
vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
|
||||
static uint8x8_t
|
||||
paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
|
||||
{
|
||||
uint8x8_t d, e;
|
||||
uint16x8_t p1, pa, pb, pc;
|
||||
|
||||
p1 = vaddl_u8(a, b); /* a + b */
|
||||
pc = vaddl_u8(c, c); /* c * 2 */
|
||||
pa = vabdl_u8(b, c); /* pa */
|
||||
pb = vabdl_u8(a, c); /* pb */
|
||||
pc = vabdq_u16(p1, pc); /* pc */
|
||||
|
||||
p1 = vcleq_u16(pa, pb); /* pa <= pb */
|
||||
pa = vcleq_u16(pa, pc); /* pa <= pc */
|
||||
pb = vcleq_u16(pb, pc); /* pb <= pc */
|
||||
|
||||
p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
|
||||
|
||||
d = vmovn_u16(pb);
|
||||
e = vmovn_u16(p1);
|
||||
|
||||
d = vbsl_u8(d, b, c);
|
||||
e = vbsl_u8(e, a, d);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_paeth3_neon(png_alloc_size_t rowbytes, unsigned int bpp,
|
||||
png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
|
||||
uint8x16_t vtmp;
|
||||
uint8x8x2_t *vrpt;
|
||||
uint8x8x2_t vrp;
|
||||
uint8x8_t vlast = vdup_n_u8(0);
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
vtmp = vld1q_u8(rp);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
for (; rp < rp_stop; pp += 12)
|
||||
{
|
||||
uint8x8x2_t *vppt;
|
||||
uint8x8x2_t vpp;
|
||||
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp = vld1q_u8(pp);
|
||||
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||
vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||
vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||
|
||||
vlast = vtmp2;
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_paeth4_neon(png_alloc_size_t rowbytes, unsigned int bpp,
|
||||
png_bytep row, png_const_bytep prev_row, png_const_bytep prev_pixels)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
uint8x8_t vlast = vdup_n_u8(0);
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp;
|
||||
uint8x8x4_t *vrpt, *vppt;
|
||||
uint8x8x4_t vrp, vpp;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
|
||||
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||
vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||
vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||
|
||||
vlast = vpp.val[3];
|
||||
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
|
||||
}
|
||||
|
||||
PNG_UNUSED(bpp)
|
||||
PNG_UNUSED(prev_pixels)
|
||||
}
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
|
||||
#endif /* READ */
|
||||
@@ -1,124 +0,0 @@
|
||||
/* Compile time options.
|
||||
* =====================
|
||||
* In a multi-arch build the compiler may compile the code several times for the
|
||||
* same object module, producing different binaries for different architectures.
|
||||
* When this happens configure-time setting of the target host options cannot be
|
||||
* done. An example is iOS vs Android compilation of ARM NEON support.
|
||||
*
|
||||
* NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
|
||||
* this is not possible with certain compilers (Oracle SUN OS CC), as a result
|
||||
* it is necessary to ensure that all extern functions that *might* be used
|
||||
* regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON
|
||||
* below is one example of this behavior because it is controlled by the
|
||||
* presence or not of -mfpu=neon on the GCC command line, it is possible to do
|
||||
* this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
|
||||
* do this.
|
||||
*/
|
||||
#ifndef PNG_ARM_NEON_OPT
|
||||
/* ARM NEON optimizations are being controlled by the compiler settings,
|
||||
* typically the target FPU. If the FPU supports NEON instructions then the
|
||||
* compiler will define __ARM_NEON and we can rely unconditionally on NEON
|
||||
* instructions not crashing, otherwise we must disable use of NEON
|
||||
* instructions.
|
||||
*
|
||||
* NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
|
||||
* can only be turned on automatically if that is supported too. If
|
||||
* PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
|
||||
* to compile with an appropriate #error if ALIGNED_MEMORY has been turned
|
||||
* off.
|
||||
*
|
||||
* Note that older versions of GCC defined __ARM_NEON__; this is no longer
|
||||
* supported. Also 32-bit ARM versions of GCC required the NEON FPU mode to
|
||||
* be turned on explicitly on the command line. If this is not done (on
|
||||
* 32-bit ARM) NEON code will not be included.
|
||||
*
|
||||
* To disable ARM_NEON optimizations entirely, and skip compiling the
|
||||
* associated assembler code, pass --enable-arm-neon=no to configure
|
||||
* or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS.
|
||||
*/
|
||||
# if defined(__ARM_NEON) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
|
||||
# define PNG_ARM_NEON_OPT 2
|
||||
# else
|
||||
# define PNG_ARM_NEON_OPT 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
/* NEON optimizations are to be at least considered by libpng, so enable the
|
||||
* callbacks to do this.
|
||||
*/
|
||||
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
|
||||
|
||||
/* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
|
||||
* if possible - if __ARM_NEON is set and the compiler version is not known
|
||||
* to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
|
||||
* be:
|
||||
*
|
||||
* 1 The intrinsics code (the default with __ARM_NEON)
|
||||
* 2 The hand coded assembler (the default without __ARM_NEON)
|
||||
*
|
||||
* It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
|
||||
* this is *NOT* supported and may cease to work even after a minor revision
|
||||
* to libpng. It *is* valid to do this for testing purposes, e.g. speed
|
||||
* testing or a new compiler, but the results should be communicated to the
|
||||
* libpng implementation list for incorporation in the next minor release.
|
||||
*/
|
||||
# ifndef PNG_ARM_NEON_IMPLEMENTATION
|
||||
# ifdef __ARM_NEON
|
||||
# if defined(__clang__)
|
||||
/* At present it is unknown by the libpng developers which versions
|
||||
* of clang support the intrinsics, however some or perhaps all
|
||||
* versions do not work with the assembler so this may be
|
||||
* irrelevant, so just use the default (do nothing here.)
|
||||
*/
|
||||
# elif defined(__GNUC__)
|
||||
/* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to
|
||||
* work, so if this *is* GCC, or G++, look for a version >4.5
|
||||
*/
|
||||
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
|
||||
# define PNG_ARM_NEON_IMPLEMENTATION 2
|
||||
# endif /* no GNUC support */
|
||||
# endif /* __GNUC__ */
|
||||
# else /* !defined __ARM_NEON */
|
||||
/* The 'intrinsics' code simply won't compile without compiler support
|
||||
* and that support switches on __ARM_NEON, so use the assembler:
|
||||
*/
|
||||
# define PNG_ARM_NEON_IMPLEMENTATION 2
|
||||
# endif /* __ARM_NEON */
|
||||
# endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */
|
||||
|
||||
# ifndef PNG_ARM_NEON_IMPLEMENTATION
|
||||
/* Use the intrinsics code by default. */
|
||||
# define PNG_ARM_NEON_IMPLEMENTATION 1
|
||||
# endif
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
|
||||
#ifdef PNG_SET_OPTION_SUPPORTED
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */
|
||||
#endif
|
||||
#endif /* SET_OPTION */
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,
|
||||
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
|
||||
png_const_bytep prev_row, png_const_bytep prev_pixels),PNG_EMPTY);
|
||||
#endif
|
||||
-3782
File diff suppressed because it is too large.
Load diff
-4252
File diff suppressed because it is too large.
Load diff
@@ -1,50 +0,0 @@
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4028)
|
||||
#endif
|
||||
|
||||
/* pngchunk.h - PNG chunk descriptions
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 2016 Glenn Randers-Pehrson
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
* If this list is changed in any way scripts/chunkhash.c must be rebuilt and
|
||||
* run to regenerate the lookup functions for the tables described from this
|
||||
* list.
|
||||
*
|
||||
* IDAT MUST be first in the list; it must have index '0'. The order of the
|
||||
* remaining chunks comes from section 5.6 "Chunk ordering" in the ISO spec
|
||||
* plus the ordering rules in the PNG extensions documnet.
|
||||
*
|
||||
* Keep PNG_CHUNK_BEGIN and PNG_CHUNK_END at the beginning and end.
|
||||
*/
|
||||
PNG_CHUNK_BEGIN(IDAT, 73, 68, 65, 84, within_IDAT, after_start)
|
||||
PNG_CHUNK( IHDR, 73, 72, 68, 82, before_start, at_start)
|
||||
PNG_CHUNK( cHRM, 99, 72, 82, 77, before_PLTE, after_start)
|
||||
PNG_CHUNK( gAMA, 103, 65, 77, 65, before_PLTE, after_start)
|
||||
PNG_CHUNK( iCCP, 105, 67, 67, 80, before_PLTE, after_start)
|
||||
PNG_CHUNK( sBIT, 115, 66, 73, 84, before_PLTE, after_start)
|
||||
PNG_CHUNK( sRGB, 115, 82, 71, 66, before_PLTE, after_start)
|
||||
PNG_CHUNK( PLTE, 80, 76, 84, 69, before_PLTE, after_start)
|
||||
PNG_CHUNK( bKGD, 98, 75, 71, 68, before_IDAT, after_PLTE)
|
||||
PNG_CHUNK( hIST, 104, 73, 83, 84, before_IDAT, after_PLTE)
|
||||
PNG_CHUNK( tRNS, 116, 82, 78, 83, before_IDAT, after_PLTE)
|
||||
PNG_CHUNK( oFFs, 111, 70, 70, 115, before_IDAT, after_start)
|
||||
PNG_CHUNK( pCAL, 112, 67, 65, 76, before_IDAT, after_start)
|
||||
PNG_CHUNK( sCAL, 115, 67, 65, 76, before_IDAT, after_start)
|
||||
PNG_CHUNK( sTER, 115, 84, 69, 82, before_IDAT, after_start)
|
||||
PNG_CHUNK( pHYs, 112, 72, 89, 115, before_IDAT, after_start)
|
||||
PNG_CHUNK( sPLT, 115, 80, 76, 84, before_IDAT, after_start)
|
||||
PNG_CHUNK( tIME, 116, 73, 77, 69, before_end, after_start)
|
||||
PNG_CHUNK( iTXt, 105, 84, 88, 116, before_end, after_start)
|
||||
PNG_CHUNK( tEXt, 116, 69, 88, 116, before_end, after_start)
|
||||
PNG_CHUNK( zTXt, 122, 84, 88, 116, before_end, after_start)
|
||||
PNG_CHUNK( fRAc, 102, 82, 65, 99, before_end, after_start)
|
||||
PNG_CHUNK( gIFg, 103, 73, 70, 103, before_end, after_start)
|
||||
PNG_CHUNK( gIFt, 103, 73, 70, 116, before_end, after_start)
|
||||
PNG_CHUNK( gIFx, 103, 73, 70, 120, before_end, after_start)
|
||||
PNG_CHUNK( dSIG, 100, 83, 73, 71, before_end, after_start)
|
||||
PNG_CHUNK_END( IEND, 73, 69, 78, 68, before_end, after_IDAT)
|
||||
@@ -1,632 +0,0 @@
|
||||
|
||||
/* pngconf.h - machine configurable file for libpng
|
||||
*
|
||||
* libpng version 1.7.0beta90, August 28, 2017
|
||||
*
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
* Any machine specific code is near the front of this file, so if you
|
||||
* are configuring libpng for a machine, you may want to read the section
|
||||
* starting here down to where it starts to typedef png_color, png_text,
|
||||
* and png_info.
|
||||
*/
|
||||
|
||||
#ifndef PNGCONF_H
|
||||
#define PNGCONF_H
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */
|
||||
|
||||
/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C
|
||||
* compiler for correct compilation. The following header files are required by
|
||||
* the standard. If your compiler doesn't provide these header files, or they
|
||||
* do not match the standard, you will need to provide/improve them.
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Library header files. These header files are all defined by ISOC90; libpng
|
||||
* expects conformant implementations, however, an ISOC90 conformant system need
|
||||
* not provide these header files if the functionality cannot be implemented.
|
||||
* In this case it will be necessary to disable the relevant parts of libpng in
|
||||
* the build of pnglibconf.h.
|
||||
*
|
||||
* Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not
|
||||
* include this unnecessary header file.
|
||||
*/
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
/* Required for the definition of FILE: */
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
/* Required for the definition of jmp_buf and the declaration of longjmp: */
|
||||
# include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef PNG_CONVERT_tIME_SUPPORTED
|
||||
/* Required for struct tm: */
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#endif /* PNG_BUILDING_SYMBOL_TABLE */
|
||||
|
||||
/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
|
||||
* PNG_NO_CONST; this is no longer supported except for data declarations which
|
||||
* apparently still cause problems in 2011 on some compilers.
|
||||
*/
|
||||
#define PNG_CONST const /* backward compatibility only */
|
||||
|
||||
/* This controls optimization of the reading of 16 and 32 bit values
|
||||
* from PNG files. It can be set on a per-app-file basis - it
|
||||
* just changes whether a macro is used when the function is called.
|
||||
* The library builder sets the default; if read functions are not
|
||||
* built into the library the macro implementation is forced on.
|
||||
*/
|
||||
#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
# define PNG_USE_READ_MACROS
|
||||
#endif
|
||||
#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS)
|
||||
# if PNG_DEFAULT_READ_MACROS
|
||||
# define PNG_USE_READ_MACROS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* COMPILER SPECIFIC OPTIONS.
|
||||
*
|
||||
* These options are provided so that a variety of difficult compilers
|
||||
* can be used. Some are fixed at build time (e.g. PNG_API_RULE
|
||||
* below) but still have compiler specific implementations, others
|
||||
* may be changed on a per-file basis when compiling against libpng.
|
||||
*/
|
||||
|
||||
/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
|
||||
* against legacy (pre ISOC90) compilers that did not understand function
|
||||
* prototypes. It is not required for modern C compilers.
|
||||
*/
|
||||
#ifndef PNGARG
|
||||
# define PNGARG(arglist) arglist
|
||||
#endif
|
||||
|
||||
/* Function calling conventions.
|
||||
* =============================
|
||||
* Normally it is not necessary to specify to the compiler how to call
|
||||
* a function - it just does it - however on x86 systems derived from
|
||||
* Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems
|
||||
* and some others) there are multiple ways to call a function and the
|
||||
* default can be changed on the compiler command line. For this reason
|
||||
* libpng specifies the calling convention of every exported function and
|
||||
* every function called via a user supplied function pointer. This is
|
||||
* done in this file by defining the following macros:
|
||||
*
|
||||
* PNGAPI Calling convention for exported functions.
|
||||
* PNGCBAPI Calling convention for user provided (callback) functions.
|
||||
* PNGCAPI Calling convention used by the ANSI-C library (required
|
||||
* for longjmp callbacks and sometimes used internally to
|
||||
* specify the calling convention for zlib).
|
||||
*
|
||||
* These macros should never be overridden. If it is necessary to
|
||||
* change calling convention in a private build this can be done
|
||||
* by setting PNG_API_RULE (which defaults to 0) to one of the values
|
||||
* below to select the correct 'API' variants.
|
||||
*
|
||||
* PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout.
|
||||
* This is correct in every known environment.
|
||||
* PNG_API_RULE=1 Use the operating system convention for PNGAPI and
|
||||
* the 'C' calling convention (from PNGCAPI) for
|
||||
* callbacks (PNGCBAPI). This is no longer required
|
||||
* in any known environment - if it has to be used
|
||||
* please post an explanation of the problem to the
|
||||
* libpng mailing list.
|
||||
*
|
||||
* These cases only differ if the operating system does not use the C
|
||||
* calling convention, at present this just means the above cases
|
||||
* (x86 DOS/Windows sytems) and, even then, this does not apply to
|
||||
* Cygwin running on those systems.
|
||||
*
|
||||
* Note that the value must be defined in pnglibconf.h so that what
|
||||
* the application uses to call the library matches the conventions
|
||||
* set when building the library.
|
||||
*/
|
||||
|
||||
/* Symbol export
|
||||
* =============
|
||||
* When building a shared library it is almost always necessary to tell
|
||||
* the compiler which symbols to export. The png.h macro 'PNG_EXPORT'
|
||||
* is used to mark the symbols. On some systems these symbols can be
|
||||
* extracted at link time and need no special processing by the compiler,
|
||||
* on other systems the symbols are flagged by the compiler and just
|
||||
* the declaration requires a special tag applied (unfortunately) in a
|
||||
* compiler dependent way. Some systems can do either.
|
||||
*
|
||||
* A small number of older systems also require a symbol from a DLL to
|
||||
* be flagged to the program that calls it. This is a problem because
|
||||
* we do not know in the header file included by application code that
|
||||
* the symbol will come from a shared library, as opposed to a statically
|
||||
* linked one. For this reason the application must tell us by setting
|
||||
* the magic flag PNG_USE_DLL to turn on the special processing before
|
||||
* it includes png.h.
|
||||
*
|
||||
* Four additional macros are used to make this happen:
|
||||
*
|
||||
* PNG_IMPEXP The magic (if any) to cause a symbol to be exported from
|
||||
* the build or imported if PNG_USE_DLL is set - compiler
|
||||
* and system specific.
|
||||
*
|
||||
* PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to
|
||||
* 'type', compiler specific.
|
||||
*
|
||||
* PNG_DLL_EXPORT Set to the magic to use during a libpng build to
|
||||
* make a symbol exported from the DLL. Not used in the
|
||||
* public header files; see pngpriv.h for how it is used
|
||||
* in the libpng build.
|
||||
*
|
||||
* PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come
|
||||
* from a DLL - used to define PNG_IMPEXP when
|
||||
* PNG_USE_DLL is set.
|
||||
*/
|
||||
|
||||
/* System specific discovery.
|
||||
* ==========================
|
||||
* This code is used at build time to find PNG_IMPEXP, the API settings
|
||||
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
|
||||
* import processing is possible. On Windows systems it also sets
|
||||
* compiler-specific macros to the values required to change the calling
|
||||
* conventions of the various functions.
|
||||
*/
|
||||
#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
|
||||
defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||
/* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
|
||||
* MinGW on any architecture currently supported by Windows. Also includes
|
||||
* Watcom builds but these need special treatment because they are not
|
||||
* compatible with GCC or Visual C because of different calling conventions.
|
||||
*/
|
||||
# if PNG_API_RULE == 2
|
||||
/* If this line results in an error, either because __watcall is not
|
||||
* understood or because of a redefine just below you cannot use *this*
|
||||
* build of the library with the compiler you are using. *This* build was
|
||||
* build using Watcom and applications must also be built using Watcom!
|
||||
*/
|
||||
# define PNGCAPI __watcall
|
||||
# endif
|
||||
|
||||
# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
|
||||
# define PNGCAPI __cdecl
|
||||
# if PNG_API_RULE == 1
|
||||
/* If this line results in an error __stdcall is not understood and
|
||||
* PNG_API_RULE should not have been set to '1'.
|
||||
*/
|
||||
# define PNGAPI __stdcall
|
||||
# endif
|
||||
# else
|
||||
/* An older compiler, or one not detected (erroneously) above,
|
||||
* if necessary override on the command line to get the correct
|
||||
* variants for the compiler.
|
||||
*/
|
||||
# ifndef PNGCAPI
|
||||
# define PNGCAPI _cdecl
|
||||
# endif
|
||||
# if PNG_API_RULE == 1 && !defined(PNGAPI)
|
||||
# define PNGAPI _stdcall
|
||||
# endif
|
||||
# endif /* compiler/api */
|
||||
|
||||
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
|
||||
|
||||
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
|
||||
# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
|
||||
# endif
|
||||
|
||||
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
|
||||
(defined(__BORLANDC__) && __BORLANDC__ < 0x500)
|
||||
/* older Borland and MSC
|
||||
* compilers used '__export' and required this to be after
|
||||
* the type.
|
||||
*/
|
||||
# ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
|
||||
# endif
|
||||
# define PNG_DLL_EXPORT __export
|
||||
# else /* newer compiler */
|
||||
# define PNG_DLL_EXPORT __declspec(dllexport)
|
||||
# ifndef PNG_DLL_IMPORT
|
||||
# define PNG_DLL_IMPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif /* compiler */
|
||||
|
||||
#else /* !Windows */
|
||||
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
|
||||
# define PNGAPI _System
|
||||
# else /* !Windows/x86 && !OS/2 */
|
||||
/* Use the defaults, or define PNG*API on the command line (but
|
||||
* this will have to be done for every compile!)
|
||||
*/
|
||||
# endif /* other system, !OS/2 */
|
||||
#endif /* !Windows/x86 */
|
||||
|
||||
/* Now do all the defaulting . */
|
||||
#ifndef PNGCAPI
|
||||
# define PNGCAPI
|
||||
#endif
|
||||
#ifndef PNGCBAPI
|
||||
# define PNGCBAPI PNGCAPI
|
||||
#endif
|
||||
#ifndef PNGAPI
|
||||
# define PNGAPI PNGCAPI
|
||||
#endif
|
||||
|
||||
/* PNG_IMPEXP may be set on the compilation system command line or (if not set)
|
||||
* then in an internal header file when building the library, otherwise (when
|
||||
* using the library) it is set here.
|
||||
*/
|
||||
#ifndef PNG_IMPEXP
|
||||
# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT)
|
||||
/* This forces use of a DLL, disallowing static linking */
|
||||
# define PNG_IMPEXP PNG_DLL_IMPORT
|
||||
# endif
|
||||
|
||||
# ifndef PNG_IMPEXP
|
||||
# define PNG_IMPEXP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat
|
||||
* 'attributes' as a storage class - the attributes go at the start of the
|
||||
* function definition, and attributes are always appended regardless of the
|
||||
* compiler. This considerably simplifies these macros but may cause problems
|
||||
* if any compilers both need function attributes and fail to handle them as
|
||||
* a storage class (this is unlikely.)
|
||||
*/
|
||||
#ifndef PNG_FUNCTION
|
||||
# define PNG_FUNCTION(type, name, args, attributes) attributes type name args
|
||||
#endif
|
||||
|
||||
#ifndef PNG_EXPORT_TYPE
|
||||
# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
|
||||
#endif
|
||||
|
||||
/* The ordinal value is only relevant when preprocessing png.h for symbol
|
||||
* table entries, so we discard it here. See the .dfn files in the
|
||||
* scripts directory.
|
||||
*/
|
||||
#ifndef PNG_EXPORTA
|
||||
|
||||
# define PNG_EXPORTA(ordinal, type, name, args, attributes)\
|
||||
PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \
|
||||
extern attributes)
|
||||
#endif
|
||||
|
||||
/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument,
|
||||
* so make something non-empty to satisfy the requirement:
|
||||
*/
|
||||
#define PNG_EMPTY /*empty list*/
|
||||
|
||||
#define PNG_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
|
||||
|
||||
/* Use PNG_REMOVED to comment out a removed interface. */
|
||||
#ifndef PNG_REMOVED
|
||||
# define PNG_REMOVED(ordinal, type, name, args, attributes)
|
||||
#endif
|
||||
|
||||
#ifndef PNG_CALLBACK
|
||||
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
|
||||
#endif
|
||||
|
||||
/* Support for compiler specific function attributes. These are used
|
||||
* so that where compiler support is available incorrect use of API
|
||||
* functions in png.h will generate compiler warnings.
|
||||
*
|
||||
* Added at libpng-1.2.41.
|
||||
*/
|
||||
|
||||
#ifndef PNG_NO_PEDANTIC_WARNINGS
|
||||
# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
# define PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
|
||||
/* Support for compiler specific function attributes. These are used
|
||||
* so that where compiler support is available, incorrect use of API
|
||||
* functions in png.h will generate compiler warnings. Added at libpng
|
||||
* version 1.2.41. Disabling these removes the warnings but may also produce
|
||||
* less efficient code.
|
||||
*/
|
||||
# if defined(__clang__) && defined(__has_attribute)
|
||||
/* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
|
||||
# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
|
||||
# define PNG_DEPRECATED __attribute__((__deprecated__))
|
||||
# endif
|
||||
# if !defined(PNG_PRIVATE)
|
||||
# ifdef __has_extension
|
||||
# if __has_extension(attribute_unavailable_with_message)
|
||||
# define PNG_PRIVATE __attribute__((__unavailable__(\
|
||||
"This function is not exported by libpng.")))
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
|
||||
# elif defined(__GNUC__)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __attribute__((__noreturn__))
|
||||
# endif
|
||||
# if __GNUC__ >= 3
|
||||
# ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED __attribute__((__malloc__))
|
||||
# endif
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __attribute__((__deprecated__))
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# if 0 /* Doesn't work so we use deprecated instead*/
|
||||
# define PNG_PRIVATE \
|
||||
__attribute__((warning("This function is not exported by libpng.")))
|
||||
# else
|
||||
# define PNG_PRIVATE \
|
||||
__attribute__((__deprecated__))
|
||||
# endif
|
||||
# endif
|
||||
# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
|
||||
# endif /* __GNUC__ >= 3 */
|
||||
|
||||
# elif defined(_MSC_VER) && (_MSC_VER >= 1300)
|
||||
# ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT /* not supported */
|
||||
# endif
|
||||
# ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN __declspec(noreturn)
|
||||
# endif
|
||||
# ifndef PNG_ALLOCATED
|
||||
# if (_MSC_VER >= 1400)
|
||||
# define PNG_ALLOCATED __declspec(restrict)
|
||||
# endif
|
||||
# endif
|
||||
# ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE __declspec(deprecated)
|
||||
# endif
|
||||
# ifndef PNG_RESTRICT
|
||||
# if (_MSC_VER >= 1400)
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# elif defined(__WATCOMC__)
|
||||
# ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT __restrict
|
||||
# endif
|
||||
# endif
|
||||
#endif /* PNG_PEDANTIC_WARNINGS */
|
||||
|
||||
#ifndef PNG_DEPRECATED
|
||||
# define PNG_DEPRECATED /* Use of this function is deprecated */
|
||||
#endif
|
||||
#ifndef PNG_USE_RESULT
|
||||
# define PNG_USE_RESULT /* The result of this function must be checked */
|
||||
#endif
|
||||
#ifndef PNG_NORETURN
|
||||
# define PNG_NORETURN /* This function does not return */
|
||||
#endif
|
||||
#ifndef PNG_ALLOCATED
|
||||
# define PNG_ALLOCATED /* The result of the function is new memory */
|
||||
#endif
|
||||
#ifndef PNG_PRIVATE
|
||||
# define PNG_PRIVATE /* This is a private libpng function */
|
||||
#endif
|
||||
#ifndef PNG_RESTRICT
|
||||
# define PNG_RESTRICT /* The C99 "restrict" feature */
|
||||
#endif
|
||||
|
||||
#ifndef PNG_FP_EXPORT /* A floating point API. */
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args);
|
||||
# else /* No floating point APIs */
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef PNG_FP_EXPORT /* A floating point API. */
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args);
|
||||
# else /* No floating point APIs */
|
||||
# define PNG_FP_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
|
||||
# ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
|
||||
PNG_EXPORT(ordinal, type, name, args);
|
||||
# else /* No fixed point APIs */
|
||||
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PNG_BUILDING_SYMBOL_TABLE
|
||||
/* Some typedefs to get us started. These should be safe on most of the common
|
||||
* platforms.
|
||||
*
|
||||
* png_uint_32 and png_int_32 may, currently, be larger than required to hold a
|
||||
* 32-bit value however this is not normally advisable.
|
||||
*
|
||||
* png_uint_16 and png_int_16 should always be two bytes in size - this is
|
||||
* verified at library build time.
|
||||
*
|
||||
* png_byte must always be one byte in size.
|
||||
*
|
||||
* The checks below use constants from limits.h, as defined by the ISOC90
|
||||
* standard.
|
||||
*/
|
||||
#if CHAR_BIT == 8 && UCHAR_MAX == 255
|
||||
typedef unsigned char png_byte;
|
||||
#else
|
||||
# error "libpng requires 8 bit bytes"
|
||||
#endif
|
||||
|
||||
#if INT_MIN == -32768 && INT_MAX == 32767
|
||||
typedef int png_int_16;
|
||||
#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
|
||||
typedef short png_int_16;
|
||||
#else
|
||||
# error "libpng requires a signed 16 bit type"
|
||||
#endif
|
||||
|
||||
#if UINT_MAX == 65535
|
||||
typedef unsigned int png_uint_16;
|
||||
#elif USHRT_MAX == 65535
|
||||
typedef unsigned short png_uint_16;
|
||||
#else
|
||||
# error "libpng requires an unsigned 16 bit type"
|
||||
#endif
|
||||
|
||||
#if INT_MIN < -2147483646 && INT_MAX > 2147483646
|
||||
typedef int png_int_32;
|
||||
#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
|
||||
typedef long int png_int_32;
|
||||
#else
|
||||
# error "libpng requires a signed 32 bit (or more) type"
|
||||
#endif
|
||||
|
||||
#if UINT_MAX > 4294967294
|
||||
typedef unsigned int png_uint_32;
|
||||
#elif ULONG_MAX > 4294967294
|
||||
typedef unsigned long int png_uint_32;
|
||||
#else
|
||||
# error "libpng requires an unsigned 32 bit (or more) type"
|
||||
#endif
|
||||
|
||||
/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however,
|
||||
* requires an ISOC90 compiler and relies on consistent behavior of sizeof.
|
||||
*
|
||||
* DEPRECATED: don't use these types, instead use size_t and ptrdiff_t.
|
||||
*/
|
||||
typedef size_t png_size_t;
|
||||
typedef ptrdiff_t png_ptrdiff_t;
|
||||
|
||||
/* libpng needs to know the maximum value of 'size_t' and this controls the
|
||||
* definition of png_alloc_size_t, below. This maximum value of size_t limits
|
||||
* but does not control the maximum allocations the library makes - there is
|
||||
* direct application control of this through png_set_user_limits().
|
||||
*/
|
||||
#ifndef PNG_SMALL_SIZE_T
|
||||
/* Compiler specific tests for systems where size_t is known to be less than
|
||||
* 32 bits (some of these systems may no longer work because of the lack of
|
||||
* 'far' support; see above.)
|
||||
*/
|
||||
# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\
|
||||
(defined(_MSC_VER) && defined(MAXSEG_64K))
|
||||
# define PNG_SMALL_SIZE_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no
|
||||
* smaller than png_uint_32. Casts from size_t or png_uint_32 to
|
||||
* png_alloc_size_t are not necessary; in fact, it is recommended not to use
|
||||
* them at all so that the compiler can complain when something turns out to be
|
||||
* problematic.
|
||||
*
|
||||
* Casts in the other direction (from png_alloc_size_t to size_t or
|
||||
* png_uint_32) should be explicitly applied; however, we do not expect to
|
||||
* encounter practical situations that require such conversions.
|
||||
*
|
||||
* PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than
|
||||
* 4294967295 - i.e. less than the maximum value of png_uint_32.
|
||||
*/
|
||||
#ifdef PNG_SMALL_SIZE_T
|
||||
typedef png_uint_32 png_alloc_size_t;
|
||||
#else
|
||||
typedef size_t png_alloc_size_t;
|
||||
#endif
|
||||
|
||||
/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
|
||||
* implementations of Intel CPU specific support of user-mode segmented address
|
||||
* spaces, where 16-bit pointers address more than 65536 bytes of memory using
|
||||
* separate 'segment' registers. The implementation requires two different
|
||||
* types of pointer (only one of which includes the segment value.)
|
||||
*
|
||||
* If required this support is available in version 1.2 of libpng and may be
|
||||
* available in versions through 1.5, although the correctness of the code has
|
||||
* not been verified recently.
|
||||
*/
|
||||
|
||||
/* Typedef for floating-point numbers that are converted to fixed-point with a
|
||||
* multiple of 100,000, e.g., gamma
|
||||
*/
|
||||
typedef png_int_32 png_fixed_point;
|
||||
|
||||
/* Add typedefs for pointers */
|
||||
typedef void * png_voidp;
|
||||
typedef const void * png_const_voidp;
|
||||
typedef png_byte * png_bytep;
|
||||
typedef const png_byte * png_const_bytep;
|
||||
typedef png_uint_32 * png_uint_32p;
|
||||
typedef const png_uint_32 * png_const_uint_32p;
|
||||
typedef png_int_32 * png_int_32p;
|
||||
typedef const png_int_32 * png_const_int_32p;
|
||||
typedef png_uint_16 * png_uint_16p;
|
||||
typedef const png_uint_16 * png_const_uint_16p;
|
||||
typedef png_int_16 * png_int_16p;
|
||||
typedef const png_int_16 * png_const_int_16p;
|
||||
typedef char * png_charp;
|
||||
typedef const char * png_const_charp;
|
||||
typedef png_fixed_point * png_fixed_point_p;
|
||||
typedef const png_fixed_point * png_const_fixed_point_p;
|
||||
typedef size_t * png_size_tp;
|
||||
typedef const size_t * png_const_size_tp;
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
typedef FILE * png_FILE_p;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double * png_doublep;
|
||||
typedef const double * png_const_doublep;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers; i.e. arrays */
|
||||
typedef png_byte * * png_bytepp;
|
||||
typedef png_uint_32 * * png_uint_32pp;
|
||||
typedef png_int_32 * * png_int_32pp;
|
||||
typedef png_uint_16 * * png_uint_16pp;
|
||||
typedef png_int_16 * * png_int_16pp;
|
||||
typedef const char * * png_const_charpp;
|
||||
typedef char * * png_charpp;
|
||||
typedef png_fixed_point * * png_fixed_point_pp;
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
typedef double * * png_doublepp;
|
||||
#endif
|
||||
|
||||
/* Pointers to pointers to pointers; i.e., pointer to array */
|
||||
typedef char * * * png_charppp;
|
||||
|
||||
#endif /* PNG_BUILDING_SYMBOL_TABLE */
|
||||
|
||||
#endif /* PNGCONF_H */
|
||||
@@ -1,150 +0,0 @@
|
||||
|
||||
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
|
||||
*
|
||||
* Last changed in libpng 1.6.8 [December 19, 2013]
|
||||
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* Define PNG_DEBUG at compile time for debugging information. Higher
|
||||
* numbers for PNG_DEBUG mean more debugging information. This has
|
||||
* only been added since version 0.95 so it is not implemented throughout
|
||||
* libpng yet, but more support will be added as needed.
|
||||
*
|
||||
* png_debug[1-2]?(level, message ,arg{0-2})
|
||||
* Expands to a statement (either a simple expression or a compound
|
||||
* do..while(0) statement) that outputs a message with parameter
|
||||
* substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG
|
||||
* is undefined, 0 or 1 every png_debug expands to a simple expression
|
||||
* (actually ((void)0)).
|
||||
*
|
||||
* level: level of detail of message, starting at 0. A level 'n'
|
||||
* message is preceded by 'n' 3-space indentations (not implemented
|
||||
* on Microsoft compilers unless PNG_DEBUG_FILE is also
|
||||
* defined, to allow debug DLL compilation with no standard IO).
|
||||
* message: a printf(3) style text string. A trailing '\n' is added
|
||||
* to the message.
|
||||
* arg: 0 to 2 arguments for printf(3) style substitution in message.
|
||||
*/
|
||||
#ifndef PNGDEBUG_H
|
||||
#define PNGDEBUG_H
|
||||
/* These settings control the formatting of messages in png.c and pngerror.c */
|
||||
/* Moved to pngdebug.h at 1.5.0 */
|
||||
# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
|
||||
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5bU
|
||||
# endif
|
||||
# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
|
||||
# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5dU
|
||||
# endif
|
||||
# ifndef PNG_STRING_NEWLINE
|
||||
# define PNG_STRING_NEWLINE "\n"
|
||||
# endif
|
||||
|
||||
#ifdef PNG_DEBUG
|
||||
# if (PNG_DEBUG > 0)
|
||||
# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
|
||||
# include <crtdbg.h>
|
||||
# if (PNG_DEBUG > 1)
|
||||
# ifndef _DEBUG
|
||||
# define _DEBUG
|
||||
# endif
|
||||
# ifndef png_debug
|
||||
# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE)
|
||||
# endif
|
||||
# ifndef png_debug1
|
||||
# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1)
|
||||
# endif
|
||||
# ifndef png_debug2
|
||||
# define png_debug2(l,m,p1,p2) \
|
||||
_RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2)
|
||||
# endif
|
||||
# endif
|
||||
# else /* PNG_DEBUG_FILE || !_MSC_VER */
|
||||
# ifndef PNG_STDIO_SUPPORTED
|
||||
# include <stdio.h> /* not included yet */
|
||||
# endif
|
||||
# ifndef PNG_DEBUG_FILE
|
||||
# define PNG_DEBUG_FILE stderr
|
||||
# endif /* PNG_DEBUG_FILE */
|
||||
|
||||
# if (PNG_DEBUG > 1)
|
||||
# ifdef __STDC__
|
||||
# ifndef png_debug
|
||||
# define png_debug(l,m) \
|
||||
do { \
|
||||
int num_tabs=l; \
|
||||
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
|
||||
(num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
|
||||
} while (0)
|
||||
# endif
|
||||
# ifndef png_debug1
|
||||
# define png_debug1(l,m,p1) \
|
||||
do { \
|
||||
int num_tabs=l; \
|
||||
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
|
||||
(num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \
|
||||
} while (0)
|
||||
# endif
|
||||
# ifndef png_debug2
|
||||
# define png_debug2(l,m,p1,p2) \
|
||||
do { \
|
||||
int num_tabs=l; \
|
||||
fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
|
||||
(num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\
|
||||
} while (0)
|
||||
# endif
|
||||
# else /* __STDC __ */
|
||||
# ifndef png_debug
|
||||
# define png_debug(l,m) \
|
||||
do { \
|
||||
int num_tabs=l; \
|
||||
char format[256]; \
|
||||
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
|
||||
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
|
||||
m,PNG_STRING_NEWLINE); \
|
||||
fprintf(PNG_DEBUG_FILE,format); \
|
||||
} while (0)
|
||||
# endif
|
||||
# ifndef png_debug1
|
||||
# define png_debug1(l,m,p1) \
|
||||
do { \
|
||||
int num_tabs=l; \
|
||||
char format[256]; \
|
||||
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
|
||||
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
|
||||
m,PNG_STRING_NEWLINE); \
|
||||
fprintf(PNG_DEBUG_FILE,format,p1); \
|
||||
} while (0)
|
||||
# endif
|
||||
# ifndef png_debug2
|
||||
# define png_debug2(l,m,p1,p2) \
|
||||
do { \
|
||||
int num_tabs=l; \
|
||||
char format[256]; \
|
||||
snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
|
||||
(num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
|
||||
m,PNG_STRING_NEWLINE); \
|
||||
fprintf(PNG_DEBUG_FILE,format,p1,p2); \
|
||||
} while (0)
|
||||
# endif
|
||||
# endif /* __STDC __ */
|
||||
# endif /* (PNG_DEBUG > 1) */
|
||||
|
||||
# endif /* _MSC_VER */
|
||||
# endif /* (PNG_DEBUG > 0) */
|
||||
#endif /* PNG_DEBUG */
|
||||
#ifndef png_debug
|
||||
# define png_debug(l, m) ((void)0)
|
||||
#endif
|
||||
#ifndef png_debug1
|
||||
# define png_debug1(l, m, p1) ((void)0)
|
||||
#endif
|
||||
#ifndef png_debug2
|
||||
# define png_debug2(l, m, p1, p2) ((void)0)
|
||||
#endif
|
||||
#endif /* PNGDEBUG_H */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,251 +0,0 @@
|
||||
|
||||
/* pnginfo.h - header file for PNG reference library
|
||||
*
|
||||
* Last changed in libpng 1.6.1 [March 28, 2013]
|
||||
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* png_info is a structure that holds the information in a PNG file so
|
||||
* that the application can find out the characteristics of the image.
|
||||
* If you are reading the file, this structure will tell you what is
|
||||
* in the PNG file. If you are writing the file, fill in the information
|
||||
* you want to put into the PNG file, using png_set_*() functions, then
|
||||
* call png_write_info().
|
||||
*
|
||||
* The names chosen should be very close to the PNG specification, so
|
||||
* consult that document for information about the meaning of each field.
|
||||
*
|
||||
* With libpng < 0.95, it was only possible to directly set and read the
|
||||
* the values in the png_info_struct, which meant that the contents and
|
||||
* order of the values had to remain fixed. With libpng 0.95 and later,
|
||||
* however, there are now functions that abstract the contents of
|
||||
* png_info_struct from the application, so this makes it easier to use
|
||||
* libpng with dynamic libraries, and even makes it possible to use
|
||||
* libraries that don't have all of the libpng ancillary chunk-handing
|
||||
* functionality. In libpng-1.5.0 this was moved into a separate private
|
||||
* file that is not visible to applications.
|
||||
*
|
||||
* The following members may have allocated storage attached that should be
|
||||
* cleaned up before the structure is discarded: palette, trans, text,
|
||||
* pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
|
||||
* splt_palettes, scal_unit, row_pointers, and unknowns. By default, these
|
||||
* are automatically freed when the info structure is deallocated, if they were
|
||||
* allocated internally by libpng. This behavior can be changed by means
|
||||
* of the png_data_freer() function.
|
||||
*
|
||||
* More allocation details: all the chunk-reading functions that
|
||||
* change these members go through the corresponding png_set_*
|
||||
* functions. A function to clear these members is available: see
|
||||
* png_free_data(). The png_set_* functions do not depend on being
|
||||
* able to point info structure members to any of the storage they are
|
||||
* passed (they make their own copies), EXCEPT that the png_set_text
|
||||
* functions use the same storage passed to them in the text_ptr or
|
||||
* itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
|
||||
* functions do not make their own copies.
|
||||
*/
|
||||
#ifndef PNGINFO_H
|
||||
#define PNGINFO_H
|
||||
|
||||
struct png_info_def
|
||||
{
|
||||
/* The following are necessary for every PNG file */
|
||||
png_uint_32 width; /* width of image in pixels (from IHDR) */
|
||||
png_uint_32 height; /* height of image in pixels (from IHDR) */
|
||||
unsigned int valid; /* valid chunk data (see PNG_INFO_ in png.h) */
|
||||
png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */
|
||||
unsigned int num_palette:9; /* number of color entries in "palette" (PLTE) */
|
||||
unsigned int num_trans:9; /* number of transparent palette color (tRNS) */
|
||||
unsigned int bit_depth:6; /* 1, 2, 4, 8, 16 or 32 bits/channel */
|
||||
unsigned int format:PNG_RF_BITS; /* row format; see png_struct.h */
|
||||
/* The following three should have been named *_method not *_type */
|
||||
png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
|
||||
png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
|
||||
png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
/* This is never set during write */
|
||||
png_byte signature[8]; /* magic bytes read by libpng from start of file */
|
||||
#endif
|
||||
|
||||
/* The rest of the data is optional. If you are reading, check the
|
||||
* valid field to see if the information in these are valid. If you
|
||||
* are writing, set the valid field to those chunks you want written,
|
||||
* and initialize the appropriate fields below.
|
||||
*/
|
||||
|
||||
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
/* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
|
||||
* defined. When COLORSPACE is switched on all the colorspace-defining
|
||||
* chunks should be enabled, when GAMMA is switched on all the gamma-defining
|
||||
* chunks should be enabled. If this is not done it becomes possible to read
|
||||
* inconsistent PNG files and assign a probably incorrect interpretation to
|
||||
* the information. (In other words, by carefully choosing which chunks to
|
||||
* recognize the system configuration can select an interpretation for PNG
|
||||
* files containing ambiguous data and this will result in inconsistent
|
||||
* behavior between different libpng builds!)
|
||||
*/
|
||||
png_colorspace colorspace;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_iCCP_SUPPORTED
|
||||
/* iCCP chunk data. */
|
||||
png_charp iccp_name; /* profile name */
|
||||
png_bytep iccp_profile; /* International Color Consortium profile data */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_TEXT_SUPPORTED
|
||||
/* The tEXt, and zTXt chunks contain human-readable textual data in
|
||||
* uncompressed, compressed, and optionally compressed forms, respectively.
|
||||
* The data in "text" is an array of pointers to uncompressed,
|
||||
* null-terminated C strings. Each chunk has a keyword that describes the
|
||||
* textual data contained in that chunk. Keywords are not required to be
|
||||
* unique, and the text string may be empty. Any number of text chunks may
|
||||
* be in an image.
|
||||
*/
|
||||
int num_text; /* number of comments read or comments to write */
|
||||
int max_text; /* current size of text array */
|
||||
png_textp text; /* array of comments read or comments to write */
|
||||
#endif /* TEXT */
|
||||
|
||||
#ifdef PNG_tIME_SUPPORTED
|
||||
/* The tIME chunk holds the last time the displayed image data was
|
||||
* modified. See the png_time struct for the contents of this struct.
|
||||
*/
|
||||
png_time mod_time;
|
||||
png_byte time_location;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_sBIT_SUPPORTED
|
||||
/* The sBIT chunk specifies the number of significant high-order bits
|
||||
* in the pixel data. Values are in the range [1, bit_depth], and are
|
||||
* only specified for the channels in the pixel data. The contents of
|
||||
* the low-order bits is not specified. Data is valid if
|
||||
* (valid & PNG_INFO_sBIT) is non-zero.
|
||||
*/
|
||||
png_color_8 sig_bit; /* significant bits in color channels */
|
||||
#endif
|
||||
|
||||
#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
|
||||
defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
/* The tRNS chunk supplies transparency data for paletted images and
|
||||
* other image types that don't need a full alpha channel. There are
|
||||
* "num_trans" transparency values for a paletted image, stored in the
|
||||
* same order as the palette colors, starting from index 0. Values
|
||||
* for the data are in the range [0, 255], ranging from fully transparent
|
||||
* to fully opaque, respectively. For non-paletted images, there is a
|
||||
* single color specified that should be treated as fully transparent.
|
||||
* Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
|
||||
*/
|
||||
png_bytep trans_alpha; /* alpha values for paletted image */
|
||||
png_color_16 trans_color; /* transparent color for non-palette image */
|
||||
#endif
|
||||
|
||||
#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
/* The bKGD chunk gives the suggested image background color if the
|
||||
* display program does not have its own background color and the image
|
||||
* is needs to composited onto a background before display. The colors
|
||||
* in "background" are normally in the same color space/depth as the
|
||||
* pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
|
||||
*/
|
||||
png_color_16 background;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_oFFs_SUPPORTED
|
||||
/* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
|
||||
* and downwards from the top-left corner of the display, page, or other
|
||||
* application-specific co-ordinate space. See the PNG_OFFSET_ defines
|
||||
* below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero.
|
||||
*/
|
||||
png_int_32 x_offset; /* x offset on page */
|
||||
png_int_32 y_offset; /* y offset on page */
|
||||
png_byte offset_unit_type; /* offset units type */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_pHYs_SUPPORTED
|
||||
/* The pHYs chunk gives the physical pixel density of the image for
|
||||
* display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
|
||||
* defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
|
||||
*/
|
||||
png_uint_32 x_pixels_per_unit; /* horizontal pixel density */
|
||||
png_uint_32 y_pixels_per_unit; /* vertical pixel density */
|
||||
png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_hIST_SUPPORTED
|
||||
/* The hIST chunk contains the relative frequency or importance of the
|
||||
* various palette entries, so that a viewer can intelligently select a
|
||||
* reduced-color palette, if required. Data is an array of "num_palette"
|
||||
* values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
|
||||
* is non-zero.
|
||||
*/
|
||||
png_uint_16p hist;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_pCAL_SUPPORTED
|
||||
/* The pCAL chunk describes a transformation between the stored pixel
|
||||
* values and original physical data values used to create the image.
|
||||
* The integer range [0, 2^bit_depth - 1] maps to the floating-point
|
||||
* range given by [pcal_X0, pcal_X1], and are further transformed by a
|
||||
* (possibly non-linear) transformation function given by "pcal_type"
|
||||
* and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_
|
||||
* defines below, and the PNG-Group's PNG extensions document for a
|
||||
* complete description of the transformations and how they should be
|
||||
* implemented, and for a description of the ASCII parameter strings.
|
||||
* Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
|
||||
*/
|
||||
png_charp pcal_purpose; /* pCAL chunk description string */
|
||||
png_int_32 pcal_X0; /* minimum value */
|
||||
png_int_32 pcal_X1; /* maximum value */
|
||||
png_charp pcal_units; /* Latin-1 string giving physical units */
|
||||
png_charpp pcal_params; /* ASCII strings containing parameter values */
|
||||
png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */
|
||||
png_byte pcal_nparams; /* number of parameters given in pcal_params */
|
||||
#endif
|
||||
|
||||
/* New members added in libpng-1.0.6 */
|
||||
png_uint_32 free_me; /* flags items libpng is responsible for freeing */
|
||||
|
||||
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
/* Storage for unknown chunks that the library doesn't recognize. */
|
||||
png_unknown_chunkp unknown_chunks;
|
||||
|
||||
/* The type of this field is limited by the type of
|
||||
* png_struct::user_chunk_cache_max, else overflow can occur.
|
||||
*/
|
||||
int unknown_chunks_num;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_sPLT_SUPPORTED
|
||||
/* Data on sPLT chunks (there may be more than one). */
|
||||
png_sPLT_tp splt_palettes;
|
||||
int splt_palettes_num; /* Match type returned by png_get API */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_sCAL_SUPPORTED
|
||||
/* The sCAL chunk describes the actual physical dimensions of the
|
||||
* subject matter of the graphic. The chunk contains a unit specification
|
||||
* a byte value, and two ASCII strings representing floating-point
|
||||
* values. The values are width and height corresponsing to one pixel
|
||||
* in the image. Data values are valid if (valid & PNG_INFO_sCAL) is
|
||||
* non-zero.
|
||||
*/
|
||||
png_byte scal_unit; /* unit of physical scale */
|
||||
png_charp scal_s_width; /* string containing height */
|
||||
png_charp scal_s_height; /* string containing width */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_INFO_IMAGE_SUPPORTED
|
||||
/* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
|
||||
non-zero */
|
||||
/* Data valid if (valid & PNG_INFO_IDAT) non-zero */
|
||||
png_bytepp row_pointers; /* the image bits */
|
||||
#endif
|
||||
|
||||
};
|
||||
#endif /* PNGINFO_H */
|
||||
@@ -1,213 +0,0 @@
|
||||
/* libpng 1.7.0beta90 STANDARD API DEFINITION */
|
||||
|
||||
/* pnglibconf.h - library build configuration */
|
||||
|
||||
/* libpng version 1.7.0beta90, August 28, 2017 */
|
||||
|
||||
/* Copyright (c) 1998-2016 Glenn Randers-Pehrson */
|
||||
|
||||
/* This code is released under the libpng license. */
|
||||
/* For conditions of distribution and use, see the disclaimer */
|
||||
/* and license in png.h */
|
||||
|
||||
/* pnglibconf.h */
|
||||
/* Machine generated file: DO NOT EDIT */
|
||||
/* Derived from: scripts/pnglibconf.dfa */
|
||||
#ifndef PNGLCONF_H
|
||||
#define PNGLCONF_H
|
||||
/* options */
|
||||
#define PNG_16BIT_SUPPORTED
|
||||
#define PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
#define PNG_BENIGN_ERRORS_SUPPORTED
|
||||
#define PNG_BENIGN_READ_ERRORS_SUPPORTED
|
||||
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
|
||||
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
|
||||
#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_COLORSPACE_SUPPORTED
|
||||
#define PNG_CONSOLE_IO_SUPPORTED
|
||||
#define PNG_CONVERT_tIME_SUPPORTED
|
||||
#define PNG_EASY_ACCESS_SUPPORTED
|
||||
#define PNG_ERROR_TEXT_SUPPORTED
|
||||
#define PNG_FIXED_POINT_SUPPORTED
|
||||
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
|
||||
#define PNG_FLOATING_POINT_SUPPORTED
|
||||
#define PNG_FORMAT_AFIRST_SUPPORTED
|
||||
#define PNG_FORMAT_BGR_SUPPORTED
|
||||
#define PNG_GAMMA_SUPPORTED
|
||||
#define PNG_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
#define PNG_INCH_CONVERSIONS_SUPPORTED
|
||||
#define PNG_INFO_IMAGE_SUPPORTED
|
||||
#define PNG_IO_STATE_SUPPORTED
|
||||
// #define PNG_MNG_FEATURES_SUPPORTED
|
||||
// #define PNG_MNG_READ_FEATURES_SUPPORTED
|
||||
// #define PNG_MNG_WRITE_FEATURES_SUPPORTED
|
||||
#define PNG_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
#define PNG_READ_16BIT_SUPPORTED
|
||||
#define PNG_READ_ALPHA_MODE_SUPPORTED
|
||||
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_BACKGROUND_SUPPORTED
|
||||
#define PNG_READ_BGR_SUPPORTED
|
||||
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
|
||||
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
|
||||
#define PNG_READ_EXPAND_16_SUPPORTED
|
||||
#define PNG_READ_EXPAND_SUPPORTED
|
||||
#define PNG_READ_FILLER_SUPPORTED
|
||||
#define PNG_READ_GAMMA_SUPPORTED
|
||||
#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
|
||||
#define PNG_READ_IMAGE_SUPPORTED
|
||||
#define PNG_READ_INTERLACING_SUPPORTED
|
||||
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_READ_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_READ_INVERT_SUPPORTED
|
||||
#define PNG_READ_OPT_PLTE_SUPPORTED
|
||||
#define PNG_READ_PACKSWAP_SUPPORTED
|
||||
#define PNG_READ_PACK_SUPPORTED
|
||||
#define PNG_READ_PNG_SUPPORTED
|
||||
#define PNG_READ_QUANTIZE_SUPPORTED
|
||||
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_SHIFT_SUPPORTED
|
||||
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
|
||||
#define PNG_READ_STRIP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SUPPORTED
|
||||
#define PNG_READ_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_READ_SWAP_SUPPORTED
|
||||
#define PNG_READ_TEXT_SUPPORTED
|
||||
#define PNG_READ_TRANSFORMS_SUPPORTED
|
||||
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_READ_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_READ_bKGD_SUPPORTED
|
||||
#define PNG_READ_cHRM_SUPPORTED
|
||||
#define PNG_READ_gAMA_SUPPORTED
|
||||
#define PNG_READ_hIST_SUPPORTED
|
||||
#define PNG_READ_iCCP_SUPPORTED
|
||||
#define PNG_READ_iTXt_SUPPORTED
|
||||
#define PNG_READ_oFFs_SUPPORTED
|
||||
#define PNG_READ_pCAL_SUPPORTED
|
||||
#define PNG_READ_pHYs_SUPPORTED
|
||||
#define PNG_READ_sBIT_SUPPORTED
|
||||
#define PNG_READ_sCAL_SUPPORTED
|
||||
#define PNG_READ_sPLT_SUPPORTED
|
||||
#define PNG_READ_sRGB_SUPPORTED
|
||||
#define PNG_READ_tEXt_SUPPORTED
|
||||
#define PNG_READ_tIME_SUPPORTED
|
||||
#define PNG_READ_tRNS_SUPPORTED
|
||||
#define PNG_READ_zTXt_SUPPORTED
|
||||
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SELECT_FILTER_SUPPORTED
|
||||
#define PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
#define PNG_SETJMP_SUPPORTED
|
||||
#define PNG_SET_OPTION_SUPPORTED
|
||||
#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SET_USER_LIMITS_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_READ_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||
#define PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||
#define PNG_STDIO_SUPPORTED
|
||||
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_TEXT_SUPPORTED
|
||||
#define PNG_TIME_RFC1123_SUPPORTED
|
||||
#define PNG_TRANSFORM_MECH_SUPPORTED
|
||||
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_CHUNKS_SUPPORTED
|
||||
#define PNG_USER_LIMITS_SUPPORTED
|
||||
#define PNG_USER_MEM_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_INFO_SUPPORTED
|
||||
#define PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
#define PNG_WARNINGS_SUPPORTED
|
||||
#define PNG_WRITE_16BIT_SUPPORTED
|
||||
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_BGR_SUPPORTED
|
||||
#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
|
||||
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
|
||||
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
|
||||
#define PNG_WRITE_FILLER_SUPPORTED
|
||||
#define PNG_WRITE_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_FLUSH_SUPPORTED
|
||||
#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
|
||||
#define PNG_WRITE_INTERLACING_SUPPORTED
|
||||
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_SUPPORTED
|
||||
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
|
||||
#define PNG_WRITE_PACKSWAP_SUPPORTED
|
||||
#define PNG_WRITE_PACK_SUPPORTED
|
||||
#define PNG_WRITE_PNG_SUPPORTED
|
||||
#define PNG_WRITE_SHIFT_SUPPORTED
|
||||
#define PNG_WRITE_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
#define PNG_WRITE_SWAP_SUPPORTED
|
||||
#define PNG_WRITE_TEXT_SUPPORTED
|
||||
#define PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
|
||||
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
|
||||
#define PNG_WRITE_bKGD_SUPPORTED
|
||||
#define PNG_WRITE_cHRM_SUPPORTED
|
||||
#define PNG_WRITE_gAMA_SUPPORTED
|
||||
#define PNG_WRITE_hIST_SUPPORTED
|
||||
#define PNG_WRITE_iCCP_SUPPORTED
|
||||
#define PNG_WRITE_iTXt_SUPPORTED
|
||||
#define PNG_WRITE_oFFs_SUPPORTED
|
||||
#define PNG_WRITE_pCAL_SUPPORTED
|
||||
#define PNG_WRITE_pHYs_SUPPORTED
|
||||
#define PNG_WRITE_sBIT_SUPPORTED
|
||||
#define PNG_WRITE_sCAL_SUPPORTED
|
||||
#define PNG_WRITE_sPLT_SUPPORTED
|
||||
#define PNG_WRITE_sRGB_SUPPORTED
|
||||
#define PNG_WRITE_tEXt_SUPPORTED
|
||||
#define PNG_WRITE_tIME_SUPPORTED
|
||||
#define PNG_WRITE_tRNS_SUPPORTED
|
||||
#define PNG_WRITE_zTXt_SUPPORTED
|
||||
#define PNG_bKGD_SUPPORTED
|
||||
#define PNG_cHRM_SUPPORTED
|
||||
#define PNG_gAMA_SUPPORTED
|
||||
#define PNG_hIST_SUPPORTED
|
||||
#define PNG_iCCP_SUPPORTED
|
||||
#define PNG_iTXt_SUPPORTED
|
||||
#define PNG_oFFs_SUPPORTED
|
||||
#define PNG_pCAL_SUPPORTED
|
||||
#define PNG_pHYs_SUPPORTED
|
||||
#define PNG_sBIT_SUPPORTED
|
||||
#define PNG_sCAL_SUPPORTED
|
||||
#define PNG_sPLT_SUPPORTED
|
||||
#define PNG_sRGB_SUPPORTED
|
||||
#define PNG_tEXt_SUPPORTED
|
||||
#define PNG_tIME_SUPPORTED
|
||||
#define PNG_tRNS_SUPPORTED
|
||||
#define PNG_zTXt_SUPPORTED
|
||||
/* end of options */
|
||||
/* settings */
|
||||
#define PNG_ABORT { (abort()); }
|
||||
#define PNG_API_RULE 0
|
||||
#define PNG_DEFAULT_COMPRESSION_LEVEL PNG_COMPRESSION_MEDIUM
|
||||
#define PNG_DEFAULT_GAMMA_ACCURACY 665
|
||||
#define PNG_DEFAULT_READ_MACROS 1
|
||||
#define PNG_GAMMA_THRESHOLD_FIXED 153
|
||||
#define PNG_IDAT_READ_SIZE 4096
|
||||
#define PNG_INFLATE_BUF_SIZE 1024
|
||||
#define PNG_MAX_GAMMA_8 11
|
||||
#define PNG_QUANTIZE_BLUE_BITS 5
|
||||
#define PNG_QUANTIZE_GREEN_BITS 5
|
||||
#define PNG_QUANTIZE_RED_BITS 5
|
||||
#define PNG_USER_CHUNK_CACHE_MAX 1000
|
||||
#define PNG_USER_CHUNK_MALLOC_MAX 8000000
|
||||
#define PNG_USER_HEIGHT_MAX 1000000
|
||||
#define PNG_USER_WIDTH_MAX 1000000
|
||||
#define PNG_ZBUF_SIZE 4096
|
||||
#define PNG_ZLIB_HEADER <zlib.h>
|
||||
#define PNG_ZLIB_VERNUM 0
|
||||
#define PNG_sCAL_PRECISION 5
|
||||
#define PNG_sRGB_PROFILE_CHECKS 2
|
||||
/* end of settings */
|
||||
#endif /* PNGLCONF_H */
|
||||
@@ -1,269 +0,0 @@
|
||||
|
||||
/* pngmem.c - stub functions for memory allocation
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
* This file provides a location for all memory allocation. Users who
|
||||
* need special memory handling are expected to supply replacement
|
||||
* functions for png_malloc() and png_free(), and to use
|
||||
* png_create_read_struct_2() and png_create_write_struct_2() to
|
||||
* identify the replacement functions.
|
||||
*/
|
||||
|
||||
#include "pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_pngmem
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
/* Free a png_struct */
|
||||
void /* PRIVATE */
|
||||
png_destroy_png_struct(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
/* png_free might call png_error and may certainly call
|
||||
* png_get_mem_ptr, so fake a temporary png_struct to support this.
|
||||
*/
|
||||
png_struct dummy_struct = *png_ptr;
|
||||
memset(png_ptr, 0, (sizeof *png_ptr));
|
||||
png_free(&dummy_struct, png_ptr);
|
||||
|
||||
# ifdef PNG_SETJMP_SUPPORTED
|
||||
/* We may have a jmp_buf left to deallocate. */
|
||||
png_free_jmpbuf(&dummy_struct);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory. For reasonable files, size should never exceed
|
||||
* 64K. However, zlib may allocate more than 64K if you don't tell
|
||||
* it not to. See zconf.h and png.h for more information. zlib does
|
||||
* need to allocate exactly 64K, so whatever you call here must
|
||||
* have the ability to do that.
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
ret = png_malloc(png_ptr, size);
|
||||
|
||||
if (ret != NULL)
|
||||
memset(ret, 0, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
|
||||
* allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
|
||||
* Checking and error handling must happen outside this routine; it returns NULL
|
||||
* if the allocation cannot be done (for any reason.)
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED)
|
||||
{
|
||||
/* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
|
||||
* allocators have also been removed in 1.6.0, so any 16-bit system now has
|
||||
* to implement a user memory handler. This checks to be sure it isn't
|
||||
* called with big numbers.
|
||||
*/
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
PNG_UNUSED(png_ptr)
|
||||
#endif
|
||||
|
||||
/* Some compilers complain that this is always true. However, it
|
||||
* can be false when integer overflow happens.
|
||||
*/
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > 0 && size <= PNG_SIZE_MAX && size <= 65536U)
|
||||
#else
|
||||
if (size > 0 && size <= PNG_SIZE_MAX)
|
||||
#endif
|
||||
{
|
||||
png_voidp result;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
|
||||
result = png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
|
||||
|
||||
else
|
||||
#endif
|
||||
result = malloc((size_t)size); /* checked for truncation above */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
|
||||
defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
|
||||
/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
|
||||
* that arises because of the checks in png_realloc_array that are repeated in
|
||||
* png_malloc_array.
|
||||
*/
|
||||
static png_voidp
|
||||
png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
|
||||
size_t element_size)
|
||||
{
|
||||
png_alloc_size_t req = nelements; /* known to be > 0 */
|
||||
|
||||
if (req <= PNG_SIZE_MAX/element_size)
|
||||
return png_malloc_base(png_ptr, req * element_size);
|
||||
|
||||
/* The failure case when the request is too large */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_malloc_array,(png_const_structrp png_ptr, int nelements,
|
||||
size_t element_size),PNG_ALLOCATED)
|
||||
{
|
||||
affirm(nelements > 0 && element_size > 0);
|
||||
return png_malloc_array_checked(png_ptr, nelements, element_size);
|
||||
}
|
||||
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_realloc_array,(png_structrp png_ptr, png_const_voidp old_array,
|
||||
int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
|
||||
{
|
||||
/* These are internal errors: */
|
||||
affirm(add_elements > 0 && element_size > 0 && old_elements >= 0 &&
|
||||
(old_array != NULL || old_elements == 0));
|
||||
|
||||
/* Check for overflow on the elements count (so the caller does not have to
|
||||
* check.)
|
||||
*/
|
||||
if (add_elements <= INT_MAX - old_elements)
|
||||
{
|
||||
png_voidp new_array = png_malloc_array_checked(png_ptr,
|
||||
old_elements+add_elements, element_size);
|
||||
|
||||
if (new_array != NULL)
|
||||
{
|
||||
/* Because png_malloc_array worked the size calculations below cannot
|
||||
* overflow.
|
||||
*/
|
||||
if (old_elements > 0)
|
||||
memcpy(new_array, old_array, element_size*(unsigned)old_elements);
|
||||
|
||||
memset((char*)new_array + element_size*(unsigned)old_elements, 0,
|
||||
element_size*(unsigned)add_elements);
|
||||
|
||||
return new_array;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
# ifdef PNG_USER_LIMITS_SUPPORTED
|
||||
/* The potential overflow case. Set the cache counter so libpng will
|
||||
* not make any more attempts
|
||||
*/
|
||||
png_ptr->user_chunk_cache_max = 2;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return NULL; /* error */
|
||||
}
|
||||
#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
|
||||
|
||||
/* Various functions that have different error handling are derived from this.
|
||||
* png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
|
||||
* function png_malloc_default is also provided.
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = png_malloc_base(png_ptr, size);
|
||||
|
||||
if (ret == NULL)
|
||||
png_error(png_ptr, "Out of memory");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
|
||||
* function will issue a png_warning and return NULL instead of issuing a
|
||||
* png_error, if it fails to allocate the requested memory.
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
png_voidp ret = png_malloc_base(png_ptr, size);
|
||||
|
||||
if (ret != NULL)
|
||||
return ret;
|
||||
|
||||
png_warning(png_ptr, "Out of memory");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
|
||||
* without taking any action.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_free(png_const_structrp png_ptr, png_voidp ptr)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr->free_fn != NULL)
|
||||
png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr);
|
||||
|
||||
else
|
||||
free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
#endif /* USER_MEM */
|
||||
|
||||
}
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
/* This function is called when the application wants to use another method
|
||||
* of allocating and freeing memory.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
|
||||
malloc_fn, png_free_ptr free_fn)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
png_ptr->mem_ptr = mem_ptr;
|
||||
png_ptr->malloc_fn = malloc_fn;
|
||||
png_ptr->free_fn = free_fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns a pointer to the mem_ptr associated with the user
|
||||
* functions. The application should free any memory associated with this
|
||||
* pointer before png_write_destroy and png_read_destroy are called.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_get_mem_ptr(png_const_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
return png_ptr->mem_ptr;
|
||||
}
|
||||
#endif /* USER_MEM */
|
||||
#endif /* READ || WRITE */
|
||||
@@ -1,866 +0,0 @@
|
||||
|
||||
/* pngpread.c - read a png file in push mode
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#include "pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_pngpread
|
||||
|
||||
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
|
||||
/* Standard callbacks */
|
||||
static void PNGCBAPI
|
||||
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
|
||||
{
|
||||
png_bytep ptr;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
ptr = buffer;
|
||||
debug(length > 0);
|
||||
|
||||
if (length > 0 && png_ptr->save_buffer_size > 0)
|
||||
{
|
||||
png_size_t save_size;
|
||||
|
||||
if (length < png_ptr->save_buffer_size)
|
||||
save_size = length;
|
||||
|
||||
else
|
||||
save_size = png_ptr->save_buffer_size;
|
||||
|
||||
memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
|
||||
length -= save_size;
|
||||
ptr += save_size;
|
||||
png_ptr->buffer_size -= save_size;
|
||||
png_ptr->save_buffer_size -= save_size;
|
||||
png_ptr->save_buffer_ptr += save_size;
|
||||
}
|
||||
|
||||
if (length > 0 && png_ptr->current_buffer_size > 0)
|
||||
{
|
||||
png_size_t save_size;
|
||||
|
||||
if (length < png_ptr->current_buffer_size)
|
||||
save_size = length;
|
||||
|
||||
else
|
||||
save_size = png_ptr->current_buffer_size;
|
||||
|
||||
memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
|
||||
png_ptr->buffer_size -= save_size;
|
||||
png_ptr->current_buffer_size -= save_size;
|
||||
png_ptr->current_buffer_ptr += save_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Push model modes: png_chunk_op plus extras */
|
||||
typedef enum
|
||||
{
|
||||
/* all the png_chunk_op codes, plus: */
|
||||
png_read_signature = 0, /* starting value */
|
||||
png_read_chunk_header,
|
||||
png_read_end_IDAT,
|
||||
png_read_done,
|
||||
png_read_chunk, /* Not a state, use these derived from png_chunk_op: */
|
||||
png_read_chunk_skip = png_read_chunk+png_chunk_skip,
|
||||
png_read_chunk_unknown = png_read_chunk+png_chunk_unknown,
|
||||
png_read_chunk_process_all = png_read_chunk+png_chunk_process_all,
|
||||
png_read_chunk_process_part = png_read_chunk+png_chunk_process_part
|
||||
} png_read_mode;
|
||||
|
||||
static void
|
||||
png_push_save_buffer_partial(png_structrp png_ptr, size_t amount)
|
||||
{
|
||||
/* Copy 'amount' bytes to the end of the save buffer from the current
|
||||
* buffer.
|
||||
*/
|
||||
png_bytep buffer;
|
||||
size_t save_size = png_ptr->save_buffer_size;
|
||||
|
||||
if (save_size > PNG_SIZE_MAX - amount)
|
||||
png_error(png_ptr, "save buffer overflow");
|
||||
|
||||
if (png_ptr->save_buffer_max < save_size + amount)
|
||||
{
|
||||
/* Reallocate the save buffer. */
|
||||
buffer = png_voidcast(png_bytep, png_malloc(png_ptr, save_size + amount));
|
||||
memcpy(buffer, png_ptr->save_buffer_ptr, save_size);
|
||||
png_free(png_ptr, png_ptr->save_buffer);
|
||||
png_ptr->save_buffer_ptr = png_ptr->save_buffer = buffer;
|
||||
}
|
||||
|
||||
else if (png_ptr->save_buffer_max -
|
||||
(png_ptr->save_buffer_ptr - png_ptr->save_buffer) < save_size + amount)
|
||||
{
|
||||
/* Move the existing saved data */
|
||||
buffer = png_ptr->save_buffer;
|
||||
memmove(buffer, png_ptr->save_buffer_ptr, save_size);
|
||||
png_ptr->save_buffer_ptr = buffer;
|
||||
}
|
||||
|
||||
else /* Just copy the data */
|
||||
buffer = png_ptr->save_buffer_ptr;
|
||||
|
||||
memcpy(buffer+save_size, png_ptr->current_buffer_ptr, amount);
|
||||
png_ptr->save_buffer_size = save_size + amount;
|
||||
png_ptr->current_buffer_ptr += amount;
|
||||
png_ptr->current_buffer_size -= amount;
|
||||
png_ptr->buffer_size -= amount;
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_save_buffer(png_structrp png_ptr)
|
||||
{
|
||||
png_push_save_buffer_partial(png_ptr, png_ptr->current_buffer_size);
|
||||
/* This terminates the process loop. */
|
||||
png_ptr->buffer_size = 0;
|
||||
}
|
||||
|
||||
#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
|
||||
if (png_ptr->chunk_length + 4 > png_ptr->buffer_size) \
|
||||
{ png_push_save_buffer(png_ptr); return; }
|
||||
#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
|
||||
if (png_ptr->buffer_size < N) \
|
||||
{ png_push_save_buffer(png_ptr); return; }
|
||||
|
||||
png_size_t PNGAPI
|
||||
png_process_data_pause(png_structrp png_ptr, int save)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
/* It's easiest for the caller if we do the save; then the caller doesn't
|
||||
* have to supply the same data again:
|
||||
*/
|
||||
if (save != 0)
|
||||
png_push_save_buffer(png_ptr);
|
||||
else
|
||||
{
|
||||
/* This includes any pending saved bytes: */
|
||||
png_size_t remaining = png_ptr->buffer_size;
|
||||
png_ptr->buffer_size = 0; /* Terminate the process loop */
|
||||
|
||||
/* So subtract the saved buffer size, unless all the data
|
||||
* is actually 'saved', in which case we just return 0
|
||||
*/
|
||||
if (png_ptr->save_buffer_size < remaining)
|
||||
return remaining - png_ptr->save_buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_process_data_skip(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && png_ptr->process_mode == png_read_chunk_skip)
|
||||
{
|
||||
/* At the end of png_process_data the buffer size must be 0 (see the loop
|
||||
* above) so we can detect a broken call here:
|
||||
*/
|
||||
if (png_ptr->buffer_size != 0)
|
||||
png_app_error(png_ptr,
|
||||
"png_process_data_skip called inside png_process_data");
|
||||
|
||||
/* If is impossible for there to be a saved buffer at this point -
|
||||
* otherwise we could not be in SKIP mode. This will also happen if
|
||||
* png_process_skip is called inside png_process_data (but only very
|
||||
* rarely.)
|
||||
*/
|
||||
else if (png_ptr->save_buffer_size != 0)
|
||||
png_app_error(png_ptr, "png_process_data_skip called with saved data");
|
||||
|
||||
else
|
||||
{
|
||||
/* Skipping png_ptr->chunk_length of data then checking the CRC, after
|
||||
* that a new chunk header will be read.
|
||||
*/
|
||||
png_ptr->process_mode = png_read_chunk_header;
|
||||
return png_ptr->chunk_length + 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
|
||||
png_size_t buffer_length)
|
||||
{
|
||||
png_ptr->current_buffer_size = buffer_length;
|
||||
png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
|
||||
png_ptr->current_buffer_ptr = buffer;
|
||||
}
|
||||
|
||||
/* Read any remaining signature bytes from the stream and compare them with
|
||||
* the correct PNG signature. It is possible that this routine is called
|
||||
* with bytes already read from the signature, either because they have been
|
||||
* checked by the calling application, or because of multiple calls to this
|
||||
* routine.
|
||||
*/
|
||||
static void
|
||||
png_push_read_signature(png_structrp png_ptr, png_inforp info_ptr)
|
||||
{
|
||||
unsigned int num_checked = png_ptr->sig_bytes;
|
||||
unsigned int num_to_check = 8 - num_checked;
|
||||
|
||||
if (png_ptr->buffer_size < num_to_check)
|
||||
num_to_check = (int)/*SAFE*/png_ptr->buffer_size;
|
||||
|
||||
png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
|
||||
num_to_check);
|
||||
png_ptr->sig_bytes = png_check_byte(png_ptr,
|
||||
png_ptr->sig_bytes + num_to_check);
|
||||
|
||||
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
|
||||
{
|
||||
if (num_checked < 4 &&
|
||||
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
|
||||
png_error(png_ptr, "Not a PNG file");
|
||||
|
||||
else
|
||||
png_error(png_ptr, "PNG file corrupted by ASCII conversion");
|
||||
}
|
||||
|
||||
else if (png_ptr->sig_bytes >= 8)
|
||||
png_ptr->process_mode = png_read_chunk_header;
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_crc_finish(png_structrp png_ptr)
|
||||
/* CRC the remainder of the chunk data; png_struct::chunk_length must be the
|
||||
* amount of data left to read excluding the CRC.
|
||||
*/
|
||||
{
|
||||
if (png_ptr->chunk_length != 0 && png_ptr->save_buffer_size != 0)
|
||||
{
|
||||
png_size_t save_size = png_ptr->save_buffer_size;
|
||||
png_uint_32 skip_length = png_ptr->chunk_length;
|
||||
|
||||
/* We want the smaller of 'skip_length' and 'save_buffer_size', but
|
||||
* they are of different types and we don't know which variable has the
|
||||
* fewest bits. Carefully select the smaller and cast it to the type of
|
||||
* the larger - this cannot overflow. Do not cast in the following test
|
||||
* - it will break on either 16 or 64 bit platforms.
|
||||
*/
|
||||
if (skip_length < save_size)
|
||||
save_size = (png_size_t)/*SAFE*/skip_length;
|
||||
|
||||
else
|
||||
skip_length = (png_uint_32)/*SAFE*/save_size;
|
||||
|
||||
png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
|
||||
|
||||
png_ptr->chunk_length -= skip_length;
|
||||
png_ptr->buffer_size -= save_size;
|
||||
png_ptr->save_buffer_size -= save_size;
|
||||
png_ptr->save_buffer_ptr += save_size;
|
||||
}
|
||||
|
||||
if (png_ptr->chunk_length != 0 && png_ptr->current_buffer_size != 0)
|
||||
{
|
||||
png_size_t save_size = png_ptr->current_buffer_size;
|
||||
png_uint_32 skip_length = png_ptr->chunk_length;
|
||||
|
||||
/* We want the smaller of 'skip_length' and 'current_buffer_size', here,
|
||||
* the same problem exists as above and the same solution.
|
||||
*/
|
||||
if (skip_length < save_size)
|
||||
save_size = (png_size_t)/*SAFE*/skip_length;
|
||||
|
||||
else
|
||||
skip_length = (png_uint_32)/*SAFE*/save_size;
|
||||
|
||||
png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
|
||||
|
||||
png_ptr->chunk_length -= skip_length;
|
||||
png_ptr->buffer_size -= save_size;
|
||||
png_ptr->current_buffer_size -= save_size;
|
||||
png_ptr->current_buffer_ptr += save_size;
|
||||
}
|
||||
|
||||
if (png_ptr->chunk_length == 0)
|
||||
{
|
||||
PNG_PUSH_SAVE_BUFFER_IF_LT(4)
|
||||
png_crc_finish(png_ptr, 0);
|
||||
png_ptr->process_mode = png_read_chunk_header;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_read_unknown(png_structrp png_ptr, png_inforp info_ptr)
|
||||
{
|
||||
/* Handle an unknown chunk. All the data is available but it may not
|
||||
* all be in the same buffer. png_handle_unknown needs the chunk data in
|
||||
* just one buffer.
|
||||
*/
|
||||
png_bytep buffer;
|
||||
png_uint_32 chunk_length = png_ptr->chunk_length;
|
||||
|
||||
if (png_ptr->save_buffer_size > 0)
|
||||
{
|
||||
png_size_t save_size = png_ptr->save_buffer_size;
|
||||
|
||||
if (save_size < chunk_length)
|
||||
{
|
||||
/* Copy the current_buffer_ptr data into the save buffer. */
|
||||
png_push_save_buffer_partial(png_ptr, chunk_length - save_size);
|
||||
save_size = chunk_length;
|
||||
}
|
||||
|
||||
buffer = png_ptr->save_buffer_ptr;
|
||||
png_ptr->save_buffer_ptr = buffer+chunk_length;
|
||||
png_ptr->save_buffer_size = save_size-chunk_length;
|
||||
png_ptr->buffer_size -= chunk_length;
|
||||
affirm(png_ptr->buffer_size >= 4);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
affirm(png_ptr->current_buffer_size >= chunk_length+4);
|
||||
buffer = png_ptr->current_buffer_ptr;
|
||||
png_ptr->current_buffer_ptr = buffer+chunk_length;
|
||||
png_ptr->current_buffer_size -= chunk_length;
|
||||
png_ptr->buffer_size -= chunk_length;
|
||||
}
|
||||
|
||||
/* Now check the CRC, before attempting the unknown handling. */
|
||||
png_calculate_crc(png_ptr, buffer, chunk_length);
|
||||
png_crc_finish(png_ptr, 0);
|
||||
# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
|
||||
png_handle_unknown(png_ptr, info_ptr, buffer);
|
||||
# else /* !READ_UNKNOWN_CHUNKS */
|
||||
PNG_UNUSED(info_ptr)
|
||||
# endif /* !READ_UNKNOWN_CHUNKS */
|
||||
png_ptr->process_mode = png_read_chunk_header;
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_have_row(png_structrp png_ptr, png_bytep row)
|
||||
{
|
||||
if (png_ptr->row_fn != NULL)
|
||||
{
|
||||
png_uint_32 row_number = png_ptr->row_number;
|
||||
png_byte pass = png_ptr->pass;
|
||||
|
||||
if (png_ptr->interlaced)
|
||||
{
|
||||
/* If the row de-interlace is not being done by PNG this wacky API
|
||||
* delivers the row number in the pass to the caller. We know that
|
||||
* if we get here the row exists, so the number is just one less than
|
||||
* the height of an interlaced image with just the rows up to this
|
||||
* one:
|
||||
*/
|
||||
# ifdef PNG_READ_INTERLACING_SUPPORTED
|
||||
if (!png_ptr->do_interlace)
|
||||
# endif /* READ_INTERLACING */
|
||||
{
|
||||
affirm(PNG_ROW_IN_INTERLACE_PASS(row_number, pass) && row != NULL);
|
||||
row_number = PNG_PASS_ROWS(row_number+1, pass);
|
||||
affirm(row_number > 0);
|
||||
--row_number;
|
||||
}
|
||||
}
|
||||
|
||||
(*(png_ptr->row_fn))(png_ptr, row, row_number, pass);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_read_sync_zstream(png_structp png_ptr, png_bytep *bufferp,
|
||||
size_t *buffer_lengthp)
|
||||
/* Synchronize the png_struct progressive read buffer
|
||||
* {*bufferp,*buffer_lengthp} with png_struct::zstream.next_in, on the
|
||||
* assumption that the zstream had previously been set up with *bufferp.
|
||||
*/
|
||||
{
|
||||
png_bytep original_start = *bufferp;
|
||||
png_alloc_size_t bytes_consumed = png_ptr->zstream.next_in - original_start;
|
||||
|
||||
affirm(buffer_lengthp != NULL);
|
||||
|
||||
/* Calculate the CRC for the consumed data: */
|
||||
png_calculate_crc(png_ptr, original_start, bytes_consumed);
|
||||
|
||||
/* Update the buffer pointers and the various lengths: */
|
||||
*bufferp = original_start + bytes_consumed; /* == png_ptr->zstream.next_in */
|
||||
|
||||
affirm(bytes_consumed <= *buffer_lengthp);
|
||||
*buffer_lengthp -= (size_t)/*SAFE*/bytes_consumed;
|
||||
|
||||
affirm(bytes_consumed <= png_ptr->chunk_length);
|
||||
png_ptr->chunk_length -= (png_uint_32)/*SAFE*/bytes_consumed;
|
||||
|
||||
affirm(bytes_consumed <= png_ptr->buffer_size);
|
||||
png_ptr->buffer_size -= (size_t)/*SAFE*/bytes_consumed;
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_read_process_IDAT(png_structp png_ptr, png_bytep *bufferp,
|
||||
size_t *buffer_lengthp)
|
||||
/* If the the *buffer_lengthp parameter is NULL there is no more input,
|
||||
* png_struct::mode & PNG_AFTER_IDAT must be set at this point.
|
||||
*/
|
||||
{
|
||||
png_alloc_size_t buffer_length;
|
||||
|
||||
if (buffer_lengthp != NULL)
|
||||
buffer_length = *buffer_lengthp;
|
||||
|
||||
else /* end of IDAT */
|
||||
{
|
||||
/* SECURITY: if this affirm fails the code would go into an infinite loop;
|
||||
* see the handling of avail_in == 0 in png_inflate_IDAT.
|
||||
*/
|
||||
affirm(png_ptr->mode & PNG_AFTER_IDAT);
|
||||
buffer_length = 0;
|
||||
}
|
||||
|
||||
/* This routine attempts to process all the data it has been given before
|
||||
* returning, calling the row callback as required to handle the
|
||||
* uncompressed results.
|
||||
*
|
||||
* If a pause happens during processing (png_ptr->buffer_size is set to 0)
|
||||
* or the end of the chunk is encountered the routine may return without
|
||||
* handling all the input data.
|
||||
*/
|
||||
if (buffer_length > png_ptr->chunk_length)
|
||||
{
|
||||
buffer_length = png_ptr->chunk_length;
|
||||
|
||||
/* This works because the last part of a 'skip' is to read and check the
|
||||
* CRC, then the process mode is set to png_read_chunk_header.
|
||||
*/
|
||||
if (buffer_length == 0)
|
||||
png_ptr->process_mode = png_read_chunk_skip;
|
||||
}
|
||||
|
||||
/* It is possble for buffer_length to be zero at this point if the stream
|
||||
* caontains a zero length IDAT. This is handled below.
|
||||
*/
|
||||
png_ptr->zstream.next_in = *bufferp;
|
||||
|
||||
while (buffer_length > 0 || buffer_lengthp == NULL)
|
||||
{
|
||||
if (buffer_length >= ZLIB_IO_MAX)
|
||||
{
|
||||
png_ptr->zstream.avail_in = ZLIB_IO_MAX;
|
||||
buffer_length -= ZLIB_IO_MAX;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
png_ptr->zstream.avail_in = (uInt)/*SAFE*/buffer_length;
|
||||
buffer_length = 0;
|
||||
}
|
||||
|
||||
/* The last row may already have been processed.
|
||||
*
|
||||
* row_number is the *current* row number in the range 0..height-1. It is
|
||||
* updated only by the call to png_read_process_IDAT that follows the call
|
||||
* which returns something other than png_row_incomplete.
|
||||
*
|
||||
* At the end of the image that call must *NOT* be made; png_process_IDAT
|
||||
* must not be called after the last row. png_struct::zstream_eod is set
|
||||
* below to allow this condition to be detected.
|
||||
*
|
||||
* Note that png_read_process_IDAT handles errors in the LZ compressed
|
||||
* data (i.e. the cases where png_struct::zstream_error is set) by filling
|
||||
* the rows in with 0, which is a safe value, so keep calling it until we
|
||||
* reach the end of the image.
|
||||
*/
|
||||
if (!png_ptr->zstream_eod)
|
||||
{
|
||||
png_bytep row_buffer = NULL;
|
||||
png_row_op row_op =
|
||||
png_read_process_IDAT(png_ptr, NULL, NULL, 1/*save row*/);
|
||||
|
||||
if (row_op != png_row_incomplete)
|
||||
{
|
||||
/* Have a complete row, so check for end-of-image; do this here
|
||||
* because interlaced images can end on earlier rows or passes but
|
||||
* we keep calling png_read_process_IDAT until it updates row_number
|
||||
* to the last row of the actual image:
|
||||
*/
|
||||
if (png_ptr->row_number+1 >= png_ptr->height &&
|
||||
(!png_ptr->interlaced || png_ptr->pass == 6))
|
||||
png_ptr->zstream_eod = 1; /* end of image */
|
||||
}
|
||||
|
||||
switch (row_op)
|
||||
{
|
||||
case png_row_incomplete:
|
||||
/* more IDAT data needed for row */
|
||||
debug(png_ptr->zstream.avail_in == 0);
|
||||
|
||||
/* png_inflate_IDAT is supposed to handle this and recognize a
|
||||
* call with 0 avail_in as end of stream:
|
||||
*/
|
||||
affirm(buffer_lengthp != NULL);
|
||||
continue;
|
||||
|
||||
case png_row_process:
|
||||
/* If a row was obtained after the end of the IDAT this was done
|
||||
* by fabricating data, ensure this is reported, else there is a
|
||||
* security issue; normally libpng does a png_error in this
|
||||
* case, even if the error is ignored png_struct::zstream_error
|
||||
* should be set so somehow the error wasn't noticed!
|
||||
*/
|
||||
affirm(buffer_lengthp != NULL || png_ptr->zstream_error);
|
||||
|
||||
/* png_struct::transformed_row contains a complete, transformed,
|
||||
* row; this is processed in both 'sparkle' and 'block' mode.
|
||||
*/
|
||||
# ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
row_buffer = png_ptr->transformed_row;
|
||||
if (row_buffer == NULL)
|
||||
# endif /* TRANSFORM_MECH */
|
||||
row_buffer = png_ptr->row_buffer;
|
||||
break;
|
||||
|
||||
case png_row_repeat:
|
||||
/* row not in this pass, but the existing row in
|
||||
* png_struct::transformed_row may be used, this is only required
|
||||
* if the 'block' or 'rectangle' mode of display is done and
|
||||
* libpng is handling the de-interlace; when the app does it it
|
||||
* only see the real rows.
|
||||
*/
|
||||
# ifdef PNG_READ_INTERLACING_SUPPORTED
|
||||
if (png_ptr->do_interlace)
|
||||
{
|
||||
# ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
row_buffer = png_ptr->transformed_row;
|
||||
if (row_buffer == NULL)
|
||||
# endif /* TRANSFORM_MECH */
|
||||
row_buffer = png_ptr->row_buffer;
|
||||
break;
|
||||
}
|
||||
# endif /* READ_INTERLACING */
|
||||
continue;
|
||||
|
||||
case png_row_skip:
|
||||
/* row not in pass and no appropriate data; skip this row,
|
||||
* nothing more need be done, except the read_row_fn. The use
|
||||
* of 'NULL' to mean this row doesn't contribute to the output
|
||||
* is historical and not documented;
|
||||
*/
|
||||
# ifdef PNG_READ_INTERLACING_SUPPORTED
|
||||
if (png_ptr->do_interlace)
|
||||
break;
|
||||
# endif /* READ_INTERLACING */
|
||||
continue;
|
||||
|
||||
default:
|
||||
impossible("not reached");
|
||||
}
|
||||
|
||||
/* Here if there is a row to process. */
|
||||
|
||||
/* Now adjust the buffer pointers before calling png_push_have_row
|
||||
* because the callback might call png_process_data_pause and that
|
||||
* calls png_push_save_row. (Yes, this is insane; it was forced on
|
||||
* libpng by writers of an external app that ignored the instructions
|
||||
* not to fiddle with the insides of png_struct in version 1.4. It
|
||||
* will probably be fixed here before 1.7.0 is released by removing
|
||||
* the need for the save buffer entirely.)
|
||||
*/
|
||||
if (buffer_lengthp != NULL)
|
||||
png_push_read_sync_zstream(png_ptr, bufferp, buffer_lengthp);
|
||||
|
||||
/* Process one row: */
|
||||
png_push_have_row(png_ptr, row_buffer);
|
||||
|
||||
/* The buffer pointer and size may have changed at this point,
|
||||
* so everything needs to be reloaded if we can continue reading.
|
||||
*/
|
||||
if (buffer_lengthp != NULL) /* not at end of IDATs */
|
||||
{
|
||||
if (png_ptr->chunk_length == 0)
|
||||
png_ptr->process_mode = png_read_chunk_skip;
|
||||
|
||||
/* If the buffer_size has been set to zero more input is required,
|
||||
* this may be a 'pause', and if the specific input buffer being
|
||||
* processed has been exhaused then more input is also required.
|
||||
* Otherwise we can keep going, however the input buffer may have
|
||||
* been changed by the app callback, so do a complete reload:
|
||||
*/
|
||||
else if (png_ptr->buffer_size > 0 && *buffer_lengthp > 0)
|
||||
png_push_read_process_IDAT(png_ptr, bufferp, buffer_lengthp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we can't continue reading because there is no more IDAT data this
|
||||
* may still be a pause.
|
||||
*/
|
||||
if (png_ptr->buffer_size == 0)
|
||||
return;
|
||||
|
||||
/* Else continue, with zero data: */
|
||||
continue;
|
||||
}
|
||||
|
||||
affirm(png_ptr->zstream_eod);
|
||||
|
||||
if (png_ptr->zowner == 0 || png_read_finish_IDAT(png_ptr))
|
||||
{
|
||||
/* The zlib stream has ended, there may still be input data in
|
||||
* png_ptr->zstream.next_in, restore this.
|
||||
*/
|
||||
debug(png_ptr->zowner == 0 && png_ptr->zstream_ended);
|
||||
|
||||
if (buffer_lengthp != NULL)
|
||||
{
|
||||
png_push_read_sync_zstream(png_ptr, bufferp, buffer_lengthp);
|
||||
|
||||
/* If the chunk_length is greater than 0 then there is extra data,
|
||||
* report this once. Notice that for IDAT after the end of the
|
||||
* stream we keep coming to this point and doing the skip.
|
||||
*/
|
||||
if (png_ptr->chunk_length > 0)
|
||||
{
|
||||
if (!png_ptr->zstream_error)
|
||||
{
|
||||
png_chunk_benign_error(png_ptr,
|
||||
"too much IDAT data (progressive read)");
|
||||
png_ptr->zstream_error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* In any case CRC the chunk, skipping any unneeded data: */
|
||||
png_ptr->process_mode = png_read_chunk_skip;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* else more input is required */
|
||||
/* NOTE: this test only fires on a small (less than 5 byte) IDAT chunk
|
||||
* which just contains the LZ EOF and the Adler32 CRC.
|
||||
*/
|
||||
affirm(png_ptr->zowner == png_IDAT && !png_ptr->zstream_ended);
|
||||
}
|
||||
|
||||
/* At this point all the input has been consumed, however the CRC has not
|
||||
* been done and the three length fields in png_struct, *buffer_lengthp,
|
||||
* buffer_size and chunk_length, all need updating.
|
||||
*/
|
||||
png_push_read_sync_zstream(png_ptr, bufferp, buffer_lengthp);
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_read_IDAT(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr->save_buffer_size > 0)
|
||||
{
|
||||
png_push_read_process_IDAT(png_ptr, &png_ptr->save_buffer_ptr,
|
||||
&png_ptr->save_buffer_size);
|
||||
|
||||
/* This is a slight optimization; normally when the process mode changes
|
||||
* there will still be something in the buffer:
|
||||
*/
|
||||
if (png_ptr->save_buffer_size > 0)
|
||||
return;
|
||||
|
||||
/* Check for a change in process mode or an application pause before
|
||||
* checking the current input buffer. This is only rarely reached.
|
||||
*/
|
||||
if (png_ptr->process_mode != png_read_chunk_process_part ||
|
||||
png_ptr->buffer_size == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (png_ptr->current_buffer_size > 0)
|
||||
png_push_read_process_IDAT(png_ptr, &png_ptr->current_buffer_ptr,
|
||||
&png_ptr->current_buffer_size);
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_finish_IDAT(png_structrp png_ptr)
|
||||
/* Called once when the first chunk after IDAT is seen. */
|
||||
{
|
||||
/* All of the IDAT data has been processed, however the stream may have
|
||||
* been truncated and the image rows may not all have been processed.
|
||||
* Clean up here (this doesn't read anything.)
|
||||
*
|
||||
* 1.7.0: this attempts some measure of compatibility with the sequential
|
||||
* API, if the IDAT is truncated and the resultant error reporting doesn't
|
||||
* abort the read the image is filled in using zeros of pixel data. This
|
||||
* actually happens inside png_inflate_IDAT (pngrutil.c) when called with
|
||||
* z_stream::avail_in == 0.
|
||||
*/
|
||||
while (png_ptr->zowner == png_IDAT)
|
||||
{
|
||||
png_byte b = 0, *pb = &b;
|
||||
|
||||
png_push_read_process_IDAT(png_ptr, &pb, NULL/*end of IDAT*/);
|
||||
|
||||
if (png_ptr->zowner == 0)
|
||||
break;
|
||||
|
||||
if (png_ptr->buffer_size == 0) /* pause */
|
||||
return;
|
||||
}
|
||||
|
||||
png_ptr->process_mode = png_check_bits(png_ptr, png_ptr->process_mode >> 4,
|
||||
4);
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
|
||||
{
|
||||
if (png_ptr->info_fn != NULL)
|
||||
(*(png_ptr->info_fn))(png_ptr, info_ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
|
||||
{
|
||||
if (png_ptr->end_fn != NULL)
|
||||
(*(png_ptr->end_fn))(png_ptr, info_ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
png_push_read_chunk_header(png_structrp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
/* Called to read a new chunk header and work out how to handle the remainder
|
||||
* of the data.
|
||||
*/
|
||||
unsigned int mode; /* mode prior to the header */
|
||||
png_byte chunk_header[8];
|
||||
|
||||
PNG_PUSH_SAVE_BUFFER_IF_LT(8)
|
||||
png_push_fill_buffer(png_ptr, chunk_header, 8);
|
||||
png_ptr->chunk_length = png_get_uint_31(png_ptr, chunk_header);
|
||||
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_header+4);
|
||||
png_reset_crc(png_ptr, chunk_header+4);
|
||||
png_check_chunk_name(png_ptr, png_ptr->chunk_name);
|
||||
png_check_chunk_length(png_ptr, png_ptr->chunk_length);
|
||||
mode = png_ptr->mode;
|
||||
png_ptr->process_mode = png_check_bits(png_ptr,
|
||||
png_read_chunk+png_find_chunk_op(png_ptr), 4);
|
||||
|
||||
/* Is this the first IDAT chunk? */
|
||||
if ((mode ^ png_ptr->mode) & PNG_HAVE_IDAT)
|
||||
png_push_have_info(png_ptr, info_ptr);
|
||||
|
||||
/* Is it the chunk after the last IDAT chunk? */
|
||||
else if (((mode ^ png_ptr->mode) & PNG_AFTER_IDAT) != 0)
|
||||
png_ptr->process_mode = png_check_bits(png_ptr,
|
||||
(png_ptr->process_mode << 4) + png_read_end_IDAT, 8);
|
||||
}
|
||||
|
||||
/* What we do with the incoming data depends on what we were previously
|
||||
* doing before we ran out of data...
|
||||
*/
|
||||
static void
|
||||
png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
switch (png_ptr->process_mode & 0xf)
|
||||
{
|
||||
case png_read_signature:
|
||||
png_push_read_signature(png_ptr, info_ptr);
|
||||
return;
|
||||
|
||||
case png_read_chunk_header:
|
||||
png_push_read_chunk_header(png_ptr, info_ptr);
|
||||
return;
|
||||
|
||||
case png_read_chunk_skip:
|
||||
png_push_crc_finish(png_ptr);
|
||||
return;
|
||||
|
||||
case png_read_chunk_unknown:
|
||||
PNG_PUSH_SAVE_BUFFER_IF_FULL
|
||||
png_push_read_unknown(png_ptr, info_ptr);
|
||||
return;
|
||||
|
||||
case png_read_chunk_process_all:
|
||||
PNG_PUSH_SAVE_BUFFER_IF_FULL
|
||||
png_handle_chunk(png_ptr, info_ptr);
|
||||
|
||||
if (png_ptr->mode & PNG_HAVE_IEND)
|
||||
{
|
||||
png_ptr->process_mode = png_read_done;
|
||||
png_push_have_end(png_ptr, info_ptr);
|
||||
png_ptr->buffer_size = 0;
|
||||
}
|
||||
|
||||
else
|
||||
png_ptr->process_mode = png_read_chunk_header;
|
||||
return;
|
||||
|
||||
case png_read_chunk_process_part:
|
||||
debug(png_ptr->chunk_name == png_IDAT &&
|
||||
(png_ptr->mode & PNG_HAVE_IDAT) &&
|
||||
!(png_ptr->mode & PNG_AFTER_IDAT));
|
||||
|
||||
if (png_ptr->zowner == 0 && !png_ptr->zstream_ended) /* first time */
|
||||
png_read_start_IDAT(png_ptr);
|
||||
|
||||
png_push_read_IDAT(png_ptr);
|
||||
return;
|
||||
|
||||
case png_read_end_IDAT:
|
||||
png_push_finish_IDAT(png_ptr);
|
||||
return;
|
||||
|
||||
case png_read_done:
|
||||
png_app_error(png_ptr, "read beyond end of stream");
|
||||
png_ptr->buffer_size = 0;
|
||||
return;
|
||||
|
||||
default:
|
||||
impossible("invalid process mode");
|
||||
}
|
||||
}
|
||||
|
||||
void PNGAPI
|
||||
png_process_data(png_structrp png_ptr, png_inforp info_ptr,
|
||||
png_bytep buffer, png_size_t buffer_size)
|
||||
{
|
||||
if (png_ptr == NULL || info_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_push_restore_buffer(png_ptr, buffer, buffer_size);
|
||||
|
||||
while (png_ptr->buffer_size)
|
||||
png_process_some_data(png_ptr, info_ptr);
|
||||
}
|
||||
|
||||
void PNGAPI
|
||||
png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
|
||||
png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
|
||||
png_progressive_end_ptr end_fn)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->info_fn = info_fn;
|
||||
png_ptr->row_fn = row_fn;
|
||||
png_ptr->end_fn = end_fn;
|
||||
|
||||
png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_get_progressive_ptr(png_const_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
return png_ptr->io_ptr;
|
||||
}
|
||||
#endif /* PROGRESSIVE_READ */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,114 +0,0 @@
|
||||
|
||||
/* pngrio.c - functions for data input
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
* This file provides a location for all input. Users who need
|
||||
* special handling are expected to write a function that has the same
|
||||
* arguments as this and performs a similar function, but that possibly
|
||||
* has a different input method. Note that you shouldn't change this
|
||||
* function, but rather write a replacement function and then make
|
||||
* libpng use it at run time with png_set_read_fn(...).
|
||||
*/
|
||||
|
||||
#include "pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_pngrio
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* Read the data from whatever input you are using. The default routine
|
||||
* reads from a file pointer. Note that this routine sometimes gets called
|
||||
* with very small lengths, so you should implement some kind of simple
|
||||
* buffering if you are using unbuffered reads. This should never be asked
|
||||
* to read more than 64K on a 16 bit machine.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_read_data(png_structrp png_ptr, png_voidp data, png_size_t length)
|
||||
{
|
||||
png_debug1(4, "reading %d bytes", (int)length);
|
||||
|
||||
/* This was guaranteed by prior versions of libpng, so app callbacks may
|
||||
* assume it even though it isn't documented to be the case.
|
||||
*/
|
||||
debug(length > 0U);
|
||||
|
||||
if (png_ptr->rw_data_fn != NULL)
|
||||
png_ptr->rw_data_fn(png_ptr, png_voidcast(png_bytep,data), length);
|
||||
|
||||
else
|
||||
png_app_error(png_ptr, "No read function");
|
||||
}
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
/* This is the function that does the actual reading of data. If you are
|
||||
* not reading from a standard C stream, you should create a replacement
|
||||
* read_data function and use it at run time with png_set_read_fn(), rather
|
||||
* than changing the library.
|
||||
*/
|
||||
void PNGCBAPI
|
||||
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_size_t check;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
|
||||
* instead of an int, which is what fread() actually returns.
|
||||
*/
|
||||
check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Read Error");
|
||||
}
|
||||
#endif /* STDIO */
|
||||
|
||||
/* This function allows the application to supply a new input function
|
||||
* for libpng if standard C streams aren't being used.
|
||||
*
|
||||
* This function takes as its arguments:
|
||||
*
|
||||
* png_ptr - pointer to a png input data structure
|
||||
*
|
||||
* io_ptr - pointer to user supplied structure containing info about
|
||||
* the input functions. May be NULL.
|
||||
*
|
||||
* read_data_fn - pointer to a new input function that takes as its
|
||||
* arguments a pointer to a png_struct, a pointer to
|
||||
* a location where input data can be stored, and a 32-bit
|
||||
* unsigned int that is the number of bytes to be read.
|
||||
* To exit and output any fatal error messages the new write
|
||||
* function should call png_error(png_ptr, "Error msg").
|
||||
* May be NULL, in which case libpng's default function will
|
||||
* be used.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr read_data_fn)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
if (!png_ptr->read_struct)
|
||||
{
|
||||
png_app_error(png_ptr, "cannot set a read function on a write struct");
|
||||
return;
|
||||
}
|
||||
|
||||
if (read_data_fn == NULL)
|
||||
{
|
||||
png_app_error(png_ptr, "API change: png_set_read_fn requires a function");
|
||||
return;
|
||||
}
|
||||
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
png_ptr->rw_data_fn = read_data_fn;
|
||||
}
|
||||
#endif /* READ */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,777 +0,0 @@
|
||||
|
||||
/* pngstruct.h - header file for PNG reference library
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* The structure that holds the information to read and write PNG files.
|
||||
* The only people who need to care about what is inside of this are the
|
||||
* people who will be modifying the library for their own special needs.
|
||||
* It should NOT be accessed directly by an application.
|
||||
*/
|
||||
|
||||
#ifndef PNGSTRUCT_H
|
||||
#define PNGSTRUCT_H
|
||||
/* zlib.h defines the structure z_stream, an instance of which is included
|
||||
* in this structure and is required for decompressing the LZ compressed
|
||||
* data in PNG files.
|
||||
*/
|
||||
#ifndef ZLIB_CONST
|
||||
/* We must ensure that zlib uses 'const' in declarations. */
|
||||
# define ZLIB_CONST
|
||||
#endif /* !ZLIB_CONST */
|
||||
|
||||
#include PNG_ZLIB_HEADER
|
||||
|
||||
#ifdef const
|
||||
/* zlib.h sometimes #defines const to nothing, undo this. */
|
||||
# undef const
|
||||
#endif /* const */
|
||||
|
||||
/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
|
||||
* with older builds.
|
||||
*/
|
||||
#if ZLIB_VERNUM < 0x1260
|
||||
# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
|
||||
# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
|
||||
#else /* ZLIB_VERNUM >= 0x1260 */
|
||||
# define PNGZ_MSG_CAST(s) (s)
|
||||
# define PNGZ_INPUT_CAST(b) (b)
|
||||
#endif /* ZLIB_VERNUM >= 0x1260 */
|
||||
|
||||
/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
|
||||
* can handle at once. This type need be no larger than 16 bits (so maximum of
|
||||
* 65535), this define allows us to discover how big it is, but limited by the
|
||||
* maximum for size_t. The value can be overridden in a library build (pngusr.h,
|
||||
* or set it in CPPFLAGS) and it works to set it to a considerably lower value
|
||||
* (e.g. 255 works). A lower value may help memory usage (slightly) and may
|
||||
* even improve performance on some systems (and degrade it on others.)
|
||||
*/
|
||||
#ifndef ZLIB_IO_MAX
|
||||
# ifdef __COVERITY__
|
||||
# define ZLIB_IO_MAX ((uInt)255U) /* else COVERITY whines */
|
||||
# else /* !COVERITY */
|
||||
# define ZLIB_IO_MAX ((uInt)-1)
|
||||
# endif /* !COVERITY */
|
||||
#endif /* !ZLIB_IO_MAX */
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
/* The write compression control (allocated on demand).
|
||||
* TODO: use this for the read state too.
|
||||
*/
|
||||
typedef struct png_zlib_state *png_zlib_statep;
|
||||
#endif /* WRITE */
|
||||
|
||||
/* Colorspace support; structures used in png_struct, png_info and in internal
|
||||
* functions to hold and communicate information about the color space.
|
||||
*
|
||||
* PNG_COLORSPACE_SUPPORTED is only required if the application will perform
|
||||
* colorspace corrections, otherwise all the colorspace information can be
|
||||
* skipped and the size of libpng can be reduced (significantly) by compiling
|
||||
* out the colorspace support.
|
||||
*/
|
||||
#ifdef PNG_COLORSPACE_SUPPORTED
|
||||
/* The chromaticities of the red, green and blue colorants and the chromaticity
|
||||
* of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
|
||||
*/
|
||||
typedef struct png_xy
|
||||
{
|
||||
png_fixed_point redx, redy;
|
||||
png_fixed_point greenx, greeny;
|
||||
png_fixed_point bluex, bluey;
|
||||
png_fixed_point whitex, whitey;
|
||||
} png_xy;
|
||||
|
||||
/* The same data as above but encoded as CIE XYZ values. When this data comes
|
||||
* from chromaticities the sum of the Y values is assumed to be 1.0
|
||||
*/
|
||||
typedef struct png_XYZ
|
||||
{
|
||||
png_fixed_point red_X, red_Y, red_Z;
|
||||
png_fixed_point green_X, green_Y, green_Z;
|
||||
png_fixed_point blue_X, blue_Y, blue_Z;
|
||||
} png_XYZ;
|
||||
#endif /* COLORSPACE */
|
||||
|
||||
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
/* A colorspace is all the above plus, potentially, profile information;
|
||||
* however at present libpng does not use the profile internally so it is only
|
||||
* stored in the png_info struct (if iCCP is supported.) The rendering intent
|
||||
* is retained here and is checked.
|
||||
*
|
||||
* The file gamma encoding information is also stored here and gamma correction
|
||||
* is done by libpng, whereas color correction must currently be done by the
|
||||
* application.
|
||||
*/
|
||||
typedef struct png_colorspace
|
||||
{
|
||||
#ifdef PNG_GAMMA_SUPPORTED
|
||||
png_fixed_point gamma; /* File gamma */
|
||||
#endif /* GAMMA */
|
||||
|
||||
#ifdef PNG_COLORSPACE_SUPPORTED
|
||||
png_xy end_points_xy; /* End points as chromaticities */
|
||||
png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
|
||||
png_uint_16 rendering_intent; /* Rendering intent of a profile */
|
||||
#endif /* COLORSPACE */
|
||||
|
||||
/* Flags are always defined to simplify the code. */
|
||||
png_uint_16 flags; /* As defined below */
|
||||
} png_colorspace, * PNG_RESTRICT png_colorspacerp;
|
||||
|
||||
typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
|
||||
|
||||
/* General flags for the 'flags' field */
|
||||
#define PNG_COLORSPACE_HAVE_GAMMA 0x0001U
|
||||
#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002U
|
||||
#define PNG_COLORSPACE_HAVE_INTENT 0x0004U
|
||||
#define PNG_COLORSPACE_FROM_gAMA 0x0008U
|
||||
#define PNG_COLORSPACE_FROM_cHRM 0x0010U
|
||||
#define PNG_COLORSPACE_FROM_sRGB 0x0020U
|
||||
#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040U
|
||||
#define PNG_COLORSPACE_MATCHES_sRGB 0x0080U /* exact match on profile */
|
||||
#define PNG_COLORSPACE_RGB_TO_GRAY_SET 0x0100U /* user specified coeffs */
|
||||
#define PNG_COLORSPACE_INVALID 0x8000U
|
||||
#define PNG_COLORSPACE_CANCEL(flags) (0xffffU - (flags))
|
||||
#endif /* COLORSPACE || GAMMA */
|
||||
|
||||
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
/***************************** READ and WRITE TRANSFORMS ***********************
|
||||
* These structures are used in pngrtran.c, pngwtran.c and pngtrans.c to hold
|
||||
* information about transforms in progress. This mechanism was introduced in
|
||||
* libpng 1.7.0 to ensure reliable transform code and to fix multiple bugs in
|
||||
* the pre-1.7 transform handling.
|
||||
*
|
||||
* Prior to 1.7.0 the internal transform routines took a png_row_infop, like the
|
||||
* user transform function, but without the png_ptr because it was never used.
|
||||
* In 1.7.0 a separate internal structure is used in place of this to allow both
|
||||
* future development to change the structure.
|
||||
*
|
||||
* The values in this structure will normally be changed by transformation
|
||||
* implementations.
|
||||
***************************** READ and WRITE TRANSFORMS **********************/
|
||||
typedef struct
|
||||
{
|
||||
png_structp png_ptr; /* png_struct for error handling and some
|
||||
* transform parameters. May be aliased.
|
||||
*/
|
||||
png_const_voidp sp; /* Source; the input row. */
|
||||
png_voidp dp; /* Output buffer for the transformed row,
|
||||
* this may be the same as sp.
|
||||
*/
|
||||
/* If the row is changed the tranform routine must write the result to
|
||||
* dp[] and set sp to dp, otherwise it must not write to dp and must leave
|
||||
* sp unchanged. dp[] and sp[] are both 'malloc' aligned; i.e. they have
|
||||
* the system alignment, so the data can be read as any valid ANSI-C
|
||||
* type.
|
||||
*/
|
||||
png_uint_32 width; /* width of row */
|
||||
# ifdef PNG_READ_GAMMA_SUPPORTED
|
||||
png_fixed_point gamma; /* Current gamma of the row data */
|
||||
/* When a row is being transformed this contains the current gamma of the
|
||||
* data if known. During initialization the value is used to accumulate
|
||||
* information for png_struct::row_gamma in the first step,
|
||||
* PNG_TC_INIT_FORMAT, then used to insert the correct gamma transforms
|
||||
* during PNG_TC_INIT_FINAL. The field is only used on read; write
|
||||
* transforms do not modify the gamma of the data.
|
||||
*/
|
||||
# endif /* READ_GAMMA */
|
||||
unsigned int format; /* As pngstruct::row_format below */
|
||||
unsigned int range; /* Count of range transforms */
|
||||
# define PNG_TC_CHANNELS(tc) PNG_FORMAT_CHANNELS((tc).format)
|
||||
unsigned int bit_depth; /* bit depth of row */
|
||||
png_byte sBIT_R;
|
||||
png_byte sBIT_G;
|
||||
png_byte sBIT_B;
|
||||
png_byte sBIT_A; /* Signnificant bits in the row channels. */
|
||||
/* The above four values are initially set to the number of bits significant
|
||||
* in the input PNG data, R/G/B are set to the same (gray) value for
|
||||
* grayscale input. All values are set to the bit depth if there is no sBIT
|
||||
* chunk, if there is no alpha channel sBIT_A is set to the bit depth.
|
||||
*
|
||||
* When any potentially spurious bits have been cleared PNG_INFO_sBIT will be
|
||||
* set in invalid_info. From this point on the above values record the
|
||||
* approximate number of bits of accuracy in the channels and the lower bits
|
||||
* should be preserved; they potentially contain useful information.
|
||||
*/
|
||||
# define PNG_TC_PIXEL_DEPTH(tc) (PNG_TC_CHANNELS(tc) * (tc).bit_depth)
|
||||
# define PNG_TC_ROWBYTES(tc) PNG_ROWBYTES(PNG_TC_PIXEL_DEPTH(tc), (tc).width)
|
||||
unsigned int invalid_info; /* PNG_INFO_* for invalidated chunks */
|
||||
unsigned int cost; /* Cache cost */
|
||||
# define PNG_CACHE_COST_LIMIT 0x100U
|
||||
/* This is a runtime structure, so size doesn't matter much, and it helps
|
||||
* code reliability to use real member names here. Feel free to experiment
|
||||
* with integer values rather than bitfields.
|
||||
*/
|
||||
unsigned int init :2; /* 0 for processing, non zero for init: */
|
||||
# define PNG_TC_INIT_FORMAT 0x01U /* Initialization step 1: just set 'format',
|
||||
* 'bit_depth' and 'gamma' to the output
|
||||
* values iff the transform corresponds to
|
||||
* a user requested change to those values.
|
||||
*/
|
||||
# define PNG_TC_INIT_FINAL 0x03U /* Initialization step 2; set the 'format'
|
||||
* 'bit_depth' and 'gamma' to the values the
|
||||
* transform will actually produce (which
|
||||
* need not be the same as the above).
|
||||
*/
|
||||
/* During initialization 'init' must be set and sp and dp may be NULL. If
|
||||
* neither flag is set sp and dp must be non-NULL.
|
||||
*
|
||||
* When the transform runs it must update 'format', 'bit_depth' and 'gamma'
|
||||
* to the values previously reported during PNG_TC_INIT_FINAL; not doing so
|
||||
* may result in an affirm from a later transform.
|
||||
*/
|
||||
unsigned int caching :1; /* The color values are being used to
|
||||
* generate a cache of the transforms.
|
||||
*/
|
||||
unsigned int palette :1; /* The values come from a PNG palette and
|
||||
* the palette will not be expanded. The
|
||||
* CACHE flag must be set too. A
|
||||
* transform which causes the palette to
|
||||
* be expanded must clear this flag.
|
||||
*/
|
||||
#if 0 /* NYI */
|
||||
unsigned int interchannel:1; /* Set by a transform that combines two or
|
||||
* more channels together; for example
|
||||
* alpha composition or RGB to gray.
|
||||
*/
|
||||
#endif /* NYI */
|
||||
unsigned int channel_add :1; /* A channel (alpha/filler) was added */
|
||||
unsigned int strip_alpha :1; /* Set if the alpha channel will be
|
||||
* stripped on read, this also prevents
|
||||
* the tRNS chunk being expanded. Only
|
||||
* some transforms check this, depending
|
||||
* on the handling order and checks in
|
||||
* pre-1.7 versions.
|
||||
*/
|
||||
unsigned int expand_tRNS :1; /* Set if the tRNS chunk should be
|
||||
* expanded (ignored if read_strip_alpha
|
||||
* is set). If this is *not* set
|
||||
* transforms which do not use alpha/tRNS
|
||||
* but would invalidate it (such as
|
||||
* simple gamma correction) will simply
|
||||
* mark the tRNS info as invalid.
|
||||
*/
|
||||
unsigned int transparent_alpha :1; /* Indicates that the alpha channel
|
||||
* consists entirely of opaque (1.0 alpha)
|
||||
* or completely transparent (0.0 alpha)
|
||||
* pixels. Set when tRNS is expanded to
|
||||
* alpha.
|
||||
*/
|
||||
unsigned int optimized_alpha :1; /* Meaningful only when bit_depth is
|
||||
* 16 and gamma is 1 or unknown (0).
|
||||
* Indicates that pixels which are opaque
|
||||
* (alpha 1.0) have not been expanded to
|
||||
* 16-bit linear; instead these pixels
|
||||
* are encoded in the final format in
|
||||
* png_struct::row_bit_depth and
|
||||
* png_struct::row_gamma. This will
|
||||
* invariably match the file format.
|
||||
*/
|
||||
} png_transform_control, *png_transform_controlp;
|
||||
|
||||
typedef const png_transform_control *png_const_transform_controlp;
|
||||
typedef const png_row_info *png_const_row_infop;
|
||||
|
||||
typedef struct png_transform *png_transformp; /* Forward declaration */
|
||||
typedef void (*png_transform_free_fn)(/* Function to free a transform */
|
||||
png_const_structrp png_ptr,
|
||||
png_transformp transform); /* pointer to this transform */
|
||||
/* This function need not exist in a transform, it must free all the data
|
||||
* allocated within the transform but not the transform itself. It is called
|
||||
* from png_transform_free.
|
||||
*/
|
||||
typedef void (*png_transform_fn)(/* Function to implement a transform */
|
||||
png_transformp *transform, /* pointer to this transform */
|
||||
png_transform_controlp control); /* row information */
|
||||
/* The transform function has two modes of operation:
|
||||
*
|
||||
* 1) Initialization. The list of transforms is processed from the start to
|
||||
* the end and each function is called with one of hte PNG_TC_INIT_ flags
|
||||
* set in control->flags, control->dp and control->sp may be NULL.
|
||||
*
|
||||
* For read the control structure contains the input row format and bit
|
||||
* depth, the transform function changes this to represent what the
|
||||
* transform will produce when it runs.
|
||||
*
|
||||
* For write the control structure contains the *required* output format
|
||||
* and bit depth. The transform function changes this to the values that
|
||||
* it needs to produce the required values.
|
||||
*
|
||||
* In both cases the transform function may update the 'fn' function to a
|
||||
* new function to perform the desired transform; this allows considerable
|
||||
* optimization on multi-row images.
|
||||
*
|
||||
* In both cases the caller considers the pixel bit depth changes and
|
||||
* records the maximum required so that it can allocate a suitably sized
|
||||
* buffer.
|
||||
*
|
||||
* 2) Execution.
|
||||
*
|
||||
* In the read case the transforms are processed in the stored order and
|
||||
* must transform the row data appropriately *and* update the bit depth
|
||||
* and format as before.
|
||||
*
|
||||
* In the write case the transforms are called in the reverse order and
|
||||
* the input bit depth and format should match the required values.
|
||||
*
|
||||
* It is valid during initialization for the transform function to push
|
||||
* another transform into the list in either the read or the write case if
|
||||
* the transform cannot handle (read) or produce (write) the required format. * The transform pushes another transform into the list ahead of itself (at
|
||||
* *transform) and runs that initialization; when control is returned to the
|
||||
* caller the caller will re-run the transform initialization.
|
||||
*
|
||||
* It is also valid (during initialization) to push new transforms onto the
|
||||
* list, just so long as the order of the transform is greater than the
|
||||
* current transform (so that the caller will still call the new transform
|
||||
* initialization.)
|
||||
*
|
||||
* In the write case the user transform callback might still end up producing
|
||||
* an unexpected format, but at present this is unavoidable; the libpng API
|
||||
* is extremely inconsistent in how a user transform reports the changes it
|
||||
* made.
|
||||
*
|
||||
* TODO: fix this, probably with an API change in 1.7.0
|
||||
*/
|
||||
typedef struct png_transform /* Linked list of transform functions */
|
||||
{
|
||||
png_transformp next; /* Next transform in the list */
|
||||
png_transform_fn fn; /* Function to implement the transform */
|
||||
png_transform_free_fn free; /* Free allocated data, normally NULL */
|
||||
unsigned int order; /* Order of the transform in the list. */
|
||||
unsigned int size; /* Size of this structure (max 65535) */
|
||||
png_uint_32 args; /* Optional transform arguments. */
|
||||
} png_transform;
|
||||
#endif /* TRANSFORM_MECH */
|
||||
|
||||
/* Action to take on CRC errors (four values) */
|
||||
typedef enum
|
||||
{
|
||||
crc_error_quit = PNG_CRC_ERROR_QUIT-1,
|
||||
crc_warn_discard = PNG_CRC_WARN_DISCARD-1,
|
||||
crc_warn_use = PNG_CRC_WARN_USE-1,
|
||||
crc_quiet_use = PNG_CRC_QUIET_USE-1
|
||||
} png_crc_action;
|
||||
|
||||
struct png_struct_def
|
||||
{
|
||||
/* Rearranged in libpng 1.7 to attempt to lessen padding; in general
|
||||
* (char), (short), (int) and pointer types are kept separate; however
|
||||
* associated members under the control of the same #define are still
|
||||
* together.
|
||||
*/
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
/* jmp_buf can have very high alignment requirements on some systems, so put
|
||||
* it first (the other setjmp members are later as they are infrequently
|
||||
* accessed.)
|
||||
*/
|
||||
jmp_buf jmp_buf_local;
|
||||
#endif /* SETJMP */
|
||||
|
||||
/* Next the frequently accessed fields. Many processors perform arithmetic
|
||||
* in the address pipeline, but frequently the amount of addition or
|
||||
* subtraction is limited. By putting these fields at the head of png_struct
|
||||
* the hope is that such processors will generate code that is both smaller
|
||||
* and faster.
|
||||
*/
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
png_colorp palette; /* palette from the input file */
|
||||
#endif /* READ */
|
||||
#ifdef PNG_READ_tRNS_SUPPORTED
|
||||
png_bytep trans_alpha; /* alpha values for paletted files */
|
||||
#endif /* READ_tRNS */
|
||||
|
||||
png_uint_32 width; /* width of image in pixels */
|
||||
png_uint_32 height; /* height of image in pixels */
|
||||
png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
png_uint_32 chunk_length; /* Length (possibly remaining) in said chunk. */
|
||||
#endif /* READ */
|
||||
png_uint_32 crc; /* current chunk CRC value */
|
||||
|
||||
unsigned int mode :6; /* where we are in the PNG file */
|
||||
unsigned int read_struct :1; /* this is a read (not write) struct */
|
||||
unsigned int num_palette :9; /* number of color entries in palette */
|
||||
#ifdef PNG_READ_tRNS_SUPPORTED
|
||||
unsigned int num_trans :9; /* number of transparency values */
|
||||
unsigned int transparent_palette :1; /* if they are all 0 or 255 */
|
||||
#endif /* READ_tRNS */
|
||||
#ifdef PNG_PALETTE_MAX_SUPPORTED
|
||||
unsigned int palette_index_max :8; /* maximum palette index in IDAT */
|
||||
unsigned int palette_index_check :2; /* one of the following: */
|
||||
# define PNG_PALETTE_CHECK_DEFAULT 0U
|
||||
# define PNG_PALETTE_CHECK_OFF 1U
|
||||
# define PNG_PALETTE_CHECK_ON 2U
|
||||
unsigned int palette_index_have_max :1; /* max is being set */
|
||||
unsigned int palette_index_check_issued :1; /* error message output */
|
||||
#endif /* PALETTE_MAX */
|
||||
#ifdef PNG_READ_tRNS_SUPPORTED
|
||||
png_color_16 trans_color; /* transparent color for non-paletted files */
|
||||
#endif /* READ_tRNS */
|
||||
#ifdef PNG_READ_sBIT_SUPPORTED
|
||||
png_color_8 sig_bit; /* significant bits in each channel */
|
||||
#endif /* READ_sBIT */
|
||||
|
||||
/* Single byte values, typically used either to save space or to hold 1-byte
|
||||
* values from the PNG chunk specifications.
|
||||
*/
|
||||
png_byte filter_method; /* file filter type (only non-0 with MNG) */
|
||||
png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
|
||||
png_byte color_type; /* color type of file */
|
||||
png_byte bit_depth; /* bit depth of file */
|
||||
png_byte sig_bytes; /* magic bytes read/written at start of file */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
/* The png_struct colorspace structure is only required on read - on write it
|
||||
* is in (just) the info_struct.
|
||||
*/
|
||||
png_colorspace colorspace;
|
||||
#endif /* COLORSPACE || GAMMA */
|
||||
#endif /* READ */
|
||||
|
||||
/* Transform handling */
|
||||
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
png_transformp transform_list; /* List of transformation to perform. */
|
||||
#endif /* TRANSFORM_MECH */
|
||||
|
||||
/* ROW BUFFERS and CONTROL
|
||||
*
|
||||
* Members used for image row compression (write) or decompression (read).
|
||||
* filter byte (which is in next_filter.) All fields are only used during
|
||||
* IDAT processing and start of 0.
|
||||
*/
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
png_bytep row_buffer; /* primary row buffer */
|
||||
#if (defined(PNG_PROGRESSIVE_READ_SUPPORTED) ||\
|
||||
defined(PNG_READ_INTERLACING_SUPPORTED)) &&\
|
||||
defined(PNG_TRANSFORM_MECH_SUPPORTED)
|
||||
png_bytep transformed_row; /* pointer to the transformed row, if
|
||||
* required. May point to row_buffer.
|
||||
*/
|
||||
#endif /* (PROGRESSIVE_READ || READ_INTERLACING) && TRANSFORM_MECH */
|
||||
|
||||
png_alloc_size_t row_bytes_read; /* Total read in row */
|
||||
#endif /* READ */
|
||||
|
||||
png_uint_32 row_number; /* current row in pass */
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
#ifdef PNG_READ_GAMMA_SUPPORTED
|
||||
png_fixed_point row_gamma; /* Gamma of final output */
|
||||
#if 0 /* NYI */
|
||||
unsigned int gamma_accuracy;
|
||||
/* LINEAR gamma cache table size (in bits) times 100; for non-linear
|
||||
* tables the value used is gamma_accuracy/gamma where 'gamma' is the
|
||||
* encoding value of the data (typically less than 1).
|
||||
*
|
||||
* default: PNG_DEFAULT_GAMMA_ACCURACY (665)
|
||||
*/
|
||||
#endif /* NYI */
|
||||
png_uint_16 gamma_threshold;
|
||||
/* Gamma threshold value as a fixed-point value in the range 0..1; the
|
||||
* threshold at or below which gamma correction is skipped. '0' forces
|
||||
* gamma correction even when there is none because the input and output
|
||||
* gammas are equal.
|
||||
*
|
||||
* default: PNG_GAMMA_THRESHOLD_FIXED (153)
|
||||
*/
|
||||
#endif /* READ_GAMMA */
|
||||
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
|
||||
unsigned int invalid_info; /* PNG_INFO_* for invalidated chunks */
|
||||
unsigned int palette_updated:1; /* png_struct::palette changed */
|
||||
#endif /* READ_TRANSFORMS */
|
||||
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
unsigned int read_started :1; /* at least one call to png_read_row */
|
||||
#endif /* SEQUENTIAL_READ */
|
||||
/* The next field is just used by the read IDAT process functions to store
|
||||
* the state of IDAT processing; they should not be altered or used by other
|
||||
* functions.
|
||||
*/
|
||||
unsigned int row_state :2; /* state of row parsing (internal) */
|
||||
#endif /* READ */
|
||||
|
||||
#if defined (PNG_READ_INTERLACING_SUPPORTED) ||\
|
||||
defined (PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
unsigned int do_interlace :1; /* libpng handles the interlace */
|
||||
# endif /* R/W INTERLACING */
|
||||
|
||||
unsigned int pass :3; /* current (interlace) pass (0 - 6) */
|
||||
|
||||
/* The following fields are set by png_row_init to the pixel depths of the
|
||||
* pixels at various states. If transforms are not supported they will
|
||||
* always be the same value:
|
||||
*
|
||||
* READ WRITE
|
||||
* input: PNG From application
|
||||
* output: To application PNG
|
||||
* max: Largest in transform
|
||||
*/
|
||||
unsigned int row_input_pixel_depth :8;
|
||||
unsigned int row_output_pixel_depth :8;
|
||||
unsigned int row_max_pixel_depth :8;
|
||||
|
||||
# define PNG_RF_BITS 9 /* Number of bits required for the row format (below) */
|
||||
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
/* The following fields describe the format of the user row; the output on
|
||||
* read or the input on write, and give the maximum pixel depth, which
|
||||
* controls the row buffer allocation size (row_allocated_bytes) above.
|
||||
*/
|
||||
unsigned int row_range :3; /* range error count */
|
||||
unsigned int row_bit_depth :6; /* bits per channel (up to 32) */
|
||||
unsigned int row_format:PNG_RF_BITS;/* format of output(R)/input(W) row: */
|
||||
/* PNG_FORMAT_FLAG_ALPHA 0x01U format with an alpha channel
|
||||
* PNG_FORMAT_FLAG_COLOR 0x02U color format: otherwise grayscale
|
||||
* PNG_FORMAT_FLAG_LINEAR 0x04U NOT used (informational)
|
||||
* PNG_FORMAT_FLAG_COLORMAP 0x08U image data is color-mapped
|
||||
* PNG_FORMAT_FLAG_BGR 0x10U BGR colors, else order is RGB
|
||||
* PNG_FORMAT_FLAG_AFIRST 0x20U alpha channel comes first *
|
||||
* PNG_FORAMT_FLAG_AFILLER 0x40U The 'alpha' channel is a filler:
|
||||
* PNG_FORMAT_FLAG_ALPHA is set however the value in the alpha channel
|
||||
* is not an alpha value and (therefore) cannot be used for alpha
|
||||
* computations, it is just a filler value. PNG_COLOR_TYPE_FROM_FORMAT
|
||||
* will return a color type *without* PNG_COLOR_MASK_ALPHA, however
|
||||
* PNG_FORMAT_CHANNELS will return the correct number, including the
|
||||
* filler channel.
|
||||
* PNG_FORMAT_FLAG_SWAPPED 0x80U bytes or bits swapped:
|
||||
* When the bit depth is 16 this means that the bytes within the
|
||||
* components have been swapped, when the bit depth is less than 8
|
||||
* it means the pixels within the bytes have been swapped. It should
|
||||
* not be set for 8-bit compononents (it is meaningless).
|
||||
* PNG_FORMAT_FLAG_RANGE 0x100U component range not 0..bit-depth:
|
||||
* Low-bit-depth grayscale components have been unpacked into bytes
|
||||
* without scaling, or RGB[A] pixels have been shifted back to the
|
||||
* significant-bit range from the sBIT chunk or channels (currently
|
||||
* alpha or gray) have been inverted.
|
||||
* PNG_FORMAT_FLAG_INVALID NOT STORED HERE
|
||||
*/
|
||||
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
unsigned int info_format:PNG_RF_BITS;
|
||||
/* This field is used to validate the png_info used to write the
|
||||
* IHDR. This is a new check in 1.7.0; previously it was possible to pass
|
||||
* a png_info from a png_read with the read tranform information in the
|
||||
* format having manually removed the required transforms from the rows
|
||||
* passed to png_write_row.
|
||||
*/
|
||||
#endif /* WRITE_TRANSFORMS */
|
||||
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
unsigned int write_invert_alpha :1;
|
||||
/* This indicates the png_set_invert_alpha was called, it is used by the
|
||||
* write code to implement the transform without needing to run the whole
|
||||
* transform mechanism on the PNG palette data.
|
||||
*/
|
||||
#endif /* WRITE_INVERT_ALPHA */
|
||||
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||
unsigned int rgb_to_gray_status :1;
|
||||
/* If set an RGB pixel was encountered by the RGB to gray transform
|
||||
* wherein !(r==g==b).
|
||||
*/
|
||||
#endif /* RGB_TO_GRAY */
|
||||
#endif /* TRANSFORM_MECH */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
/* These, and IDAT_size below, control how much input and output (at most) is
|
||||
* available to zlib during read decompression.
|
||||
*/
|
||||
png_alloc_size_t read_buffer_size; /* current size of the buffer */
|
||||
#endif /* READ */
|
||||
|
||||
#if defined(PNG_SEQUENTIAL_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
png_uint_32 IDAT_size; /* limit on IDAT read and write IDAT size */
|
||||
#endif /* SEQUENTIAL_READ || WRITE */
|
||||
|
||||
/* ERROR HANDLING */
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
|
||||
png_longjmp_ptr longjmp_fn; /* setjmp non-local goto function. */
|
||||
size_t jmp_buf_size; /* size of *jmp_buf_ptr, if allocated */
|
||||
#endif /* SETJMP */
|
||||
|
||||
/* Error/warning callbacks */
|
||||
png_error_ptr error_fn; /* print an error message and abort */
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
png_error_ptr warning_fn; /* print a warning and continue */
|
||||
#endif /* WARNINGS */
|
||||
png_voidp error_ptr; /* user supplied data for the above */
|
||||
|
||||
/* MEMORY ALLOCATION */
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
png_malloc_ptr malloc_fn; /* allocate memory */
|
||||
png_free_ptr free_fn; /* free memory */
|
||||
png_voidp mem_ptr; /* user supplied data for the above */
|
||||
#endif /* USER_MEM */
|
||||
|
||||
/* IO and BASIC READ/WRITE SUPPORT */
|
||||
png_voidp io_ptr; /* user supplied data for IO callbacks */
|
||||
png_rw_ptr rw_data_fn; /* read/write some bytes (must succeed) */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
png_read_status_ptr read_row_fn; /* called after each row is decoded */
|
||||
png_bytep read_buffer; /* buffer for reading chunk data */
|
||||
|
||||
/* During read the following array is set up to point to the appropriate
|
||||
* un-filter function, this allows per-image and per-processor optimization.
|
||||
*/
|
||||
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_alloc_size_t row_bytes,
|
||||
unsigned int bpp, png_bytep row, png_const_bytep prev_row,
|
||||
png_const_bytep prev_pixels);
|
||||
#endif /* READ */
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
png_write_status_ptr write_row_fn; /* called after each row is encoded */
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
png_flush_ptr output_flush_fn; /* Function for flushing output */
|
||||
#endif /* WRITE_FLUSH */
|
||||
#endif /* WRITE */
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
png_uint_32 user_width_max; /* Maximum width on read */
|
||||
png_uint_32 user_height_max; /* Maximum height on read */
|
||||
/* Total memory that a single zTXt, sPLT, iTXt, iCCP, or unknown chunk
|
||||
* can occupy when decompressed. 0 means unlimited. This field is a counter
|
||||
* - it is decremented as memory is allocated.
|
||||
*/
|
||||
png_alloc_size_t user_chunk_malloc_max;
|
||||
#endif /* SET_USER_LIMITS */
|
||||
#ifdef PNG_USER_LIMITS_SUPPORTED
|
||||
/* limit on total *number* of sPLT, text and unknown chunks that can be
|
||||
* stored. 0 means unlimited. This field is a counter - it is decremented
|
||||
* as chunks are encountered.
|
||||
*/
|
||||
png_uint_32 user_chunk_cache_max;
|
||||
#endif /* USER_LIMITS */
|
||||
|
||||
/* The progressive reader gets passed data and calls application handling
|
||||
* functions when appropriate.
|
||||
*/
|
||||
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
png_progressive_info_ptr info_fn; /* called after header data fully read */
|
||||
png_progressive_row_ptr row_fn; /* called after a row is decoded */
|
||||
png_progressive_end_ptr end_fn; /* called after image is complete */
|
||||
|
||||
/* Progressive read control data */
|
||||
png_bytep save_buffer_ptr; /* current location in save_buffer */
|
||||
png_bytep save_buffer; /* buffer for previously read data */
|
||||
png_bytep current_buffer_ptr; /* current location in current_buffer */
|
||||
|
||||
size_t save_buffer_size; /* amount of data now in save_buffer */
|
||||
size_t save_buffer_max; /* total size of save_buffer */
|
||||
size_t current_buffer_size; /* amount of data now in current_buffer */
|
||||
size_t buffer_size; /* total amount of available input data */
|
||||
|
||||
unsigned int process_mode :8;
|
||||
/* This is one or two four bit codes describing the current state of the
|
||||
* 'push' reader. Normally the low four bits are a state code, however in
|
||||
* some cases this may be pushed to the top four bits and replaced by a
|
||||
* different temporary state code. The value is, in effect, a two entry
|
||||
* stack.
|
||||
*/
|
||||
#endif /* PROGRESSIVE_READ */
|
||||
|
||||
#ifdef PNG_IO_STATE_SUPPORTED
|
||||
png_uint_32 io_state; /* tells the app read/write progress */
|
||||
#endif /* IO_STATE */
|
||||
|
||||
/* UNKNOWN CHUNK HANDLING */
|
||||
/* TODO: this is excessively complicated, there are multiple ways of doing
|
||||
* the same thing. It should be cleaned up, possibly by finding out which
|
||||
* APIs applications really use.
|
||||
*/
|
||||
#ifdef PNG_USER_CHUNKS_SUPPORTED
|
||||
/* General purpose pointer for all user/unknown chunk handling; points to
|
||||
* application supplied data for use in the read_user_chunk_fn callback
|
||||
* (currently there is no write side support - the write side must use the
|
||||
* set_unknown_chunks interface.)
|
||||
*/
|
||||
png_voidp user_chunk_ptr;
|
||||
#endif /* USER_CHUNKS */
|
||||
|
||||
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
/* This is called back from the unknown chunk handling */
|
||||
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
|
||||
#endif /* READ_USER_CHUNKS */
|
||||
|
||||
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
png_uint_32 known_unknown; /* Bit mask of known chunks to be treated as
|
||||
* unknown in the read code.
|
||||
*/
|
||||
#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
png_uint_32 save_unknown; /* Whether to save or skip these chunks:
|
||||
* 'save' is 'known & save', 'skip' is
|
||||
* 'known & ~save'.
|
||||
*/
|
||||
# define png_IDATs_skipped(pp) (((pp)->known_unknown & ~(pp)->save_unknown)&1U)
|
||||
#else /* !SAVE_UNKNOWN_CHUNKS */
|
||||
# define png_IDATs_skipped(pp) ((pp)->known_unknown & 1U)
|
||||
#endif /* !SAVE_UNKNOWN_CHUNKS */
|
||||
#endif /* HANDLE_AS_UNKNOWN */
|
||||
|
||||
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
|
||||
png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
|
||||
* followed by a PNG_HANDLE_* byte */
|
||||
unsigned int unknown_default :2; /* As PNG_HANDLE_* */
|
||||
unsigned int num_chunk_list; /* Number of entries in the list */
|
||||
#endif /* SET_UNKNOWN_CHUNKS */
|
||||
|
||||
/* COMPRESSION AND DECOMPRESSION SUPPORT.
|
||||
*
|
||||
* zlib expects a 'zstream' as the fundamental control structure, it allows
|
||||
* all the parameters to be passed as one pointer.
|
||||
*/
|
||||
png_uint_32 zowner; /* ID (chunk type) of zlib owner, 0 if none */
|
||||
# ifdef PNG_WRITE_SUPPORTED
|
||||
png_zlib_statep zlib_state; /* State of zlib compression */
|
||||
# endif /* WRITE */
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
z_stream zstream; /* decompression structure */
|
||||
unsigned int zstream_ended:1; /* no more zlib output available [read] */
|
||||
unsigned int zstream_error:1; /* zlib error message has been output [read] */
|
||||
# endif /* READ */
|
||||
# ifdef PNG_PROGRESSIVE_READ_SUPPORTED
|
||||
unsigned int zstream_eod :1; /* all the required uncompressed data has been
|
||||
* received; set by the zstream using code for
|
||||
* its own purposes. [progressive read] */
|
||||
# endif /* PROGRESSIVE_READ */
|
||||
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
|
||||
unsigned int benign_error_action :2;
|
||||
unsigned int app_warning_action :2;
|
||||
unsigned int app_error_action :2;
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
unsigned int IDAT_error_action :2;
|
||||
# endif /* READ */
|
||||
# endif /* BENIGN_ERRORS */
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
/* CRC checking actions, one for critical chunks, one for ancillary
|
||||
* chunks.
|
||||
*/
|
||||
unsigned int critical_crc :2;
|
||||
unsigned int ancillary_crc :2;
|
||||
unsigned int current_crc :2; /* Cache of one or other of the above */
|
||||
# endif
|
||||
# ifdef PNG_SET_OPTION_SUPPORTED
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
unsigned int maximum_inflate_window :1U;
|
||||
# endif /* READ */
|
||||
unsigned int skip_sRGB_profile_check :1U;
|
||||
# endif /* SET_OPTION */
|
||||
|
||||
/* MNG SUPPORT */
|
||||
#ifdef PNG_MNG_FEATURES_SUPPORTED
|
||||
unsigned int mng_features_permitted :3;
|
||||
#endif /* MNG_FEATURES */
|
||||
|
||||
/* SCRATCH buffers, used when control returns to the application or a read
|
||||
* loop.
|
||||
*/
|
||||
# ifdef PNG_READ_SUPPORTED
|
||||
png_byte scratch[PNG_ROW_BUFFER_SIZE+16U];
|
||||
# endif /* READ */
|
||||
};
|
||||
#endif /* PNGSTRUCT_H */
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,146 +0,0 @@
|
||||
|
||||
/* pngwio.c - functions for data output
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*
|
||||
* This file provides a location for all output. Users who need
|
||||
* special handling are expected to write functions that have the same
|
||||
* arguments as these and perform similar functions, but that possibly
|
||||
* use different output methods. Note that you shouldn't change these
|
||||
* functions, but rather write replacement functions and then change
|
||||
* them at run time with png_set_write_fn(...).
|
||||
*/
|
||||
|
||||
#include "pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_pngwio
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
|
||||
/* Write the data to whatever output you are using. The default routine
|
||||
* writes to a file pointer. Note that this routine sometimes gets called
|
||||
* with very small lengths, so you should implement some kind of simple
|
||||
* buffering if you are using unbuffered writes. This should never be asked
|
||||
* to write more than 64K on a 16 bit machine.
|
||||
*/
|
||||
|
||||
void /* PRIVATE */
|
||||
png_write_data(png_structrp png_ptr, png_const_voidp data, png_size_t length)
|
||||
{
|
||||
/* This was guaranteed by prior versions of libpng, so app callbacks may
|
||||
* assume it even though it isn't documented to be the case.
|
||||
*/
|
||||
debug(length > 0U);
|
||||
|
||||
/* NOTE: write_data_fn must not change the buffer!
|
||||
* This cast is required because of the API; changing the type of the
|
||||
* callback would require every app to change the callback and that change
|
||||
* would have to be conditional on the libpng version.
|
||||
*/
|
||||
if (png_ptr->rw_data_fn != NULL )
|
||||
png_ptr->rw_data_fn(png_ptr,
|
||||
png_constcast(png_bytep,png_voidcast(png_const_bytep,data)), length);
|
||||
|
||||
else
|
||||
png_app_error(png_ptr, "No write function");
|
||||
}
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
/* This is the function that does the actual writing of data. If you are
|
||||
* not writing to a standard C stream, you should create a replacement
|
||||
* write_data function and use it at run time with png_set_write_fn(), rather
|
||||
* than changing the library.
|
||||
*/
|
||||
void PNGCBAPI
|
||||
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_size_t check;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
check = fwrite(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
# ifdef PNG_STDIO_SUPPORTED
|
||||
void PNGCBAPI
|
||||
png_default_flush(png_structp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
fflush(png_voidcast(png_FILE_p, (png_ptr->io_ptr)));
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This function allows the application to supply new output functions for
|
||||
* libpng if standard C streams aren't being used.
|
||||
*
|
||||
* This function takes as its arguments:
|
||||
* png_ptr - pointer to a png output data structure
|
||||
* io_ptr - pointer to user supplied structure containing info about
|
||||
* the output functions. May be NULL.
|
||||
* write_data_fn - pointer to a new output function that takes as its
|
||||
* arguments a pointer to a png_struct, a pointer to
|
||||
* data to be written, and a 32-bit unsigned int that is
|
||||
* the number of bytes to be written. The new write
|
||||
* function should call png_error(png_ptr, "Error msg")
|
||||
* to exit and output any fatal error messages. May be
|
||||
* NULL, in which case libpng's default function will
|
||||
* be used.
|
||||
* flush_data_fn - pointer to a new flush function that takes as its
|
||||
* arguments a pointer to a png_struct. After a call to
|
||||
* the flush function, there should be no data in any buffers
|
||||
* or pending transmission. If the output method doesn't do
|
||||
* any buffering of output, a function prototype must still be
|
||||
* supplied although it doesn't have to do anything. If
|
||||
* PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
|
||||
* time, output_flush_fn will be ignored, although it must be
|
||||
* supplied for compatibility. May be NULL, in which case
|
||||
* libpng's default function will be used, if
|
||||
* PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
|
||||
* a good idea if io_ptr does not point to a standard
|
||||
* *FILE structure.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
if (png_ptr->read_struct)
|
||||
{
|
||||
png_app_error(png_ptr, "cannot set a write function on a read struct");
|
||||
return;
|
||||
}
|
||||
|
||||
if (write_data_fn == NULL)
|
||||
{
|
||||
png_app_error(png_ptr,
|
||||
"API change: png_set_write_fn requires a function");
|
||||
return;
|
||||
}
|
||||
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
png_ptr->rw_data_fn = write_data_fn;
|
||||
# ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
if (output_flush_fn != NULL)
|
||||
png_ptr->output_flush_fn = output_flush_fn;
|
||||
# else
|
||||
PNG_UNUSED(output_flush_fn)
|
||||
# endif /* WRITE_FLUSH */
|
||||
}
|
||||
#endif /* WRITE */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,148 +0,0 @@
|
||||
|
||||
/* pngwtran.c - transforms the data in a row for PNG writers
|
||||
*
|
||||
* Last changed in libpng 1.7.0 [(PENDING RELEASE)]
|
||||
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#include "pngpriv.h"
|
||||
#define PNG_SRC_FILE PNG_SRC_FILE_pngwtran
|
||||
|
||||
#ifdef PNG_WRITE_PACK_SUPPORTED
|
||||
/* Pack pixels into bytes. */
|
||||
static void
|
||||
png_do_write_pack(png_transformp *transform, png_transform_controlp tc)
|
||||
{
|
||||
png_alloc_size_t rowbytes = PNG_TC_ROWBYTES(*tc);
|
||||
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
|
||||
png_const_bytep ep = png_upcast(png_const_bytep, tc->sp) + rowbytes;
|
||||
png_bytep dp = png_voidcast(png_bytep, tc->dp);
|
||||
|
||||
png_debug(1, "in png_do_pack");
|
||||
|
||||
# define png_ptr tc->png_ptr
|
||||
|
||||
switch ((*transform)->args)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
unsigned int mask = 0x80, v = 0;
|
||||
|
||||
while (sp < ep)
|
||||
{
|
||||
if (*sp++ != 0)
|
||||
v |= mask;
|
||||
|
||||
mask >>= 1;
|
||||
|
||||
if (mask == 0)
|
||||
{
|
||||
mask = 0x80;
|
||||
*dp++ = PNG_BYTE(v);
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask != 0x80)
|
||||
*dp++ = PNG_BYTE(v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
unsigned int shift = 8, v = 0;
|
||||
|
||||
while (sp < ep)
|
||||
{
|
||||
shift -= 2;
|
||||
v |= (*sp++ & 0x3) << shift;
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 8;
|
||||
*dp++ = PNG_BYTE(v);
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift != 8)
|
||||
*dp++ = PNG_BYTE(v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
unsigned int shift = 8, v = 0;
|
||||
|
||||
while (sp < ep)
|
||||
{
|
||||
shift -= 4;
|
||||
v |= ((*sp++ & 0xf) << shift);
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 8;
|
||||
*dp++ = PNG_BYTE(v);
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift != 8)
|
||||
*dp++ = PNG_BYTE(v);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
impossible("bit depth");
|
||||
}
|
||||
|
||||
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0 &&
|
||||
--(tc->range) == 0)
|
||||
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);
|
||||
|
||||
tc->bit_depth = (*transform)->args;
|
||||
tc->sp = tc->dp;
|
||||
# undef png_ptr
|
||||
}
|
||||
|
||||
void /* PRIVATE */
|
||||
png_init_write_pack(png_transformp *transform, png_transform_controlp tc)
|
||||
{
|
||||
# define png_ptr tc->png_ptr
|
||||
debug(tc->init);
|
||||
# undef png_ptr
|
||||
|
||||
/* The init routine is called *forward* so the transform control we get has
|
||||
* the required bit depth and the transform routine will increase it to 8
|
||||
* bits per channel. The code doesn't really care how many channels there
|
||||
* are, but the only way to get a channel depth of less than 8 is to have
|
||||
* just one channel.
|
||||
*/
|
||||
if (tc->bit_depth < 8) /* else no packing/unpacking */
|
||||
{
|
||||
if (tc->init == PNG_TC_INIT_FINAL)
|
||||
{
|
||||
(*transform)->fn = png_do_write_pack;
|
||||
/* Record this for the backwards run: */
|
||||
(*transform)->args = tc->bit_depth & 0xf;
|
||||
}
|
||||
|
||||
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0)
|
||||
{
|
||||
tc->range++;
|
||||
tc->format |= PNG_FORMAT_FLAG_RANGE; /* forwards: backwards cancels */
|
||||
}
|
||||
|
||||
tc->bit_depth = 8;
|
||||
}
|
||||
|
||||
else /* the transform is not applicable */
|
||||
(*transform)->fn = NULL;
|
||||
}
|
||||
#endif /* WRITE_PACK */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,136 +0,0 @@
|
||||
# Copyright (C) 2009 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libzip
|
||||
LOCAL_SRC_FILES :=\
|
||||
zip_add.c \
|
||||
zip_add_dir.c \
|
||||
zip_add_entry.c \
|
||||
zip_algorithm_deflate.c \
|
||||
zip_buffer.c \
|
||||
zip_close.c \
|
||||
zip_delete.c \
|
||||
zip_dir_add.c \
|
||||
zip_dirent.c \
|
||||
zip_discard.c \
|
||||
zip_entry.c \
|
||||
zip_error.c \
|
||||
zip_error_clear.c \
|
||||
zip_error_get.c \
|
||||
zip_error_get_sys_type.c \
|
||||
zip_error_strerror.c \
|
||||
zip_error_to_str.c \
|
||||
zip_extra_field.c \
|
||||
zip_extra_field_api.c \
|
||||
zip_fclose.c \
|
||||
zip_fdopen.c \
|
||||
zip_file_add.c \
|
||||
zip_file_error_clear.c \
|
||||
zip_file_error_get.c \
|
||||
zip_file_get_comment.c \
|
||||
zip_file_get_external_attributes.c \
|
||||
zip_file_get_offset.c \
|
||||
zip_file_rename.c \
|
||||
zip_file_replace.c \
|
||||
zip_file_set_comment.c \
|
||||
zip_file_set_encryption.c \
|
||||
zip_file_set_external_attributes.c \
|
||||
zip_file_set_mtime.c \
|
||||
zip_file_strerror.c \
|
||||
zip_fopen.c \
|
||||
zip_fopen_encrypted.c \
|
||||
zip_fopen_index.c \
|
||||
zip_fopen_index_encrypted.c \
|
||||
zip_fread.c \
|
||||
zip_fseek.c \
|
||||
zip_ftell.c \
|
||||
zip_get_archive_comment.c \
|
||||
zip_get_archive_flag.c \
|
||||
zip_get_encryption_implementation.c \
|
||||
zip_get_file_comment.c \
|
||||
zip_get_name.c \
|
||||
zip_get_num_entries.c \
|
||||
zip_get_num_files.c \
|
||||
zip_hash.c \
|
||||
zip_io_util.c \
|
||||
zip_libzip_version.c \
|
||||
zip_memdup.c \
|
||||
zip_name_locate.c \
|
||||
zip_new.c \
|
||||
zip_open.c \
|
||||
zip_pkware.c \
|
||||
zip_progress.c \
|
||||
zip_rename.c \
|
||||
zip_replace.c \
|
||||
zip_set_archive_comment.c \
|
||||
zip_set_archive_flag.c \
|
||||
zip_set_default_password.c \
|
||||
zip_set_file_comment.c \
|
||||
zip_set_file_compression.c \
|
||||
zip_set_name.c \
|
||||
zip_source_accept_empty.c \
|
||||
zip_source_begin_write.c \
|
||||
zip_source_begin_write_cloning.c \
|
||||
zip_source_buffer.c \
|
||||
zip_source_call.c \
|
||||
zip_source_close.c \
|
||||
zip_source_commit_write.c \
|
||||
zip_source_compress.c \
|
||||
zip_source_crc.c \
|
||||
zip_source_error.c \
|
||||
zip_source_file_common.c \
|
||||
zip_source_file_stdio.c \
|
||||
zip_source_free.c \
|
||||
zip_source_function.c \
|
||||
zip_source_get_file_attributes.c \
|
||||
zip_source_is_deleted.c \
|
||||
zip_source_layered.c \
|
||||
zip_source_open.c \
|
||||
zip_source_pkware_decode.c \
|
||||
zip_source_pkware_encode.c \
|
||||
zip_source_read.c \
|
||||
zip_source_remove.c \
|
||||
zip_source_rollback_write.c \
|
||||
zip_source_seek.c \
|
||||
zip_source_seek_write.c \
|
||||
zip_source_stat.c \
|
||||
zip_source_supports.c \
|
||||
zip_source_tell.c \
|
||||
zip_source_tell_write.c \
|
||||
zip_source_window.c \
|
||||
zip_source_write.c \
|
||||
zip_source_zip.c \
|
||||
zip_source_zip_new.c \
|
||||
zip_stat.c \
|
||||
zip_stat_index.c \
|
||||
zip_stat_init.c \
|
||||
zip_strerror.c \
|
||||
zip_string.c \
|
||||
zip_unchange.c \
|
||||
zip_unchange_all.c \
|
||||
zip_unchange_archive.c \
|
||||
zip_unchange_data.c \
|
||||
zip_utf-8.c \
|
||||
zip_err_str.c \
|
||||
zip_mkstempm.c \
|
||||
zip_source_file_stdio_named.c \
|
||||
zip_random_unix.c
|
||||
|
||||
LOCAL_CFLAGS := -O2
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -1,135 +0,0 @@
|
||||
set(SRCS
|
||||
zip_add.c
|
||||
zip_add_dir.c
|
||||
zip_add_entry.c
|
||||
zip_algorithm_deflate.c
|
||||
zip_buffer.c
|
||||
zip_close.c
|
||||
zip_delete.c
|
||||
zip_dir_add.c
|
||||
zip_dirent.c
|
||||
zip_discard.c
|
||||
zip_entry.c
|
||||
zip_error.c
|
||||
zip_error_clear.c
|
||||
zip_error_get.c
|
||||
zip_error_get_sys_type.c
|
||||
zip_error_strerror.c
|
||||
zip_error_to_str.c
|
||||
zip_extra_field.c
|
||||
zip_extra_field_api.c
|
||||
zip_fclose.c
|
||||
zip_fdopen.c
|
||||
zip_file_add.c
|
||||
zip_file_error_clear.c
|
||||
zip_file_error_get.c
|
||||
zip_file_get_comment.c
|
||||
zip_file_get_external_attributes.c
|
||||
zip_file_get_offset.c
|
||||
zip_file_rename.c
|
||||
zip_file_replace.c
|
||||
zip_file_set_comment.c
|
||||
zip_file_set_encryption.c
|
||||
zip_file_set_external_attributes.c
|
||||
zip_file_set_mtime.c
|
||||
zip_file_strerror.c
|
||||
zip_fopen.c
|
||||
zip_fopen_encrypted.c
|
||||
zip_fopen_index.c
|
||||
zip_fopen_index_encrypted.c
|
||||
zip_fread.c
|
||||
zip_fseek.c
|
||||
zip_ftell.c
|
||||
zip_get_archive_comment.c
|
||||
zip_get_archive_flag.c
|
||||
zip_get_encryption_implementation.c
|
||||
zip_get_file_comment.c
|
||||
zip_get_name.c
|
||||
zip_get_num_entries.c
|
||||
zip_get_num_files.c
|
||||
zip_hash.c
|
||||
zip_io_util.c
|
||||
zip_libzip_version.c
|
||||
zip_memdup.c
|
||||
zip_name_locate.c
|
||||
zip_new.c
|
||||
zip_open.c
|
||||
zip_pkware.c
|
||||
zip_progress.c
|
||||
zip_rename.c
|
||||
zip_replace.c
|
||||
zip_set_archive_comment.c
|
||||
zip_set_archive_flag.c
|
||||
zip_set_default_password.c
|
||||
zip_set_file_comment.c
|
||||
zip_set_file_compression.c
|
||||
zip_set_name.c
|
||||
zip_source_accept_empty.c
|
||||
zip_source_begin_write.c
|
||||
zip_source_begin_write_cloning.c
|
||||
zip_source_buffer.c
|
||||
zip_source_call.c
|
||||
zip_source_close.c
|
||||
zip_source_commit_write.c
|
||||
zip_source_compress.c
|
||||
zip_source_crc.c
|
||||
zip_source_error.c
|
||||
zip_source_file_common.c
|
||||
zip_source_file_stdio.c
|
||||
zip_source_free.c
|
||||
zip_source_function.c
|
||||
zip_source_get_file_attributes.c
|
||||
zip_source_is_deleted.c
|
||||
zip_source_layered.c
|
||||
zip_source_open.c
|
||||
zip_source_pkware_decode.c
|
||||
zip_source_pkware_encode.c
|
||||
zip_source_read.c
|
||||
zip_source_remove.c
|
||||
zip_source_rollback_write.c
|
||||
zip_source_seek.c
|
||||
zip_source_seek_write.c
|
||||
zip_source_stat.c
|
||||
zip_source_supports.c
|
||||
zip_source_tell.c
|
||||
zip_source_tell_write.c
|
||||
zip_source_window.c
|
||||
zip_source_write.c
|
||||
zip_source_zip.c
|
||||
zip_source_zip_new.c
|
||||
zip_stat.c
|
||||
zip_stat_index.c
|
||||
zip_stat_init.c
|
||||
zip_strerror.c
|
||||
zip_string.c
|
||||
zip_unchange.c
|
||||
zip_unchange_all.c
|
||||
zip_unchange_archive.c
|
||||
zip_unchange_data.c
|
||||
zip_utf-8.c
|
||||
zip_err_str.c)
|
||||
|
||||
if(WIN32)
|
||||
set(SRCS ${SRCS}
|
||||
zip_source_file_win32.c
|
||||
zip_source_file_win32_named.c
|
||||
zip_source_file_win32_utf16.c
|
||||
zip_source_file_win32_utf8.c)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
|
||||
set(SRCS ${SRCS} zip_random_uwp.c)
|
||||
else()
|
||||
set(SRCS ${SRCS} zip_source_file_win32_ansi.c zip_random_win32.c)
|
||||
endif()
|
||||
else()
|
||||
set(SRCS ${SRCS}
|
||||
zip_mkstempm.c
|
||||
zip_source_file_stdio_named.c
|
||||
zip_random_unix.c)
|
||||
endif()
|
||||
|
||||
add_library(zip STATIC ${SRCS})
|
||||
|
||||
if(UNIX)
|
||||
add_definitions(-fPIC)
|
||||
endif(UNIX)
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
#ifndef _HAD_LIBZIP_COMPAT_H
|
||||
#define _HAD_LIBZIP_COMPAT_H
|
||||
|
||||
/*
|
||||
compat.h -- compatibility defines.
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include "zipconf.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* to have *_MAX definitions for all types when compiling with g++ */
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef ZIP_EXTERN
|
||||
#ifndef ZIP_STATIC
|
||||
#define ZIP_EXTERN __declspec(dllexport)
|
||||
#endif
|
||||
#endif
|
||||
/* for dup(), close(), etc. */
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
typedef char bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/* at least MinGW does not provide EOPNOTSUPP, see
|
||||
* http://sourceforge.net/p/mingw/bugs/263/
|
||||
*/
|
||||
#ifndef EOPNOTSUPP
|
||||
#define EOPNOTSUPP EINVAL
|
||||
#endif
|
||||
|
||||
/* at least MinGW does not provide EOVERFLOW, see
|
||||
* http://sourceforge.net/p/mingw/bugs/242/
|
||||
*/
|
||||
#ifndef EOVERFLOW
|
||||
#define EOVERFLOW EFBIG
|
||||
#endif
|
||||
|
||||
/* not supported on at least Windows */
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(HAVE__CLOSE)
|
||||
#define close _close
|
||||
#endif
|
||||
#if defined(HAVE__DUP)
|
||||
#define dup _dup
|
||||
#endif
|
||||
/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */
|
||||
#if defined(HAVE__FDOPEN)
|
||||
#define fdopen _fdopen
|
||||
#endif
|
||||
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
|
||||
#define fileno _fileno
|
||||
#endif
|
||||
#if defined(HAVE__SNPRINTF)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#if defined(HAVE__STRDUP)
|
||||
#if !defined(HAVE_STRDUP) || defined(_WIN32)
|
||||
#undef strdup
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE)
|
||||
#define _setmode setmode
|
||||
#endif
|
||||
#if !defined(HAVE_STRTOLL) && defined(HAVE__STRTOI64)
|
||||
#define strtoll _strtoi64
|
||||
#endif
|
||||
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
|
||||
#define strtoull _strtoui64
|
||||
#endif
|
||||
#if defined(HAVE__UNLINK)
|
||||
#define unlink _unlink
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
#define fseeko(s, o, w) (fseek((s), (long int)(o), (w)))
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FTELLO
|
||||
#define ftello(s) ((long)ftell((s)))
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRCASECMP)
|
||||
#if defined(HAVE__STRICMP)
|
||||
#define strcasecmp _stricmp
|
||||
#elif defined(HAVE_STRICMP)
|
||||
#define strcasecmp stricmp
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SIZEOF_OFF_T == 8
|
||||
#define ZIP_OFF_MAX ZIP_INT64_MAX
|
||||
#define ZIP_OFF_MIN ZIP_INT64_MIN
|
||||
#elif SIZEOF_OFF_T == 4
|
||||
#define ZIP_OFF_MAX ZIP_INT32_MAX
|
||||
#define ZIP_OFF_MIN ZIP_INT32_MIN
|
||||
#elif SIZEOF_OFF_T == 2
|
||||
#define ZIP_OFF_MAX ZIP_INT16_MAX
|
||||
#define ZIP_OFF_MIN ZIP_INT16_MIN
|
||||
#else
|
||||
#error unsupported size of off_t
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO)
|
||||
#define ZIP_FSEEK_MAX ZIP_OFF_MAX
|
||||
#define ZIP_FSEEK_MIN ZIP_OFF_MIN
|
||||
#else
|
||||
#include <limits.h>
|
||||
#define ZIP_FSEEK_MAX LONG_MAX
|
||||
#define ZIP_FSEEK_MIN LONG_MIN
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#if SIZEOF_SIZE_T == 8
|
||||
#define SIZE_MAX ZIP_INT64_MAX
|
||||
#elif SIZEOF_SIZE_T == 4
|
||||
#define SIZE_MAX ZIP_INT32_MAX
|
||||
#elif SIZEOF_SIZE_T == 2
|
||||
#define SIZE_MAX ZIP_INT16_MAX
|
||||
#else
|
||||
#error unsupported size of size_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRId64
|
||||
#ifdef _MSC_VER
|
||||
#define PRId64 "I64d"
|
||||
#else
|
||||
#define PRId64 "lld"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIu64
|
||||
#ifdef _MSC_VER
|
||||
#define PRIu64 "I64u"
|
||||
#else
|
||||
#define PRIu64 "llu"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
|
||||
#endif /* compat.h */
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef HAD_CONFIG_H
|
||||
#define HAD_CONFIG_H
|
||||
#ifndef _HAD_ZIPCONF_H
|
||||
#include "zipconf.h"
|
||||
#endif
|
||||
|
||||
#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
|
||||
#define MS_UWP
|
||||
#define _WIN32_WINNT 0x0602
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* BEGIN DEFINES */
|
||||
#ifdef _WIN32
|
||||
#define HAVE__CLOSE
|
||||
#define HAVE__DUP
|
||||
#define HAVE__FDOPEN
|
||||
#define HAVE__FILENO
|
||||
#define HAVE__SETMODE
|
||||
#define HAVE__STRDUP
|
||||
#define HAVE__STRICMP
|
||||
#define HAVE__STRTOI64
|
||||
#define HAVE__STRTOUI64
|
||||
#define HAVE__UMASK
|
||||
#define HAVE__UNLINK
|
||||
#endif
|
||||
#ifndef MS_UWP
|
||||
#define HAVE_FILENO
|
||||
#define HAVE_GETPROGNAME
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#define HAVE_FSEEKO
|
||||
#define HAVE_FTELLO
|
||||
#define HAVE_LOCALTIME_R
|
||||
#define HAVE_MKSTEMP 1
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
#define HAVE_FSEEKO
|
||||
#define HAVE_FTELLO
|
||||
#endif
|
||||
#define HAVE_SNPRINTF
|
||||
#define HAVE_STDBOOL_H 1
|
||||
#define HAVE_STRDUP
|
||||
#if !defined(__MINGW32__) && defined(_WIN32)
|
||||
#define HAVE_STRICMP
|
||||
#else
|
||||
#define HAVE_STRCASECMP
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_UNISTD_H
|
||||
#endif
|
||||
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__mips64__)
|
||||
#define SIZEOF_OFF_T 8
|
||||
#define SIZEOF_SIZE_T 8
|
||||
#else
|
||||
#define SIZEOF_OFF_T 4
|
||||
#define SIZEOF_SIZE_T 4
|
||||
#endif
|
||||
/* END DEFINES */
|
||||
#define PACKAGE "libzip"
|
||||
#define VERSION "1.7.3"
|
||||
|
||||
#endif /* HAD_CONFIG_H */
|
||||
@@ -1,41 +0,0 @@
|
||||
# libzip.la - a libtool library file
|
||||
# Generated by ltmain.sh (GNU libtool) 2.2.6b
|
||||
#
|
||||
# Please DO NOT delete this file!
|
||||
# It is necessary for linking the library.
|
||||
|
||||
# The name that we can dlopen(3).
|
||||
dlname='libzip.so.1'
|
||||
|
||||
# Names of this library.
|
||||
library_names='libzip.so.1.0.0 libzip.so.1 libzip.so'
|
||||
|
||||
# The name of the static archive.
|
||||
old_library='libzip.a'
|
||||
|
||||
# Linker flags that can not go in dependency_libs.
|
||||
inherited_linker_flags=''
|
||||
|
||||
# Libraries that this one depends upon.
|
||||
dependency_libs=' -lz'
|
||||
|
||||
# Names of additional weak libraries provided by this library
|
||||
weak_library_names=''
|
||||
|
||||
# Version information for libzip.
|
||||
current=1
|
||||
age=0
|
||||
revision=0
|
||||
|
||||
# Is this an already installed library?
|
||||
installed=no
|
||||
|
||||
# Should we warn about portability when linking against -modules?
|
||||
shouldnotlink=no
|
||||
|
||||
# Files to dlopen/dlpreopen
|
||||
dlopen=''
|
||||
dlpreopen=''
|
||||
|
||||
# Directory that this library needs to be installed in:
|
||||
libdir='/usr/local/lib'
|
||||
@@ -1,479 +0,0 @@
|
||||
#ifndef _HAD_ZIP_H
|
||||
#define _HAD_ZIP_H
|
||||
|
||||
/*
|
||||
zip.h -- exported declarations.
|
||||
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#if 0
|
||||
} /* fix autoindent */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "zipconf.h"
|
||||
|
||||
#ifndef ZIP_EXTERN
|
||||
#ifndef ZIP_STATIC
|
||||
#ifdef _WIN32
|
||||
#define ZIP_EXTERN __declspec(dllimport)
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define ZIP_EXTERN __attribute__((visibility("default")))
|
||||
#else
|
||||
#define ZIP_EXTERN
|
||||
#endif
|
||||
#else
|
||||
#define ZIP_EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
/* flags for zip_open */
|
||||
|
||||
#define ZIP_CREATE 1
|
||||
#define ZIP_EXCL 2
|
||||
#define ZIP_CHECKCONS 4
|
||||
#define ZIP_TRUNCATE 8
|
||||
#define ZIP_RDONLY 16
|
||||
|
||||
|
||||
/* flags for zip_name_locate, zip_fopen, zip_stat, ... */
|
||||
|
||||
#define ZIP_FL_NOCASE 1u /* ignore case on name lookup */
|
||||
#define ZIP_FL_NODIR 2u /* ignore directory component */
|
||||
#define ZIP_FL_COMPRESSED 4u /* read compressed data */
|
||||
#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */
|
||||
#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */
|
||||
#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */
|
||||
#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */
|
||||
#define ZIP_FL_ENC_RAW 64u /* get unmodified string */
|
||||
#define ZIP_FL_ENC_STRICT 128u /* follow specification strictly */
|
||||
#define ZIP_FL_LOCAL 256u /* in local header */
|
||||
#define ZIP_FL_CENTRAL 512u /* in central directory */
|
||||
/* 1024u reserved for internal use */
|
||||
#define ZIP_FL_ENC_UTF_8 2048u /* string is UTF-8 encoded */
|
||||
#define ZIP_FL_ENC_CP437 4096u /* string is CP437 encoded */
|
||||
#define ZIP_FL_OVERWRITE 8192u /* zip_file_add: if file with name exists, overwrite (replace) it */
|
||||
|
||||
/* archive global flags flags */
|
||||
|
||||
#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */
|
||||
|
||||
|
||||
/* create a new extra field */
|
||||
|
||||
#define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX
|
||||
#define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX
|
||||
|
||||
|
||||
/* libzip error codes */
|
||||
|
||||
#define ZIP_ER_OK 0 /* N No error */
|
||||
#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */
|
||||
#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */
|
||||
#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */
|
||||
#define ZIP_ER_SEEK 4 /* S Seek error */
|
||||
#define ZIP_ER_READ 5 /* S Read error */
|
||||
#define ZIP_ER_WRITE 6 /* S Write error */
|
||||
#define ZIP_ER_CRC 7 /* N CRC error */
|
||||
#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */
|
||||
#define ZIP_ER_NOENT 9 /* N No such file */
|
||||
#define ZIP_ER_EXISTS 10 /* N File already exists */
|
||||
#define ZIP_ER_OPEN 11 /* S Can't open file */
|
||||
#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */
|
||||
#define ZIP_ER_ZLIB 13 /* Z Zlib error */
|
||||
#define ZIP_ER_MEMORY 14 /* N Malloc failure */
|
||||
#define ZIP_ER_CHANGED 15 /* N Entry has been changed */
|
||||
#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */
|
||||
#define ZIP_ER_EOF 17 /* N Premature end of file */
|
||||
#define ZIP_ER_INVAL 18 /* N Invalid argument */
|
||||
#define ZIP_ER_NOZIP 19 /* N Not a zip archive */
|
||||
#define ZIP_ER_INTERNAL 20 /* N Internal error */
|
||||
#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */
|
||||
#define ZIP_ER_REMOVE 22 /* S Can't remove file */
|
||||
#define ZIP_ER_DELETED 23 /* N Entry has been deleted */
|
||||
#define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */
|
||||
#define ZIP_ER_RDONLY 25 /* N Read-only archive */
|
||||
#define ZIP_ER_NOPASSWD 26 /* N No password provided */
|
||||
#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */
|
||||
#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */
|
||||
#define ZIP_ER_INUSE 29 /* N Resource still in use */
|
||||
#define ZIP_ER_TELL 30 /* S Tell error */
|
||||
#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */
|
||||
#define ZIP_ER_CANCELLED 32 /* N Operation cancelled */
|
||||
|
||||
/* type of system error value */
|
||||
|
||||
#define ZIP_ET_NONE 0 /* sys_err unused */
|
||||
#define ZIP_ET_SYS 1 /* sys_err is errno */
|
||||
#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */
|
||||
|
||||
/* compression methods */
|
||||
|
||||
#define ZIP_CM_DEFAULT -1 /* better of deflate or store */
|
||||
#define ZIP_CM_STORE 0 /* stored (uncompressed) */
|
||||
#define ZIP_CM_SHRINK 1 /* shrunk */
|
||||
#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */
|
||||
#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */
|
||||
#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */
|
||||
#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */
|
||||
#define ZIP_CM_IMPLODE 6 /* imploded */
|
||||
/* 7 - Reserved for Tokenizing compression algorithm */
|
||||
#define ZIP_CM_DEFLATE 8 /* deflated */
|
||||
#define ZIP_CM_DEFLATE64 9 /* deflate64 */
|
||||
#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */
|
||||
/* 11 - Reserved by PKWARE */
|
||||
#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */
|
||||
/* 13 - Reserved by PKWARE */
|
||||
#define ZIP_CM_LZMA 14 /* LZMA (EFS) */
|
||||
/* 15-17 - Reserved by PKWARE */
|
||||
#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
|
||||
#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */
|
||||
#define ZIP_CM_LZMA2 33
|
||||
#define ZIP_CM_XZ 95 /* XZ compressed data */
|
||||
#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */
|
||||
#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */
|
||||
#define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */
|
||||
|
||||
/* encryption methods */
|
||||
|
||||
#define ZIP_EM_NONE 0 /* not encrypted */
|
||||
#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */
|
||||
#if 0 /* Strong Encryption Header not parsed yet */
|
||||
#define ZIP_EM_DES 0x6601 /* strong encryption: DES */
|
||||
#define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */
|
||||
#define ZIP_EM_3DES_168 0x6603
|
||||
#define ZIP_EM_3DES_112 0x6609
|
||||
#define ZIP_EM_PKZIP_AES_128 0x660e
|
||||
#define ZIP_EM_PKZIP_AES_192 0x660f
|
||||
#define ZIP_EM_PKZIP_AES_256 0x6610
|
||||
#define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */
|
||||
#define ZIP_EM_RC4 0x6801
|
||||
#endif
|
||||
#define ZIP_EM_AES_128 0x0101 /* Winzip AES encryption */
|
||||
#define ZIP_EM_AES_192 0x0102
|
||||
#define ZIP_EM_AES_256 0x0103
|
||||
#define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */
|
||||
|
||||
#define ZIP_OPSYS_DOS 0x00u
|
||||
#define ZIP_OPSYS_AMIGA 0x01u
|
||||
#define ZIP_OPSYS_OPENVMS 0x02u
|
||||
#define ZIP_OPSYS_UNIX 0x03u
|
||||
#define ZIP_OPSYS_VM_CMS 0x04u
|
||||
#define ZIP_OPSYS_ATARI_ST 0x05u
|
||||
#define ZIP_OPSYS_OS_2 0x06u
|
||||
#define ZIP_OPSYS_MACINTOSH 0x07u
|
||||
#define ZIP_OPSYS_Z_SYSTEM 0x08u
|
||||
#define ZIP_OPSYS_CPM 0x09u
|
||||
#define ZIP_OPSYS_WINDOWS_NTFS 0x0au
|
||||
#define ZIP_OPSYS_MVS 0x0bu
|
||||
#define ZIP_OPSYS_VSE 0x0cu
|
||||
#define ZIP_OPSYS_ACORN_RISC 0x0du
|
||||
#define ZIP_OPSYS_VFAT 0x0eu
|
||||
#define ZIP_OPSYS_ALTERNATE_MVS 0x0fu
|
||||
#define ZIP_OPSYS_BEOS 0x10u
|
||||
#define ZIP_OPSYS_TANDEM 0x11u
|
||||
#define ZIP_OPSYS_OS_400 0x12u
|
||||
#define ZIP_OPSYS_OS_X 0x13u
|
||||
|
||||
#define ZIP_OPSYS_DEFAULT ZIP_OPSYS_UNIX
|
||||
|
||||
|
||||
enum zip_source_cmd {
|
||||
ZIP_SOURCE_OPEN, /* prepare for reading */
|
||||
ZIP_SOURCE_READ, /* read data */
|
||||
ZIP_SOURCE_CLOSE, /* reading is done */
|
||||
ZIP_SOURCE_STAT, /* get meta information */
|
||||
ZIP_SOURCE_ERROR, /* get error information */
|
||||
ZIP_SOURCE_FREE, /* cleanup and free resources */
|
||||
ZIP_SOURCE_SEEK, /* set position for reading */
|
||||
ZIP_SOURCE_TELL, /* get read position */
|
||||
ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */
|
||||
ZIP_SOURCE_COMMIT_WRITE, /* writing is done */
|
||||
ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */
|
||||
ZIP_SOURCE_WRITE, /* write data */
|
||||
ZIP_SOURCE_SEEK_WRITE, /* set position for writing */
|
||||
ZIP_SOURCE_TELL_WRITE, /* get write position */
|
||||
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
|
||||
ZIP_SOURCE_REMOVE, /* remove file */
|
||||
ZIP_SOURCE_RESERVED_1, /* previously used internally */
|
||||
ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
|
||||
ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */
|
||||
ZIP_SOURCE_GET_FILE_ATTRIBUTES /* get additional file attributes */
|
||||
};
|
||||
typedef enum zip_source_cmd zip_source_cmd_t;
|
||||
|
||||
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd))
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_CLOSE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_STAT) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ERROR) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_FREE))
|
||||
|
||||
#define ZIP_SOURCE_SUPPORTS_SEEKABLE (ZIP_SOURCE_SUPPORTS_READABLE \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS))
|
||||
|
||||
#define ZIP_SOURCE_SUPPORTS_WRITABLE (ZIP_SOURCE_SUPPORTS_SEEKABLE \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_COMMIT_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ROLLBACK_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \
|
||||
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE))
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
/* for use by sources */
|
||||
struct zip_source_args_seek {
|
||||
zip_int64_t offset;
|
||||
int whence;
|
||||
};
|
||||
|
||||
typedef struct zip_source_args_seek zip_source_args_seek_t;
|
||||
#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), (type *)NULL : (type *)(data))
|
||||
|
||||
|
||||
/* error information */
|
||||
/* use zip_error_*() to access */
|
||||
struct zip_error {
|
||||
int zip_err; /* libzip error code (ZIP_ER_*) */
|
||||
int sys_err; /* copy of errno (E*) or zlib error code */
|
||||
char *_Nullable str; /* string representation or NULL */
|
||||
};
|
||||
|
||||
#define ZIP_STAT_NAME 0x0001u
|
||||
#define ZIP_STAT_INDEX 0x0002u
|
||||
#define ZIP_STAT_SIZE 0x0004u
|
||||
#define ZIP_STAT_COMP_SIZE 0x0008u
|
||||
#define ZIP_STAT_MTIME 0x0010u
|
||||
#define ZIP_STAT_CRC 0x0020u
|
||||
#define ZIP_STAT_COMP_METHOD 0x0040u
|
||||
#define ZIP_STAT_ENCRYPTION_METHOD 0x0080u
|
||||
#define ZIP_STAT_FLAGS 0x0100u
|
||||
|
||||
struct zip_stat {
|
||||
zip_uint64_t valid; /* which fields have valid values */
|
||||
const char *_Nullable name; /* name of the file */
|
||||
zip_uint64_t index; /* index within archive */
|
||||
zip_uint64_t size; /* size of file (uncompressed) */
|
||||
zip_uint64_t comp_size; /* size of file (compressed) */
|
||||
time_t mtime; /* modification time */
|
||||
zip_uint32_t crc; /* crc of file data */
|
||||
zip_uint16_t comp_method; /* compression method used */
|
||||
zip_uint16_t encryption_method; /* encryption method used */
|
||||
zip_uint32_t flags; /* reserved for future use */
|
||||
};
|
||||
|
||||
struct zip_buffer_fragment {
|
||||
zip_uint8_t *_Nonnull data;
|
||||
zip_uint64_t length;
|
||||
};
|
||||
|
||||
struct zip_file_attributes {
|
||||
zip_uint64_t valid; /* which fields have valid values */
|
||||
zip_uint8_t version; /* version of this struct, currently 1 */
|
||||
zip_uint8_t host_system; /* host system on which file was created */
|
||||
zip_uint8_t ascii; /* flag whether file is ASCII text */
|
||||
zip_uint8_t version_needed; /* minimum version needed to extract file */
|
||||
zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */
|
||||
zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */
|
||||
zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */
|
||||
};
|
||||
|
||||
#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u
|
||||
#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u
|
||||
#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u
|
||||
#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u
|
||||
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u
|
||||
|
||||
struct zip;
|
||||
struct zip_file;
|
||||
struct zip_source;
|
||||
|
||||
typedef struct zip zip_t;
|
||||
typedef struct zip_error zip_error_t;
|
||||
typedef struct zip_file zip_file_t;
|
||||
typedef struct zip_file_attributes zip_file_attributes_t;
|
||||
typedef struct zip_source zip_source_t;
|
||||
typedef struct zip_stat zip_stat_t;
|
||||
typedef struct zip_buffer_fragment zip_buffer_fragment_t;
|
||||
|
||||
typedef zip_uint32_t zip_flags_t;
|
||||
|
||||
typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
|
||||
typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable);
|
||||
typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable);
|
||||
|
||||
#ifndef ZIP_DISABLE_DEPRECATED
|
||||
typedef void (*zip_progress_callback_t)(double);
|
||||
ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable); /* use zip_register_progress_callback_with_state */
|
||||
|
||||
ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull); /* use zip_file_add */
|
||||
ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull); /* use zip_dir_add */
|
||||
ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int); /* use zip_file_get_comment */
|
||||
ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull); /* use zip_get_num_entries instead */
|
||||
ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull); /* use zip_file_rename */
|
||||
ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull); /* use zip_file_replace */
|
||||
ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int); /* use zip_file_set_comment */
|
||||
ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */
|
||||
ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
|
||||
ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */
|
||||
ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */
|
||||
#endif
|
||||
|
||||
ZIP_EXTERN int zip_close(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_delete(zip_t *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN void zip_discard(zip_t *_Nonnull);
|
||||
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_get_error(zip_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_clear(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_error_init_with_code(zip_error_t *_Nonnull, int);
|
||||
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int);
|
||||
ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||
|
||||
ZIP_EXTERN int zip_fclose(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN zip_t *_Nullable zip_fdopen(int, int, int *_Nullable);
|
||||
ZIP_EXTERN zip_int64_t zip_file_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_file_error_clear(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_file_extra_field_delete(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_extra_field_set(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *_Nullable, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_uint16_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable);
|
||||
ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_dostime(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_encryption(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, const char *_Nullable);
|
||||
ZIP_EXTERN int zip_file_set_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
|
||||
ZIP_EXTERN int zip_file_set_mtime(zip_t *_Nonnull, zip_uint64_t, time_t, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nonnull zip_file_strerror(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_encrypted(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, const char *_Nullable);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index_encrypted(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, const char *_Nullable);
|
||||
ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int);
|
||||
ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN const char *_Nullable zip_get_archive_comment(zip_t *_Nonnull, int *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN int zip_get_archive_flag(zip_t *_Nonnull, zip_flags_t, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nullable zip_get_name(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
|
||||
ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN const char *_Nonnull zip_libzip_version(void);
|
||||
ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN zip_t *_Nullable zip_open(const char *_Nonnull, int, int *_Nullable);
|
||||
ZIP_EXTERN zip_t *_Nullable zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *_Nonnull, double, zip_progress_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
|
||||
ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
|
||||
ZIP_EXTERN int zip_set_archive_comment(zip_t *_Nonnull, const char *_Nullable, zip_uint16_t);
|
||||
ZIP_EXTERN int zip_set_archive_flag(zip_t *_Nonnull, zip_flags_t, int);
|
||||
ZIP_EXTERN int zip_set_default_password(zip_t *_Nonnull, const char *_Nullable);
|
||||
ZIP_EXTERN int zip_set_file_compression(zip_t *_Nonnull, zip_uint64_t, zip_int32_t, zip_uint32_t);
|
||||
ZIP_EXTERN int zip_source_begin_write(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer(zip_t *_Nonnull, const void *_Nullable, zip_uint64_t, int);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment(zip_t *_Nonnull, const zip_buffer_fragment_t *_Nonnull, zip_uint64_t, int);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_commit_write(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_file(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_filep(zip_t *_Nonnull, FILE *_Nonnull, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_filep_create(FILE *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_is_deleted(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
|
||||
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int);
|
||||
ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int);
|
||||
ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull);
|
||||
ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull);
|
||||
#ifdef _WIN32
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32handle(zip_t *, void *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
#endif
|
||||
ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN const char *_Nonnull zip_strerror(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_unchange(zip_t *_Nonnull, zip_uint64_t);
|
||||
ZIP_EXTERN int zip_unchange_all(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_unchange_archive(zip_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress);
|
||||
ZIP_EXTERN int zip_encryption_method_supported(zip_uint16_t method, int encode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _HAD_ZIP_H */
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
zip_add.c -- add file via callback function
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
/*
|
||||
NOTE: Return type is signed so we can return -1 on error.
|
||||
The index can not be larger than ZIP_INT64_MAX since the size
|
||||
of the central directory cannot be larger than
|
||||
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
|
||||
*/
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_add(zip_t *za, const char *name, zip_source_t *source) {
|
||||
return zip_file_add(za, name, source, 0);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
zip_add_dir.c -- add directory
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_add_dir(zip_t *za, const char *name) {
|
||||
return zip_dir_add(za, name, 0);
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
zip_add_entry.c -- create and init struct zip_entry
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
zip_int64_t
|
||||
_zip_add_entry(zip_t *za) {
|
||||
zip_uint64_t idx;
|
||||
|
||||
if (za->nentry + 1 >= za->nentry_alloc) {
|
||||
zip_entry_t *rentries;
|
||||
zip_uint64_t nalloc = za->nentry_alloc;
|
||||
zip_uint64_t additional_entries = 2 * nalloc;
|
||||
zip_uint64_t realloc_size;
|
||||
|
||||
if (additional_entries < 16) {
|
||||
additional_entries = 16;
|
||||
}
|
||||
else if (additional_entries > 1024) {
|
||||
additional_entries = 1024;
|
||||
}
|
||||
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
|
||||
nalloc += additional_entries;
|
||||
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
|
||||
|
||||
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
|
||||
if (!rentries) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
za->entry = rentries;
|
||||
za->nentry_alloc = nalloc;
|
||||
}
|
||||
|
||||
idx = za->nentry++;
|
||||
|
||||
_zip_entry_init(za->entry + idx);
|
||||
|
||||
return (zip_int64_t)idx;
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
zip_algorithm_deflate.c -- deflate (de)compression routines
|
||||
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
struct ctx {
|
||||
zip_error_t *error;
|
||||
bool compress;
|
||||
int compression_flags;
|
||||
bool end_of_input;
|
||||
z_stream zstr;
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
allocate(bool compress, int compression_flags, zip_error_t *error) {
|
||||
struct ctx *ctx;
|
||||
|
||||
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ET_SYS, errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->error = error;
|
||||
ctx->compress = compress;
|
||||
ctx->compression_flags = compression_flags;
|
||||
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
|
||||
ctx->compression_flags = Z_BEST_COMPRESSION;
|
||||
}
|
||||
ctx->end_of_input = false;
|
||||
|
||||
ctx->zstr.zalloc = Z_NULL;
|
||||
ctx->zstr.zfree = Z_NULL;
|
||||
ctx->zstr.opaque = NULL;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(true, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(false, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deallocate(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static zip_uint16_t
|
||||
general_purpose_bit_flags(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (!ctx->compress) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->compression_flags < 3) {
|
||||
return 2 << 1;
|
||||
}
|
||||
else if (ctx->compression_flags > 7) {
|
||||
return 1 << 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
start(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int ret;
|
||||
|
||||
ctx->zstr.avail_in = 0;
|
||||
ctx->zstr.next_in = NULL;
|
||||
ctx->zstr.avail_out = 0;
|
||||
ctx->zstr.next_out = NULL;
|
||||
|
||||
if (ctx->compress) {
|
||||
/* negative value to tell zlib not to write a header */
|
||||
ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
else {
|
||||
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
|
||||
}
|
||||
|
||||
if (ret != Z_OK) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
end(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int err;
|
||||
|
||||
if (ctx->compress) {
|
||||
err = deflateEnd(&ctx->zstr);
|
||||
}
|
||||
else {
|
||||
err = inflateEnd(&ctx->zstr);
|
||||
}
|
||||
|
||||
if (err != Z_OK) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->zstr.avail_in = (uInt)length;
|
||||
ctx->zstr.next_in = (Bytef *)data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
}
|
||||
|
||||
|
||||
static zip_compression_status_t
|
||||
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
int ret;
|
||||
|
||||
ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
|
||||
ctx->zstr.next_out = (Bytef *)data;
|
||||
|
||||
if (ctx->compress) {
|
||||
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
|
||||
}
|
||||
else {
|
||||
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
|
||||
}
|
||||
|
||||
*length = *length - ctx->zstr.avail_out;
|
||||
|
||||
switch (ret) {
|
||||
case Z_OK:
|
||||
return ZIP_COMPRESSION_OK;
|
||||
|
||||
case Z_STREAM_END:
|
||||
return ZIP_COMPRESSION_END;
|
||||
|
||||
case Z_BUF_ERROR:
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
|
||||
default:
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
/* clang-format on */
|
||||
@@ -1,324 +0,0 @@
|
||||
/*
|
||||
zip_buffer.c -- bounds checked access to memory buffer
|
||||
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
zip_uint8_t *
|
||||
_zip_buffer_data(zip_buffer_t *buffer) {
|
||||
return buffer->data;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_buffer_free(zip_buffer_t *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->free_data) {
|
||||
free(buffer->data);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_buffer_eof(zip_buffer_t *buffer) {
|
||||
return buffer->ok && buffer->offset == buffer->size;
|
||||
}
|
||||
|
||||
|
||||
zip_uint8_t *
|
||||
_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint8_t *data;
|
||||
|
||||
data = _zip_buffer_peek(buffer, length);
|
||||
|
||||
if (data != NULL) {
|
||||
buffer->offset += length;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
zip_uint16_t
|
||||
_zip_buffer_get_16(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (zip_uint16_t)(data[0] + (data[1] << 8));
|
||||
}
|
||||
|
||||
|
||||
zip_uint32_t
|
||||
_zip_buffer_get_32(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
|
||||
}
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_get_64(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0];
|
||||
}
|
||||
|
||||
|
||||
zip_uint8_t
|
||||
_zip_buffer_get_8(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return data[0];
|
||||
}
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_left(zip_buffer_t *buffer) {
|
||||
return buffer->ok ? buffer->size - buffer->offset : 0;
|
||||
}
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
|
||||
if (_zip_buffer_left(buffer) < length) {
|
||||
length = _zip_buffer_left(buffer);
|
||||
}
|
||||
|
||||
memcpy(data, _zip_buffer_get(buffer, length), length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
zip_buffer_t *
|
||||
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
|
||||
bool free_data = (data == NULL);
|
||||
zip_buffer_t *buffer;
|
||||
|
||||
if (data == NULL) {
|
||||
if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
|
||||
if (free_data) {
|
||||
free(data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->ok = true;
|
||||
buffer->data = data;
|
||||
buffer->size = size;
|
||||
buffer->offset = 0;
|
||||
buffer->free_data = free_data;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
zip_buffer_t *
|
||||
_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) {
|
||||
zip_buffer_t *buffer;
|
||||
|
||||
if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_zip_read(src, buffer->data, size, error) < 0) {
|
||||
_zip_buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_offset(zip_buffer_t *buffer) {
|
||||
return buffer->ok ? buffer->offset : 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_buffer_ok(zip_buffer_t *buffer) {
|
||||
return buffer->ok;
|
||||
}
|
||||
|
||||
|
||||
zip_uint8_t *
|
||||
_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint8_t *data;
|
||||
|
||||
if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
|
||||
buffer->ok = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = buffer->data + buffer->offset;
|
||||
return data;
|
||||
}
|
||||
|
||||
int
|
||||
_zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
|
||||
zip_uint8_t *dst = _zip_buffer_get(buffer, length);
|
||||
|
||||
if (dst == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst, src, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (zip_uint8_t)(i & 0xff);
|
||||
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (zip_uint8_t)(i & 0xff);
|
||||
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
|
||||
data[2] = (zip_uint8_t)((i >> 16) & 0xff);
|
||||
data[3] = (zip_uint8_t)((i >> 24) & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (zip_uint8_t)(i & 0xff);
|
||||
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
|
||||
data[2] = (zip_uint8_t)((i >> 16) & 0xff);
|
||||
data[3] = (zip_uint8_t)((i >> 24) & 0xff);
|
||||
data[4] = (zip_uint8_t)((i >> 32) & 0xff);
|
||||
data[5] = (zip_uint8_t)((i >> 40) & 0xff);
|
||||
data[6] = (zip_uint8_t)((i >> 48) & 0xff);
|
||||
data[7] = (zip_uint8_t)((i >> 56) & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
|
||||
if (offset > buffer->size) {
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->ok = true;
|
||||
buffer->offset = offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint64_t offset = buffer->offset + length;
|
||||
|
||||
if (offset < buffer->offset) {
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
}
|
||||
return _zip_buffer_set_offset(buffer, offset);
|
||||
}
|
||||
|
||||
zip_uint64_t
|
||||
_zip_buffer_size(zip_buffer_t *buffer) {
|
||||
return buffer->size;
|
||||
}
|
||||
@@ -1,703 +0,0 @@
|
||||
/*
|
||||
zip_close.c -- close zip archive and update changes
|
||||
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
|
||||
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
|
||||
static int copy_data(zip_t *, zip_uint64_t);
|
||||
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
|
||||
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
|
||||
static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64);
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_close(zip_t *za) {
|
||||
zip_uint64_t i, j, survivors, unchanged_offset;
|
||||
zip_int64_t off;
|
||||
int error;
|
||||
zip_filelist_t *filelist;
|
||||
int changed;
|
||||
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
|
||||
changed = _zip_changed(za, &survivors);
|
||||
|
||||
/* don't create zip files with no entries */
|
||||
if (survivors == 0) {
|
||||
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
|
||||
if (zip_source_remove(za->src) < 0) {
|
||||
if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
zip_discard(za);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
zip_discard(za);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (survivors > za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
|
||||
return -1;
|
||||
|
||||
unchanged_offset = ZIP_UINT64_MAX;
|
||||
/* create list of files with index into original archive */
|
||||
for (i = j = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
|
||||
}
|
||||
if (za->entry[i].deleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j >= survivors) {
|
||||
free(filelist);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
filelist[j].idx = i;
|
||||
j++;
|
||||
}
|
||||
if (j < survivors) {
|
||||
free(filelist);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
else {
|
||||
if (unchanged_offset == ZIP_UINT64_MAX) {
|
||||
/* we're keeping all file data, find the end of the last one */
|
||||
zip_uint64_t last_index = ZIP_UINT64_MAX;
|
||||
unchanged_offset = 0;
|
||||
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL) {
|
||||
if (za->entry[i].orig->offset >= unchanged_offset) {
|
||||
unchanged_offset = za->entry[i].orig->offset;
|
||||
last_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_index != ZIP_UINT64_MAX) {
|
||||
if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset > 0) {
|
||||
if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
|
||||
/* cloning not supported, need to copy everything */
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset == 0) {
|
||||
if (zip_source_begin_write(za->src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_zip_progress_start(za->progress) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
zip_source_rollback_write(za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
error = 0;
|
||||
for (j = 0; j < survivors; j++) {
|
||||
int new_data;
|
||||
zip_entry_t *entry;
|
||||
zip_dirent_t *de;
|
||||
|
||||
if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
i = filelist[j].idx;
|
||||
entry = za->entry + i;
|
||||
|
||||
if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
|
||||
/* already implicitly copied by cloning */
|
||||
continue;
|
||||
}
|
||||
|
||||
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
|
||||
|
||||
/* create new local directory entry */
|
||||
if (entry->changes == NULL) {
|
||||
if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
de = entry->changes;
|
||||
|
||||
if (_zip_read_local_ef(za, i) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((off = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
de->offset = (zip_uint64_t)off;
|
||||
|
||||
if (new_data) {
|
||||
zip_source_t *zs;
|
||||
|
||||
zs = NULL;
|
||||
if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
|
||||
if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add_data writes dirent */
|
||||
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
|
||||
error = 1;
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
break;
|
||||
}
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
}
|
||||
else {
|
||||
zip_uint64_t offset;
|
||||
|
||||
if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
|
||||
/* when copying data, all sizes are known -> no data descriptor needed */
|
||||
/* except for PKWare encryption, where removing the data descriptor breaks password validation */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (copy_data(za, de->comp_size) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
if (write_cdir(za, filelist, survivors) < 0)
|
||||
error = 1;
|
||||
}
|
||||
|
||||
free(filelist);
|
||||
|
||||
if (!error) {
|
||||
if (zip_source_commit_write(za->src) != 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
}
|
||||
_zip_progress_end(za->progress);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
zip_source_rollback_write(za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_discard(za);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
zip_int64_t offstart, offdata, offend, data_length;
|
||||
zip_stat_t st;
|
||||
zip_file_attributes_t attributes;
|
||||
zip_source_t *src_final, *src_tmp;
|
||||
int ret;
|
||||
int is_zip64;
|
||||
zip_flags_t flags;
|
||||
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
|
||||
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
|
||||
st.valid |= ZIP_STAT_COMP_METHOD;
|
||||
st.comp_method = ZIP_CM_STORE;
|
||||
}
|
||||
|
||||
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
|
||||
de->comp_method = st.comp_method;
|
||||
else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
|
||||
st.valid |= ZIP_STAT_COMP_SIZE;
|
||||
st.comp_size = st.size;
|
||||
}
|
||||
else {
|
||||
/* we'll recompress */
|
||||
st.valid &= ~ZIP_STAT_COMP_SIZE;
|
||||
}
|
||||
|
||||
if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
|
||||
st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
|
||||
st.encryption_method = ZIP_EM_NONE;
|
||||
}
|
||||
|
||||
flags = ZIP_EF_LOCAL;
|
||||
|
||||
if ((st.valid & ZIP_STAT_SIZE) == 0) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
data_length = -1;
|
||||
}
|
||||
else {
|
||||
de->uncomp_size = st.size;
|
||||
/* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
|
||||
data_length = (zip_int64_t)st.size;
|
||||
|
||||
if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
|
||||
zip_uint64_t max_size;
|
||||
|
||||
switch (ZIP_CM_ACTUAL(de->comp_method)) {
|
||||
case ZIP_CM_BZIP2:
|
||||
/* computed by looking at increase of 10 random files of size 1MB when
|
||||
* compressed with bzip2, rounded up: 1.006 */
|
||||
max_size = 4269351188u;
|
||||
break;
|
||||
|
||||
case ZIP_CM_DEFLATE:
|
||||
/* max deflate size increase: size + ceil(size/16k)*5+6 */
|
||||
max_size = 4293656963u;
|
||||
break;
|
||||
|
||||
case ZIP_CM_STORE:
|
||||
max_size = 0xffffffffu;
|
||||
break;
|
||||
|
||||
default:
|
||||
max_size = 0;
|
||||
}
|
||||
|
||||
if (st.size > max_size) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
}
|
||||
}
|
||||
else
|
||||
de->comp_size = st.comp_size;
|
||||
}
|
||||
|
||||
if ((offstart = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* as long as we don't support non-seekable output, clear data descriptor bit */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
|
||||
needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
|
||||
needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
|
||||
needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
|
||||
|
||||
needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
|
||||
needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
|
||||
needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);
|
||||
|
||||
src_final = src;
|
||||
zip_source_keep(src_final);
|
||||
|
||||
if (needs_decrypt) {
|
||||
zip_encryption_implementation impl;
|
||||
|
||||
if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
|
||||
/* error set by impl */
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (needs_decompress) {
|
||||
if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (needs_crc) {
|
||||
if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (needs_compress) {
|
||||
if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
|
||||
if (needs_encrypt) {
|
||||
zip_encryption_implementation impl;
|
||||
const char *password = NULL;
|
||||
|
||||
if (de->password) {
|
||||
password = de->password;
|
||||
}
|
||||
else if (za->default_password) {
|
||||
password = za->default_password;
|
||||
}
|
||||
|
||||
if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
|
||||
/* error set by impl */
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
|
||||
if ((offdata = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = copy_source(za, src_final, data_length);
|
||||
|
||||
if (zip_source_stat(src_final, &st) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((offend = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
|
||||
if (st.valid & ZIP_STAT_MTIME)
|
||||
de->last_mod = st.mtime;
|
||||
else
|
||||
time(&de->last_mod);
|
||||
}
|
||||
de->comp_method = st.comp_method;
|
||||
de->crc = st.crc;
|
||||
de->uncomp_size = st.size;
|
||||
de->comp_size = (zip_uint64_t)(offend - offdata);
|
||||
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
|
||||
|
||||
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||
return -1;
|
||||
|
||||
if (is_zip64 != ret) {
|
||||
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, is_zip64) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
copy_data(zip_t *za, zip_uint64_t len) {
|
||||
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
|
||||
size_t n;
|
||||
double total = (double)len;
|
||||
|
||||
if (!byte_array_init(buf, BUFSIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
n = len > BUFSIZE ? BUFSIZE : len;
|
||||
if (_zip_read(za->src, buf, n, &za->error) < 0) {
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_write(za, buf, n) < 0) {
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
len -= n;
|
||||
|
||||
if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
byte_array_fini(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
|
||||
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
|
||||
zip_int64_t n, current;
|
||||
int ret;
|
||||
|
||||
if (zip_source_open(src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!byte_array_init(buf, BUFSIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
current = 0;
|
||||
while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) {
|
||||
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (n == BUFSIZE && za->progress && data_length > 0) {
|
||||
current += n;
|
||||
if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
byte_array_fini(buf);
|
||||
|
||||
zip_source_close(src);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
|
||||
zip_int64_t cd_start, end, size;
|
||||
|
||||
if ((cd_start = zip_source_tell_write(za->src)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((end = zip_source_tell_write(za->src)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
|
||||
int changed;
|
||||
zip_uint64_t i, survivors;
|
||||
|
||||
changed = 0;
|
||||
survivors = 0;
|
||||
|
||||
if (za->comment_changed || za->ch_flags != za->flags) {
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
changed = 1;
|
||||
}
|
||||
if (!za->entry[i].deleted) {
|
||||
survivors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (survivorsp) {
|
||||
*survivorsp = survivors;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static int
|
||||
write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
|
||||
zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH);
|
||||
int ret = 0;
|
||||
|
||||
if (buffer == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_zip_buffer_put(buffer, DATADES_MAGIC, 4);
|
||||
_zip_buffer_put_32(buffer, de->crc);
|
||||
if (is_zip64) {
|
||||
_zip_buffer_put_64(buffer, de->comp_size);
|
||||
_zip_buffer_put_64(buffer, de->uncomp_size);
|
||||
}
|
||||
else {
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
|
||||
}
|
||||
|
||||
if (!_zip_buffer_ok(buffer)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
|
||||
}
|
||||
|
||||
_zip_buffer_free(buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
zip_delete.c -- delete file from zip archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_delete(zip_t *za, zip_uint64_t idx) {
|
||||
const char *name;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allow duplicate file names, because the file will
|
||||
* be removed directly afterwards */
|
||||
if (_zip_unchange(za, idx, 1) != 0)
|
||||
return -1;
|
||||
|
||||
za->entry[idx].deleted = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
zip_dir_add.c -- add directory
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
|
||||
size_t len;
|
||||
zip_int64_t idx;
|
||||
char *s;
|
||||
zip_source_t *source;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = NULL;
|
||||
len = strlen(name);
|
||||
|
||||
if (name[len - 1] != '/') {
|
||||
if ((s = (char *)malloc(len + 2)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
strcpy(s, name);
|
||||
s[len] = '/';
|
||||
s[len + 1] = '\0';
|
||||
}
|
||||
|
||||
if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) {
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
|
||||
|
||||
free(s);
|
||||
|
||||
if (idx < 0)
|
||||
zip_source_free(source);
|
||||
else {
|
||||
if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
|
||||
zip_delete(za, (zip_uint64_t)idx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
zip_discard.c -- discard and free struct zip
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
/* zip_discard:
|
||||
frees the space allocated to a zipfile struct, and closes the
|
||||
corresponding file. */
|
||||
|
||||
void
|
||||
zip_discard(zip_t *za) {
|
||||
zip_uint64_t i;
|
||||
|
||||
if (za == NULL)
|
||||
return;
|
||||
|
||||
if (za->src) {
|
||||
zip_source_close(za->src);
|
||||
zip_source_free(za->src);
|
||||
}
|
||||
|
||||
free(za->default_password);
|
||||
_zip_string_free(za->comment_orig);
|
||||
_zip_string_free(za->comment_changes);
|
||||
|
||||
_zip_hash_free(za->names);
|
||||
|
||||
if (za->entry) {
|
||||
for (i = 0; i < za->nentry; i++)
|
||||
_zip_entry_finalize(za->entry + i);
|
||||
free(za->entry);
|
||||
}
|
||||
|
||||
for (i = 0; i < za->nopen_source; i++) {
|
||||
_zip_source_invalidate(za->open_source[i]);
|
||||
}
|
||||
free(za->open_source);
|
||||
|
||||
_zip_progress_free(za->progress);
|
||||
|
||||
zip_error_fini(&za->error);
|
||||
|
||||
free(za);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
zip_entry.c -- struct zip_entry helper functions
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
void
|
||||
_zip_entry_finalize(zip_entry_t *e) {
|
||||
_zip_unchange_data(e);
|
||||
_zip_dirent_free(e->orig);
|
||||
_zip_dirent_free(e->changes);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_entry_init(zip_entry_t *e) {
|
||||
e->orig = NULL;
|
||||
e->changes = NULL;
|
||||
e->source = NULL;
|
||||
e->deleted = 0;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
This file was generated automatically by CMake
|
||||
from zip.h; make changes there.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
const char * const _zip_err_str[] = {
|
||||
"No error",
|
||||
"Multi-disk zip archives not supported",
|
||||
"Renaming temporary file failed",
|
||||
"Closing zip archive failed",
|
||||
"Seek error",
|
||||
"Read error",
|
||||
"Write error",
|
||||
"CRC error",
|
||||
"Containing zip archive was closed",
|
||||
"No such file",
|
||||
"File already exists",
|
||||
"Can't open file",
|
||||
"Failure to create temporary file",
|
||||
"Zlib error",
|
||||
"Malloc failure",
|
||||
"Entry has been changed",
|
||||
"Compression method not supported",
|
||||
"Premature end of file",
|
||||
"Invalid argument",
|
||||
"Not a zip archive",
|
||||
"Internal error",
|
||||
"Zip archive inconsistent",
|
||||
"Can't remove file",
|
||||
"Entry has been deleted",
|
||||
"Encryption method not supported",
|
||||
"Read-only archive",
|
||||
"No password provided",
|
||||
"Wrong password provided",
|
||||
"Operation not supported",
|
||||
"Resource still in use",
|
||||
"Tell error",
|
||||
"Compressed data invalid",
|
||||
"Operation cancelled",
|
||||
};
|
||||
|
||||
const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);
|
||||
|
||||
#define N ZIP_ET_NONE
|
||||
#define S ZIP_ET_SYS
|
||||
#define Z ZIP_ET_ZLIB
|
||||
|
||||
const int _zip_err_type[] = {
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
S,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
S,
|
||||
Z,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
N,
|
||||
S,
|
||||
N,
|
||||
N,
|
||||
};
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
zip_error.c -- zip_error_t helper functions
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_code_system(const zip_error_t *error) {
|
||||
return error->sys_err;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_code_zip(const zip_error_t *error) {
|
||||
return error->zip_err;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_fini(zip_error_t *err) {
|
||||
free(err->str);
|
||||
err->str = NULL;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_init(zip_error_t *err) {
|
||||
err->zip_err = ZIP_ER_OK;
|
||||
err->sys_err = 0;
|
||||
err->str = NULL;
|
||||
}
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_init_with_code(zip_error_t *error, int ze) {
|
||||
zip_error_init(error);
|
||||
error->zip_err = ze;
|
||||
switch (zip_error_system_type(error)) {
|
||||
case ZIP_ET_SYS:
|
||||
error->sys_err = errno;
|
||||
break;
|
||||
|
||||
default:
|
||||
error->sys_err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_system_type(const zip_error_t *error) {
|
||||
if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str)
|
||||
return ZIP_ET_NONE;
|
||||
|
||||
return _zip_err_type[error->zip_err];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_error_clear(zip_error_t *err) {
|
||||
if (err == NULL)
|
||||
return;
|
||||
|
||||
err->zip_err = ZIP_ER_OK;
|
||||
err->sys_err = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
|
||||
if (dst == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
dst->zip_err = src->zip_err;
|
||||
dst->sys_err = src->sys_err;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_error_get(const zip_error_t *err, int *zep, int *sep) {
|
||||
if (zep)
|
||||
*zep = err->zip_err;
|
||||
if (sep) {
|
||||
if (zip_error_system_type(err) != ZIP_ET_NONE)
|
||||
*sep = err->sys_err;
|
||||
else
|
||||
*sep = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
zip_error_set(zip_error_t *err, int ze, int se) {
|
||||
if (err) {
|
||||
err->zip_err = ze;
|
||||
err->sys_err = se;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
|
||||
_zip_error_copy(err, zip_source_error(src));
|
||||
}
|
||||
|
||||
|
||||
zip_int64_t
|
||||
zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) {
|
||||
int *e = (int *)data;
|
||||
|
||||
if (length < sizeof(int) * 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
e[0] = zip_error_code_zip(error);
|
||||
e[1] = zip_error_code_system(error);
|
||||
return sizeof(int) * 2;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
zip_error_clear.c -- clear zip error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_clear(zip_t *za) {
|
||||
if (za == NULL)
|
||||
return;
|
||||
|
||||
_zip_error_clear(&za->error);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
zip_error_get.c -- get zip error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN void
|
||||
zip_error_get(zip_t *za, int *zep, int *sep) {
|
||||
_zip_error_get(&za->error, zep, sep);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_error_t *
|
||||
zip_get_error(zip_t *za) {
|
||||
return &za->error;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN zip_error_t *
|
||||
zip_file_get_error(zip_file_t *f) {
|
||||
return &f->error;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
zip_error_get_sys_type.c -- return type of system error code
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#define _ZIP_COMPILING_DEPRECATED
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_get_sys_type(int ze) {
|
||||
if (ze < 0 || ze >= _zip_nerr_str)
|
||||
return 0;
|
||||
|
||||
return _zip_err_type[ze];
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
zip_error_sterror.c -- get string representation of struct zip_error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
|
||||
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.
|
||||
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 names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_error_strerror(zip_error_t *err) {
|
||||
const char *zs, *ss;
|
||||
char buf[128], *s;
|
||||
|
||||
zip_error_fini(err);
|
||||
|
||||
if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) {
|
||||
sprintf(buf, "Unknown error %d", err->zip_err);
|
||||
zs = NULL;
|
||||
ss = buf;
|
||||
}
|
||||
else {
|
||||
zs = _zip_err_str[err->zip_err];
|
||||
|
||||
switch (_zip_err_type[err->zip_err]) {
|
||||
case ZIP_ET_SYS:
|
||||
ss = strerror(err->sys_err);
|
||||
break;
|
||||
|
||||
case ZIP_ET_ZLIB:
|
||||
ss = zError(err->sys_err);
|
||||
break;
|
||||
|
||||
default:
|
||||
ss = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ss == NULL)
|
||||
return zs;
|
||||
else {
|
||||
if ((s = (char *)malloc(strlen(ss) + (zs ? strlen(zs) + 2 : 0) + 1)) == NULL)
|
||||
return _zip_err_str[ZIP_ER_MEMORY];
|
||||
|
||||
sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss);
|
||||
err->str = s;
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 252 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user