mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
Update vendor/libarchive to 3.8.10
ChangeLog: https://github.com/libarchive/libarchive/compare/v3.8.9...v3.8.10 Obtained from: libarchive Libarcive commit: 0c48412be2d94afe1859a807ea7896a18d8900bd
This commit is contained in:
1 parent
6d46c752af
commit
a8dfdb79eb
317 files changed
+14996
-3465
No files matched your search
+82
-22
@@ -6,18 +6,67 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
debian-i386:
|
||||
name: Debian (cmake, i386)
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: i386/debian:bookworm
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential ca-certificates cmake git pkg-config \
|
||||
libacl1-dev libbz2-dev liblz4-dev liblzma-dev \
|
||||
libssl-dev libzstd-dev zlib1g-dev
|
||||
# Plain git instead of the checkout action: the runner executes
|
||||
# actions with its own 64-bit node, which cannot run inside a
|
||||
# 32-bit container.
|
||||
- name: Check out
|
||||
run: |
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
git init -q
|
||||
git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY"
|
||||
git fetch -q --depth 1 origin "$GITHUB_SHA"
|
||||
git checkout -q FETCH_HEAD
|
||||
- name: Configure
|
||||
run: ./build/ci/build.sh -a configure
|
||||
env:
|
||||
BS: cmake
|
||||
- name: Build
|
||||
run: ./build/ci/build.sh -a build
|
||||
env:
|
||||
BS: cmake
|
||||
MAKE_ARGS: -j4
|
||||
- name: Test
|
||||
run: ./build/ci/build.sh -a test
|
||||
env:
|
||||
BS: cmake
|
||||
CTEST_OUTPUT_ON_FAILURE: ON
|
||||
- name: Install
|
||||
run: ./build/ci/build.sh -a install
|
||||
env:
|
||||
BS: cmake
|
||||
# The artifact is built like in the other jobs, but not uploaded:
|
||||
# the upload-artifact action cannot run in this container either,
|
||||
# for the same reason as the checkout action above.
|
||||
- name: Artifact
|
||||
run: ./build/ci/build.sh -a artifact
|
||||
env:
|
||||
BS: cmake
|
||||
|
||||
FreeBSD:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
bs: [autotools, cmake]
|
||||
steps:
|
||||
- name: Build and test on a FreeBSD 15 firecracker VM
|
||||
uses: acj/freebsd-firecracker-action@e04896d2dd91f7ec7381e5f363c6fbe83ee445c3 # v0.11.0
|
||||
- name: Build and test on a FreeBSD 15.1 firecracker VM
|
||||
uses: acj/freebsd-firecracker-action@ba4f70408ef1d979acdd7bd36fc4b27e06fe5abe # v0.12.0
|
||||
with:
|
||||
run-in-vm: |
|
||||
chflags -R noschg / && \
|
||||
fetch -o - https://download.freebsd.org/releases/amd64/15.0-RELEASE/base.txz | bsdtar -x -C / -f - && \
|
||||
fetch -o - https://download.freebsd.org/releases/amd64/15.1-RELEASE/base.txz | bsdtar -x -C / -f - && \
|
||||
pkg bootstrap -y && \
|
||||
cd firecracker-freebsd && \
|
||||
env BS=${{ matrix.bs }} ./build/ci/github_actions/freebsd.sh prepare && \
|
||||
@@ -68,7 +117,7 @@ jobs:
|
||||
run: ./build/ci/build.sh -a artifact
|
||||
env:
|
||||
BS: ${{ matrix.bs }}
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: libarchive-macos-${{ matrix.bs }}-${{ github.sha }}
|
||||
path: libarchive.tar.xz
|
||||
@@ -114,7 +163,7 @@ jobs:
|
||||
run: ./build/ci/build.sh -a artifact
|
||||
env:
|
||||
BS: ${{ matrix.bs }}
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: libarchive-ubuntu-${{ matrix.bs }}-${{ matrix.crypto }}-${{ github.sha }}
|
||||
path: libarchive.tar.xz
|
||||
@@ -133,10 +182,11 @@ jobs:
|
||||
- name: Distcheck
|
||||
run: ./build/ci/build.sh -a distcheck
|
||||
env:
|
||||
CTEST_OUTPUT_ON_FAILURE: ON
|
||||
SKIP_OPEN_FD_ERR_TEST: 1
|
||||
- name: Dist-Artifact
|
||||
run: ./build/ci/build.sh -a dist-artifact
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: libarchive-${{ github.sha }}
|
||||
path: libarchive-dist.tar
|
||||
@@ -146,7 +196,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
be: [mingw-gcc, cygwin-gcc, msvc]
|
||||
be: [cygwin-gcc, msvc]
|
||||
include:
|
||||
- { be: mingw, msystem: mingw64 }
|
||||
- { be: mingw, msystem: ucrt64 }
|
||||
- { be: mingw, msystem: clang64 }
|
||||
env:
|
||||
MSYSTEM: ${{ matrix.msystem }}
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Cygwin
|
||||
@@ -161,21 +217,23 @@ jobs:
|
||||
liblz4-devel libiconv-devel libxml2-devel
|
||||
libzstd-devel libssl-devel
|
||||
- name: Install MinGW (msys2)
|
||||
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
|
||||
if: ${{ matrix.be=='mingw-gcc' }}
|
||||
uses: msys2/setup-msys2@ec48f7c5447b3140e2b088413ae3a55687bccb6e # v2.33.0
|
||||
if: ${{ matrix.be=='mingw' }}
|
||||
with:
|
||||
location: "D:\\"
|
||||
install: |-
|
||||
mingw-w64-x86_64-gcc
|
||||
mingw-w64-x86_64-autotools
|
||||
mingw-w64-x86_64-binutils
|
||||
mingw-w64-x86_64-pkgconf
|
||||
mingw-w64-x86_64-cmake
|
||||
mingw-w64-x86_64-make
|
||||
mingw-w64-x86_64-zlib
|
||||
mingw-w64-x86_64-bzip2
|
||||
mingw-w64-x86_64-xz
|
||||
mingw-w64-x86_64-zstd
|
||||
suppress-deprecation-warnings: msystem-mingw64
|
||||
msystem: ${{ matrix.msystem }}
|
||||
pacboy: |-
|
||||
gcc:p
|
||||
autotools:p
|
||||
binutils:p
|
||||
pkgconf:p
|
||||
cmake:p
|
||||
make:p
|
||||
zlib:p
|
||||
bzip2:p
|
||||
xz:p
|
||||
zstd:p
|
||||
- name: Configure
|
||||
run: ./build/ci/github_actions/ci.cmd configure
|
||||
shell: cmd
|
||||
@@ -202,7 +260,9 @@ jobs:
|
||||
shell: cmd
|
||||
env:
|
||||
BE: ${{ matrix.be }}
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: libarchive-windows-${{ matrix.be }}-${{ github.sha }}
|
||||
# for msvc and cygwin, libarchive-windows-backend-arch
|
||||
# for mingw, libarchive-windows-mingw-msystem-arch
|
||||
name: libarchive-windows-${{ matrix.be }}${{ matrix.be=='mingw' && format('-{0}', matrix.msystem) || '' }}-${{ github.sha }}
|
||||
path: ${{ matrix.be=='cygwin-gcc' && 'libarchive.tar.xz' || 'libarchive.zip' }}
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
||||
@@ -29,15 +29,15 @@ jobs:
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
uses: github/codeql-action/autobuild@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- name: Configure
|
||||
run: ./build/ci/build.sh -a configure
|
||||
env:
|
||||
CMAKE_ARGS: -GNinja -DENABLE_CLANG_TIDY=YES -DCLANG_TIDY_PATH=la-lint
|
||||
CMAKE_ARGS: -GNinja -DENABLE_CLANG_TIDY=YES -DCLANG_TIDY_PATH=la-lint;--extra-arg=-Werror=newline-eof
|
||||
- name: Build
|
||||
run: ./build/ci/build.sh -a build
|
||||
env:
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -60,6 +60,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
+91
-50
@@ -223,6 +223,7 @@ option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
OPTION(ENABLE_MBEDTLS "Enable use of mbed TLS" OFF)
|
||||
OPTION(ENABLE_NETTLE "Enable use of Nettle" OFF)
|
||||
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
|
||||
OPTION(ENABLE_MD "Enable use of Message Digest" ON)
|
||||
OPTION(ENABLE_LIBB2 "Enable the use of the system LIBB2 library if found" ON)
|
||||
OPTION(ENABLE_LZ4 "Enable the use of the system LZ4 library if found" ON)
|
||||
OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF)
|
||||
@@ -232,13 +233,14 @@ OPTION(ENABLE_ZSTD "Enable the use of the system zstd library if found" ON)
|
||||
OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON)
|
||||
OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON)
|
||||
OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON)
|
||||
OPTION(ENABLE_BSDXML "Enable the use of the system bsdxml library if found" ON)
|
||||
OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON)
|
||||
OPTION(ENABLE_WIN32_XMLLITE "Enable the use of the Windows XmlLite library if found" ON)
|
||||
OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON)
|
||||
OPTION(ENABLE_PCRE2POSIX "Enable the use of the system PCRE2POSIX library if found" ON)
|
||||
OPTION(ENABLE_LIBGCC "Enable the use of the system LibGCC library if found" ON)
|
||||
# CNG is used for encrypt/decrypt Zip archives on Windows.
|
||||
OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON)
|
||||
OPTION(ENABLE_CNG "Enable the use of Windows CNG (Crypto Next Generation) if found" ON)
|
||||
|
||||
OPTION(ENABLE_TAR "Enable tar building" ON)
|
||||
OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" FALSE)
|
||||
@@ -316,8 +318,8 @@ IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$")
|
||||
ENDIF()
|
||||
|
||||
IF(MINGW)
|
||||
ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO)
|
||||
ADD_DEFINITIONS(-D__MINGW_USE_VC2005_COMPAT)
|
||||
ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO=1)
|
||||
ADD_DEFINITIONS(-D__MINGW_USE_VC2005_COMPAT=1)
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
@@ -801,9 +803,11 @@ LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/richacl.h" HAVE_SYS_RICHACL_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/single_threaded.h" HAVE_SYS_SINGLE_THREADED_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/sysctl.h" HAVE_SYS_SYSCTL_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/sysmacros.h" HAVE_SYS_SYSMACROS_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H)
|
||||
LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H)
|
||||
@@ -817,10 +821,11 @@ LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H)
|
||||
LA_CHECK_INCLUDE_FILE("wchar.h" HAVE_WCHAR_H)
|
||||
LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H)
|
||||
LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H)
|
||||
IF(ENABLE_CNG)
|
||||
LA_CHECK_INCLUDE_FILE("bcrypt.h" HAVE_BCRYPT_H)
|
||||
IF(HAVE_BCRYPT_H)
|
||||
LIST(APPEND ADDITIONAL_LIBS "bcrypt")
|
||||
LA_CHECK_INCLUDE_FILE("bcrypt.h" HAVE_BCRYPT_H)
|
||||
IF(HAVE_BCRYPT_H)
|
||||
LIST(APPEND ADDITIONAL_LIBS "bcrypt")
|
||||
IF(ENABLE_CNG)
|
||||
SET(ARCHIVE_CRYPTO_WIN 1)
|
||||
# bcrypt supports these algorithms on all available versions
|
||||
SET(ARCHIVE_CRYPTO_MD5 1)
|
||||
SET(ARCHIVE_CRYPTO_MD5_WIN 1)
|
||||
@@ -832,10 +837,8 @@ IF(ENABLE_CNG)
|
||||
SET(ARCHIVE_CRYPTO_SHA384_WIN 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA512 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA512_WIN 1)
|
||||
ENDIF(HAVE_BCRYPT_H)
|
||||
ELSE(ENABLE_CNG)
|
||||
UNSET(HAVE_BCRYPT_H CACHE)
|
||||
ENDIF(ENABLE_CNG)
|
||||
ENDIF(ENABLE_CNG)
|
||||
ENDIF(HAVE_BCRYPT_H)
|
||||
# Following files need windows.h, so we should test it after windows.h test.
|
||||
LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H)
|
||||
|
||||
@@ -895,6 +898,8 @@ IF(ENABLE_NETTLE)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/sha1.h" HAVE_NETTLE_SHA1_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/sha2.h" HAVE_NETTLE_SHA2_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/version.h" HAVE_NETTLE_VERSION_H)
|
||||
CMAKE_POP_CHECK_STATE()
|
||||
|
||||
@@ -928,7 +933,7 @@ ELSE()
|
||||
ENDIF()
|
||||
|
||||
# FreeBSD libmd
|
||||
IF(NOT OPENSSL_FOUND)
|
||||
IF(ENABLE_MD AND NOT OPENSSL_FOUND)
|
||||
CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND)
|
||||
IF(LIBMD_FOUND)
|
||||
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
|
||||
@@ -937,7 +942,7 @@ IF(NOT OPENSSL_FOUND)
|
||||
LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY})
|
||||
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
|
||||
ENDIF(LIBMD_FOUND)
|
||||
ENDIF(NOT OPENSSL_FOUND)
|
||||
ENDIF(ENABLE_MD AND NOT OPENSSL_FOUND)
|
||||
|
||||
# libbsd for readpassphrase on Haiku
|
||||
IF("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku")
|
||||
@@ -1145,7 +1150,6 @@ IF(ENABLE_ICONV)
|
||||
CHECK_ICONV("libiconv" "const")
|
||||
CHECK_ICONV("libiconv" "")
|
||||
IF (HAVE_ICONV)
|
||||
SET(HAVE_LIBICONV 1)
|
||||
LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH})
|
||||
ENDIF(HAVE_ICONV)
|
||||
ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH)
|
||||
@@ -1189,7 +1193,6 @@ ELSE(ENABLE_ICONV)
|
||||
# (once enabled).
|
||||
UNSET(HAVE_LOCALE_CHARSET CACHE)
|
||||
UNSET(HAVE_ICONV CACHE)
|
||||
UNSET(HAVE_LIBICONV CACHE)
|
||||
UNSET(HAVE_ICONV_libc_ CACHE)
|
||||
UNSET(HAVE_ICONV_libc_const CACHE)
|
||||
UNSET(HAVE_ICONV_libiconv_ CACHE)
|
||||
@@ -1206,7 +1209,7 @@ ENDIF(ENABLE_ICONV)
|
||||
# Find Libxml2
|
||||
#
|
||||
IF(ENABLE_LIBXML2 AND HAVE_ICONV)
|
||||
FIND_PACKAGE(LibXml2)
|
||||
FIND_PACKAGE(LibXml2 2.7.3)
|
||||
ELSE()
|
||||
SET(LIBXML2_FOUND FALSE)
|
||||
ENDIF()
|
||||
@@ -1233,40 +1236,61 @@ IF(LIBXML2_FOUND)
|
||||
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
|
||||
ELSE(LIBXML2_FOUND)
|
||||
#
|
||||
# Find Expat
|
||||
# Find XmlLite
|
||||
#
|
||||
IF(ENABLE_EXPAT)
|
||||
FIND_PACKAGE(EXPAT)
|
||||
ELSE()
|
||||
SET(EXPAT_FOUND FALSE)
|
||||
ENDIF()
|
||||
IF(EXPAT_FOUND)
|
||||
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
|
||||
INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES})
|
||||
SET(HAVE_LIBEXPAT 1)
|
||||
LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
|
||||
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
|
||||
ELSE(EXPAT_FOUND)
|
||||
IF(WIN32 AND ENABLE_WIN32_XMLLITE)
|
||||
# Check linkage as well; versions of mingw-w64 before v11.0.0
|
||||
# do not contain an import library for xmllite.
|
||||
cmake_push_check_state()
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "xmllite" "uuid")
|
||||
check_c_source_compiles("
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
int main() {
|
||||
return CreateXmlReader(&IID_IXmlReader, NULL, NULL);
|
||||
}
|
||||
" HAVE_XMLLITE_H)
|
||||
cmake_pop_check_state()
|
||||
IF(HAVE_XMLLITE_H)
|
||||
SET(XMLLITE_FOUND TRUE)
|
||||
LIST(APPEND ADDITIONAL_LIBS "xmllite" "uuid")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF(EXPAT_FOUND)
|
||||
IF(WIN32 AND ENABLE_WIN32_XMLLITE)
|
||||
# Check linkage as well; versions of mingw-w64 before v11.0.0
|
||||
# do not contain an import library for XmlLite.
|
||||
cmake_push_check_state()
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "xmllite" "uuid")
|
||||
check_c_source_compiles("
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
int main() {
|
||||
return CreateXmlReader(&IID_IXmlReader, NULL, NULL);
|
||||
}
|
||||
" HAVE_XMLLITE_H)
|
||||
cmake_pop_check_state()
|
||||
IF(HAVE_XMLLITE_H)
|
||||
SET(HAVE_LIBXMLLITE 1)
|
||||
SET(XMLLITE_FOUND TRUE)
|
||||
LIST(APPEND ADDITIONAL_LIBS "xmllite" "uuid")
|
||||
ENDIF(HAVE_XMLLITE_H)
|
||||
ENDIF(WIN32 AND ENABLE_WIN32_XMLLITE)
|
||||
IF(NOT XMLLITE_FOUND)
|
||||
#
|
||||
# Find Expat
|
||||
#
|
||||
IF(ENABLE_EXPAT)
|
||||
FIND_PACKAGE(EXPAT)
|
||||
ELSE(ENABLE_EXPAT)
|
||||
SET(EXPAT_FOUND FALSE)
|
||||
ENDIF(ENABLE_EXPAT)
|
||||
IF(EXPAT_FOUND)
|
||||
CMAKE_PUSH_CHECK_STATE() # Save the state of the variables
|
||||
INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIRS})
|
||||
LIST(APPEND CMAKE_REQUIRED_INCLUDES ${EXPAT_INCLUDE_DIR})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES})
|
||||
SET(HAVE_LIBEXPAT 1)
|
||||
LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H)
|
||||
CMAKE_POP_CHECK_STATE() # Restore the state of the variables
|
||||
ENDIF(EXPAT_FOUND)
|
||||
#
|
||||
# Find bsdxml
|
||||
#
|
||||
IF(NOT EXPAT_FOUND)
|
||||
IF(ENABLE_BSDXML)
|
||||
FIND_PATH(BSDXML_INCLUDE_DIR NAMES bsdxml.h)
|
||||
FIND_LIBRARY(BSDXML_LIBRARY NAMES bsdxml)
|
||||
IF(BSDXML_INCLUDE_DIR AND BSDXML_LIBRARY)
|
||||
INCLUDE_DIRECTORIES(${BSDXML_INCLUDE_DIR})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${BSDXML_LIBRARY})
|
||||
SET(HAVE_LIBBSDXML 1)
|
||||
LA_CHECK_INCLUDE_FILE("bsdxml.h" HAVE_BSDXML_H)
|
||||
ENDIF(BSDXML_INCLUDE_DIR AND BSDXML_LIBRARY)
|
||||
ENDIF(ENABLE_BSDXML)
|
||||
ENDIF(NOT EXPAT_FOUND)
|
||||
ENDIF(NOT XMLLITE_FOUND)
|
||||
ENDIF(LIBXML2_FOUND)
|
||||
MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES)
|
||||
@@ -1462,6 +1486,17 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
|
||||
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin")
|
||||
ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
|
||||
CMAKE_C_COMPILER_ID MATCHES "^Clang$")
|
||||
IF (MSVC)
|
||||
#
|
||||
# The Windows CRT marks a number of standard functions (e.g. wcscpy) as
|
||||
# deprecated. All source files in this project are compiled with those
|
||||
# deprecations suppressed, so suppress these warnings for the following
|
||||
# symbol checks as well. Otherwise, the deprecation warnings get turned into
|
||||
# errors by ENABLE_WERROR's /WX flag and the check fails even when the
|
||||
# function exists.
|
||||
#
|
||||
LIST(APPEND CMAKE_REQUIRED_DEFINITIONS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS)
|
||||
ENDIF (MSVC)
|
||||
CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
|
||||
@@ -1470,6 +1505,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(closefrom HAVE_CLOSEFROM)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(close_range HAVE_CLOSE_RANGE)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(explicit_bzero HAVE_EXPLICIT_BZERO)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
|
||||
@@ -1510,6 +1546,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(memset_explicit HAVE_MEMSET_EXPLICIT)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(mknod HAVE_MKNOD)
|
||||
@@ -1564,6 +1601,7 @@ CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
|
||||
CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R)
|
||||
CHECK_FUNCTION_EXISTS(strftime HAVE_STRFTIME)
|
||||
CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF)
|
||||
CHECK_FUNCTION_EXISTS(waitpid HAVE_WAITPID)
|
||||
CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP)
|
||||
CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY)
|
||||
CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE)
|
||||
@@ -2218,7 +2256,10 @@ ENDIF(WIN32 AND NOT CYGWIN AND ENABLE_INSTALL)
|
||||
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/libarchive)
|
||||
#
|
||||
IF(MSVC)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
ADD_DEFINITIONS(
|
||||
-D_CRT_NONSTDC_NO_WARNINGS
|
||||
-D_CRT_SECURE_NO_DEPRECATE
|
||||
)
|
||||
ENDIF(MSVC)
|
||||
|
||||
OPTION(DONT_FAIL_ON_CRC_ERROR "Ignore CRC errors during parsing (For fuzzing)" OFF)
|
||||
|
||||
+103
-13
@@ -108,7 +108,6 @@ include_HEADERS= libarchive/archive.h libarchive/archive_entry.h
|
||||
noinst_HEADERS= \
|
||||
libarchive/archive_acl_private.h \
|
||||
libarchive/archive_cmdline_private.h \
|
||||
libarchive/archive_crc32.h \
|
||||
libarchive/archive_cryptor_private.h \
|
||||
libarchive/archive_digest_private.h \
|
||||
libarchive/archive_endian.h \
|
||||
@@ -137,9 +136,11 @@ noinst_HEADERS= \
|
||||
libarchive/archive_string.h \
|
||||
libarchive/archive_string_composition.h \
|
||||
libarchive/archive_time_private.h \
|
||||
libarchive/archive_umask_private.h \
|
||||
libarchive/archive_write_disk_private.h \
|
||||
libarchive/archive_write_private.h \
|
||||
libarchive/archive_write_set_format_private.h \
|
||||
libarchive/archive_xml_private.h \
|
||||
libarchive/archive_xxhash.h \
|
||||
libarchive/config_freebsd.h \
|
||||
libarchive/filter_fork.h
|
||||
@@ -148,6 +149,7 @@ libarchive_la_SOURCES= \
|
||||
libarchive/archive_acl.c \
|
||||
libarchive/archive_check_magic.c \
|
||||
libarchive/archive_cmdline.c \
|
||||
libarchive/archive_crc32.c \
|
||||
libarchive/archive_cryptor.c \
|
||||
libarchive/archive_digest.c \
|
||||
libarchive/archive_entry.c \
|
||||
@@ -217,6 +219,7 @@ libarchive_la_SOURCES= \
|
||||
libarchive/archive_string.c \
|
||||
libarchive/archive_string_sprintf.c \
|
||||
libarchive/archive_time.c \
|
||||
libarchive/archive_umask.c \
|
||||
libarchive/archive_util.c \
|
||||
libarchive/archive_version_details.c \
|
||||
libarchive/archive_virtual.c \
|
||||
@@ -302,7 +305,10 @@ endif
|
||||
|
||||
# -no-undefined marks that libarchive doesn't rely on symbols
|
||||
# defined in the application. This is mandatory for cygwin.
|
||||
libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION) $(DEAD_CODE_REMOVAL)
|
||||
# For Windows, set libtool bindir.
|
||||
libarchive_la_LDFLAGS= -no-undefined -version-info $(ARCHIVE_LIBTOOL_VERSION) \
|
||||
$(DEAD_CODE_REMOVAL) $(DLL_BINDIR)
|
||||
|
||||
libarchive_la_LIBADD= $(LTLIBICONV)
|
||||
|
||||
# Manpages to install
|
||||
@@ -382,6 +388,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/read_open_memory.c \
|
||||
libarchive/test/test_7zip_filename_encoding.c \
|
||||
libarchive/test/test_acl_from_text_overread.c \
|
||||
libarchive/test/test_archive_crc32.c \
|
||||
libarchive/test/test_acl_nfs4.c \
|
||||
libarchive/test/test_acl_nfs4_null_id_overflow.c \
|
||||
libarchive/test/test_acl_nfs4_text.c \
|
||||
@@ -399,15 +406,18 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_archive_match_owner.c \
|
||||
libarchive/test/test_archive_match_path.c \
|
||||
libarchive/test/test_archive_match_time.c \
|
||||
libarchive/test/test_archive_ntfs_time.c \
|
||||
libarchive/test/test_archive_parse_date.c \
|
||||
libarchive/test/test_archive_pathmatch.c \
|
||||
libarchive/test/test_archive_pathmatch_oob.c \
|
||||
libarchive/test/test_archive_read.c \
|
||||
libarchive/test/test_archive_read_add_passphrase.c \
|
||||
libarchive/test/test_archive_read_append_filter.c \
|
||||
libarchive/test/test_archive_read_close_twice.c \
|
||||
libarchive/test/test_archive_read_multiple_data_objects.c \
|
||||
libarchive/test/test_archive_read_next_header_empty.c \
|
||||
libarchive/test/test_archive_read_next_header_raw.c \
|
||||
libarchive/test/test_archive_read_open_filenames.c \
|
||||
libarchive/test/test_archive_read_open2.c \
|
||||
libarchive/test/test_archive_read_set_options.c \
|
||||
libarchive/test/test_archive_read_support.c \
|
||||
@@ -445,6 +455,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_compat_xz.c \
|
||||
libarchive/test/test_compat_zip.c \
|
||||
libarchive/test/test_compat_zstd.c \
|
||||
libarchive/test/test_create_child_environment.c \
|
||||
libarchive/test/test_empty_write.c \
|
||||
libarchive/test/test_entry.c \
|
||||
libarchive/test/test_entry_strmode.c \
|
||||
@@ -459,6 +470,8 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_open_filename.c \
|
||||
libarchive/test/test_pax_filename_encoding.c \
|
||||
libarchive/test/test_pax_xattr_header.c \
|
||||
libarchive/test/test_read_data_block_offset_at_eof.c \
|
||||
libarchive/test/test_read_data_into_fd_no_offset_reported.c \
|
||||
libarchive/test/test_read_data_into_fd_size_exceeds_declared.c \
|
||||
libarchive/test/test_read_data_large.c \
|
||||
libarchive/test/test_read_disk.c \
|
||||
@@ -478,6 +491,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_filter_program_signature.c \
|
||||
libarchive/test/test_read_filter_zstd_raw.c \
|
||||
libarchive/test/test_read_filter_uudecode.c \
|
||||
libarchive/test/test_read_filter_uudecode_newlines.c \
|
||||
libarchive/test/test_read_filter_uudecode_raw.c \
|
||||
libarchive/test/test_read_format_7zip.c \
|
||||
libarchive/test/test_read_format_7zip_encryption_data.c \
|
||||
@@ -493,9 +507,11 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_cab_filename.c \
|
||||
libarchive/test/test_read_format_cab_lzx_16bit.c \
|
||||
libarchive/test/test_read_format_cab_lzx_e8.c \
|
||||
libarchive/test/test_read_format_cab_lzx_invalid_history.c \
|
||||
libarchive/test/test_read_format_cab_lzx_oob.c \
|
||||
libarchive/test/test_read_format_cab_mszip_oob.c \
|
||||
libarchive/test/test_read_format_cab_multi.c \
|
||||
libarchive/test/test_read_format_cab_skip_across_folders.c \
|
||||
libarchive/test/test_read_format_cab_skip_malformed.c \
|
||||
libarchive/test/test_read_format_cpio_afio.c \
|
||||
libarchive/test/test_read_format_cpio_bin.c \
|
||||
@@ -520,6 +536,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_gtar_lzma.c \
|
||||
libarchive/test/test_read_format_gtar_redundant_L.c \
|
||||
libarchive/test/test_read_format_gtar_sparse.c \
|
||||
libarchive/test/test_read_format_gtar_sparse_exceeds_length.c \
|
||||
libarchive/test/test_read_format_gtar_sparse_length.c \
|
||||
libarchive/test/test_read_format_gtar_sparse_skip_entry.c \
|
||||
libarchive/test/test_read_format_huge_rpm.c \
|
||||
@@ -537,9 +554,12 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_isorr_new_compress.c \
|
||||
libarchive/test/test_read_format_isorr_rr_moved.c \
|
||||
libarchive/test/test_read_format_isozisofs_compress.c \
|
||||
libarchive/test/test_read_format_iso_rockridge_ce_overflow.c \
|
||||
libarchive/test/test_read_format_iso_rockridge_cl_re_cycle.c \
|
||||
libarchive/test/test_read_format_iso_rockridge_zf_overflow.c \
|
||||
libarchive/test/test_read_format_iso_zisofs_overflow.c \
|
||||
libarchive/test/test_read_format_lha.c \
|
||||
libarchive/test/test_read_format_lha_amiga_script.c \
|
||||
libarchive/test/test_read_format_lha_bugfix_0.c \
|
||||
libarchive/test/test_read_format_lha_filename.c \
|
||||
libarchive/test/test_read_format_lha_filename_utf16.c \
|
||||
@@ -547,6 +567,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_lha_symlink_missing_target.c \
|
||||
libarchive/test/test_read_format_mtree.c \
|
||||
libarchive/test/test_read_format_mtree_crash747.c \
|
||||
libarchive/test/test_read_format_mtree_size.c \
|
||||
libarchive/test/test_read_format_pax_bz2.c \
|
||||
libarchive/test/test_read_format_rar.c \
|
||||
libarchive/test/test_read_format_rar_encryption.c \
|
||||
@@ -554,13 +575,19 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_rar_encryption_partially.c \
|
||||
libarchive/test/test_read_format_rar_encryption_header.c \
|
||||
libarchive/test/test_read_format_rar_filter.c \
|
||||
libarchive/test/test_read_format_rar_filter_incomplete_block.c \
|
||||
libarchive/test/test_read_format_rar_invalid1.c \
|
||||
libarchive/test/test_read_format_rar_overflow.c \
|
||||
libarchive/test/test_read_format_rar5.c \
|
||||
libarchive/test/test_read_format_rar5_bad_filter.c \
|
||||
libarchive/test/test_read_format_rar5_bad_tables.c \
|
||||
libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c \
|
||||
libarchive/test/test_read_format_rar5_extra_field_underflow.c \
|
||||
libarchive/test/test_read_format_rar5_header_size_wraparound.c \
|
||||
libarchive/test/test_read_format_rar5_loop_bug.c \
|
||||
libarchive/test/test_read_format_rar5_redir_overflow.c \
|
||||
libarchive/test/test_read_format_rar5_truncated_htime.c \
|
||||
libarchive/test/test_read_format_rar5_varint_near_eof.c \
|
||||
libarchive/test/test_read_format_raw.c \
|
||||
libarchive/test/test_read_format_tar.c \
|
||||
libarchive/test/test_read_format_tar_acl_oob_read.c \
|
||||
@@ -573,6 +600,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_tar_invalid_pax_size.c \
|
||||
libarchive/test/test_read_format_tar_mac_metadata.c \
|
||||
libarchive/test/test_read_format_tar_pax_g_large.c \
|
||||
libarchive/test/test_read_format_tar_pax_global_header.c \
|
||||
libarchive/test/test_read_format_tar_pax_large_attr.c \
|
||||
libarchive/test/test_read_format_tar_pax_negative_time.c \
|
||||
libarchive/test/test_read_format_tar_pax_sun_holesdata.c \
|
||||
@@ -589,7 +617,10 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_xar_doublelink.c \
|
||||
libarchive/test/test_read_format_zip.c \
|
||||
libarchive/test/test_read_format_zip_7075_utf8_paths.c \
|
||||
libarchive/test/test_read_format_zip_ambiguous_timestamps.c \
|
||||
libarchive/test/test_read_format_zip_comment_stored.c \
|
||||
libarchive/test/test_read_format_zip_dos_mtime_precedence.c \
|
||||
libarchive/test/test_read_format_zip_empty.c \
|
||||
libarchive/test/test_read_format_zip_encryption_data.c \
|
||||
libarchive/test/test_read_format_zip_encryption_partially.c \
|
||||
libarchive/test/test_read_format_zip_encryption_header.c \
|
||||
@@ -597,17 +628,22 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_read_format_zip_filename.c \
|
||||
libarchive/test/test_read_format_zip_high_compression.c \
|
||||
libarchive/test/test_read_format_zip_jar.c \
|
||||
libarchive/test/test_read_format_zip_lzma_alone_large_size.c \
|
||||
libarchive/test/test_read_format_zip_mac_metadata.c \
|
||||
libarchive/test/test_read_format_zip_malformed.c \
|
||||
libarchive/test/test_read_format_zip_msdos.c \
|
||||
libarchive/test/test_read_format_zip_negative_timestamps.c \
|
||||
libarchive/test/test_read_format_zip_nested.c \
|
||||
libarchive/test/test_read_format_zip_nofiletype.c \
|
||||
libarchive/test/test_read_format_zip_ntfs_precedence.c \
|
||||
libarchive/test/test_read_format_zip_ntfs_timestamp.c \
|
||||
libarchive/test/test_read_format_zip_padded.c \
|
||||
libarchive/test/test_read_format_zip_sfx.c \
|
||||
libarchive/test/test_read_format_zip_size_exceeds_declared.c \
|
||||
libarchive/test/test_read_format_zip_symlink_unsupported_compression.c \
|
||||
libarchive/test/test_read_format_zip_traditional_encryption_data.c \
|
||||
libarchive/test/test_read_format_zip_uncompressed_size_off_by_4gib.c \
|
||||
libarchive/test/test_read_format_zip_unset_times.c \
|
||||
libarchive/test/test_read_format_zip_winzip_aes.c \
|
||||
libarchive/test/test_read_format_zip_winzip_aes_large.c \
|
||||
libarchive/test/test_read_format_zip_zip64.c \
|
||||
@@ -644,6 +680,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_write_disk_perms.c \
|
||||
libarchive/test/test_write_disk_secure.c \
|
||||
libarchive/test/test_write_disk_secure_noabsolutepaths.c \
|
||||
libarchive/test/test_write_disk_secure_physicaldrive.c \
|
||||
libarchive/test/test_write_disk_secure744.c \
|
||||
libarchive/test/test_write_disk_secure745.c \
|
||||
libarchive/test/test_write_disk_secure746.c \
|
||||
@@ -683,6 +720,7 @@ libarchive_test_SOURCES= \
|
||||
libarchive/test/test_write_format_iso9660_joliet_id.c \
|
||||
libarchive/test/test_write_format_iso9660_rockridge.c \
|
||||
libarchive/test/test_write_format_iso9660_rockridge_overflow.c \
|
||||
libarchive/test/test_write_format_iso9660_rr_moved_notdir.c \
|
||||
libarchive/test/test_write_format_iso9660_zisofs.c \
|
||||
libarchive/test/test_write_format_iso9660_zisofs_overflow.c \
|
||||
libarchive/test/test_write_format_mtree.c \
|
||||
@@ -747,8 +785,8 @@ libarchive_test_LDADD= $(LTLIBICONV)
|
||||
# Building it automatically provides a sanity-check on libarchive_test_SOURCES
|
||||
# above.
|
||||
libarchive/test/list.h: $(libarchive_test_SOURCES)
|
||||
$(MKDIR_P) libarchive/test
|
||||
grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
@$(MKDIR_P) libarchive/test
|
||||
$(AM_V_GEN)grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
|
||||
libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/libarchive/test LRZIP=NOCONFIG
|
||||
|
||||
@@ -757,6 +795,8 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_fuzz_consumer.h \
|
||||
libarchive/test/test_acl_pax_posix1e.tar.uu \
|
||||
libarchive/test/test_acl_pax_nfs4.tar.uu \
|
||||
libarchive/test/test_archive_read_open_filenames_split_uaf_1.tar.uu \
|
||||
libarchive/test/test_archive_read_open_filenames_split_uaf_2.tar.uu \
|
||||
libarchive/test/test_archive_string_conversion.txt.Z.uu \
|
||||
libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu \
|
||||
libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu \
|
||||
@@ -813,6 +853,7 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_compat_zip_8.zip.uu \
|
||||
libarchive/test/test_compat_zstd_1.tar.zst.uu \
|
||||
libarchive/test/test_compat_zstd_2.tar.zst.uu \
|
||||
libarchive/test/test_compat_zstd_3.tar.zst.uu \
|
||||
libarchive/test/test_fuzz.cab.uu \
|
||||
libarchive/test/test_fuzz.lzh.uu \
|
||||
libarchive/test/test_fuzz_1.iso.Z.uu \
|
||||
@@ -873,7 +914,13 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_7zip_copy_2.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_arm64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_arm64_large.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_arm_arm64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_armthumb.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_delta.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_ia64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_powerpc.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_deflate_riscv.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_delta_lzma1.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_delta_lzma2.7z.uu \
|
||||
@@ -891,6 +938,13 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_7zip_lzma1.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_2.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_arm.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_arm64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_armthumb.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_ia64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_powerpc.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_riscv.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma1_sparc.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma2.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma2_arm64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_lzma2_arm.7z.uu \
|
||||
@@ -902,8 +956,12 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_7zip_malformed3.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_malformed4.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_null_client_next.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_ppmd.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_ppmd_arm64.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_ppmd_bcj.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_ppmd_small_block.7z.uu \
|
||||
libarchive/test/test_read_format_7zip_sfx_boundary_elf.elf.uu \
|
||||
libarchive/test/test_read_format_7zip_sfx_boundary_pe.exe.uu \
|
||||
libarchive/test/test_read_format_7zip_sfx_elf.elf.uu \
|
||||
@@ -925,9 +983,12 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_cab_filename_cp932.cab.uu \
|
||||
libarchive/test/test_read_format_cab_lzx_16bit.cab.uu \
|
||||
libarchive/test/test_read_format_cab_lzx_e8.cab.uu \
|
||||
libarchive/test/test_read_format_cab_lzx_invalid_history.cab.uu \
|
||||
libarchive/test/test_read_format_cab_lzx_literal_control.cab.uu \
|
||||
libarchive/test/test_read_format_cab_lzx_oob.cab.uu \
|
||||
libarchive/test/test_read_format_cab_multi.p1.cab.uu \
|
||||
libarchive/test/test_read_format_cab_multi.p2.cab.uu \
|
||||
libarchive/test/test_read_format_cab_skip_across_folders.cab.uu \
|
||||
libarchive/test/test_read_format_cab_skip_malformed.cab.uu \
|
||||
libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu \
|
||||
libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu \
|
||||
@@ -951,6 +1012,7 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_gtar_sparse_1_17_posix01.tar.uu \
|
||||
libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu \
|
||||
libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu \
|
||||
libarchive/test/test_read_format_gtar_sparse_exceeds_length.tar.Z.uu \
|
||||
libarchive/test/test_read_format_gtar_sparse_reuse.tar.uu \
|
||||
libarchive/test/test_read_format_gtar_sparse_length.tar.Z.uu \
|
||||
libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu \
|
||||
@@ -967,12 +1029,16 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_iso_rockridge.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_ce_overflow.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_cl_re_control.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_cl_re_cycle.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_rockridge_zf_overflow.iso.uu \
|
||||
libarchive/test/test_read_format_iso_xorriso.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_zisofs.iso.Z.uu \
|
||||
libarchive/test/test_read_format_iso_zisofs_overflow.iso.uu \
|
||||
libarchive/test/test_read_format_lha_amiga_script.lha.uu \
|
||||
libarchive/test/test_read_format_lha_bugfix_0.lzh.uu \
|
||||
libarchive/test/test_read_format_lha_filename_cp932.lzh.uu \
|
||||
libarchive/test/test_read_format_lha_filename_utf16.lzh.uu \
|
||||
@@ -999,6 +1065,7 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_rar_encryption_partially.rar.uu \
|
||||
libarchive/test/test_read_format_rar_endarc_huge.rar.uu \
|
||||
libarchive/test/test_read_format_rar_filter.rar.uu \
|
||||
libarchive/test/test_read_format_rar_filter_incomplete_block.rar.uu \
|
||||
libarchive/test/test_read_format_rar_invalid1.rar.uu \
|
||||
libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu \
|
||||
libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu \
|
||||
@@ -1040,13 +1107,17 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_rar5_different_window_size.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_distance_overflow.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_extra_data_size_toolong.rar.Z.uu \
|
||||
libarchive/test/test_read_format_rar5_extra_field_underflow.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_extra_field_version.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_fileattr.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_group_name_toolong.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_hardlink.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_invalid_dict_reference.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_leftshift1.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_leftshift2.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_loop_bug.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_redir_overflow.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_multiarchive.part02.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_multiarchive.part03.rar.uu \
|
||||
@@ -1064,7 +1135,9 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_rar5_nonempty_dir_stream.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_dirdata.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_owner.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_owner_name_toolong.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_readtables_overflow.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_redir_varint_2byte.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_sfx.exe.uu \
|
||||
libarchive/test/test_read_format_rar5_solid.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_stored.rar.uu \
|
||||
@@ -1082,6 +1155,7 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_rar5_bad_tables.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_bad_window_sz_in_mltarc_file.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_data_ready_pointer_leak.rar.uu \
|
||||
libarchive/test/test_read_format_rar5_zip_in_rar.rar.uu \
|
||||
libarchive/test/test_read_format_raw.bufr.uu \
|
||||
libarchive/test/test_read_format_raw.data.gz.uu \
|
||||
libarchive/test/test_read_format_raw.data.Z.uu \
|
||||
@@ -1096,6 +1170,8 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_tar_invalid_pax_size.tar.uu \
|
||||
libarchive/test/test_read_format_tar_mac_metadata_1.tar.uu \
|
||||
libarchive/test/test_read_format_tar_pax_g_large.tar.uu \
|
||||
libarchive/test/test_read_format_tar_pax_global_header.tar.uu \
|
||||
libarchive/test/test_read_format_tar_pax_global_header_ignorable.tar.uu \
|
||||
libarchive/test/test_read_format_tar_pax_large_attr.tar.Z.uu \
|
||||
libarchive/test/test_read_format_tar_pax_negative_time.tar.uu \
|
||||
libarchive/test/test_read_format_tar_pax_sun_holesdata.tar.uu \
|
||||
@@ -1104,14 +1180,18 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \
|
||||
libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \
|
||||
libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
|
||||
libarchive/test/test_read_format_warc.warc.uu \
|
||||
libarchive/test/test_read_format_warc_uri_nul.warc.uu \
|
||||
libarchive/test/test_read_format_warc_incomplete.warc.uu \
|
||||
libarchive/test/test_read_format_warc.warc.uu \
|
||||
libarchive/test/test_read_format_xar_atou64_overread.xar.uu \
|
||||
libarchive/test/test_read_format_xar_base64_oob.xar.uu \
|
||||
libarchive/test/test_read_format_xar_doublelink.xar.uu \
|
||||
libarchive/test/test_read_format_xar_duplicate_filename_node.xar.uu \
|
||||
libarchive/test/test_read_format_xar_empty_xattr.xar.uu \
|
||||
libarchive/test/test_read_format_xar_large_mode.xar.uu \
|
||||
libarchive/test/test_read_format_xar_parse_time_overread.xar.uu \
|
||||
libarchive/test/test_read_format_xar_toc_premature_stream_end.xar.uu \
|
||||
libarchive/test/test_read_format_xar_toc_premature_stream_end_control.xar.uu \
|
||||
libarchive/test/test_read_format_zip.zip.uu \
|
||||
libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \
|
||||
libarchive/test/test_read_format_zip_7z_deflate.zip.uu \
|
||||
@@ -1134,6 +1214,7 @@ libarchive_test_EXTRA_DIST=\
|
||||
libarchive/test/test_read_format_zip_high_compression.zip.uu \
|
||||
libarchive/test/test_read_format_zip_length_at_end.zip.uu \
|
||||
libarchive/test/test_read_format_zip_lzma.zipx.uu \
|
||||
libarchive/test/test_read_format_zip_lzma_alone_large_size.zip.uu \
|
||||
libarchive/test/test_read_format_zip_lzma_alone_leak.zipx.uu \
|
||||
libarchive/test/test_read_format_zip_lzma_multi.zipx.uu \
|
||||
libarchive/test/test_read_format_zip_lzma_stream_end.zipx.uu \
|
||||
@@ -1211,15 +1292,19 @@ libarchive_test_EXTRA_DIST=\
|
||||
#
|
||||
noinst_HEADERS+= \
|
||||
libarchive_fe/lafe_err.h \
|
||||
libarchive_fe/lafe_explicit_bzero.h \
|
||||
libarchive_fe/lafe_fnmatch.h \
|
||||
libarchive_fe/lafe_getline.h \
|
||||
libarchive_fe/lafe_platform.h \
|
||||
libarchive_fe/lafe_setmode.h \
|
||||
libarchive_fe/line_reader.h \
|
||||
libarchive_fe/passphrase.h
|
||||
libarchive_fe_la_SOURCES= \
|
||||
libarchive_fe/lafe_err.c \
|
||||
libarchive_fe/lafe_explicit_bzero.c \
|
||||
libarchive_fe/lafe_fnmatch.c \
|
||||
libarchive_fe/lafe_getline.c \
|
||||
libarchive_fe/lafe_setmode.c \
|
||||
libarchive_fe/line_reader.c \
|
||||
libarchive_fe/passphrase.c
|
||||
|
||||
@@ -1315,6 +1400,7 @@ bsdtar_test_SOURCES= \
|
||||
tar/test/test_extract_tar_lzo.c \
|
||||
tar/test/test_extract_tar_xz.c \
|
||||
tar/test/test_extract_tar_zstd.c \
|
||||
tar/test/test_edit_pathname_hardlink.c \
|
||||
tar/test/test_format_newc.c \
|
||||
tar/test/test_help.c \
|
||||
tar/test/test_leading_slash.c \
|
||||
@@ -1347,6 +1433,7 @@ bsdtar_test_SOURCES= \
|
||||
tar/test/test_option_lz4.c \
|
||||
tar/test/test_option_lzma.c \
|
||||
tar/test/test_option_lzop.c \
|
||||
tar/test/test_option_mode.c \
|
||||
tar/test/test_option_mtime.c \
|
||||
tar/test/test_option_n.c \
|
||||
tar/test/test_option_newer_than.c \
|
||||
@@ -1381,8 +1468,8 @@ bsdtar_test_CPPFLAGS=\
|
||||
$(PLATFORMCPPFLAGS)
|
||||
|
||||
tar/test/list.h: $(bsdtar_test_SOURCES)
|
||||
$(MKDIR_P) tar/test
|
||||
grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
@$(MKDIR_P) tar/test
|
||||
$(AM_V_GEN)grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
|
||||
if BUILD_BSDTAR
|
||||
bsdtar_test_programs= bsdtar_test
|
||||
@@ -1406,6 +1493,7 @@ bsdtar_test_EXTRA_DIST= \
|
||||
tar/test/test_extract.tar.lzo.uu \
|
||||
tar/test/test_extract.tar.xz.uu \
|
||||
tar/test/test_leading_slash.tar.uu \
|
||||
tar/test/test_edit_pathname_hardlink.tar.Z.uu \
|
||||
tar/test/test_list_item.tar.uu \
|
||||
tar/test/test_option_keep_newer_files.tar.Z.uu \
|
||||
tar/test/test_option_passphrase.zip.uu \
|
||||
@@ -1539,8 +1627,8 @@ bsdcpio_test_CPPFLAGS= \
|
||||
bsdcpio_test_LDADD=libarchive_fe.la
|
||||
|
||||
cpio/test/list.h: $(bsdcpio_test_SOURCES)
|
||||
$(MKDIR_P) cpio/test
|
||||
grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
@$(MKDIR_P) cpio/test
|
||||
$(AM_V_GEN)grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
|
||||
if BUILD_BSDCPIO
|
||||
bsdcpio_test_programs= bsdcpio_test
|
||||
@@ -1662,8 +1750,8 @@ bsdcat_test_CPPFLAGS= \
|
||||
bsdcat_test_LDADD=libarchive_fe.la
|
||||
|
||||
cat/test/list.h: $(bsdcat_test_SOURCES)
|
||||
$(MKDIR_P) cat/test
|
||||
grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
@$(MKDIR_P) cat/test
|
||||
$(AM_V_GEN)grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
|
||||
if BUILD_BSDCAT
|
||||
bsdcat_test_programs= bsdcat_test
|
||||
@@ -1780,6 +1868,7 @@ bsdunzip_test_SOURCES= \
|
||||
unzip/test/test_t_bad.c \
|
||||
unzip/test/test_u.c \
|
||||
unzip/test/test_version.c \
|
||||
unzip/test/test_windows_paths.c \
|
||||
unzip/test/test_x.c \
|
||||
unzip/test/test_Z1.c \
|
||||
unzip/test/test_P_encryption.c \
|
||||
@@ -1794,8 +1883,8 @@ bsdunzip_test_CPPFLAGS= \
|
||||
bsdunzip_test_LDADD=libarchive_fe.la
|
||||
|
||||
unzip/test/list.h: $(bsdunzip_test_SOURCES)
|
||||
$(MKDIR_P) unzip/test
|
||||
grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
@$(MKDIR_P) unzip/test
|
||||
$(AM_V_GEN)grep -h '^DEFINE_TEST(' $^ | LC_COLLATE=C sort > $@
|
||||
|
||||
if BUILD_BSDUNZIP
|
||||
bsdunzip_test_programs= bsdunzip_test
|
||||
@@ -1815,6 +1904,7 @@ bsdunzip_test_EXTRA_DIST= \
|
||||
unzip/test/test_symlink_1.zip.uu \
|
||||
unzip/test/test_symlink_2.zip.uu \
|
||||
unzip/test/test_symlink_dotdot.zip.uu \
|
||||
unzip/test/test_windows_paths.zip.uu \
|
||||
unzip/test/test_t_bad.zip.uu \
|
||||
unzip/test/test_u_new.zip.uu \
|
||||
unzip/test/test_u_old.zip.uu \
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Oct 14, 2026: libarchive 3.8.10 released
|
||||
|
||||
Jul 28, 2026: libarchive 3.8.9 released
|
||||
|
||||
Jun 23, 2026: libarchive 3.8.8 released
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# visibility.m4
|
||||
# serial 9
|
||||
dnl Copyright (C) 2005, 2008, 2010-2026 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
dnl This file is offered as-is, without any warranty.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
dnl Tests whether the compiler supports the command-line option
|
||||
dnl -fvisibility=hidden and the function and variable attributes
|
||||
dnl __attribute__((__visibility__("hidden"))) and
|
||||
dnl __attribute__((__visibility__("default"))).
|
||||
dnl Does *not* test for __visibility__("protected") - which has tricky
|
||||
dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
|
||||
dnl Mac OS X.
|
||||
dnl Does *not* test for __visibility__("internal") - which has processor
|
||||
dnl dependent semantics.
|
||||
dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
|
||||
dnl "really only recommended for legacy code".
|
||||
dnl Set the variable CFLAG_VISIBILITY.
|
||||
dnl Defines and sets the variable HAVE_VISIBILITY.
|
||||
|
||||
AC_DEFUN([gl_VISIBILITY],
|
||||
[
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
CFLAG_VISIBILITY=
|
||||
HAVE_VISIBILITY=0
|
||||
if test -n "$GCC"; then
|
||||
dnl First, check whether -Werror can be added to the command line, or
|
||||
dnl whether it leads to an error because of some other option that the
|
||||
dnl user has put into $CC $CFLAGS $CPPFLAGS.
|
||||
AC_CACHE_CHECK([whether the -Werror option is usable],
|
||||
[gl_cv_cc_vis_werror],
|
||||
[gl_saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[]], [[]])],
|
||||
[gl_cv_cc_vis_werror=yes],
|
||||
[gl_cv_cc_vis_werror=no])
|
||||
CFLAGS="$gl_saved_CFLAGS"
|
||||
])
|
||||
dnl Now check whether visibility declarations are supported.
|
||||
AC_CACHE_CHECK([for simple visibility declarations],
|
||||
[gl_cv_cc_visibility],
|
||||
[gl_saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fvisibility=hidden"
|
||||
dnl We use the option -Werror and a function dummyfunc, because on some
|
||||
dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning
|
||||
dnl "visibility attribute not supported in this configuration; ignored"
|
||||
dnl at the first function definition in every compilation unit, and we
|
||||
dnl don't want to use the option in this case.
|
||||
if test $gl_cv_cc_vis_werror = yes; then
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
fi
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[extern __attribute__((__visibility__("hidden"))) int hiddenvar;
|
||||
extern __attribute__((__visibility__("default"))) int exportedvar;
|
||||
extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
|
||||
extern __attribute__((__visibility__("default"))) int exportedfunc (void);
|
||||
void dummyfunc (void);
|
||||
int hiddenvar;
|
||||
int exportedvar;
|
||||
int hiddenfunc (void) { return 51; }
|
||||
int exportedfunc (void) { return 1225736919; }
|
||||
void dummyfunc (void) {}
|
||||
]],
|
||||
[[]])],
|
||||
[gl_cv_cc_visibility=yes],
|
||||
[gl_cv_cc_visibility=no])
|
||||
CFLAGS="$gl_saved_CFLAGS"
|
||||
])
|
||||
if test $gl_cv_cc_visibility = yes; then
|
||||
CFLAG_VISIBILITY="-fvisibility=hidden"
|
||||
HAVE_VISIBILITY=1
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([CFLAG_VISIBILITY])
|
||||
AC_SUBST([HAVE_VISIBILITY])
|
||||
AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
|
||||
[Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
|
||||
])
|
||||
+14
-21
@@ -4,6 +4,7 @@
|
||||
#
|
||||
# Variables that can be passed via environment:
|
||||
# BS= # build system (autotools or cmake)
|
||||
# BUILD_SYSTEM= # alias for BS, overrides BS if set
|
||||
# CRYPTO= # cryptography provider (openssl, nettle or mbedtls)
|
||||
# BUILDDIR= # build directory
|
||||
# SRCDIR= # source directory
|
||||
@@ -26,10 +27,9 @@ CMAKE_ARGS="${CMAKE_ARGS:-}"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS:-}"
|
||||
CURDIR=`pwd`
|
||||
SRCDIR="${SRCDIR:-`pwd`}"
|
||||
RET=0
|
||||
|
||||
usage () {
|
||||
echo "Usage: $0 [-b autotools|cmake] [-a autogen|configure|build|test|install|distcheck ] [ -a ... ] [ -d builddir ] [-c openssl|nettle|mbedtls] [-s srcdir ]"
|
||||
echo "Usage: $0 [-b autotools|cmake] [-a autogen|configure|build|test|install|distcheck|artifact|dist-artifact ] [ -a ... ] [ -d builddir ] [-c openssl|nettle|mbedtls] [-s srcdir ]"
|
||||
}
|
||||
inputerror () {
|
||||
echo $1
|
||||
@@ -117,6 +117,15 @@ fi
|
||||
if [ -z "${BUILDDIR:-}" ]; then
|
||||
BUILDDIR="${CURDIR}/build_ci/${BS}"
|
||||
fi
|
||||
# The loop below cd's around, so make these absolute.
|
||||
case "${SRCDIR}" in
|
||||
/*) ;;
|
||||
*) SRCDIR="${CURDIR}/${SRCDIR}" ;;
|
||||
esac
|
||||
case "${BUILDDIR}" in
|
||||
/*) ;;
|
||||
*) BUILDDIR="${CURDIR}/${BUILDDIR}" ;;
|
||||
esac
|
||||
mkdir -p "${BUILDDIR}"
|
||||
for action in ${ACTIONS}; do
|
||||
cd "${BUILDDIR}"
|
||||
@@ -126,7 +135,6 @@ for action in ${ACTIONS}; do
|
||||
autotools)
|
||||
cd "${SRCDIR}"
|
||||
sh build/autogen.sh
|
||||
RET="$?"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
@@ -135,38 +143,27 @@ for action in ${ACTIONS}; do
|
||||
autotools) "${SRCDIR}/configure" ${CONFIGURE_ARGS} ;;
|
||||
cmake) ${CMAKE} ${CMAKE_ARGS} "${SRCDIR}" ;;
|
||||
esac
|
||||
RET="$?"
|
||||
;;
|
||||
build)
|
||||
${MAKE} ${MAKE_ARGS}
|
||||
RET="$?"
|
||||
;;
|
||||
test)
|
||||
case "${BS}" in
|
||||
autotools)
|
||||
${MAKE} ${MAKE_ARGS} check LOG_DRIVER="${SRCDIR}/build/ci/test_driver"
|
||||
${MAKE} ${MAKE_ARGS} check LOG_DRIVER="${SRCDIR}/build/ci/test_driver" _VERBOSITY_LEVEL=2
|
||||
;;
|
||||
cmake)
|
||||
${MAKE} ${MAKE_ARGS} test
|
||||
${MAKE} ${MAKE_ARGS} test _VERBOSITY_LEVEL=2
|
||||
;;
|
||||
esac
|
||||
RET="$?"
|
||||
find ${TMPDIR:-/tmp} -path '*_test.*' -name '*.log' -print -exec cat {} \; 2>/dev/null || /bin/true
|
||||
;;
|
||||
install)
|
||||
${MAKE} ${MAKE_ARGS} install DESTDIR="${BUILDDIR}/destdir"
|
||||
RET="$?"
|
||||
cd "${BUILDDIR}/destdir" && ls -lR .
|
||||
./usr/local/bin/bsdtar --version
|
||||
;;
|
||||
distcheck)
|
||||
${MAKE} ${MAKE_ARGS} distcheck || (
|
||||
RET="$?"
|
||||
find . -name 'test-suite.log' -print -exec cat {} \;
|
||||
find ${TMPDIR:-/tmp} -path '*_test.*' -name '*.log' -print -exec cat {} \; 2>/dev/null || /bin/true
|
||||
exit "${RET}"
|
||||
)
|
||||
RET="$?"
|
||||
${MAKE} ${MAKE_ARGS} distcheck _VERBOSITY_LEVEL=2
|
||||
;;
|
||||
artifact)
|
||||
tar -c -J -C "${BUILDDIR}/destdir" -f "${CURDIR}/libarchive.tar.xz" usr
|
||||
@@ -178,9 +175,5 @@ for action in ${ACTIONS}; do
|
||||
ls -l "${CURDIR}/libarchive-dist.tar"
|
||||
;;
|
||||
esac
|
||||
if [ "${RET}" != "0" ]; then
|
||||
exit "${RET}"
|
||||
fi
|
||||
cd "${CURDIR}"
|
||||
done
|
||||
exit "${RET}"
|
||||
@@ -1,20 +1,20 @@
|
||||
@ECHO OFF
|
||||
IF NOT "%BE%"=="mingw-gcc" (
|
||||
IF NOT "%BE%"=="mingw" (
|
||||
IF NOT "%BE%"=="msvc" (
|
||||
IF NOT "%BE%"=="cygwin-gcc" (
|
||||
ECHO Environment variable BE must be cygwin-gcc, mingw-gcc or msvc
|
||||
ECHO Environment variable BE must be cygwin-gcc, mingw or msvc
|
||||
EXIT /b 1
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
SET ORIGPATH=%PATH%
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\msys64\mingw64\bin;C:\Program Files\cmake\bin
|
||||
IF "%BE%"=="mingw" (
|
||||
SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\msys64\%MSYSTEM%\bin;C:\Program Files\cmake\bin
|
||||
)
|
||||
|
||||
IF "%1%"=="configure" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
IF "%BE%"=="mingw" (
|
||||
SET PATH=%MINGWPATH%
|
||||
MKDIR build_ci\cmake
|
||||
CD build_ci\cmake
|
||||
@@ -29,7 +29,7 @@ IF "%1%"=="configure" (
|
||||
D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a configure" || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="build" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
IF "%BE%"=="mingw" (
|
||||
SET PATH=%MINGWPATH%
|
||||
CD build_ci\cmake
|
||||
mingw32-make -j %NUMBER_OF_PROCESSORS% VERBOSE=1 || EXIT /b 1
|
||||
@@ -38,12 +38,13 @@ IF "%1%"=="configure" (
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
SET MAKE_ARGS=-j
|
||||
SET MAKE_ARGS=-j %NUMBER_OF_PROCESSORS%
|
||||
SET CYGWIN_NOWINPATH=1
|
||||
D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a build" || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="test" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET _VERBOSITY_LEVEL=2
|
||||
IF "%BE%"=="mingw" (
|
||||
SET PATH=%MINGWPATH%
|
||||
CD build_ci\cmake
|
||||
SET SKIP_TEST_SPARSE=1
|
||||
@@ -60,7 +61,7 @@ IF "%1%"=="configure" (
|
||||
EXIT /b 0
|
||||
)
|
||||
) ELSE IF "%1%"=="install" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
IF "%BE%"=="mingw" (
|
||||
SET PATH=%MINGWPATH%
|
||||
CD build_ci\cmake
|
||||
mingw32-make install || EXIT /b 1
|
||||
|
||||
@@ -34,7 +34,7 @@ then
|
||||
fi
|
||||
BUILDDIR="${CURDIR}/build_ci/${BS}"
|
||||
cd "$BUILDDIR"
|
||||
TMPDIR=/tmp_acl_nfsv4 ${BIN_SUBDIR}/libarchive_test -r "${CURDIR}/libarchive/test" -v test_acl_platform_nfs4
|
||||
_VERBOSITY_LEVEL=2 TMPDIR=/tmp_acl_nfsv4 ${BIN_SUBDIR}/libarchive_test -r "${CURDIR}/libarchive/test" -v test_acl_platform_nfs4
|
||||
else
|
||||
echo "Usage: $0 prepare | test"
|
||||
exit 1
|
||||
|
||||
+262
-226
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1 +1 @@
|
||||
3008009
|
||||
3008010
|
||||
+320
-280
@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
|
||||
dnl In particular, this allows the version macro to be used in AC_INIT
|
||||
|
||||
dnl These first two version numbers are updated automatically on each release.
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.8.9])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3008009])
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.8.10])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3008010])
|
||||
|
||||
dnl bsdtar and bsdcpio versioning tracks libarchive
|
||||
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
|
||||
@@ -15,39 +15,39 @@ m4_define([BSDUNZIP_VERSION_S],LIBARCHIVE_VERSION_S())
|
||||
|
||||
AC_PREREQ([2.71])
|
||||
|
||||
#
|
||||
# Now starts the "real" configure script.
|
||||
#
|
||||
dnl
|
||||
dnl Now starts the "real" configure script.
|
||||
dnl
|
||||
|
||||
AC_INIT([libarchive],[LIBARCHIVE_VERSION_S()],[[email protected]])
|
||||
# Make sure the srcdir contains "libarchive" directory
|
||||
dnl Make sure the srcdir contains "libarchive" directory
|
||||
AC_CONFIG_SRCDIR([libarchive])
|
||||
# Use auxiliary subscripts from this subdirectory (cleans up root)
|
||||
dnl Use auxiliary subscripts from this subdirectory (cleans up root)
|
||||
AC_CONFIG_AUX_DIR([build/autoconf])
|
||||
# M4 scripts
|
||||
dnl M4 scripts
|
||||
AC_CONFIG_MACRO_DIR([build/autoconf])
|
||||
# Must follow AC_CONFIG macros above...
|
||||
dnl Must follow AC_CONFIG macros above...
|
||||
AM_INIT_AUTOMAKE([1.11 dist-xz dist-zip])
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
# Libtool's "interface version" can be computed from the libarchive version.
|
||||
dnl Libtool's "interface version" can be computed from the libarchive version.
|
||||
|
||||
# Libtool interface version bumps on any API change, so increments
|
||||
# whenever libarchive minor version does.
|
||||
dnl Libtool interface version bumps on any API change, so increments
|
||||
dnl whenever libarchive minor version does.
|
||||
ARCHIVE_MINOR=$(( (LIBARCHIVE_VERSION_N() / 1000) % 1000 ))
|
||||
# Libarchive 2.7 == libtool interface 9 = 2 + 7
|
||||
# Libarchive 2.8 == libtool interface 10 = 2 + 8
|
||||
# Libarchive 2.9 == libtool interface 11 = 2 + 9
|
||||
# Libarchive 3.0 == libtool interface 12
|
||||
# Libarchive 3.1 == libtool interface 13
|
||||
dnl Libarchive 2.7 == libtool interface 9 = 2 + 7
|
||||
dnl Libarchive 2.8 == libtool interface 10 = 2 + 8
|
||||
dnl Libarchive 2.9 == libtool interface 11 = 2 + 9
|
||||
dnl Libarchive 3.0 == libtool interface 12
|
||||
dnl Libarchive 3.1 == libtool interface 13
|
||||
ARCHIVE_INTERFACE=`echo $((13 + ${ARCHIVE_MINOR}))`
|
||||
# Libarchive revision is bumped on any source change === libtool revision
|
||||
dnl Libarchive revision is bumped on any source change === libtool revision
|
||||
ARCHIVE_REVISION=$(( LIBARCHIVE_VERSION_N() % 1000 ))
|
||||
# Libarchive minor is bumped on any interface addition === libtool age
|
||||
dnl Libarchive minor is bumped on any interface addition === libtool age
|
||||
ARCHIVE_LIBTOOL_VERSION=$ARCHIVE_INTERFACE:$ARCHIVE_REVISION:$ARCHIVE_MINOR
|
||||
|
||||
# Stick the version numbers into config.h
|
||||
dnl Stick the version numbers into config.h
|
||||
AC_DEFINE([__LIBARCHIVE_CONFIG_H_INCLUDED], [1],
|
||||
[Internal macro for sanity checks])
|
||||
AC_DEFINE([LIBARCHIVE_VERSION_STRING],"LIBARCHIVE_VERSION_S()",
|
||||
@@ -63,9 +63,9 @@ AC_DEFINE([BSDCAT_VERSION_STRING],"BSDTAR_VERSION_S()",
|
||||
AC_DEFINE([BSDUNZIP_VERSION_STRING],"BSDUNZIP_VERSION_S()",
|
||||
[Version number of bsdunzip])
|
||||
|
||||
# The shell variables here must be the same as the AC_SUBST() variables
|
||||
# below, but the shell variable names apparently cannot be the same as
|
||||
# the m4 macro names above. Why? Ask autoconf.
|
||||
dnl The shell variables here must be the same as the AC_SUBST() variables
|
||||
dnl below, but the shell variable names apparently cannot be the same as
|
||||
dnl the m4 macro names above. Why? Ask autoconf.
|
||||
BSDCPIO_VERSION_STRING=BSDCPIO_VERSION_S()
|
||||
BSDTAR_VERSION_STRING=BSDTAR_VERSION_S()
|
||||
BSDCAT_VERSION_STRING=BSDCAT_VERSION_S()
|
||||
@@ -73,9 +73,9 @@ BSDUNZIP_VERSION_STRING=BSDUNZIP_VERSION_S()
|
||||
LIBARCHIVE_VERSION_STRING=LIBARCHIVE_VERSION_S()
|
||||
LIBARCHIVE_VERSION_NUMBER=LIBARCHIVE_VERSION_N()
|
||||
|
||||
# Substitute the above version numbers into the various files below.
|
||||
# Yes, I believe this is the fourth time we define what are essentially
|
||||
# the same symbols. Why? Ask autoconf.
|
||||
dnl Substitute the above version numbers into the various files below.
|
||||
dnl Yes, I believe this is the fourth time we define what are essentially
|
||||
dnl the same symbols. Why? Ask autoconf.
|
||||
AC_SUBST(ARCHIVE_LIBTOOL_VERSION)
|
||||
AC_SUBST(BSDCPIO_VERSION_STRING)
|
||||
AC_SUBST(BSDTAR_VERSION_STRING)
|
||||
@@ -88,7 +88,7 @@ AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([build/pkgconfig/libarchive.pc])
|
||||
|
||||
# Check for host type
|
||||
dnl Check for host type
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
dnl Compilation on mingw and Cygwin needs special Makefile rules
|
||||
@@ -107,7 +107,7 @@ AS_IF([test $inc_windows_files = yes], [AC_CHECK_TOOL([WINDRES], [windres])])
|
||||
dnl Defines that are required for specific platforms (e.g. -D_POSIX_SOURCE, etc)
|
||||
PLATFORMCPPFLAGS=
|
||||
case "$host_os" in
|
||||
*mingw* ) PLATFORMCPPFLAGS=-D__USE_MINGW_ANSI_STDIO -D__MINGW_USE_VC2005_COMPAT ;;
|
||||
*mingw* ) PLATFORMCPPFLAGS="-D__USE_MINGW_ANSI_STDIO=1 -D__MINGW_USE_VC2005_COMPAT=1" ;;
|
||||
esac
|
||||
AC_SUBST(PLATFORMCPPFLAGS)
|
||||
|
||||
@@ -116,7 +116,7 @@ case "$host_os" in
|
||||
haiku*) LIBS="-lbsd $LIBS" ;;
|
||||
esac
|
||||
|
||||
# Checks for programs.
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CPP
|
||||
@@ -126,11 +126,11 @@ LT_INIT([win32-dll])
|
||||
AC_CHECK_TOOL([STRIP],[strip])
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
#
|
||||
# Options for building bsdtar.
|
||||
#
|
||||
# Default is to build bsdtar, but allow people to override that.
|
||||
#
|
||||
dnl
|
||||
dnl Options for building bsdtar.
|
||||
dnl
|
||||
dnl Default is to build bsdtar, but allow people to override that.
|
||||
dnl
|
||||
AC_ARG_ENABLE([bsdtar],
|
||||
[AS_HELP_STRING([--enable-bsdtar], [enable build of bsdtar (default)])
|
||||
AS_HELP_STRING([--enable-bsdtar=static], [force static build of bsdtar])
|
||||
@@ -170,11 +170,11 @@ esac
|
||||
AM_CONDITIONAL([BUILD_BSDTAR], [ test "$build_bsdtar" = yes ])
|
||||
AM_CONDITIONAL([STATIC_BSDTAR], [ test "$static_bsdtar" = yes ])
|
||||
|
||||
#
|
||||
# Options for building bsdcat.
|
||||
#
|
||||
# Default is to build bsdcat, but allow people to override that.
|
||||
#
|
||||
dnl
|
||||
dnl Options for building bsdcat.
|
||||
dnl
|
||||
dnl Default is to build bsdcat, but allow people to override that.
|
||||
dnl
|
||||
AC_ARG_ENABLE([bsdcat],
|
||||
[AS_HELP_STRING([--enable-bsdcat], [enable build of bsdcat (default)])
|
||||
AS_HELP_STRING([--enable-bsdcat=static], [force static build of bsdcat])
|
||||
@@ -214,11 +214,11 @@ esac
|
||||
AM_CONDITIONAL([BUILD_BSDCAT], [ test "$build_bsdcat" = yes ])
|
||||
AM_CONDITIONAL([STATIC_BSDCAT], [ test "$static_bsdcat" = yes ])
|
||||
|
||||
#
|
||||
# Options for building bsdcpio.
|
||||
#
|
||||
# Default is not to build bsdcpio, but that can be overridden.
|
||||
#
|
||||
dnl
|
||||
dnl Options for building bsdcpio.
|
||||
dnl
|
||||
dnl Default is to build bsdcpio, but allow people to override that.
|
||||
dnl
|
||||
AC_ARG_ENABLE([bsdcpio],
|
||||
[AS_HELP_STRING([--enable-bsdcpio], [enable build of bsdcpio (default)])
|
||||
AS_HELP_STRING([--enable-bsdcpio=static], [static build of bsdcpio])
|
||||
@@ -257,50 +257,17 @@ esac
|
||||
AM_CONDITIONAL([BUILD_BSDCPIO], [ test "$build_bsdcpio" = yes ])
|
||||
AM_CONDITIONAL([STATIC_BSDCPIO], [ test "$static_bsdcpio" = yes ])
|
||||
|
||||
# Set up defines needed before including any headers
|
||||
case $host in
|
||||
*mingw* | *cygwin* | *msys* )
|
||||
AC_PREPROC_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <windows.h>
|
||||
#ifdef _WIN32_WINNT
|
||||
# error _WIN32_WINNT already defined
|
||||
#endif
|
||||
]],[[;]])
|
||||
],[
|
||||
AC_DEFINE([_WIN32_WINNT], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.])
|
||||
AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.])
|
||||
])
|
||||
AC_PREPROC_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <windows.h>
|
||||
#ifdef WINVER
|
||||
# error WINVER already defined
|
||||
#endif
|
||||
]],[[;]])
|
||||
],[
|
||||
AC_DEFINE([WINVER], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.])
|
||||
])
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Options for building bsdunzip.
|
||||
#
|
||||
# Default is to build bsdunzip, but allow people to override that.
|
||||
# Bsdunzip has not yet been ported for Windows
|
||||
#
|
||||
case "$host_os" in
|
||||
*mingw* | *msys*)
|
||||
enable_bsdunzip=no
|
||||
;;
|
||||
*)
|
||||
AC_ARG_ENABLE([bsdunzip],
|
||||
[AS_HELP_STRING([--enable-bsdunzip], [enable build of bsdunzip (default)])
|
||||
AS_HELP_STRING([--enable-bsdunzip=static], [force static build of bsdunzip])
|
||||
AS_HELP_STRING([--enable-bsdunzip=shared], [force dynamic build of bsdunzip])
|
||||
AS_HELP_STRING([--disable-bsdunzip], [disable build of bsdunzip])],
|
||||
[], [enable_bsdunzip=yes])
|
||||
;;
|
||||
esac
|
||||
dnl
|
||||
dnl Options for building bsdunzip.
|
||||
dnl
|
||||
dnl Default is to build bsdunzip, but allow people to override that.
|
||||
dnl
|
||||
AC_ARG_ENABLE([bsdunzip],
|
||||
[AS_HELP_STRING([--enable-bsdunzip], [enable build of bsdunzip (default)])
|
||||
AS_HELP_STRING([--enable-bsdunzip=static], [force static build of bsdunzip])
|
||||
AS_HELP_STRING([--enable-bsdunzip=shared], [force dynamic build of bsdunzip])
|
||||
AS_HELP_STRING([--disable-bsdunzip], [disable build of bsdunzip])],
|
||||
[], [enable_bsdunzip=yes])
|
||||
|
||||
case "$enable_bsdunzip" in
|
||||
yes)
|
||||
@@ -334,12 +301,53 @@ esac
|
||||
AM_CONDITIONAL([BUILD_BSDUNZIP], [ test "$build_bsdunzip" = yes ])
|
||||
AM_CONDITIONAL([STATIC_BSDUNZIP], [ test "$static_bsdunzip" = yes ])
|
||||
|
||||
# Checks for header files.
|
||||
dnl Set up libtool bindir for dll generation on Windows
|
||||
AC_MSG_CHECKING([if Windows libtool -bindir is needed])
|
||||
case "$host_os" in
|
||||
*cygwin* | *mingw* | *msys*)
|
||||
AC_MSG_RESULT([yes])
|
||||
DLL_BINDIR="-bindir \$(bindir)"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT([no])
|
||||
DLL_BINDIR=""
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([DLL_BINDIR])
|
||||
|
||||
dnl Set up defines needed before including any headers
|
||||
case $host in
|
||||
*mingw* | *cygwin* | *msys* )
|
||||
AC_PREPROC_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <windows.h>
|
||||
#ifdef _WIN32_WINNT
|
||||
# error _WIN32_WINNT already defined
|
||||
#endif
|
||||
]],[[;]])
|
||||
],[
|
||||
AC_DEFINE([_WIN32_WINNT], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.])
|
||||
AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.])
|
||||
])
|
||||
AC_PREPROC_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <windows.h>
|
||||
#ifdef WINVER
|
||||
# error WINVER already defined
|
||||
#endif
|
||||
]],[[;]])
|
||||
],[
|
||||
AC_DEFINE([WINVER], 0x0502, [Define to '0x0502' for Windows Server 2003 APIs.])
|
||||
])
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS([acl/libacl.h attr/xattr.h])
|
||||
AC_CHECK_HEADERS([copyfile.h ctype.h])
|
||||
AC_CHECK_HEADERS([errno.h ext2fs/ext2_fs.h fcntl.h fnmatch.h grp.h])
|
||||
AC_CHECK_HEADERS(m4_flatten([
|
||||
acl/libacl.h attr/xattr.h
|
||||
copyfile.h ctype.h direct.h
|
||||
errno.h ext2fs/ext2_fs.h fcntl.h fnmatch.h grp.h
|
||||
]))
|
||||
|
||||
AC_CACHE_CHECK([whether EXT2_IOC_GETFLAGS is usable],
|
||||
[ac_cv_have_decl_EXT2_IOC_GETFLAGS],
|
||||
@@ -353,8 +361,10 @@ AS_VAR_IF([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes],
|
||||
[AC_DEFINE_UNQUOTED([HAVE_WORKING_EXT2_IOC_GETFLAGS], [1],
|
||||
[Define to 1 if you have a working EXT2_IOC_GETFLAGS])])
|
||||
|
||||
AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h])
|
||||
AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/magic.h linux/types.h])
|
||||
AC_CHECK_HEADERS(m4_flatten([
|
||||
inttypes.h io.h langinfo.h limits.h
|
||||
linux/fiemap.h linux/fs.h linux/magic.h linux/types.h
|
||||
]))
|
||||
|
||||
AC_CACHE_CHECK([whether FS_IOC_GETFLAGS is usable],
|
||||
[ac_cv_have_decl_FS_IOC_GETFLAGS],
|
||||
@@ -368,25 +378,29 @@ AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes],
|
||||
[AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1],
|
||||
[Define to 1 if you have a working FS_IOC_GETFLAGS])])
|
||||
|
||||
AC_CHECK_HEADERS([intsafe.h locale.h membership.h paths.h poll.h pthread.h])
|
||||
AC_CHECK_HEADERS([pwd.h readpassphrase.h signal.h spawn.h])
|
||||
AC_CHECK_HEADERS([stdarg.h stdckdint.h stdint.h stdlib.h string.h])
|
||||
AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h])
|
||||
AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h])
|
||||
AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h])
|
||||
AC_CHECK_HEADERS([sys/select.h sys/statfs.h sys/statvfs.h sys/sysmacros.h])
|
||||
AC_CHECK_HEADERS([sys/time.h sys/utime.h sys/utsname.h sys/vfs.h sys/xattr.h])
|
||||
AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h])
|
||||
AC_CHECK_HEADERS(m4_flatten([
|
||||
intsafe.h locale.h membership.h paths.h poll.h pthread.h
|
||||
pwd.h readpassphrase.h signal.h spawn.h
|
||||
stdarg.h stdckdint.h stdint.h stdlib.h string.h
|
||||
sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h
|
||||
sys/ioctl.h sys/mkdev.h sys/mount.h
|
||||
sys/param.h sys/poll.h sys/richacl.h
|
||||
sys/select.h sys/single_threaded.h
|
||||
sys/statfs.h sys/statvfs.h sys/sysctl.h
|
||||
sys/sysmacros.h sys/time.h sys/utime.h sys/utsname.h
|
||||
sys/vfs.h sys/xattr.h time.h unistd.h utime.h wchar.h
|
||||
wctype.h
|
||||
]))
|
||||
AC_CHECK_TYPE([suseconds_t])
|
||||
AC_CHECK_HEADERS([windows.h])
|
||||
# check windows.h first; the other headers require it.
|
||||
dnl check windows.h first; the other headers require it.
|
||||
AC_CHECK_HEADERS([winioctl.h],[],[],
|
||||
[[#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
]])
|
||||
|
||||
# Checks for libraries.
|
||||
dnl Checks for libraries.
|
||||
AC_ARG_WITH([zlib],
|
||||
AS_HELP_STRING([--without-zlib], [Don't build support for gzip through zlib]))
|
||||
|
||||
@@ -431,7 +445,7 @@ if test "x$with_bz2lib" != "xno"; then
|
||||
LIBS="$old_LIBS"
|
||||
AC_MSG_RESULT($ac_cv_lib_bz2_BZ2_bzDecompressInit)
|
||||
if test "x$ac_cv_lib_bz2_BZ2_bzDecompressInit" = xyes; then
|
||||
AC_DEFINE([HAVE_LIBBZ2], [1], [Define to 1 if you have the `bz2' library (-lbz2).])
|
||||
AC_DEFINE([HAVE_LIBBZ2], [1], [Define to 1 if you have the 'bz2' library (-lbz2).])
|
||||
LIBS="-lbz2 $LIBS"
|
||||
fi
|
||||
;;
|
||||
@@ -467,17 +481,15 @@ if test "x$with_iconv" != "xno"; then
|
||||
AC_CHECK_HEADERS([localcharset.h])
|
||||
LIBS="${LIBS} ${LIBICONV}"
|
||||
if test -n "$LIBICONV"; then
|
||||
AC_DEFINE([HAVE_LIBICONV], [1], [Define to 1 if you have the `iconv' library (-liconv).])
|
||||
|
||||
# Most platforms do not provide iconv.pc, but MSYS2 MinGW does.
|
||||
# We add it to our Requires.private only if it exists.
|
||||
dnl Most platforms do not provide iconv.pc, but MSYS2 MinGW does.
|
||||
dnl We add it to our Requires.private only if it exists.
|
||||
PKG_CHECK_MODULES(ICONV_PC, [iconv], [
|
||||
LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }iconv"
|
||||
], [true])
|
||||
fi
|
||||
AC_CHECK_FUNCS([locale_charset])
|
||||
if test "x$ac_cv_func_locale_charset" != "xyes"; then
|
||||
# If locale_charset() is not in libiconv, we have to find libcharset.
|
||||
dnl If locale_charset() is not in libiconv, we have to find libcharset.
|
||||
AC_CHECK_LIB(charset,locale_charset)
|
||||
fi
|
||||
fi
|
||||
@@ -498,9 +510,9 @@ if test "x$with_zstd" != "xno"; then
|
||||
AC_CHECK_HEADERS([zstd.h])
|
||||
AC_CHECK_LIB(zstd,ZSTD_decompressStream)
|
||||
AC_CHECK_LIB(zstd,ZSTD_compressStream,
|
||||
AC_DEFINE([HAVE_ZSTD_compressStream], [1], [Define to 1 if you have the `zstd' library (-lzstd) with compression support.]))
|
||||
AC_DEFINE([HAVE_ZSTD_compressStream], [1], [Define to 1 if you have the 'zstd' library (-lzstd) with compression support.]))
|
||||
AC_CHECK_LIB(zstd,ZSTD_minCLevel,
|
||||
AC_DEFINE([HAVE_ZSTD_minCLevel], [1], [Define to 1 if you have a `zstd' library version with ZSTD_minCLevel().]))
|
||||
AC_DEFINE([HAVE_ZSTD_minCLevel], [1], [Define to 1 if you have a 'zstd' library version with ZSTD_minCLevel().]))
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([lzma],
|
||||
@@ -511,16 +523,16 @@ if test "x$with_lzma" != "xno"; then
|
||||
PKG_CHECK_MODULES(LZMA_PC, [liblzma], [
|
||||
CPPFLAGS="${CPPFLAGS} ${LZMA_PC_CFLAGS}"
|
||||
LIBS="${LIBS} ${LZMA_PC_LIBS}"
|
||||
AC_DEFINE(HAVE_LIBLZMA, [1], [Define to 1 if you have the `lzma' library.])
|
||||
AC_DEFINE(HAVE_LIBLZMA, [1], [Define to 1 if you have the 'lzma' library.])
|
||||
], [
|
||||
AC_CHECK_LIB(lzma,lzma_stream_decoder)
|
||||
])
|
||||
AC_CHECK_HEADERS([lzma.h])
|
||||
|
||||
# Some pre-release (but widely distributed) versions of liblzma
|
||||
# included a disabled version of lzma_stream_encoder_mt that
|
||||
# fools a naive AC_CHECK_LIB or AC_CHECK_FUNC, so we need
|
||||
# to do something more complex here:
|
||||
dnl Some pre-release (but widely distributed) versions of liblzma
|
||||
dnl included a disabled version of lzma_stream_encoder_mt that
|
||||
dnl fools a naive AC_CHECK_LIB or AC_CHECK_FUNC, so we need
|
||||
dnl to do something more complex here:
|
||||
AC_CACHE_CHECK(
|
||||
[whether we have multithread support in lzma],
|
||||
ac_cv_lzma_has_mt,
|
||||
@@ -532,7 +544,7 @@ if test "x$with_lzma" != "xno"; then
|
||||
[[int ignored __attribute__((unused)); ignored = lzma_stream_encoder_mt(0, 0);]])],
|
||||
[ac_cv_lzma_has_mt=yes], [ac_cv_lzma_has_mt=no])])
|
||||
if test "x$ac_cv_lzma_has_mt" != xno; then
|
||||
AC_DEFINE([HAVE_LZMA_STREAM_ENCODER_MT], [1], [Define to 1 if you have the `lzma_stream_encoder_mt' function.])
|
||||
AC_DEFINE([HAVE_LZMA_STREAM_ENCODER_MT], [1], [Define to 1 if you have the 'lzma_stream_encoder_mt' function.])
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -545,7 +557,7 @@ if test "x$with_lzo2" = "xyes"; then
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([cng],
|
||||
AS_HELP_STRING([--without-cng], [Don't build support of CNG(Crypto Next Generation)]))
|
||||
AS_HELP_STRING([--without-cng], [Don't build with crypto support from Windows CNG (Crypto Next Generation)]))
|
||||
|
||||
AC_ARG_WITH([mbedtls],
|
||||
AS_HELP_STRING([--with-mbedtls], [Build with crypto support from mbed TLS]))
|
||||
@@ -553,18 +565,24 @@ AC_ARG_WITH([nettle],
|
||||
AS_HELP_STRING([--with-nettle], [Build with crypto support from Nettle]))
|
||||
AC_ARG_WITH([openssl],
|
||||
AS_HELP_STRING([--without-openssl], [Don't build support for mtree and xar hashes through openssl]))
|
||||
AC_ARG_WITH([md],
|
||||
AS_HELP_STRING([--without-md], [Don't build with crypto support from Message Digest]))
|
||||
case "$host_os" in
|
||||
*darwin* ) with_openssl=no ;;
|
||||
esac
|
||||
|
||||
AC_ARG_WITH([xml2],
|
||||
AS_HELP_STRING([--without-xml2], [Don't build support for xar through libxml2]))
|
||||
AC_ARG_WITH([xmllite],
|
||||
AS_HELP_STRING([--without-xmllite], [Don't build support for xar through XmlLite]))
|
||||
AC_ARG_WITH([bsdxml],
|
||||
AS_HELP_STRING([--without-bsdxml], [Don't build support for xar through bsdxml]))
|
||||
AC_ARG_WITH([expat],
|
||||
AS_HELP_STRING([--without-expat], [Don't build support for xar through expat]))
|
||||
|
||||
if test "x$with_xml2" != "xno"; then
|
||||
PKG_PROG_PKG_CONFIG
|
||||
PKG_CHECK_MODULES(LIBXML2_PC, [libxml-2.0], [
|
||||
PKG_CHECK_MODULES(LIBXML2_PC, [libxml-2.0 >= 2.7.3], [
|
||||
CPPFLAGS="${CPPFLAGS} ${LIBXML2_PC_CFLAGS}"
|
||||
LIBS="${LIBS} ${LIBXML2_PC_LIBS}"
|
||||
AC_CHECK_LIB(xml2,xmlInitParser,[true],AC_MSG_FAILURE(Missing xml2 library))
|
||||
@@ -574,9 +592,49 @@ if test "x$with_xml2" != "xno"; then
|
||||
AC_CHECK_HEADERS([libxml/xmlreader.h libxml/xmlwriter.h libxml/xmlversion.h])
|
||||
fi
|
||||
if test "x$ac_cv_header_libxml_xmlreader_h" != "xyes"; then
|
||||
if test "x$with_expat" != "xno"; then
|
||||
AC_CHECK_HEADERS([expat.h])
|
||||
AC_CHECK_LIB(expat,XML_ParserCreate)
|
||||
if test "x$with_xmllite" != "xno"; then
|
||||
AC_CHECK_HEADERS([xmllite.h])
|
||||
if test "x$ac_cv_header_xmllite_h" == "xyes"; then
|
||||
AC_MSG_CHECKING([for xmllite])
|
||||
saved_LIBS=$LIBS
|
||||
LIBS="$LIBS -lxmllite -luuid -lole32"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
int main() {
|
||||
return CreateXmlReader(&IID_IXmlReader, NULL, NULL);
|
||||
}
|
||||
])],
|
||||
[ AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_LIBXMLLITE], [1], [Define to 1 if you have the 'xmllite' library.])
|
||||
found_xmllite=yes
|
||||
],
|
||||
[ AC_MSG_RESULT([no])
|
||||
LIBS=$saved_LIBS
|
||||
])
|
||||
fi
|
||||
fi
|
||||
if test "x$found_xmllite" != "xyes"; then
|
||||
if test "x$with_expat" != "xno"; then
|
||||
PKG_CHECK_MODULES(EXPAT_PC, [expat], [
|
||||
CPPFLAGS="${CPPFLAGS} ${EXPAT_PC_CFLAGS}"
|
||||
LIBS="${LIBS} ${EXPAT_PC_LIBS}"
|
||||
AC_DEFINE(HAVE_LIBEXPAT, [1], [Define to 1 if you have the 'expat' library.])
|
||||
have_libexpat="yes"
|
||||
], [
|
||||
AC_CHECK_LIB(expat,XML_ParserCreate)
|
||||
if test "x$ac_cv_lib_expat_XML_ParserCreate" != "xyes"; then
|
||||
have_libexpat="yes"
|
||||
fi
|
||||
])
|
||||
AC_CHECK_HEADERS([expat.h])
|
||||
fi
|
||||
if test "x$ac_cv_header_expat_h" != "xyes" || test "x$have_libexpat" != "xyes"; then
|
||||
if test "x$with_bsdxml" != "xno"; then
|
||||
AC_CHECK_HEADERS([bsdxml.h])
|
||||
AC_CHECK_LIB(bsdxml,XML_ParserCreate)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -672,18 +730,18 @@ if test -z $posix_regex_lib_found && (test "$enable_posix_regex_lib" = "auto" ||
|
||||
fi
|
||||
fi
|
||||
|
||||
# TODO: Give the user the option of using a pre-existing system
|
||||
# libarchive. This will define HAVE_LIBARCHIVE which will cause
|
||||
# bsdtar_platform.h to use #include <...> for the libarchive headers.
|
||||
# Need to include Makefile.am magic to link against system
|
||||
# -larchive in that case.
|
||||
#AC_CHECK_LIB(archive,archive_version)
|
||||
dnl TODO: Give the user the option of using a pre-existing system
|
||||
dnl libarchive. This will define HAVE_LIBARCHIVE which will cause
|
||||
dnl bsdtar_platform.h to use #include <...> for the libarchive headers.
|
||||
dnl Need to include Makefile.am magic to link against system
|
||||
dnl -larchive in that case.
|
||||
dnl AC_CHECK_LIB(archive,archive_version)
|
||||
|
||||
# Checks for supported compiler flags
|
||||
dnl Checks for supported compiler flags
|
||||
AX_APPEND_COMPILE_FLAGS([-Wall -Wformat -Wformat-security])
|
||||
|
||||
# Place the functions and data into separate sections, allowing GNU style
|
||||
# linkers to garbage collect the unused ones.
|
||||
dnl Place the functions and data into separate sections, allowing GNU style
|
||||
dnl linkers to garbage collect the unused ones.
|
||||
save_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -Wl,--gc-sections"
|
||||
AC_MSG_CHECKING([whether ld supports --gc-sections])
|
||||
@@ -697,7 +755,7 @@ AC_LINK_IFELSE(
|
||||
LDFLAGS=$save_LDFLAGS
|
||||
|
||||
if test "$DEAD_CODE_REMOVAL" = ""; then
|
||||
# Macos linkers have a -dead_strip flag, which is similar to --gc-sections.
|
||||
dnl Macos linkers have a -dead_strip flag, which is similar to --gc-sections.
|
||||
save_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -Wl,-dead_strip"
|
||||
AC_MSG_CHECKING([whether ld supports -dead_strip])
|
||||
@@ -712,67 +770,67 @@ fi
|
||||
|
||||
AC_SUBST(DEAD_CODE_REMOVAL)
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
# la_TYPE_UID_T defaults to "int", which is incorrect for MinGW
|
||||
# and MSVC. Use a customized version.
|
||||
dnl la_TYPE_UID_T defaults to "int", which is incorrect for MinGW
|
||||
dnl and MSVC. Use a customized version.
|
||||
la_TYPE_UID_T
|
||||
AC_TYPE_MODE_T
|
||||
# AC_TYPE_OFF_T defaults to "long", which limits us to 4GB files on
|
||||
# most systems... default to "long long" instead.
|
||||
dnl AC_TYPE_OFF_T defaults to "long", which limits us to 4GB files on
|
||||
dnl most systems... default to "long long" instead.
|
||||
AC_CHECK_TYPE(off_t, [long long])
|
||||
AC_TYPE_SIZE_T
|
||||
AC_CHECK_TYPE(id_t, [unsigned long])
|
||||
AC_CHECK_TYPE(uintptr_t, [unsigned int])
|
||||
|
||||
# Check for tm_gmtoff in struct tm
|
||||
dnl Check for tm_gmtoff in struct tm
|
||||
AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,,
|
||||
[
|
||||
#include <time.h>
|
||||
])
|
||||
|
||||
# Check for f_namemax in struct statfs
|
||||
dnl Check for f_namemax in struct statfs
|
||||
AC_CHECK_MEMBERS([struct statfs.f_namemax],,,
|
||||
[
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
])
|
||||
|
||||
# Check for f_iosize in struct statfs
|
||||
dnl Check for f_iosize in struct statfs
|
||||
AC_CHECK_MEMBERS([struct statfs.f_iosize],,,
|
||||
[
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
])
|
||||
|
||||
# Check for f_iosize in struct statvfs
|
||||
dnl Check for f_iosize in struct statvfs
|
||||
AC_CHECK_MEMBERS([struct statvfs.f_iosize],,,
|
||||
[
|
||||
#include <sys/statvfs.h>
|
||||
])
|
||||
|
||||
# Check for birthtime in struct stat
|
||||
dnl Check for birthtime in struct stat
|
||||
AC_CHECK_MEMBERS([struct stat.st_birthtime])
|
||||
|
||||
# Check for high-resolution timestamps in struct stat
|
||||
dnl Check for high-resolution timestamps in struct stat
|
||||
AC_CHECK_MEMBERS([struct stat.st_birthtimespec.tv_nsec])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtime_n]) # AIX
|
||||
AC_CHECK_MEMBERS([struct stat.st_umtime]) # Tru64
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtime_usec]) # Hurd
|
||||
# Check for block size support in struct stat
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtime_n]) dnl AIX
|
||||
AC_CHECK_MEMBERS([struct stat.st_umtime]) dnl Tru64
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtime_usec]) dnl Hurd
|
||||
dnl Check for block size support in struct stat
|
||||
AC_CHECK_MEMBERS([struct stat.st_blksize])
|
||||
# Check for st_flags in struct stat (BSD fflags)
|
||||
dnl Check for st_flags in struct stat (BSD fflags)
|
||||
AC_CHECK_MEMBERS([struct stat.st_flags])
|
||||
|
||||
# If you have uintmax_t, we assume printf supports %ju
|
||||
# If you have unsigned long long, we assume printf supports %llu
|
||||
# TODO: Check for %ju and %llu support directly.
|
||||
dnl If you have uintmax_t, we assume printf supports %ju
|
||||
dnl If you have unsigned long long, we assume printf supports %llu
|
||||
dnl TODO: Check for %ju and %llu support directly.
|
||||
AC_CHECK_TYPES([uintmax_t, unsigned long long])
|
||||
|
||||
# We use C99-style integer types
|
||||
# Declare them if the local platform doesn't already do so.
|
||||
dnl We use C99-style integer types
|
||||
dnl Declare them if the local platform doesn't already do so.
|
||||
AC_TYPE_INTMAX_T
|
||||
AC_TYPE_UINTMAX_T
|
||||
AC_TYPE_INT64_T
|
||||
@@ -788,7 +846,7 @@ AC_CHECK_DECLS([INT64_MAX, INT64_MIN, UINT64_MAX, UINT32_MAX])
|
||||
AC_CHECK_DECLS([INTMAX_MAX, INTMAX_MIN, UINTMAX_MAX])
|
||||
|
||||
AC_CHECK_DECL([SSIZE_MAX],
|
||||
[AC_DEFINE(HAVE_DECL_SSIZE_MAX, 1, [Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you don't.])],
|
||||
[AC_DEFINE(HAVE_DECL_SSIZE_MAX, 1, [Define to 1 if you have the declaration of 'SSIZE_MAX', and to 0 if you don't.])],
|
||||
[],
|
||||
[#include <limits.h>])
|
||||
|
||||
@@ -801,7 +859,7 @@ AC_CHECK_DECL([EILSEQ],
|
||||
[],
|
||||
[#include <errno.h>])
|
||||
AC_CHECK_TYPE([wchar_t],
|
||||
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]wchar_t), 1, [Define to 1 if the system has the type `wchar_t'.])dnl
|
||||
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_[]wchar_t), 1, [Define to 1 if the system has the type 'wchar_t'.])dnl
|
||||
AC_CHECK_SIZEOF([wchar_t])],
|
||||
[])
|
||||
|
||||
@@ -810,7 +868,7 @@ AX_COMPILE_CHECK_SIZEOF(long)
|
||||
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h])
|
||||
|
||||
# Checks for library functions.
|
||||
dnl Checks for library functions.
|
||||
AC_HEADER_MAJOR
|
||||
AC_FUNC_FSEEKO
|
||||
AC_FUNC_MEMCMP
|
||||
@@ -819,35 +877,39 @@ AC_FUNC_STAT
|
||||
AC_FUNC_STRERROR_R
|
||||
AC_FUNC_STRFTIME
|
||||
AC_FUNC_VPRINTF
|
||||
# check for:
|
||||
# CreateHardLinkA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES)
|
||||
# To avoid necessity for including windows.h or special forward declaration
|
||||
# workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *'
|
||||
dnl check for:
|
||||
dnl CreateHardLinkA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES)
|
||||
dnl To avoid necessity for including windows.h or special forward declaration
|
||||
dnl workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *'
|
||||
AC_CHECK_STDCALL_FUNC([CreateHardLinkA],[const char *, const char *, void *])
|
||||
AC_CHECK_FUNCS([arc4random_buf chflags chown chroot])
|
||||
AC_CHECK_FUNCS([closefrom close_range ctime_r])
|
||||
AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fdopendir fnmatch fork])
|
||||
AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate])
|
||||
AC_CHECK_FUNCS([futimens futimes futimesat])
|
||||
AC_CHECK_FUNCS([getegid geteuid getline getpid getresgid getresuid])
|
||||
AC_CHECK_FUNCS([getgrgid_r getgrnam_r getpwnam_r getpwuid_r])
|
||||
AC_CHECK_FUNCS([gettimeofday getvfsbyname gmtime_r])
|
||||
AC_CHECK_FUNCS([issetugid])
|
||||
AC_CHECK_FUNCS([lchflags lchmod lchown link linkat localtime_r lstat lutimes])
|
||||
AC_CHECK_FUNCS([mbrtowc memmove memset])
|
||||
AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp])
|
||||
AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawn posix_spawnp])
|
||||
AC_CHECK_FUNCS([readlink readlinkat])
|
||||
AC_CHECK_FUNCS([readpassphrase])
|
||||
AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
|
||||
AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strnlen strrchr symlink])
|
||||
AC_CHECK_FUNCS([sysconf])
|
||||
AC_CHECK_FUNCS([tcgetattr tcsetattr])
|
||||
AC_CHECK_FUNCS([timegm tzset unlinkat unsetenv utime utimensat utimes vfork])
|
||||
AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove])
|
||||
AC_CHECK_FUNCS([_fseeki64 _get_timezone])
|
||||
AC_CHECK_DECL([cmtime_s],
|
||||
[AC_DEFINE(HAVE_CMTIME_S, 1, [cmtime_s function])],
|
||||
AC_CHECK_FUNCS(m4_flatten([
|
||||
arc4random_buf
|
||||
chflags chown chroot closefrom close_range ctime_r
|
||||
explicit_bzero
|
||||
fchdir fchflags fchmod fchown fcntl fdopendir fnmatch fork
|
||||
fstat fstatat fstatfs fstatvfs ftruncate
|
||||
futimens futimes futimesat
|
||||
getegid geteuid getline getpid getresgid getresuid
|
||||
getgrgid_r getgrnam_r getpwnam_r getpwuid_r
|
||||
gettimeofday getvfsbyname gmtime_r
|
||||
issetugid
|
||||
lchflags lchmod lchown link linkat localtime_r lstat lutimes
|
||||
mbrtowc memmove memset memset_explicit mkdir mkfifo mknod mkstemp
|
||||
nl_langinfo
|
||||
openat
|
||||
pipe poll posix_spawn posix_spawnp
|
||||
readlink readlinkat readpassphrase
|
||||
select setenv setlocale sigaction statfs statvfs
|
||||
strchr strdup strerror strncpy_s strnlen strrchr symlink
|
||||
sysconf
|
||||
tcgetattr tcsetattr timegm tzset
|
||||
unlinkat unsetenv utime utimensat utimes
|
||||
vfork
|
||||
waitpid wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove
|
||||
_fseeki64 _get_timezone
|
||||
]))
|
||||
AC_CHECK_DECL([ctime_s],
|
||||
[AC_DEFINE(HAVE_CTIME_S, 1, [ctime_s function])],
|
||||
[],
|
||||
[#include <time.h>])
|
||||
AC_CHECK_DECL([gmtime_s],
|
||||
@@ -863,10 +925,10 @@ AC_CHECK_DECL([_mkgmtime],
|
||||
[],
|
||||
[#include <time.h>])
|
||||
|
||||
# detects cygwin-1.7, as opposed to older versions
|
||||
dnl detects cygwin-1.7, as opposed to older versions
|
||||
AC_CHECK_FUNCS([cygwin_conv_path])
|
||||
|
||||
# DragonFly uses vfsconf, FreeBSD xvfsconf.
|
||||
dnl DragonFly uses vfsconf, FreeBSD xvfsconf.
|
||||
AC_CHECK_TYPES(struct vfsconf,,,
|
||||
[#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
@@ -888,7 +950,7 @@ AC_CHECK_TYPES(struct statfs,,,
|
||||
#include <sys/mount.h>
|
||||
])
|
||||
|
||||
# dirfd can be either a function or a macro.
|
||||
dnl dirfd can be either a function or a macro.
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <dirent.h>
|
||||
DIR *dir;]],
|
||||
@@ -896,9 +958,9 @@ AC_LINK_IFELSE(
|
||||
[AC_DEFINE(HAVE_DIRFD,1,[Define to 1 if you have a dirfd function or macro])]
|
||||
)
|
||||
|
||||
# FreeBSD's nl_langinfo supports an option to specify whether the
|
||||
# current locale uses month/day or day/month ordering. It makes the
|
||||
# output a little prettier...
|
||||
dnl FreeBSD's nl_langinfo supports an option to specify whether the
|
||||
dnl current locale uses month/day or day/month ordering. It makes the
|
||||
dnl output a little prettier...
|
||||
AC_CHECK_DECL([D_MD_ORDER],
|
||||
[AC_DEFINE(HAVE_D_MD_ORDER, 1, [Define to 1 if nl_langinfo supports D_MD_ORDER])],
|
||||
[],
|
||||
@@ -907,16 +969,16 @@ AC_CHECK_DECL([D_MD_ORDER],
|
||||
#endif
|
||||
])
|
||||
|
||||
# Check for dirent.d_namlen field explicitly
|
||||
# (This is a bit more straightforward than, if not quite as portable as,
|
||||
# the recipe given by the autoconf maintainers.)
|
||||
dnl Check for dirent.d_namlen field explicitly
|
||||
dnl (This is a bit more straightforward than, if not quite as portable as,
|
||||
dnl the recipe given by the autoconf maintainers.)
|
||||
AC_CHECK_MEMBER(struct dirent.d_namlen,,,
|
||||
[#if HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
# Check for Extended Attributes support
|
||||
dnl Check for Extended Attributes support
|
||||
AC_ARG_ENABLE([xattr],
|
||||
AS_HELP_STRING([--disable-xattr],
|
||||
[Disable Extended Attributes support (default: check)]))
|
||||
@@ -934,7 +996,7 @@ if test "x$enable_xattr" != "xno"; then
|
||||
fi
|
||||
if test "x$ac_cv_header_sys_xattr_h" = "xyes" \
|
||||
-a "x$ac_cv_have_decl_XATTR_NOFOLLOW" = "xyes"; then
|
||||
# Darwin extended attributes support
|
||||
dnl Darwin extended attributes support
|
||||
AC_CACHE_VAL([ac_cv_archive_xattr_darwin],
|
||||
[AC_CHECK_FUNCS(fgetxattr \
|
||||
flistxattr \
|
||||
@@ -948,7 +1010,7 @@ if test "x$enable_xattr" != "xno"; then
|
||||
)
|
||||
elif test "x$ac_cv_header_sys_extattr_h" = "xyes" \
|
||||
-a "x$ac_cv_have_decl_EXTATTR_NAMESPACE_USER" = "xyes"; then
|
||||
# FreeBSD extended attributes support
|
||||
dnl FreeBSD extended attributes support
|
||||
AC_CACHE_VAL([ac_cv_archive_xattr_freebsd],
|
||||
[AC_CHECK_FUNCS(extattr_get_fd \
|
||||
extattr_get_file \
|
||||
@@ -964,7 +1026,7 @@ if test "x$enable_xattr" != "xno"; then
|
||||
)
|
||||
elif test "x$ac_cv_header_sys_xattr_h" = "xyes" \
|
||||
-o "x$ac_cv_header_attr_xattr_h" = "xyes"; then
|
||||
# Linux extended attributes support
|
||||
dnl Linux extended attributes support
|
||||
AC_CACHE_VAL([ac_cv_archive_xattr_linux],
|
||||
[AC_CHECK_FUNCS(fgetxattr \
|
||||
flistxattr \
|
||||
@@ -979,7 +1041,7 @@ if test "x$enable_xattr" != "xno"; then
|
||||
]
|
||||
)
|
||||
elif test "x$ac_cv_header_sys_ea_h" = "xyes"; then
|
||||
# AIX extended attributes support
|
||||
dnl AIX extended attributes support
|
||||
AC_CACHE_VAL([ac_cv_archive_xattr_aix],
|
||||
[AC_CHECK_FUNCS(fgetea \
|
||||
flistea \
|
||||
@@ -1013,19 +1075,19 @@ if test "x$enable_xattr" != "xno"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for ACL support
|
||||
#
|
||||
# The ACL support in libarchive is written against the POSIX1e draft,
|
||||
# which was never officially approved and varies quite a bit across
|
||||
# platforms. Worse, some systems have completely non-POSIX acl functions,
|
||||
# which makes the following checks rather more complex than I would like.
|
||||
#
|
||||
dnl Check for ACL support
|
||||
dnl
|
||||
dnl The ACL support in libarchive is written against the POSIX1e draft,
|
||||
dnl which was never officially approved and varies quite a bit across
|
||||
dnl platforms. Worse, some systems have completely non-POSIX acl functions,
|
||||
dnl which makes the following checks rather more complex than I would like.
|
||||
dnl
|
||||
AC_ARG_ENABLE([acl],
|
||||
AS_HELP_STRING([--disable-acl],
|
||||
[Disable ACL support (default: check)]))
|
||||
|
||||
if test "x$enable_acl" != "xno"; then
|
||||
# Libacl
|
||||
dnl Libacl
|
||||
AC_CHECK_LIB([acl], [acl_get_file])
|
||||
ACL_PC_VER=`$PKG_CONFIG --modversion libacl`
|
||||
if test "x$ACL_PC_VER" != "x"; then
|
||||
@@ -1051,7 +1113,7 @@ if test "x$enable_acl" != "xno"; then
|
||||
#endif
|
||||
])
|
||||
|
||||
# Solaris and derivates ACLs
|
||||
dnl Solaris and derivates ACLs
|
||||
AC_CHECK_FUNCS(acl facl)
|
||||
|
||||
if test "x$ac_cv_lib_richacl_richacl_get_file" = "xyes" \
|
||||
@@ -1089,7 +1151,7 @@ if test "x$enable_acl" != "xno"; then
|
||||
-a "x$ac_cv_type_acl_entry_t" = "xyes" \
|
||||
-a "x$ac_cv_type_acl_permset_t" = "xyes" \
|
||||
-a "x$ac_cv_type_acl_tag_t" = "xyes"; then
|
||||
# POSIX.1e ACL functions
|
||||
dnl POSIX.1e ACL functions
|
||||
AC_CACHE_VAL([ac_cv_posix_acl_funcs],
|
||||
[AC_CHECK_FUNCS(acl_add_perm \
|
||||
acl_clear_perms \
|
||||
@@ -1121,7 +1183,7 @@ if test "x$enable_acl" != "xno"; then
|
||||
AC_DEFINE([ARCHIVE_ACL_LIBACL], [1],
|
||||
[POSIX.1e ACL support via libacl])
|
||||
else
|
||||
# FreeBSD/Darwin
|
||||
dnl FreeBSD/Darwin
|
||||
AC_CHECK_FUNCS(acl_add_flag_np \
|
||||
acl_clear_flags_np \
|
||||
acl_get_brand_np \
|
||||
@@ -1227,7 +1289,7 @@ AM_CONDITIONAL([INC_DARWIN_ACL],
|
||||
AM_CONDITIONAL([INC_FREEBSD_ACL],
|
||||
[test "x$ac_cv_archive_acl_freebsd" = "xyes"])
|
||||
|
||||
# Additional requirements
|
||||
dnl Additional requirements
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
dnl NOTE: Crypto checks must run last.
|
||||
@@ -1265,32 +1327,6 @@ main(int argc, char **argv)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([CRYPTO_CHECK_WIN], [
|
||||
if test "$found_$1" != yes; then
|
||||
AC_MSG_CHECKING([support for ARCHIVE_CRYPTO_$1_WIN])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#define ARCHIVE_$1_COMPILE_TEST
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
return ($2);
|
||||
}
|
||||
])],
|
||||
[ AC_MSG_RESULT([yes])
|
||||
found_$1=yes
|
||||
found_WIN=yes
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_$1_WIN, 1, [ $1 via ARCHIVE_CRYPTO_$1_WIN supported.])
|
||||
],
|
||||
[ AC_MSG_RESULT([no])])
|
||||
fi
|
||||
])
|
||||
|
||||
case "$host_os" in
|
||||
*mingw* | *cygwin* | *msys*)
|
||||
;;
|
||||
@@ -1317,15 +1353,34 @@ case "$host_os" in
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "x$with_cng" != "xno"; then
|
||||
AC_CHECK_HEADERS([bcrypt.h],[
|
||||
LIBS="$LIBS -lbcrypt"
|
||||
],[],
|
||||
[[#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
]])
|
||||
fi
|
||||
AC_CHECK_HEADERS([bcrypt.h],[
|
||||
LIBS="$LIBS -lbcrypt"
|
||||
if test "x$with_cng" != "xno"; then
|
||||
dnl bcrypt supports these algorithms on all available versions
|
||||
found_WIN=yes
|
||||
found_MD5=yes
|
||||
found_SHA1=yes
|
||||
found_SHA256=yes
|
||||
found_SHA384=yes
|
||||
found_SHA512=yes
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_WIN, 1,
|
||||
[ Use Windows CNG (Crypto Next Generation)])
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_MD5_WIN, 1,
|
||||
[ MD5 via ARCHIVE_CRYPTO_MD5_WIN supported.])
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_SHA1_WIN, 1,
|
||||
[ SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported.])
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_SHA256_WIN, 1,
|
||||
[ SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported.])
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_SHA384_WIN, 1,
|
||||
[ SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported.])
|
||||
AC_DEFINE(ARCHIVE_CRYPTO_SHA512_WIN, 1,
|
||||
[ SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported.])
|
||||
fi
|
||||
],[],
|
||||
[[#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
]])
|
||||
|
||||
if test "x$with_mbedtls" = "xyes"; then
|
||||
AC_CHECK_HEADERS([mbedtls/aes.h mbedtls/md.h mbedtls/pkcs5.h])
|
||||
@@ -1345,6 +1400,7 @@ fi
|
||||
|
||||
if test "x$with_nettle" = "xyes"; then
|
||||
AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h])
|
||||
AC_CHECK_HEADERS([nettle/sha1.h nettle/sha2.h])
|
||||
AC_CHECK_HEADERS([nettle/pbkdf2.h nettle/aes.h nettle/hmac.h])
|
||||
AC_CHECK_HEADERS([nettle/version.h])
|
||||
saved_LIBS=$LIBS
|
||||
@@ -1362,7 +1418,6 @@ fi
|
||||
|
||||
if test "x$with_openssl" != "xno"; then
|
||||
AC_CHECK_HEADERS([openssl/evp.h openssl/opensslv.h])
|
||||
saved_LIBS=$LIBS
|
||||
LIBSREQUIRED="$LIBSREQUIRED${LIBSREQUIRED:+ }libcrypto"
|
||||
AC_CHECK_LIB(crypto,OPENSSL_config)
|
||||
CRYPTO_CHECK(MD5, OPENSSL, md5)
|
||||
@@ -1376,42 +1431,27 @@ fi
|
||||
|
||||
AC_SUBST(LIBSREQUIRED)
|
||||
|
||||
# Probe libmd AFTER OpenSSL/libcrypto.
|
||||
# The two are incompatible and OpenSSL is more complete.
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(md, MD5Init)
|
||||
CRYPTO_CHECK(MD5, LIBMD, md5)
|
||||
CRYPTO_CHECK(RMD160, LIBMD, rmd160)
|
||||
CRYPTO_CHECK(SHA1, LIBMD, sha1)
|
||||
CRYPTO_CHECK(SHA256, LIBMD, sha256)
|
||||
CRYPTO_CHECK(SHA512, LIBMD, sha512)
|
||||
if test "x$found_LIBMD" != "xyes"; then
|
||||
LIBS=$saved_LIBS
|
||||
if test "x$with_md" != "xno"; then
|
||||
dnl Probe libmd AFTER OpenSSL/libcrypto.
|
||||
dnl The two are incompatible and OpenSSL is more complete.
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(md, MD5Init)
|
||||
CRYPTO_CHECK(MD5, LIBMD, md5)
|
||||
CRYPTO_CHECK(RMD160, LIBMD, rmd160)
|
||||
CRYPTO_CHECK(SHA1, LIBMD, sha1)
|
||||
CRYPTO_CHECK(SHA256, LIBMD, sha256)
|
||||
CRYPTO_CHECK(SHA512, LIBMD, sha512)
|
||||
if test "x$found_LIBMD" != "xyes"; then
|
||||
LIBS=$saved_LIBS
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$host_os" in
|
||||
*mingw* | *cygwin* | *msys*)
|
||||
CRYPTO_CHECK_WIN(MD5, CALG_MD5)
|
||||
CRYPTO_CHECK_WIN(SHA1, CALG_SHA1)
|
||||
CRYPTO_CHECK_WIN(SHA256, CALG_SHA_256)
|
||||
CRYPTO_CHECK_WIN(SHA384, CALG_SHA_384)
|
||||
CRYPTO_CHECK_WIN(SHA512, CALG_SHA_512)
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Visibility annotations...
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fvisibility=hidden -Werror"
|
||||
AC_MSG_CHECKING(whether compiler supports visibility annotations)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
int foo( void ) __attribute__((visibility("default")));
|
||||
])],
|
||||
[CFLAGS="$saved_CFLAGS -fvisibility=hidden -D__LIBARCHIVE_ENABLE_VISIBILITY";
|
||||
AC_MSG_RESULT(yes)],
|
||||
[CFLAGS="$saved_CFLAGS"
|
||||
AC_MSG_RESULT(no)])
|
||||
gl_VISIBILITY
|
||||
AX_APPEND_FLAG([$CFLAG_VISIBILITY])
|
||||
AS_IF([test "$HAVE_VISIBILITY" = "1"], [AX_APPEND_FLAG([-D__LIBARCHIVE_ENABLE_VISIBILITY])])
|
||||
|
||||
# Ensure test directories are present if building out-of-tree
|
||||
dnl Ensure test directories are present if building out-of-tree
|
||||
AC_CONFIG_COMMANDS([mkdirs],
|
||||
[mkdir -p libarchive/test tar/test cat/test cpio/test])
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ libarchive_src_files := libarchive/archive_acl.c \
|
||||
libarchive/archive_string.c \
|
||||
libarchive/archive_string_sprintf.c \
|
||||
libarchive/archive_time.c \
|
||||
libarchive/archive_umask.c \
|
||||
libarchive/archive_util.c \
|
||||
libarchive/archive_version_details.c \
|
||||
libarchive/archive_virtual.c \
|
||||
|
||||
@@ -118,6 +118,9 @@
|
||||
/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */
|
||||
#define ARCHIVE_CRYPTO_SHA512_WIN 1
|
||||
|
||||
/* Use Windows CNG (Crypto Next Generation) */
|
||||
#define ARCHIVE_CRYPTO_WIN 1
|
||||
|
||||
/* Define to 1 if you have the `acl_create_entry' function. */
|
||||
/* #undef HAVE_ACL_CREATE_ENTRY */
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ dnl @synopsis ST_LIB_ARCHIVE([ENABLED-DEFAULT])
|
||||
dnl
|
||||
dnl This macro figures out what's necessary to link a program against an
|
||||
dnl instance of the BSD libarchive package by Tim Kientzle.
|
||||
dnl
|
||||
dnl
|
||||
dnl See http://people.freebsd.org/~kientzle/libarchive/ for more info.
|
||||
dnl
|
||||
dnl It exports and substitutes the variables LIBARCHIVE_LIBS, LIBARCHIVE_LDFLAGS,
|
||||
@@ -29,26 +29,25 @@ dnl @author Andre Stechert <[email protected]>
|
||||
dnl @version 2006-04-20
|
||||
dnl @license GPLWithACException
|
||||
|
||||
AC_DEFUN([ST_LIB_ARCHIVE],
|
||||
[
|
||||
#
|
||||
# Handle input from the configurer and blend with the requirements from the maintainer.
|
||||
# We go through the trouble of creating a second set of variables other than the with_foo
|
||||
# variables in order to be sure that error/corner cases have been cleaned up.
|
||||
#
|
||||
# After this statement, three trusted variable are defined.
|
||||
#
|
||||
# st_lib_archive_ENABLED will be either "yes" or "no". its value determines whether
|
||||
# or not we bother with the rest of the checks and whether or not we export a
|
||||
# bunch of variables.
|
||||
#
|
||||
# st_lib_archive_LOCATION will be either "auto" or "defined". if it is "auto", then
|
||||
# we try a bunch of standard locations. if it is "defined", then we just try the value
|
||||
# provided in st_lib_archive_DIR.
|
||||
#
|
||||
# st_lib_archive_DIR will contain the string provided by the user, provided that it's
|
||||
# actually a directory.
|
||||
#
|
||||
AC_DEFUN([ST_LIB_ARCHIVE], [dnl
|
||||
dnl
|
||||
dnl Handle input from the configurer and blend with the requirements from the maintainer.
|
||||
dnl We go through the trouble of creating a second set of variables other than the with_foo
|
||||
dnl variables in order to be sure that error/corner cases have been cleaned up.
|
||||
dnl
|
||||
dnl After this statement, three trusted variable are defined.
|
||||
dnl
|
||||
dnl st_lib_archive_ENABLED will be either "yes" or "no". its value determines whether
|
||||
dnl or not we bother with the rest of the checks and whether or not we export a
|
||||
dnl bunch of variables.
|
||||
dnl
|
||||
dnl st_lib_archive_LOCATION will be either "auto" or "defined". if it is "auto", then
|
||||
dnl we try a bunch of standard locations. if it is "defined", then we just try the value
|
||||
dnl provided in st_lib_archive_DIR.
|
||||
dnl
|
||||
dnl st_lib_archive_DIR will contain the string provided by the user, provided that it's
|
||||
dnl actually a directory.
|
||||
dnl
|
||||
AC_MSG_CHECKING([if libarchive is wanted])
|
||||
AC_ARG_WITH([libarchive],
|
||||
AS_HELP_STRING([--with-libarchive=DIR], [libarchive installation directory]),
|
||||
@@ -76,12 +75,12 @@ AC_ARG_WITH([libarchive],
|
||||
|
||||
if test "$st_lib_archive_ENABLED" = "yes" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
#
|
||||
# After this statement, one trusted variable is defined.
|
||||
#
|
||||
# st_lib_archive_LIB will be either "lib" or "lib64", depending on whether the configurer
|
||||
# specified 32, 64. The default is "lib".
|
||||
#
|
||||
dnl
|
||||
dnl After this statement, one trusted variable is defined.
|
||||
dnl
|
||||
dnl st_lib_archive_LIB will be either "lib" or "lib64", depending on whether the configurer
|
||||
dnl specified 32, 64. The default is "lib".
|
||||
dnl
|
||||
AC_MSG_CHECKING([whether to use lib or lib64])
|
||||
AC_ARG_WITH([libarchive-bits],
|
||||
AS_HELP_STRING([--with-libarchive-bits=32/64], [if 64, look in /lib64 on hybrid systems]),
|
||||
@@ -94,9 +93,9 @@ if test "$st_lib_archive_ENABLED" = "yes" ; then
|
||||
fi],
|
||||
[st_lib_archive_LIB=lib])
|
||||
AC_MSG_RESULT($st_lib_archive_LIB)
|
||||
#
|
||||
# Save the environment before verifying libarchive availability
|
||||
#
|
||||
dnl
|
||||
dnl Save the environment before verifying libarchive availability
|
||||
dnl
|
||||
st_lib_archive_SAVECPPFLAGS="$CPPFLAGS"
|
||||
st_lib_archive_SAVELDFLAGS="$LDFLAGS"
|
||||
AC_LANG_SAVE
|
||||
@@ -114,9 +113,9 @@ if test "$st_lib_archive_ENABLED" = "yes" ; then
|
||||
AC_MSG_ERROR([could not find libarchive in the requested location])
|
||||
fi
|
||||
else
|
||||
#
|
||||
# These are the common install directories for Linux, FreeBSD, Solaris, and Mac.
|
||||
#
|
||||
dnl
|
||||
dnl These are the common install directories for Linux, FreeBSD, Solaris, and Mac.
|
||||
dnl
|
||||
for dir in /usr /usr/local /usr/sfw /opt/csw /opt/local /sw
|
||||
do
|
||||
if test -d "$dir" ; then
|
||||
@@ -141,9 +140,9 @@ if test "$st_lib_archive_ENABLED" = "yes" ; then
|
||||
AC_SUBST(LIBARCHIVE_LDFLAGS)
|
||||
fi
|
||||
|
||||
#
|
||||
# Restore the environment now that we're done.
|
||||
#
|
||||
dnl
|
||||
dnl Restore the environment now that we're done.
|
||||
dnl
|
||||
AC_LANG_RESTORE
|
||||
CPPFLAGS="$st_lib_archive_SAVECPPFLAGS"
|
||||
LDFLAGS="$st_lib_archive_SAVELDFLAGS"
|
||||
|
||||
@@ -67,17 +67,20 @@ echo "Building seed corpora..."
|
||||
cp "$FUZZ_DIR/corpus.zip" "$OUT/libarchive_fuzzer_seed_corpus.zip"
|
||||
|
||||
# Function to create corpus from test files
|
||||
# Usage: create_corpus <fuzzer name> <pattern> [<pattern>...]
|
||||
create_corpus() {
|
||||
local name=$1
|
||||
local pattern=$2
|
||||
shift
|
||||
local dir="/tmp/${name}_corpus"
|
||||
|
||||
mkdir -p "$dir"
|
||||
for f in $TEST_DIR/$pattern; do
|
||||
if [ -f "$f" ]; then
|
||||
base=$(basename "$f" .uu)
|
||||
uudecode -o "$dir/$base" "$f" 2>/dev/null || true
|
||||
fi
|
||||
for pattern in "$@"; do
|
||||
for f in $TEST_DIR/$pattern; do
|
||||
if [ -f "$f" ]; then
|
||||
base=$(basename "$f" .uu)
|
||||
uudecode -o "$dir/$base" "$f" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [ "$(ls -A $dir 2>/dev/null)" ]; then
|
||||
@@ -88,23 +91,26 @@ create_corpus() {
|
||||
}
|
||||
|
||||
# Create format-specific corpora
|
||||
create_corpus "libarchive_tar_fuzzer" "test_compat_*tar*.uu"
|
||||
create_corpus "libarchive_tar_fuzzer" "test_compat_*tar*.uu" "*.tar.uu" "*.tar.*.uu"
|
||||
create_corpus "libarchive_zip_fuzzer" "test_*zip*.uu"
|
||||
create_corpus "libarchive_7zip_fuzzer" "test_read_format_7zip*.uu"
|
||||
create_corpus "libarchive_rar_fuzzer" "test_read_format_rar_*.uu"
|
||||
create_corpus "libarchive_rar_fuzzer" "test_read_format_rar[!5]*.uu"
|
||||
create_corpus "libarchive_rar5_fuzzer" "test_read_format_rar5*.uu"
|
||||
create_corpus "libarchive_xar_fuzzer" "test_read_format_xar*.uu"
|
||||
create_corpus "libarchive_cab_fuzzer" "test_read_format_cab*.uu"
|
||||
create_corpus "libarchive_lha_fuzzer" "test_read_format_lha*.uu"
|
||||
create_corpus "libarchive_iso9660_fuzzer" "test_read_format_iso*.uu"
|
||||
create_corpus "libarchive_cpio_fuzzer" "test_compat_cpio*.uu"
|
||||
create_corpus "libarchive_cpio_fuzzer" "*cpio*.uu"
|
||||
create_corpus "libarchive_warc_fuzzer" "test_read_format_warc*.uu"
|
||||
create_corpus "libarchive_mtree_fuzzer" "test_read_format_mtree*.uu"
|
||||
create_corpus "libarchive_ar_fuzzer" "test_read_format_ar*.uu"
|
||||
|
||||
# Filter corpus - use compressed test files
|
||||
mkdir -p /tmp/filter_corpus
|
||||
for f in $TEST_DIR/*.gz.uu $TEST_DIR/*.bz2.uu $TEST_DIR/*.xz.uu $TEST_DIR/*.lz4.uu $TEST_DIR/*.zst.uu $TEST_DIR/*.Z.uu; do
|
||||
for f in $TEST_DIR/*.gz.uu $TEST_DIR/*.bz2.uu $TEST_DIR/*.xz.uu $TEST_DIR/*.lz4.uu \
|
||||
$TEST_DIR/*.zst.uu $TEST_DIR/*.Z.uu $TEST_DIR/*.lz.uu $TEST_DIR/*.rpm.uu \
|
||||
$TEST_DIR/test_read_filter_uudecode*.uu \
|
||||
$TEST_DIR/*.lrz.uu $TEST_DIR/*.grz.uu $TEST_DIR/*.lzo.uu; do
|
||||
if [ -f "$f" ]; then
|
||||
base=$(basename "$f" .uu)
|
||||
uudecode -o "/tmp/filter_corpus/$base" "$f" 2>/dev/null || true
|
||||
|
||||
@@ -15,6 +15,8 @@ IF(ENABLE_CPIO)
|
||||
cpio_platform.h
|
||||
../libarchive_fe/lafe_err.c
|
||||
../libarchive_fe/lafe_err.h
|
||||
../libarchive_fe/lafe_explicit_bzero.c
|
||||
../libarchive_fe/lafe_explicit_bzero.h
|
||||
../libarchive_fe/lafe_getline.c
|
||||
../libarchive_fe/lafe_getline.h
|
||||
../libarchive_fe/lafe_platform.h
|
||||
|
||||
+24
-1
@@ -79,6 +79,14 @@ Reset access times on files after they are read.
|
||||
.It Fl B
|
||||
(o mode only)
|
||||
Block output to records of 5120 bytes.
|
||||
.It Fl Fl b64encode
|
||||
(o mode only)
|
||||
Encode the archive with base64, after any compression.
|
||||
In input mode, this option is ignored; base64-encoded archives are
|
||||
recognized automatically on input.
|
||||
If both this option and
|
||||
.Fl Fl uuencode
|
||||
are given, the last one specified is used.
|
||||
.It Fl C Ar size
|
||||
(o mode only)
|
||||
Block output to records of
|
||||
@@ -154,7 +162,7 @@ automatically on input.
|
||||
.It Fl j
|
||||
Synonym for
|
||||
.Fl y .
|
||||
.It Fl L
|
||||
.It Fl L , Fl Fl dereference
|
||||
(o and p modes)
|
||||
All symbolic links will be followed.
|
||||
Normally, symbolic links are archived and copied as symbolic links.
|
||||
@@ -163,6 +171,11 @@ With this option, the target of the link will be archived or copied instead.
|
||||
(p mode only)
|
||||
Create links from the target directory to the original files,
|
||||
instead of copying.
|
||||
.It Fl Fl grzip
|
||||
(o mode only)
|
||||
Compress the resulting archive with
|
||||
.Xr grzip 1 .
|
||||
In input mode, this option is ignored.
|
||||
.It Fl Fl lrzip
|
||||
(o mode only)
|
||||
Compress the resulting archive with
|
||||
@@ -265,6 +278,16 @@ do not restore the contents to disk.
|
||||
(i and p modes)
|
||||
Unconditionally overwrite existing files.
|
||||
Ordinarily, an older file will not overwrite a newer file on disk.
|
||||
.It Fl Fl uuencode
|
||||
(o mode only)
|
||||
Encode the archive with
|
||||
.Xr uuencode 1 ,
|
||||
after any compression.
|
||||
In input mode, this option is ignored; uuencoded archives are
|
||||
recognized automatically on input.
|
||||
If both this option and
|
||||
.Fl Fl b64encode
|
||||
are given, the last one specified is used.
|
||||
.It Fl V , Fl Fl dot
|
||||
Print a dot to stderr for each file as it is processed.
|
||||
Superseded by
|
||||
|
||||
+35
-45
@@ -66,6 +66,7 @@
|
||||
|
||||
#include "cpio.h"
|
||||
#include "lafe_err.h"
|
||||
#include "lafe_explicit_bzero.h"
|
||||
#include "line_reader.h"
|
||||
#include "passphrase.h"
|
||||
|
||||
@@ -77,8 +78,6 @@
|
||||
#endif
|
||||
|
||||
struct name_cache {
|
||||
int probes;
|
||||
int hits;
|
||||
size_t size;
|
||||
struct {
|
||||
id_t id;
|
||||
@@ -87,7 +86,6 @@ struct name_cache {
|
||||
};
|
||||
|
||||
static int extract_data(struct archive *, struct archive *);
|
||||
const char * cpio_i64toa(int64_t);
|
||||
static void cpio_rename(struct archive_entry *);
|
||||
static int entry_to_archive(struct cpio *, struct archive_entry *);
|
||||
static int file_to_archive(struct cpio *, const char *);
|
||||
@@ -409,6 +407,10 @@ main(int argc, char *argv[])
|
||||
else
|
||||
cpio->format = "cpio";
|
||||
}
|
||||
if (cpio->argc > 0)
|
||||
lafe_errc(1, 0,
|
||||
"Too many arguments for -o mode (got %d, expected 0)",
|
||||
cpio->argc);
|
||||
mode_out(cpio);
|
||||
break;
|
||||
case 'i':
|
||||
@@ -429,6 +431,10 @@ main(int argc, char *argv[])
|
||||
if (*cpio->argv == NULL || **cpio->argv == '\0')
|
||||
lafe_errc(1, 0,
|
||||
"-p mode requires a target directory");
|
||||
if (cpio->argc > 1)
|
||||
lafe_errc(1, 0,
|
||||
"Too many arguments for -p mode (got %d, expected 1)",
|
||||
cpio->argc);
|
||||
mode_pass(cpio, *cpio->argv);
|
||||
break;
|
||||
default:
|
||||
@@ -728,12 +734,16 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
return (r);
|
||||
}
|
||||
|
||||
if (cpio->uid_override >= 0)
|
||||
if (cpio->uid_override >= 0) {
|
||||
archive_entry_set_uid(entry, cpio->uid_override);
|
||||
archive_entry_set_uname(entry, NULL);
|
||||
}
|
||||
if (cpio->uname_override != NULL)
|
||||
archive_entry_set_uname(entry, cpio->uname_override);
|
||||
if (cpio->gid_override >= 0)
|
||||
if (cpio->gid_override >= 0) {
|
||||
archive_entry_set_gid(entry, cpio->gid_override);
|
||||
archive_entry_set_gname(entry, NULL);
|
||||
}
|
||||
if (cpio->gname_override != NULL)
|
||||
archive_entry_set_gname(entry, cpio->gname_override);
|
||||
|
||||
@@ -842,7 +852,11 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
lafe_warnc(0, "Copying file instead");
|
||||
} else
|
||||
#endif
|
||||
return (0);
|
||||
{
|
||||
if (r != ARCHIVE_OK)
|
||||
cpio->return_value = 1;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1160,6 +1174,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
const char *uname, *gname;
|
||||
FILE *out = stdout;
|
||||
const char *fmt;
|
||||
double age;
|
||||
time_t mtime;
|
||||
static time_t now;
|
||||
struct tm *ltime;
|
||||
@@ -1172,9 +1187,11 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
|
||||
if (cpio->option_numeric_uid_gid) {
|
||||
/* Format numeric uid/gid for display. */
|
||||
strcpy(uids, cpio_i64toa(archive_entry_uid(entry)));
|
||||
snprintf(uids, sizeof(uids), "%lld",
|
||||
(long long)archive_entry_uid(entry));
|
||||
uname = uids;
|
||||
strcpy(gids, cpio_i64toa(archive_entry_gid(entry)));
|
||||
snprintf(gids, sizeof(gids), "%lld",
|
||||
(long long)archive_entry_gid(entry));
|
||||
gname = gids;
|
||||
} else {
|
||||
/* Use uname if it's present, else lookup name from uid. */
|
||||
@@ -1194,21 +1211,21 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
(unsigned long)archive_entry_rdevmajor(entry),
|
||||
(unsigned long)archive_entry_rdevminor(entry));
|
||||
} else {
|
||||
strcpy(size, cpio_i64toa(archive_entry_size(entry)));
|
||||
snprintf(size, sizeof(size), "%lld",
|
||||
(long long)archive_entry_size(entry));
|
||||
}
|
||||
|
||||
/* Format the time using 'ls -l' conventions. */
|
||||
mtime = archive_entry_mtime(entry);
|
||||
age = difftime(mtime, now);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Windows' strftime function does not support %e format. */
|
||||
if (mtime - now > 365*86400/2
|
||||
|| mtime - now < -365*86400/2)
|
||||
if (age > 365.0 * 86400 / 2 || age < -365.0 * 86400 / 2)
|
||||
fmt = cpio->day_first ? "%d %b %Y" : "%b %d %Y";
|
||||
else
|
||||
fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
|
||||
#else
|
||||
if (mtime - now > 365*86400/2
|
||||
|| mtime - now < -365*86400/2)
|
||||
if (age > 365.0 * 86400 / 2 || age < -365.0 * 86400 / 2)
|
||||
fmt = cpio->day_first ? "%e %b %Y" : "%b %e %Y";
|
||||
else
|
||||
fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
|
||||
@@ -1392,12 +1409,10 @@ lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable,
|
||||
}
|
||||
|
||||
cache = *name_cache_variable;
|
||||
cache->probes++;
|
||||
|
||||
slot = id % cache->size;
|
||||
if (cache->cache[slot].name != NULL) {
|
||||
if (cache->cache[slot].id == id) {
|
||||
cache->hits++;
|
||||
return (cache->cache[slot].name);
|
||||
}
|
||||
free(cache->cache[slot].name);
|
||||
@@ -1442,8 +1457,8 @@ lookup_uname_helper(struct cpio *cpio, const char **name, id_t id)
|
||||
pwent = getpwuid((uid_t)id);
|
||||
if (pwent == NULL) {
|
||||
if (errno && errno != ENOENT)
|
||||
lafe_warnc(errno, "getpwuid(%s) failed",
|
||||
cpio_i64toa((int64_t)id));
|
||||
lafe_warnc(errno, "getpwuid(%lld) failed",
|
||||
(long long)id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1469,8 +1484,8 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
|
||||
grent = getgrgid((gid_t)id);
|
||||
if (grent == NULL) {
|
||||
if (errno && errno != ENOENT)
|
||||
lafe_warnc(errno, "getgrgid(%s) failed",
|
||||
cpio_i64toa((int64_t)id));
|
||||
lafe_warnc(errno, "getgrgid(%lld) failed",
|
||||
(long long)id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1478,31 +1493,6 @@ lookup_gname_helper(struct cpio *cpio, const char **name, id_t id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* It would be nice to just use printf() for formatting large numbers,
|
||||
* but the compatibility problems are a big headache. Hence the
|
||||
* following simple utility function.
|
||||
*/
|
||||
const char *
|
||||
cpio_i64toa(int64_t n0)
|
||||
{
|
||||
/* 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice.
|
||||
* We also need 1 byte for '-' and 1 for '\0'.
|
||||
*/
|
||||
static char buff[22];
|
||||
int64_t n = n0 < 0 ? -n0 : n0;
|
||||
char *p = buff + sizeof(buff);
|
||||
|
||||
*--p = '\0';
|
||||
do {
|
||||
*--p = '0' + (int)(n % 10);
|
||||
n /= 10;
|
||||
} while (n > 0);
|
||||
if (n0 < 0)
|
||||
*--p = '-';
|
||||
return p;
|
||||
}
|
||||
|
||||
#define PPBUFF_SIZE 1024
|
||||
static const char *
|
||||
passphrase_callback(struct archive *a, void *_client_data)
|
||||
@@ -1523,7 +1513,7 @@ static void
|
||||
passphrase_free(char *ppbuff)
|
||||
{
|
||||
if (ppbuff != NULL) {
|
||||
memset(ppbuff, 0, PPBUFF_SIZE);
|
||||
explicit_bzero(ppbuff, PPBUFF_SIZE);
|
||||
free(ppbuff);
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ struct cpio {
|
||||
int dot; /* -V */
|
||||
int quiet; /* --quiet */
|
||||
int extract_flags; /* Flags for extract operation */
|
||||
const char *compress_program;
|
||||
int option_append; /* -A, only relevant for -o */
|
||||
int option_atime_restore; /* -a */
|
||||
int option_follow_links; /* -L */
|
||||
|
||||
+8
-66
@@ -45,7 +45,7 @@ static void
|
||||
basic_cpio(const char *target,
|
||||
const char *pack_options,
|
||||
const char *unpack_options,
|
||||
const char *se, const char *se2)
|
||||
const char *se)
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -74,7 +74,7 @@ basic_cpio(const char *target,
|
||||
|
||||
/* Verify stderr. */
|
||||
failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
|
||||
assertTextFileContents(se2, "unpack.err");
|
||||
assertTextFileContents(se, "unpack.err");
|
||||
|
||||
verify_files(pack_options);
|
||||
|
||||
@@ -112,7 +112,6 @@ DEFINE_TEST(test_basic)
|
||||
{
|
||||
FILE *filelist;
|
||||
const char *msg;
|
||||
char result[1024];
|
||||
|
||||
assertUmask(0);
|
||||
|
||||
@@ -120,85 +119,28 @@ DEFINE_TEST(test_basic)
|
||||
* Create an assortment of files on disk.
|
||||
*/
|
||||
filelist = fopen("filelist", "w");
|
||||
memset(result, 0, sizeof(result));
|
||||
|
||||
/* File with 10 bytes content. */
|
||||
assertMakeFile("file", 0644, "1234567890");
|
||||
fprintf(filelist, "file\n");
|
||||
if (is_LargeInode("file")) {
|
||||
strncat(result,
|
||||
"bsdcpio: file: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* hardlink to above file. */
|
||||
assertMakeHardlink("linkfile", "file");
|
||||
fprintf(filelist, "linkfile\n");
|
||||
if (is_LargeInode("linkfile")) {
|
||||
strncat(result,
|
||||
"bsdcpio: linkfile: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Symlink to above file. */
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("symlink", "file", 0);
|
||||
fprintf(filelist, "symlink\n");
|
||||
if (is_LargeInode("symlink")) {
|
||||
strncat(result,
|
||||
"bsdcpio: symlink: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Another file with different permissions. */
|
||||
assertMakeFile("file2", 0777, "1234567890");
|
||||
fprintf(filelist, "file2\n");
|
||||
if (is_LargeInode("file2")) {
|
||||
strncat(result,
|
||||
"bsdcpio: file2: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Directory. */
|
||||
assertMakeDir("dir", 0775);
|
||||
fprintf(filelist, "dir\n");
|
||||
if (is_LargeInode("dir")) {
|
||||
strncat(result,
|
||||
"bsdcpio: dir: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
|
||||
|
||||
/* All done. */
|
||||
fclose(filelist);
|
||||
@@ -207,14 +149,14 @@ DEFINE_TEST(test_basic)
|
||||
|
||||
/* Archive/dearchive with a variety of options. */
|
||||
msg = canSymlink() ? "2 blocks\n" : "1 block\n";
|
||||
basic_cpio("copy", "", "", msg, msg);
|
||||
basic_cpio("copy_odc", "--format=odc", "", msg, msg);
|
||||
basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
|
||||
basic_cpio("copy_cpio", "-H odc", "", msg, msg);
|
||||
basic_cpio("copy", "", "", msg);
|
||||
basic_cpio("copy_odc", "--format=odc", "", msg);
|
||||
basic_cpio("copy_newc", "-H newc", "", "2 blocks\n");
|
||||
basic_cpio("copy_cpio", "-H odc", "", msg);
|
||||
msg = "1 block\n";
|
||||
basic_cpio("copy_bin", "-H bin", "", msg, msg);
|
||||
basic_cpio("copy_bin", "-H bin", "", msg);
|
||||
msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
|
||||
basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
|
||||
basic_cpio("copy_ustar", "-H ustar", "", msg);
|
||||
|
||||
/* Copy in one step using -p */
|
||||
passthrough("passthrough");
|
||||
|
||||
@@ -82,7 +82,15 @@ DEFINE_TEST(test_cmdline)
|
||||
assert(0 != systemf("%s -p -o <empty >16.out 2>16.err", testprog));
|
||||
assertEmptyFile("16.out");
|
||||
|
||||
failure("-p with empty input should fail");
|
||||
failure("-p with missing directory should fail");
|
||||
assert(0 != systemf("%s -p <empty >17.out 2>17.err", testprog));
|
||||
assertEmptyFile("17.out");
|
||||
|
||||
failure("-p with more than one argument should fail");
|
||||
assert(0 != systemf("%s -p out abc <empty >18.out 2>18.err", testprog));
|
||||
assertEmptyFile("18.out");
|
||||
|
||||
failure("-o with arguments should fail");
|
||||
assert(0 != systemf("%s -o abc <empty >19.out 2>19.err", testprog));
|
||||
assertEmptyFile("19.out");
|
||||
}
|
||||
@@ -113,42 +113,6 @@ DEFINE_TEST(test_format_newc)
|
||||
|
||||
/* Setup result message. */
|
||||
memset(result, 0, sizeof(result));
|
||||
if (is_LargeInode("file1")) {
|
||||
strncat(result,
|
||||
"bsdcpio: file1: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
if (canSymlink() && is_LargeInode("symlink")) {
|
||||
strncat(result,
|
||||
"bsdcpio: symlink: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
if (is_LargeInode("dir")) {
|
||||
strncat(result,
|
||||
"bsdcpio: dir: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
if (is_LargeInode("hardlink")) {
|
||||
strncat(result,
|
||||
"bsdcpio: hardlink: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Record some facts about what we just created: */
|
||||
now = time(NULL); /* They were all created w/in last two seconds. */
|
||||
@@ -225,7 +189,7 @@ DEFINE_TEST(test_format_newc)
|
||||
/* "symlink" pointing to "file1" */
|
||||
assert(is_hex(e, 110));
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
assert(is_hex(e + 6, 8)); /* ino */
|
||||
assert(ino != from_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Mode: Group members bits and others bits do not work. */
|
||||
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
|
||||
@@ -258,7 +222,7 @@ DEFINE_TEST(test_format_newc)
|
||||
/* "dir" */
|
||||
assert(is_hex(e, 110));
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
assert(is_hex(e + 6, 8)); /* ino */
|
||||
assert(ino != from_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualInt(0x41c0, from_hex(e + 14, 8) & 0xffc0); /* Mode */
|
||||
|
||||
@@ -28,4 +28,11 @@ DEFINE_TEST(test_option_l)
|
||||
|
||||
/* Check that this is a link and not a copy. */
|
||||
assertIsHardlink("f", "link/f");
|
||||
|
||||
/* A failed hard link must make pass mode fail. */
|
||||
r = systemf("echo f | %s -pl missing/parent >invalid.out 2>invalid.err",
|
||||
testprog);
|
||||
assert(r != 0);
|
||||
assertFileNotExists("missing/parent/f");
|
||||
assertNonEmptyFile("invalid.err");
|
||||
}
|
||||
@@ -22,7 +22,7 @@ SET(libarchive_SOURCES
|
||||
archive_check_magic.c
|
||||
archive_cmdline.c
|
||||
archive_cmdline_private.h
|
||||
archive_crc32.h
|
||||
archive_crc32.c
|
||||
archive_cryptor.c
|
||||
archive_cryptor_private.h
|
||||
archive_digest.c
|
||||
@@ -120,6 +120,8 @@ SET(libarchive_SOURCES
|
||||
archive_string_sprintf.c
|
||||
archive_time.c
|
||||
archive_time_private.h
|
||||
archive_umask.c
|
||||
archive_umask_private.h
|
||||
archive_util.c
|
||||
archive_version_details.c
|
||||
archive_virtual.c
|
||||
@@ -170,6 +172,7 @@ SET(libarchive_SOURCES
|
||||
archive_write_set_format_zip.c
|
||||
archive_write_set_options.c
|
||||
archive_write_set_passphrase.c
|
||||
archive_xml_private.h
|
||||
archive_xxhash.h
|
||||
filter_fork_posix.c
|
||||
filter_fork.h
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3008009
|
||||
#define ARCHIVE_VERSION_NUMBER 3008010
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
@@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void);
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.9"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.10"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
@@ -204,6 +204,7 @@ __LA_DECL const char * archive_liblzo2_version(void);
|
||||
__LA_DECL const char * archive_libexpat_version(void);
|
||||
__LA_DECL const char * archive_libbsdxml_version(void);
|
||||
__LA_DECL const char * archive_libxml2_version(void);
|
||||
__LA_DECL const char * archive_xmllite_version(void);
|
||||
__LA_DECL const char * archive_mbedtls_version(void);
|
||||
__LA_DECL const char * archive_nettle_version(void);
|
||||
__LA_DECL const char * archive_openssl_version(void);
|
||||
@@ -273,7 +274,8 @@ typedef la_int64_t archive_skip_callback(struct archive *,
|
||||
|
||||
/* Seeks to specified location in the file and returns the position.
|
||||
* Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
|
||||
* Return ARCHIVE_FATAL if the seek fails for any reason.
|
||||
* Return ARCHIVE_FAILED if the seek failed in a way that keeps its
|
||||
* current read position, ARCHIVE_FATAL for any other error reason.
|
||||
*/
|
||||
typedef la_int64_t archive_seek_callback(struct archive *,
|
||||
void *_client_data, la_int64_t offset, int whence);
|
||||
@@ -647,7 +649,7 @@ __LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int);
|
||||
* A zero-copy version of archive_read_data that also exposes the file offset
|
||||
* of each returned block. Note that the client has no way to specify
|
||||
* the desired size of the block. The API does guarantee that offsets will
|
||||
* be strictly increasing and that returned blocks will not overlap.
|
||||
* be increasing and that returned blocks will not overlap.
|
||||
*/
|
||||
__LA_DECL int archive_read_data_block(struct archive *a,
|
||||
const void **buff, size_t *size, la_int64_t *offset);
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Rename functions for libarchive namespacing.
|
||||
#define blake2s __archive_blake2s
|
||||
#define blake2s_final __archive_blake2s_final
|
||||
#define blake2s_init __archive_blake2s_init
|
||||
#define blake2s_init_key __archive_blake2s_init_key
|
||||
#define blake2s_init_param __archive_blake2s_init_param
|
||||
#define blake2sp __archive_blake2sp
|
||||
#define blake2sp_final __archive_blake2sp_final
|
||||
#define blake2sp_init __archive_blake2sp_init
|
||||
#define blake2sp_init_key __archive_blake2sp_init_key
|
||||
#define blake2sp_update __archive_blake2sp_update
|
||||
#define blake2s_update __archive_blake2s_update
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
@@ -83,6 +83,7 @@ state_name(unsigned s)
|
||||
{
|
||||
switch (s) {
|
||||
case ARCHIVE_STATE_NEW: return ("new");
|
||||
case ARCHIVE_STATE_OPEN: return ("open");
|
||||
case ARCHIVE_STATE_HEADER: return ("header");
|
||||
case ARCHIVE_STATE_DATA: return ("data");
|
||||
case ARCHIVE_STATE_DATA_RECOVERY: return ("data_recovery");
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Joerg Sonnenberger
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) 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 "archive_platform.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
#if defined(HAVE_ZLIB_H)
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#if (defined(__aarch64__) || defined(_M_ARM64)) && \
|
||||
defined(__ARM_FEATURE_CRC32) && !defined(__ARM_BIG_ENDIAN) && \
|
||||
!defined(__AARCH64EB__)
|
||||
/*
|
||||
* Implementation 1: Hardware-accelerated CRC32 using ARMv8 ACLE instructions.
|
||||
* Only use this when the compiler target guarantees CRC extension support.
|
||||
* The extension is optional in ARMv8.0, so enabling it here without runtime
|
||||
* detection would make generic AArch64 binaries unsafe on older CPUs.
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <arm64_acle.h>
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#include <arm_acle.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
unsigned long
|
||||
__archive_crc32(unsigned long crc, const void *_p, size_t len)
|
||||
{
|
||||
const unsigned char *p = (const unsigned char *)_p;
|
||||
uint32_t c = (uint32_t)crc ^ 0xffffffffU;
|
||||
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
|
||||
/* Align to 8 bytes */
|
||||
while (len > 0 && ((uintptr_t)p & 7)) {
|
||||
c = __crc32b(c, *p++);
|
||||
len--;
|
||||
}
|
||||
|
||||
/* 8-way unrolled 64-bit loop */
|
||||
while (len >= 64) {
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
c = __crc32d(c, *(const uint64_t *)p); p += 8;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
while (len >= 8) {
|
||||
c = __crc32d(c, *(const uint64_t *)p);
|
||||
p += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* Trailing bytes */
|
||||
while (len > 0) {
|
||||
c = __crc32b(c, *p++);
|
||||
len--;
|
||||
}
|
||||
|
||||
return (c ^ 0xffffffffU);
|
||||
}
|
||||
|
||||
#elif defined(HAVE_ZLIB_H)
|
||||
/*
|
||||
* Implementation 2: zlib crc32().
|
||||
* zlib provides a highly-optimized CRC32 implementation across many platforms.
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
__archive_crc32(unsigned long crc, const void *_p, size_t len)
|
||||
{
|
||||
if (_p == NULL)
|
||||
return (0);
|
||||
return crc32(crc, _p, (uInt)len);
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* Implementation 3: Portable 256-entry table fallback.
|
||||
* Used when neither hardware CRC32 nor zlib is available.
|
||||
* Key feature: Reasonably fast and requires no platform-specific support.
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
__archive_crc32(unsigned long crc, const void *_p, size_t len)
|
||||
{
|
||||
const unsigned char *p = (const unsigned char *)_p;
|
||||
static const unsigned long crc_tbl[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d
|
||||
};
|
||||
|
||||
if (_p == NULL)
|
||||
return (0);
|
||||
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
for (;len >= 8; len -= 8) {
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
while (len--)
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
return (crc ^ 0xffffffffUL);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -31,19 +31,6 @@
|
||||
#include "archive.h"
|
||||
#include "archive_cryptor_private.h"
|
||||
|
||||
/*
|
||||
* On systems that do not support any recognized crypto libraries,
|
||||
* this file will normally define no usable symbols.
|
||||
*
|
||||
* But some compilers and linkers choke on empty object files, so
|
||||
* define a public symbol that will always exist. This could
|
||||
* be removed someday if this file gains another always-present
|
||||
* symbol definition.
|
||||
*/
|
||||
int __libarchive_cryptor_build_hack(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
|
||||
|
||||
static int
|
||||
@@ -57,7 +44,7 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(ARCHIVE_CRYPTO_WIN)
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "Bcrypt.lib")
|
||||
#endif
|
||||
@@ -197,7 +184,7 @@ aes_ctr_release(archive_crypto_ctx *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(ARCHIVE_CRYPTO_WIN)
|
||||
|
||||
static int
|
||||
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
|
||||
|
||||
@@ -29,16 +29,6 @@
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
/*
|
||||
* On systems that do not support any recognized crypto libraries,
|
||||
* the archive_cryptor.c file will normally define no usable symbols.
|
||||
*
|
||||
* But some compilers and linkers choke on empty object files, so
|
||||
* define a public symbol that will always exist. This could
|
||||
* be removed someday if this file gains another always-present
|
||||
* symbol definition.
|
||||
*/
|
||||
int __libarchive_cryptor_build_hack(void);
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <AvailabilityMacros.h>
|
||||
@@ -62,7 +52,7 @@ typedef struct {
|
||||
size_t encr_pos;
|
||||
} archive_crypto_ctx;
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(ARCHIVE_CRYPTO_WIN)
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_CNG 1
|
||||
|
||||
|
||||
+44
-20
@@ -44,7 +44,7 @@
|
||||
/*
|
||||
* Message digest functions for Windows platform.
|
||||
*/
|
||||
#if defined(HAVE_BCRYPT_H)
|
||||
#if defined(ARCHIVE_CRYPTO_WIN)
|
||||
|
||||
/*
|
||||
* Initialize a Message digest.
|
||||
@@ -97,7 +97,7 @@ win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_BCRYPT_H) */
|
||||
#endif /* defined(ARCHIVE_CRYPTO_WIN) */
|
||||
|
||||
|
||||
/* MD5 implementations */
|
||||
@@ -211,7 +211,7 @@ static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
mbedtls_md5_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_md5_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_md5_starts_ret(ctx) == 0)
|
||||
@@ -225,7 +225,7 @@ static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_md5_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
|
||||
@@ -238,7 +238,7 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_md5_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_md5_finish_ret(ctx, md) == 0) {
|
||||
@@ -271,7 +271,11 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
md5_digest(ctx, MD5_DIGEST_SIZE, md);
|
||||
#else
|
||||
md5_digest(ctx, md);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -394,7 +398,7 @@ static int
|
||||
__archive_ripemd160init(archive_rmd160_ctx *ctx)
|
||||
{
|
||||
mbedtls_ripemd160_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_ripemd160_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_ripemd160_starts_ret(ctx) == 0)
|
||||
@@ -408,7 +412,7 @@ static int
|
||||
__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_ripemd160_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
|
||||
@@ -421,7 +425,7 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_ripemd160_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
|
||||
@@ -454,7 +458,11 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
ripemd160_digest(ctx, RIPEMD160_DIGEST_SIZE, md);
|
||||
#else
|
||||
ripemd160_digest(ctx, md);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -618,7 +626,7 @@ static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha1_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha1_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_sha1_starts_ret(ctx) == 0)
|
||||
@@ -632,7 +640,7 @@ static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha1_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
|
||||
@@ -645,7 +653,7 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha1_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
|
||||
@@ -678,7 +686,11 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
sha1_digest(ctx, SHA1_DIGEST_SIZE, md);
|
||||
#else
|
||||
sha1_digest(ctx, md);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -894,7 +906,7 @@ static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha256_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha256_starts(ctx, 0) == 0)
|
||||
#else
|
||||
if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
|
||||
@@ -908,7 +920,7 @@ static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha256_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
|
||||
@@ -921,7 +933,7 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha256_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
|
||||
@@ -954,7 +966,11 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
sha256_digest(ctx, SHA256_DIGEST_SIZE, md);
|
||||
#else
|
||||
sha256_digest(ctx, md);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -1142,7 +1158,7 @@ static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha512_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha512_starts(ctx, 1) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
|
||||
@@ -1156,7 +1172,7 @@ static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
|
||||
@@ -1169,7 +1185,7 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha512_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
|
||||
@@ -1202,7 +1218,11 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
sha384_digest(ctx, SHA384_DIGEST_SIZE, md);
|
||||
#else
|
||||
sha384_digest(ctx, md);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -1414,7 +1434,7 @@ static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha512_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha512_starts(ctx, 0) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
|
||||
@@ -1428,7 +1448,7 @@ static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
|
||||
@@ -1441,7 +1461,7 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
|
||||
if (mbedtls_sha512_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
|
||||
@@ -1474,7 +1494,11 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
sha512_digest(ctx, SHA512_DIGEST_SIZE, md);
|
||||
#else
|
||||
sha512_digest(ctx, md);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,9 @@
|
||||
#endif
|
||||
|
||||
/* Nettle crypto headers */
|
||||
#if defined(HAVE_NETTLE_VERSION_H)
|
||||
#include <nettle/version.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_NETTLE)
|
||||
#include <nettle/md5.h>
|
||||
#endif
|
||||
@@ -145,8 +148,19 @@
|
||||
defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
|
||||
#if NETTLE_VERSION_MAJOR < 4
|
||||
#if defined(HAVE_NETTLE_SHA_H)
|
||||
#include <nettle/sha.h>
|
||||
#endif
|
||||
#else
|
||||
#if defined(HAVE_NETTLE_SHA1_H)
|
||||
#include <nettle/sha1.h>
|
||||
#endif
|
||||
#if defined(HAVE_NETTLE_SHA2_H)
|
||||
#include <nettle/sha2.h>
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* OpenSSL crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
|
||||
@@ -165,7 +179,6 @@
|
||||
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
#if defined(HAVE_BCRYPT_H)
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTO_CNG 1
|
||||
typedef struct {
|
||||
@@ -174,7 +187,6 @@ typedef struct {
|
||||
BCRYPT_HASH_HANDLE hHash;
|
||||
} Digest_CTX;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* typedefs */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
|
||||
|
||||
@@ -80,7 +80,7 @@ Allocate and return a blank
|
||||
object.
|
||||
.El
|
||||
.Ss Function groups
|
||||
Due to high number of functions, the accessor functions can be found in
|
||||
Due to the high number of functions, the accessor functions can be found in
|
||||
man pages grouped by the purpose.
|
||||
.Bl -tag -width ".Xr archive_entry_perms 3"
|
||||
.It Xr archive_entry_acl 3
|
||||
|
||||
+14
-23
@@ -121,15 +121,6 @@ static const wchar_t *ae_wcstofflags(const wchar_t *stringp,
|
||||
static const char *ae_strtofflags(const char *stringp, size_t length,
|
||||
unsigned long *setp, unsigned long *clrp);
|
||||
|
||||
#ifndef HAVE_WCSCPY
|
||||
static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2)
|
||||
{
|
||||
wchar_t *dest = s1;
|
||||
while ((*s1 = *s2) != L'\0')
|
||||
++s1, ++s2;
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
#ifndef HAVE_WCSLEN
|
||||
static size_t wcslen(const wchar_t *s)
|
||||
{
|
||||
@@ -469,7 +460,7 @@ archive_entry_gname_w(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_gname_l(struct archive_entry *entry,
|
||||
archive_entry_gname_l(struct archive_entry *entry,
|
||||
const char **p, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc));
|
||||
@@ -533,7 +524,7 @@ archive_entry_hardlink_is_set(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_hardlink_l(struct archive_entry *entry,
|
||||
archive_entry_hardlink_l(struct archive_entry *entry,
|
||||
const char **p, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
if ((entry->ae_set & AE_SET_HARDLINK) == 0) {
|
||||
@@ -643,7 +634,7 @@ archive_entry_pathname_w(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_pathname_l(struct archive_entry *entry,
|
||||
archive_entry_pathname_l(struct archive_entry *entry,
|
||||
const char **p, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc));
|
||||
@@ -799,7 +790,7 @@ archive_entry_symlink_w(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_symlink_l(struct archive_entry *entry,
|
||||
archive_entry_symlink_l(struct archive_entry *entry,
|
||||
const char **p, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
if ((entry->ae_set & AE_SET_SYMLINK) == 0) {
|
||||
@@ -856,7 +847,7 @@ archive_entry_uname_w(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_uname_l(struct archive_entry *entry,
|
||||
archive_entry_uname_l(struct archive_entry *entry,
|
||||
const char **p, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc));
|
||||
@@ -974,7 +965,7 @@ archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_copy_gname_l(struct archive_entry *entry,
|
||||
archive_entry_copy_gname_l(struct archive_entry *entry,
|
||||
const char *name, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc));
|
||||
@@ -1075,7 +1066,7 @@ archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *targ
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_copy_hardlink_l(struct archive_entry *entry,
|
||||
archive_entry_copy_hardlink_l(struct archive_entry *entry,
|
||||
const char *target, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
int r;
|
||||
@@ -1225,7 +1216,7 @@ archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_copy_link_l(struct archive_entry *entry,
|
||||
archive_entry_copy_link_l(struct archive_entry *entry,
|
||||
const char *target, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
int r;
|
||||
@@ -1306,7 +1297,7 @@ archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_copy_pathname_l(struct archive_entry *entry,
|
||||
archive_entry_copy_pathname_l(struct archive_entry *entry,
|
||||
const char *name, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname,
|
||||
@@ -1460,7 +1451,7 @@ archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkn
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_copy_symlink_l(struct archive_entry *entry,
|
||||
archive_entry_copy_symlink_l(struct archive_entry *entry,
|
||||
const char *linkname, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
int r;
|
||||
@@ -1544,7 +1535,7 @@ archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_enc
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_copy_uname_l(struct archive_entry *entry,
|
||||
archive_entry_copy_uname_l(struct archive_entry *entry,
|
||||
const char *name, size_t len, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_mstring_copy_mbs_len_l(&entry->ae_uname,
|
||||
@@ -1748,7 +1739,7 @@ archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
|
||||
}
|
||||
|
||||
char *
|
||||
_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
|
||||
archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len,
|
||||
int flags, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_acl_to_text_l(&entry->acl, len, flags, sc));
|
||||
@@ -1772,7 +1763,7 @@ archive_entry_acl_from_text(struct archive_entry *entry,
|
||||
}
|
||||
|
||||
int
|
||||
_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
|
||||
archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text,
|
||||
int type, struct archive_string_conv *sc)
|
||||
{
|
||||
return (archive_acl_from_text_l(&entry->acl, text, type, sc));
|
||||
@@ -1825,7 +1816,7 @@ archive_entry_acl_text(struct archive_entry *entry, int flags)
|
||||
|
||||
/* Deprecated */
|
||||
int
|
||||
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
|
||||
archive_entry_acl_text_l(struct archive_entry *entry, int flags,
|
||||
const char **acl_text, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
free(entry->acl.acl_text);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3008009
|
||||
#define ARCHIVE_VERSION_NUMBER 3008010
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
|
||||
@@ -161,11 +161,11 @@ Directories have an additional ACL
|
||||
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
|
||||
which controls the initial access ACL for newly-created directory entries.
|
||||
.Ss NFSv4 Access Control Lists
|
||||
A NFSv4 ACL consists of multiple individual entries called Access Control
|
||||
An NFSv4 ACL consists of multiple individual entries called Access Control
|
||||
Entries (ACEs).
|
||||
.Pp
|
||||
There are four possible types of a NFSv4 ACE:
|
||||
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW"
|
||||
There are four possible types of an NFSv4 ACE:
|
||||
.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW
|
||||
Allow principal to perform actions requiring given permissions.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY
|
||||
@@ -338,13 +338,13 @@ character
|
||||
are skipped.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_next
|
||||
return the next entry of the ACL list.
|
||||
This functions may only be called after
|
||||
returns the next entry of the ACL list.
|
||||
This function may only be called after
|
||||
.Fn archive_entry_acl_reset
|
||||
has indicated the presence of extended ACL entries.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_reset
|
||||
prepare reading the list of ACL entries with
|
||||
prepares reading the list of ACL entries with
|
||||
.Fn archive_entry_acl_next .
|
||||
The function returns 0 if no non-extended ACLs are found.
|
||||
In this case, the access permissions should be obtained by
|
||||
@@ -380,7 +380,7 @@ Output POSIX.1e default ACLs.
|
||||
Prefix each default ACL entry with the word
|
||||
.Dq default: .
|
||||
.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS
|
||||
The mask and other ACLs don not contain a double colon.
|
||||
The mask and other ACLs do not contain a double colon.
|
||||
.El
|
||||
.Pp
|
||||
The following flags are effective only on NFSv4 ACL:
|
||||
@@ -399,7 +399,7 @@ Separate ACL entries with comma instead of newline.
|
||||
.El
|
||||
.Pp
|
||||
If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned.
|
||||
It the entry contains POSIX.1e ACLs and none of the flags
|
||||
If the entry contains POSIX.1e ACLs and none of the flags
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
or
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT
|
||||
@@ -408,7 +408,7 @@ are prefixed with
|
||||
.Dq default: .
|
||||
.Pp
|
||||
.Fn archive_entry_acl_types
|
||||
get ACL entry types contained in an archive entry's ACL.
|
||||
gets ACL entry types contained in an archive entry's ACL.
|
||||
As POSIX.1e and NFSv4
|
||||
ACL entries cannot be mixed, this function is a very efficient way to detect if
|
||||
an ACL already contains POSIX.1e or NFSv4 ACL entries.
|
||||
@@ -416,7 +416,7 @@ an ACL already contains POSIX.1e or NFSv4 ACL entries.
|
||||
.Fn archive_entry_acl_count
|
||||
and
|
||||
.Fn archive_entry_acl_reset
|
||||
returns the number of ACL entries that match the given type mask.
|
||||
return the number of ACL entries that match the given type mask.
|
||||
For POSIX.1e ACLS if the type mask includes
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
and at least one extended ACL entry exists, the three classic Unix
|
||||
|
||||
@@ -37,11 +37,11 @@ archive_entry_copy_bhfi(struct archive_entry *entry,
|
||||
int64_t secs;
|
||||
uint32_t nsecs;
|
||||
|
||||
ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
|
||||
archive_entry_set_atime(entry, secs, nsecs);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
|
||||
archive_entry_set_mtime(entry, secs, nsecs);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
|
||||
archive_entry_set_birthtime(entry, secs, nsecs);
|
||||
archive_entry_set_ctime(entry, secs, nsecs);
|
||||
archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
|
||||
|
||||
@@ -69,15 +69,15 @@ Store the body the last time an inode is seen (new cpio).
|
||||
The
|
||||
.Nm
|
||||
functions help by providing a unified interface and handling the complexity
|
||||
behind the scene.
|
||||
behind the scenes.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
functions assume that
|
||||
.Vt archive_entry
|
||||
instances have valid nlinks, inode and device values.
|
||||
The inode and device value is used to match entries.
|
||||
The nlinks value is used to determined if all references have been found and
|
||||
The inode and device values are used to match entries.
|
||||
The nlinks value is used to determine if all references have been found and
|
||||
if the internal references can be recycled.
|
||||
.Pp
|
||||
The
|
||||
@@ -100,7 +100,7 @@ The
|
||||
function is the core of
|
||||
.Nm .
|
||||
The
|
||||
.Fn entry
|
||||
.Fa entry
|
||||
argument points to the
|
||||
.Vt archive_entry
|
||||
that should be written.
|
||||
|
||||
@@ -44,47 +44,47 @@ struct archive_string_conv;
|
||||
* Return -1 if the string conversion failed.
|
||||
*/
|
||||
|
||||
#define archive_entry_gname_l _archive_entry_gname_l
|
||||
int _archive_entry_gname_l(struct archive_entry *,
|
||||
#define archive_entry_gname_l __archive_entry_gname_l
|
||||
int archive_entry_gname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_hardlink_l _archive_entry_hardlink_l
|
||||
int _archive_entry_hardlink_l(struct archive_entry *,
|
||||
#define archive_entry_hardlink_l __archive_entry_hardlink_l
|
||||
int archive_entry_hardlink_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_pathname_l _archive_entry_pathname_l
|
||||
int _archive_entry_pathname_l(struct archive_entry *,
|
||||
#define archive_entry_pathname_l __archive_entry_pathname_l
|
||||
int archive_entry_pathname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_symlink_l _archive_entry_symlink_l
|
||||
int _archive_entry_symlink_l(struct archive_entry *,
|
||||
#define archive_entry_symlink_l __archive_entry_symlink_l
|
||||
int archive_entry_symlink_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_uname_l _archive_entry_uname_l
|
||||
int _archive_entry_uname_l(struct archive_entry *,
|
||||
#define archive_entry_uname_l __archive_entry_uname_l
|
||||
int archive_entry_uname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_acl_text_l _archive_entry_acl_text_l
|
||||
int _archive_entry_acl_text_l(struct archive_entry *, int,
|
||||
const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED;
|
||||
#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l
|
||||
char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
|
||||
#define archive_entry_acl_text_l __archive_entry_acl_text_l
|
||||
int archive_entry_acl_text_l(struct archive_entry *, int,
|
||||
const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED;
|
||||
#define archive_entry_acl_to_text_l __archive_entry_acl_to_text_l
|
||||
char *archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int,
|
||||
struct archive_string_conv *);
|
||||
#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l
|
||||
int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
|
||||
#define archive_entry_acl_from_text_l __archive_entry_acl_from_text_l
|
||||
int archive_entry_acl_from_text_l(struct archive_entry *, const char* text,
|
||||
int type, struct archive_string_conv *);
|
||||
#define archive_entry_copy_gname_l _archive_entry_copy_gname_l
|
||||
int _archive_entry_copy_gname_l(struct archive_entry *,
|
||||
#define archive_entry_copy_gname_l __archive_entry_copy_gname_l
|
||||
int archive_entry_copy_gname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_hardlink_l _archive_entry_copy_hardlink_l
|
||||
int _archive_entry_copy_hardlink_l(struct archive_entry *,
|
||||
#define archive_entry_copy_hardlink_l __archive_entry_copy_hardlink_l
|
||||
int archive_entry_copy_hardlink_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_link_l _archive_entry_copy_link_l
|
||||
int _archive_entry_copy_link_l(struct archive_entry *,
|
||||
#define archive_entry_copy_link_l __archive_entry_copy_link_l
|
||||
int archive_entry_copy_link_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_pathname_l _archive_entry_copy_pathname_l
|
||||
int _archive_entry_copy_pathname_l(struct archive_entry *,
|
||||
#define archive_entry_copy_pathname_l __archive_entry_copy_pathname_l
|
||||
int archive_entry_copy_pathname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_symlink_l _archive_entry_copy_symlink_l
|
||||
int _archive_entry_copy_symlink_l(struct archive_entry *,
|
||||
#define archive_entry_copy_symlink_l __archive_entry_copy_symlink_l
|
||||
int archive_entry_copy_symlink_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_uname_l _archive_entry_copy_uname_l
|
||||
int _archive_entry_copy_uname_l(struct archive_entry *,
|
||||
#define archive_entry_copy_uname_l __archive_entry_copy_uname_l
|
||||
int archive_entry_copy_uname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
|
||||
#endif /* !ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
|
||||
@@ -205,6 +205,6 @@ The platform types
|
||||
.Vt uid_t
|
||||
and
|
||||
.Vt gid_t
|
||||
are often 16 or 32 bit wide.
|
||||
are often 16 or 32 bits wide.
|
||||
In this case it is possible that the ids can not be correctly restored
|
||||
from archives and get truncated.
|
||||
@@ -251,18 +251,18 @@ is the preferred interface.
|
||||
Block and character devices are characterised either using a device number
|
||||
or a pair of major and minor number.
|
||||
The combined device number can be obtained with
|
||||
.Fn archive_device_rdev
|
||||
.Fn archive_entry_rdev
|
||||
and set with
|
||||
.Fn archive_device_set_rdev .
|
||||
.Fn archive_entry_set_rdev .
|
||||
The major and minor numbers are accessed by
|
||||
.Fn archive_device_rdevmajor ,
|
||||
.Fn archive_device_rdevminor
|
||||
.Fn archive_device_set_rdevmajor
|
||||
.Fn archive_entry_rdevmajor ,
|
||||
.Fn archive_entry_rdevminor
|
||||
.Fn archive_entry_set_rdevmajor
|
||||
and
|
||||
.Fn archive_device_set_rdevminor .
|
||||
.Fn archive_entry_set_rdevminor .
|
||||
.Pp
|
||||
The process of splitting the combined device number into major and
|
||||
minor number and the reverse process of combing them differs between
|
||||
minor number and the reverse process of combining them differs between
|
||||
platforms.
|
||||
Some archive formats use the combined form, while other formats use
|
||||
the split form.
|
||||
|
||||
@@ -31,20 +31,6 @@
|
||||
#include "archive.h"
|
||||
#include "archive_hmac_private.h"
|
||||
|
||||
/*
|
||||
* On systems that do not support any recognized crypto libraries,
|
||||
* the archive_hmac.c file is expected to define no usable symbols.
|
||||
*
|
||||
* But some compilers and linkers choke on empty object files, so
|
||||
* define a public symbol that will always exist. This could
|
||||
* be removed someday if this file gains another always-present
|
||||
* symbol definition.
|
||||
*/
|
||||
int __libarchive_hmac_build_hack(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
|
||||
|
||||
static int
|
||||
@@ -74,7 +60,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(ARCHIVE_CRYPTO_WIN)
|
||||
|
||||
#ifndef BCRYPT_HASH_REUSABLE_FLAG
|
||||
# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
|
||||
|
||||
@@ -29,16 +29,6 @@
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
/*
|
||||
* On systems that do not support any recognized crypto libraries,
|
||||
* the archive_hmac.c file is expected to define no usable symbols.
|
||||
*
|
||||
* But some compilers and linkers choke on empty object files, so
|
||||
* define a public symbol that will always exist. This could
|
||||
* be removed someday if this file gains another always-present
|
||||
* symbol definition.
|
||||
*/
|
||||
int __libarchive_hmac_build_hack(void);
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <AvailabilityMacros.h>
|
||||
@@ -52,7 +42,7 @@ int __libarchive_hmac_build_hack(void);
|
||||
|
||||
typedef CCHmacContext archive_hmac_sha1_ctx;
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(ARCHIVE_CRYPTO_WIN)
|
||||
#include <bcrypt.h>
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -269,6 +269,7 @@ archive_match_free(struct archive *_a)
|
||||
free(a->inclusion_gids.ids);
|
||||
match_list_free(&(a->inclusion_unames));
|
||||
match_list_free(&(a->inclusion_gnames));
|
||||
archive_string_free(&a->archive.error_string);
|
||||
free(a);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@@ -1172,8 +1173,8 @@ set_timefilter_find_data(struct archive_match *a, int timetype,
|
||||
time_t ctime_sec, mtime_sec;
|
||||
uint32_t ctime_ns, mtime_ns;
|
||||
|
||||
ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
|
||||
return set_timefilter(a, timetype,
|
||||
mtime_sec, mtime_ns, ctime_sec, ctime_ns);
|
||||
}
|
||||
|
||||
@@ -101,8 +101,7 @@ static const char tooManyFields[] = "too many fields for format";
|
||||
#define apd_makedev(maj, min) makedev((maj), (min))
|
||||
#endif
|
||||
|
||||
/* exported */
|
||||
dev_t
|
||||
static dev_t
|
||||
pack_native(int n, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
@@ -317,7 +316,7 @@ compare_format(const void *key, const void *element)
|
||||
|
||||
|
||||
pack_t *
|
||||
pack_find(const char *name)
|
||||
__archive_pack_find(const char *name)
|
||||
{
|
||||
const struct format *format;
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
|
||||
typedef dev_t pack_t(int, unsigned long [], const char **);
|
||||
|
||||
pack_t *pack_find(const char *);
|
||||
pack_t pack_native;
|
||||
pack_t *__archive_pack_find(const char *);
|
||||
|
||||
#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
|
||||
#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
|
||||
|
||||
@@ -72,23 +72,25 @@
|
||||
* Generally checked via `__archive_check_magic()`.
|
||||
*/
|
||||
|
||||
/* Newly created archive object, not yet opened */
|
||||
#define ARCHIVE_STATE_NEW 1U
|
||||
/* Newly created archive object, not yet opened. */
|
||||
#define ARCHIVE_STATE_NEW 0x01U
|
||||
/* Archive is opened. */
|
||||
#define ARCHIVE_STATE_OPEN 0x02U
|
||||
/* Archive is ready to read a header. */
|
||||
#define ARCHIVE_STATE_HEADER 2U
|
||||
#define ARCHIVE_STATE_HEADER 0x04U
|
||||
/* A header has been read: client can ask for data
|
||||
* or they can ask for the next header and
|
||||
* we'll automatically skip the remaining data. */
|
||||
#define ARCHIVE_STATE_DATA 4U
|
||||
#define ARCHIVE_STATE_DATA 0x08U
|
||||
/* Similar to STATE_DATA but after a FAILED header:
|
||||
* the client may not read data, but they may ask
|
||||
* for the next header and we'll recover. */
|
||||
#define ARCHIVE_STATE_DATA_RECOVERY 8U
|
||||
#define ARCHIVE_STATE_DATA_RECOVERY 0x10U
|
||||
/* End-of-archive has been reached. Client can only
|
||||
* close or free the archive. */
|
||||
#define ARCHIVE_STATE_EOF 0x10U
|
||||
#define ARCHIVE_STATE_EOF 0x20U
|
||||
/* Archive is closed; client is only allowed to free the archive. */
|
||||
#define ARCHIVE_STATE_CLOSED 0x20U
|
||||
#define ARCHIVE_STATE_CLOSED 0x40U
|
||||
/* Archive is in a FATAL error state: a close request
|
||||
* is permitted but ignored. */
|
||||
#define ARCHIVE_STATE_FATAL 0x8000U
|
||||
@@ -206,4 +208,6 @@ void __archive_reset_read_data(struct archive *);
|
||||
# define ARCHIVE_LITERAL_ULL(x) x##ull
|
||||
#endif
|
||||
|
||||
unsigned long __archive_crc32(unsigned long crc, const void *p, size_t len);
|
||||
|
||||
#endif
|
||||
@@ -83,12 +83,16 @@ archive_random(void *buf, size_t nbytes)
|
||||
BCRYPT_ALG_HANDLE hAlg;
|
||||
|
||||
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0);
|
||||
if (!BCRYPT_SUCCESS(status))
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
la_dosmaperr(GetLastError());
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
status = BCryptGenRandom(hAlg, buf, (ULONG)nbytes, 0);
|
||||
BCryptCloseAlgorithmProvider(hAlg, 0);
|
||||
if (!BCRYPT_SUCCESS(status))
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
la_dosmaperr(GetLastError());
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
|
||||
return ARCHIVE_OK;
|
||||
#elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
|
||||
|
||||
@@ -152,7 +152,7 @@ __archive_rb_tree_find_node_leq(struct archive_rb_tree *rbt, const void *key)
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__archive_rb_tree_insert_node(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self)
|
||||
@@ -218,7 +218,7 @@ __archive_rb_tree_insert_node(struct archive_rb_tree *rbt,
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Swap the location and colors of 'self' and its child @ which. The child
|
||||
* can not be a sentinel node. This is our rotation function. However,
|
||||
@@ -268,7 +268,7 @@ __archive_rb_tree_reparent_nodes(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
__archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self)
|
||||
@@ -343,7 +343,7 @@ __archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
|
||||
*/
|
||||
RB_MARK_BLACK(rbt->rbt_root);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
__archive_rb_tree_prune_node(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self, int rebalance)
|
||||
@@ -363,7 +363,7 @@ __archive_rb_tree_prune_node(struct archive_rb_tree *rbt,
|
||||
if (rebalance)
|
||||
__archive_rb_tree_removal_rebalance(rbt, father, which);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When deleting an interior node
|
||||
*/
|
||||
|
||||
@@ -170,7 +170,7 @@ list_archive(const char *name)
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
|
||||
mydata = malloc(sizeof(struct mydata));
|
||||
mydata = malloc(sizeof(*mydata));
|
||||
a = archive_read_new();
|
||||
mydata->name = name;
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
+269
-234
@@ -58,6 +58,7 @@
|
||||
|
||||
#define minimum(a, b) (a < b ? a : b)
|
||||
|
||||
static int bid_format(struct archive_read *, int);
|
||||
static int choose_filters(struct archive_read *);
|
||||
static int choose_format(struct archive_read *);
|
||||
static int close_filters(struct archive_read *);
|
||||
@@ -175,100 +176,6 @@ archive_read_open2(struct archive *a, void *client_data,
|
||||
return archive_read_open1(a);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
client_read_proxy(struct archive_read_filter *f, const void **buff)
|
||||
{
|
||||
ssize_t r;
|
||||
r = (f->archive->client.reader)(&f->archive->archive,
|
||||
f->data, buff);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
client_skip_proxy(struct archive_read_filter *f, int64_t request)
|
||||
{
|
||||
if (request < 0)
|
||||
__archive_errx(1, "Negative skip requested");
|
||||
if (request == 0)
|
||||
return 0;
|
||||
|
||||
if (f->archive->client.skipper != NULL) {
|
||||
int64_t total = 0;
|
||||
for (;;) {
|
||||
int64_t get, ask = request;
|
||||
get = (f->archive->client.skipper)
|
||||
(&f->archive->archive, f->data, ask);
|
||||
total += get;
|
||||
if (get == 0 || get == request)
|
||||
return (total);
|
||||
if (get > request)
|
||||
return ARCHIVE_FATAL;
|
||||
request -= get;
|
||||
}
|
||||
} else if (f->archive->client.seeker != NULL
|
||||
&& request > 64 * 1024) {
|
||||
/* If the client provided a seeker but not a skipper,
|
||||
* we can use the seeker to skip forward.
|
||||
*
|
||||
* Note: This isn't always a good idea. The client
|
||||
* skipper is allowed to skip by less than requested
|
||||
* if it needs to maintain block alignment. The
|
||||
* seeker is not allowed to play such games, so using
|
||||
* the seeker here may be a performance loss compared
|
||||
* to just reading and discarding. That's why we
|
||||
* only do this for skips of over 64k.
|
||||
*/
|
||||
int64_t before = f->position;
|
||||
int64_t after = (f->archive->client.seeker)
|
||||
(&f->archive->archive, f->data, request, SEEK_CUR);
|
||||
if (after != before + request)
|
||||
return ARCHIVE_FATAL;
|
||||
return after - before;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
client_seek_proxy(struct archive_read_filter *f, int64_t offset, int whence)
|
||||
{
|
||||
/* DO NOT use the skipper here! If we transparently handled
|
||||
* forward seek here by using the skipper, that will break
|
||||
* other libarchive code that assumes a successful forward
|
||||
* seek means it can also seek backwards.
|
||||
*/
|
||||
if (f->archive->client.seeker == NULL) {
|
||||
archive_set_error(&f->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Current client reader does not support seeking a device");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
return (f->archive->client.seeker)(&f->archive->archive,
|
||||
f->data, offset, whence);
|
||||
}
|
||||
|
||||
static int
|
||||
read_client_close_proxy(struct archive_read *a)
|
||||
{
|
||||
int r = ARCHIVE_OK, r2;
|
||||
unsigned int i;
|
||||
|
||||
if (a->client.closer == NULL)
|
||||
return (r);
|
||||
for (i = 0; i < a->client.nodes; i++)
|
||||
{
|
||||
r2 = (a->client.closer)
|
||||
((struct archive *)a, a->client.dataset[i].data);
|
||||
if (r > r2)
|
||||
r = r2;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
client_close_proxy(struct archive_read_filter *f)
|
||||
{
|
||||
return read_client_close_proxy(f->archive);
|
||||
}
|
||||
|
||||
static int
|
||||
client_switch_proxy(struct archive_read_filter *f, unsigned int iindex)
|
||||
{
|
||||
@@ -276,8 +183,6 @@ client_switch_proxy(struct archive_read_filter *f, unsigned int iindex)
|
||||
int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK;
|
||||
void *data2;
|
||||
|
||||
while (f->upstream != NULL)
|
||||
f = f->upstream;
|
||||
a = f->archive;
|
||||
|
||||
/* Don't do anything if already in the specified data node */
|
||||
@@ -303,9 +208,76 @@ client_switch_proxy(struct archive_read_filter *f, unsigned int iindex)
|
||||
r2 = (a->client.opener)
|
||||
((struct archive *)a, f->data);
|
||||
}
|
||||
f->client_total = f->client_avail = 0;
|
||||
return (r1 < r2) ? r1 : r2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads data from client.
|
||||
*
|
||||
* Automatically switches clients if end of file of a client is reached.
|
||||
* This simplifies handling of multi volume archives for readers.
|
||||
*/
|
||||
static ssize_t
|
||||
client_read_proxy(struct archive_read_filter *f, const void **buff)
|
||||
{
|
||||
ssize_t bytes_read = 0;
|
||||
|
||||
for (;;) {
|
||||
bytes_read = (f->archive->client.reader)(&f->archive->archive,
|
||||
f->data, buff);
|
||||
if (bytes_read == 0) {
|
||||
unsigned int cursor = f->archive->client.cursor;
|
||||
|
||||
/* Continue with next client object if available. */
|
||||
if (cursor != f->archive->client.nodes - 1 &&
|
||||
client_switch_proxy(f, cursor + 1) == ARCHIVE_OK)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return (bytes_read);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
client_skip_proxy(struct archive_read_filter *f, int64_t request)
|
||||
{
|
||||
return (f->archive->client.skipper)(&f->archive->archive,
|
||||
f->data, request);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
client_seek_proxy(struct archive_read_filter *f, int64_t offset, int whence)
|
||||
{
|
||||
/* DO NOT use the skipper here! If we transparently handled
|
||||
* forward seek here by using the skipper, that will break
|
||||
* other libarchive code that assumes a successful forward
|
||||
* seek means it can also seek backwards.
|
||||
*/
|
||||
return (f->archive->client.seeker)(&f->archive->archive,
|
||||
f->data, offset, whence);
|
||||
}
|
||||
|
||||
static int
|
||||
client_close_proxy(struct archive_read_filter *f)
|
||||
{
|
||||
struct archive_read *a = f->archive;
|
||||
int r = ARCHIVE_OK, r2;
|
||||
unsigned int i;
|
||||
|
||||
if (a->client.closer == NULL)
|
||||
return (r);
|
||||
for (i = 0; i < a->client.nodes; i++)
|
||||
{
|
||||
r2 = (a->client.closer)
|
||||
((struct archive *)a, a->client.dataset[i].data);
|
||||
if (r > r2)
|
||||
r = r2;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_open_callback(struct archive *_a,
|
||||
archive_open_callback *client_opener)
|
||||
@@ -496,19 +468,13 @@ archive_read_open1(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Open data source. */
|
||||
if (a->client.opener != NULL) {
|
||||
e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
|
||||
if (e != 0) {
|
||||
/* If the open failed, call the closer to clean up. */
|
||||
read_client_close_proxy(a);
|
||||
return (e);
|
||||
}
|
||||
}
|
||||
a->archive.state = ARCHIVE_STATE_OPEN;
|
||||
|
||||
f = calloc(1, sizeof(*f));
|
||||
if (f == NULL)
|
||||
if (f == NULL) {
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
f->bidder = NULL;
|
||||
f->upstream = NULL;
|
||||
f->archive = a;
|
||||
@@ -516,8 +482,20 @@ archive_read_open1(struct archive *_a)
|
||||
f->vtable = &none_reader_vtable;
|
||||
f->name = "none";
|
||||
f->code = ARCHIVE_FILTER_NONE;
|
||||
f->can_skip = 1;
|
||||
f->can_seek = 1;
|
||||
f->can_skip = a->client.skipper != NULL;
|
||||
f->can_seek = a->client.seeker != NULL;
|
||||
|
||||
/* Open data source. */
|
||||
if (a->client.opener != NULL) {
|
||||
e = (a->client.opener)(&a->archive, a->client.dataset[0].data);
|
||||
if (e != ARCHIVE_OK) {
|
||||
/* If the open failed, call the closer to clean up. */
|
||||
client_close_proxy(f);
|
||||
free(f);
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (e);
|
||||
}
|
||||
}
|
||||
|
||||
a->client.dataset[0].begin_position = 0;
|
||||
if (!a->filter || !a->bypass_filter_bidding)
|
||||
@@ -549,11 +527,22 @@ archive_read_open1(struct archive *_a)
|
||||
}
|
||||
a->format = &(a->formats[slot]);
|
||||
}
|
||||
else if (a->format->bid != NULL)
|
||||
{
|
||||
if (bid_format(a, -1) < 0) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Registered format does not match");
|
||||
close_filters(a);
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
a->archive.state = ARCHIVE_STATE_HEADER;
|
||||
|
||||
/* Ensure libarchive starts from the first node in a multivolume set */
|
||||
client_switch_proxy(a->filter, 0);
|
||||
client_switch_proxy(f, 0);
|
||||
return (e);
|
||||
}
|
||||
|
||||
@@ -714,7 +703,6 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry)
|
||||
|
||||
__archive_reset_read_data(&a->archive);
|
||||
|
||||
a->data_start_node = a->client.cursor;
|
||||
/* EOF always wins; otherwise return the worst error. */
|
||||
return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1;
|
||||
}
|
||||
@@ -730,6 +718,21 @@ _archive_read_next_header(struct archive *_a, struct archive_entry **entryp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bid_format(struct archive_read *a, int best_bid)
|
||||
{
|
||||
int bid;
|
||||
|
||||
bid = (a->format->bid)(a, best_bid);
|
||||
if (bid == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (a->filter->position != 0 &&
|
||||
__archive_read_seek(a, 0, SEEK_SET) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
return (bid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow each registered format to bid on whether it wants to handle
|
||||
* the next entry. Return index of winning bidder.
|
||||
@@ -750,11 +753,9 @@ choose_format(struct archive_read *a)
|
||||
a->format = &(a->formats[0]);
|
||||
for (i = 0; i < slots; i++, a->format++) {
|
||||
if (a->format->bid) {
|
||||
bid = (a->format->bid)(a, best_bid);
|
||||
bid = bid_format(a, best_bid);
|
||||
if (bid == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (a->filter->position != 0)
|
||||
__archive_read_seek(a, 0, SEEK_SET);
|
||||
if ((bid > best_bid) || (best_bid_slot < 0)) {
|
||||
best_bid = bid;
|
||||
best_bid_slot = i;
|
||||
@@ -1290,7 +1291,6 @@ __archive_read_register_format(struct archive_read *a,
|
||||
int
|
||||
__archive_read_register_bidder(struct archive_read *a,
|
||||
void *bidder_data,
|
||||
const char *name,
|
||||
const struct archive_read_filter_bidder_vtable *vtable)
|
||||
{
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
@@ -1307,7 +1307,6 @@ __archive_read_register_bidder(struct archive_read *a,
|
||||
memset(a->bidders + i, 0, sizeof(a->bidders[0]));
|
||||
bidder = (a->bidders + i);
|
||||
bidder->data = bidder_data;
|
||||
bidder->name = name;
|
||||
bidder->vtable = vtable;
|
||||
if (bidder->vtable->bid == NULL || bidder->vtable->init == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
@@ -1358,6 +1357,38 @@ __archive_read_register_bidder(struct archive_read *a,
|
||||
* code that has uncertain look-ahead needs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reads data into client buffer.
|
||||
*
|
||||
* In case of error or end of file, filter flags are set.
|
||||
* Client buffer related fields are updated.
|
||||
*/
|
||||
static ssize_t
|
||||
read_client_data(struct archive_read_filter *f)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
|
||||
if (f->end_of_file)
|
||||
return (0);
|
||||
|
||||
bytes_read = (f->vtable->read)(f, &f->client_buff);
|
||||
if (bytes_read < 0) {
|
||||
f->client_total = f->client_avail = 0;
|
||||
f->client_next = f->client_buff = NULL;
|
||||
f->fatal = 1;
|
||||
} else if (bytes_read == 0) {
|
||||
f->client_total = f->client_avail = 0;
|
||||
f->client_next = f->client_buff = NULL;
|
||||
f->end_of_file = 1;
|
||||
} else {
|
||||
f->client_total = bytes_read;
|
||||
f->client_avail = f->client_total;
|
||||
f->client_next = f->client_buff;
|
||||
}
|
||||
|
||||
return (bytes_read);
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks ahead in the input stream:
|
||||
* * If 'avail' pointer is provided, that returns number of bytes available
|
||||
@@ -1383,34 +1414,24 @@ __archive_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
|
||||
|
||||
const void *
|
||||
__archive_read_filter_ahead(struct archive_read_filter *f,
|
||||
size_t min, ssize_t *avail)
|
||||
size_t request, ssize_t *avail)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
size_t tocopy;
|
||||
size_t min, tocopy;
|
||||
|
||||
if (f->fatal) {
|
||||
if (avail)
|
||||
*avail = ARCHIVE_FATAL;
|
||||
return (NULL);
|
||||
}
|
||||
/* request == 0 is perfectly well-defined.*/
|
||||
min = request == 0 ? 1 : request;
|
||||
|
||||
/*
|
||||
* Keep pulling more data until we can satisfy the request.
|
||||
*/
|
||||
for (;;) {
|
||||
|
||||
/*
|
||||
* If we can satisfy from the copy buffer (and the
|
||||
* copy buffer isn't empty), we're done. In particular,
|
||||
* note that min == 0 is a perfectly well-defined
|
||||
* request.
|
||||
*/
|
||||
if (f->avail >= min && f->avail > 0) {
|
||||
if (avail != NULL)
|
||||
*avail = f->avail;
|
||||
return (f->next);
|
||||
}
|
||||
|
||||
/*
|
||||
* We can satisfy directly from client buffer if everything
|
||||
* currently in the copy buffer is still in the client buffer.
|
||||
@@ -1429,55 +1450,36 @@ __archive_read_filter_ahead(struct archive_read_filter *f,
|
||||
return (f->client_next);
|
||||
}
|
||||
|
||||
/* Move data forward in copy buffer if necessary. */
|
||||
if (f->next > f->buffer &&
|
||||
min > f->buffer_size - (f->next - f->buffer)) {
|
||||
if (f->avail > 0)
|
||||
memmove(f->buffer, f->next,
|
||||
f->avail);
|
||||
f->next = f->buffer;
|
||||
/* If we can satisfy from the copy buffer, we're done. */
|
||||
if (f->avail >= min) {
|
||||
if (avail != NULL)
|
||||
*avail = f->avail;
|
||||
return (f->next);
|
||||
}
|
||||
|
||||
/* If we've used up the client data, get more. */
|
||||
if (f->client_avail <= 0) {
|
||||
if (f->end_of_file) {
|
||||
if (avail != NULL)
|
||||
*avail = f->avail;
|
||||
return (NULL);
|
||||
}
|
||||
bytes_read = (f->vtable->read)(f,
|
||||
&f->client_buff);
|
||||
if (bytes_read < 0) { /* Read error. */
|
||||
f->client_total = f->client_avail = 0;
|
||||
f->client_next =
|
||||
f->client_buff = NULL;
|
||||
f->fatal = 1;
|
||||
bytes_read = read_client_data(f);
|
||||
if (bytes_read < 0) {
|
||||
/* Read error. */
|
||||
if (avail != NULL)
|
||||
*avail = ARCHIVE_FATAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (bytes_read == 0) {
|
||||
/* Check for another client object first */
|
||||
if (f->archive->client.cursor !=
|
||||
f->archive->client.nodes - 1) {
|
||||
if (client_switch_proxy(f,
|
||||
f->archive->client.cursor + 1)
|
||||
== ARCHIVE_OK)
|
||||
continue;
|
||||
}
|
||||
/* Premature end-of-file. */
|
||||
f->client_total = f->client_avail = 0;
|
||||
f->client_next =
|
||||
f->client_buff = NULL;
|
||||
f->end_of_file = 1;
|
||||
/* Return whatever we do have. */
|
||||
static const char *empty = "";
|
||||
const char *eof;
|
||||
|
||||
/* Premature end-of-file.
|
||||
* Return whatever we do have. */
|
||||
if (avail != NULL)
|
||||
*avail = f->avail;
|
||||
return (NULL);
|
||||
if (request == 0)
|
||||
eof = f->avail == 0 ? empty : f->next;
|
||||
else
|
||||
eof = NULL;
|
||||
return (eof);
|
||||
}
|
||||
f->client_total = bytes_read;
|
||||
f->client_avail = f->client_total;
|
||||
f->client_next = f->client_buff;
|
||||
} else {
|
||||
/*
|
||||
* We can't satisfy the request from the copy
|
||||
@@ -1523,19 +1525,23 @@ __archive_read_filter_ahead(struct archive_read_filter *f,
|
||||
}
|
||||
/* Move data into newly-enlarged buffer. */
|
||||
if (f->avail > 0)
|
||||
memmove(p, f->next, f->avail);
|
||||
memcpy(p, f->next, f->avail);
|
||||
free(f->buffer);
|
||||
f->next = f->buffer = p;
|
||||
f->buffer_size = s;
|
||||
} else if (f->next > f->buffer &&
|
||||
min > f->buffer_size - (f->next - f->buffer)) {
|
||||
/* Move data forward in copy buffer
|
||||
* if necessary. */
|
||||
if (f->avail > 0)
|
||||
memmove(f->buffer, f->next,
|
||||
f->avail);
|
||||
f->next = f->buffer;
|
||||
}
|
||||
|
||||
/* We can add client data to copy buffer. */
|
||||
/* First estimate: copy to fill rest of buffer. */
|
||||
tocopy = (f->buffer + f->buffer_size)
|
||||
- (f->next + f->avail);
|
||||
/* Don't waste time buffering more than we need to. */
|
||||
if (tocopy + f->avail > min)
|
||||
tocopy = min - f->avail;
|
||||
tocopy = min - f->avail;
|
||||
/* Don't copy more than is available. */
|
||||
if (tocopy > f->client_avail)
|
||||
tocopy = f->client_avail;
|
||||
@@ -1593,16 +1599,14 @@ __archive_read_filter_consume(struct archive_read_filter *f,
|
||||
static int64_t
|
||||
advance_file_pointer(struct archive_read_filter *f, int64_t request)
|
||||
{
|
||||
int64_t bytes_skipped, total_bytes_skipped = 0;
|
||||
ssize_t bytes_read;
|
||||
size_t min;
|
||||
int64_t total_bytes_skipped = 0;
|
||||
|
||||
if (f->fatal)
|
||||
return (-1);
|
||||
|
||||
/* Use up the copy buffer first. */
|
||||
if (f->avail > 0) {
|
||||
min = (size_t)minimum(request, (int64_t)f->avail);
|
||||
size_t min = (size_t)minimum(request, (int64_t)f->avail);
|
||||
f->next += min;
|
||||
f->avail -= min;
|
||||
request -= min;
|
||||
@@ -1612,7 +1616,7 @@ advance_file_pointer(struct archive_read_filter *f, int64_t request)
|
||||
|
||||
/* Then use up the client buffer. */
|
||||
if (f->client_avail > 0) {
|
||||
min = (size_t)minimum(request, (int64_t)f->client_avail);
|
||||
size_t min = (size_t)minimum(request, (int64_t)f->client_avail);
|
||||
f->client_next += min;
|
||||
f->client_avail -= min;
|
||||
request -= min;
|
||||
@@ -1624,12 +1628,41 @@ advance_file_pointer(struct archive_read_filter *f, int64_t request)
|
||||
|
||||
/* If there's an optimized skip function, use it. */
|
||||
if (f->can_skip != 0) {
|
||||
bytes_skipped = client_skip_proxy(f, request);
|
||||
if (bytes_skipped < 0) { /* error */
|
||||
f->fatal = 1;
|
||||
return (bytes_skipped);
|
||||
while (request > 0) {
|
||||
int64_t get = client_skip_proxy(f, request);
|
||||
if (get < 0 || get > request) {
|
||||
f->fatal = 1;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (get == 0)
|
||||
break;
|
||||
f->position += get;
|
||||
total_bytes_skipped += get;
|
||||
request -= get;
|
||||
}
|
||||
f->position += bytes_skipped;
|
||||
if (request == 0)
|
||||
return (total_bytes_skipped);
|
||||
} else if (f->can_seek != 0 && request > 64 * 1024) {
|
||||
/* If the client provided a seeker but not a skipper,
|
||||
* we can use the seeker to skip forward.
|
||||
*
|
||||
* Note: This isn't always a good idea. The client
|
||||
* skipper is allowed to skip by less than requested
|
||||
* if it needs to maintain block alignment. The
|
||||
* seeker is not allowed to play such games, so using
|
||||
* the seeker here may be a performance loss compared
|
||||
* to just reading and discarding. That's why we
|
||||
* only do this for skips of over 64k.
|
||||
*/
|
||||
int64_t bytes_skipped;
|
||||
int64_t before = f->position;
|
||||
int64_t after = __archive_read_filter_seek(f,
|
||||
request, SEEK_CUR);
|
||||
if (after != before + request) {
|
||||
f->fatal = 1;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
bytes_skipped = after - before;
|
||||
total_bytes_skipped += bytes_skipped;
|
||||
request -= bytes_skipped;
|
||||
if (request == 0)
|
||||
@@ -1638,31 +1671,16 @@ advance_file_pointer(struct archive_read_filter *f, int64_t request)
|
||||
|
||||
/* Use ordinary reads as necessary to complete the request. */
|
||||
for (;;) {
|
||||
bytes_read = (f->vtable->read)(f, &f->client_buff);
|
||||
if (bytes_read < 0) {
|
||||
f->client_buff = NULL;
|
||||
f->fatal = 1;
|
||||
ssize_t bytes_read = read_client_data(f);
|
||||
if (bytes_read < 0)
|
||||
return (bytes_read);
|
||||
}
|
||||
|
||||
if (bytes_read == 0) {
|
||||
if (f->archive->client.cursor !=
|
||||
f->archive->client.nodes - 1) {
|
||||
if (client_switch_proxy(f,
|
||||
f->archive->client.cursor + 1)
|
||||
== ARCHIVE_OK)
|
||||
continue;
|
||||
}
|
||||
f->client_buff = NULL;
|
||||
f->end_of_file = 1;
|
||||
if (bytes_read == 0)
|
||||
return (total_bytes_skipped);
|
||||
}
|
||||
|
||||
if (bytes_read >= request) {
|
||||
f->client_next =
|
||||
((const char *)f->client_buff) + request;
|
||||
f->client_avail = (size_t)(bytes_read - request);
|
||||
f->client_total = bytes_read;
|
||||
f->client_next += request;
|
||||
f->client_avail -= request;
|
||||
total_bytes_skipped += request;
|
||||
f->position += request;
|
||||
return (total_bytes_skipped);
|
||||
@@ -1689,7 +1707,8 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
{
|
||||
struct archive_read_client *client;
|
||||
int64_t r;
|
||||
unsigned int cursor;
|
||||
unsigned int cursor, old_cursor;
|
||||
int sought = 0;
|
||||
|
||||
if (f->closed || f->fatal)
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1697,6 +1716,8 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
return (ARCHIVE_FAILED);
|
||||
|
||||
client = &(f->archive->client);
|
||||
old_cursor = client->cursor;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_CUR:
|
||||
/* Adjust the offset and use SEEK_SET instead */
|
||||
@@ -1709,7 +1730,7 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
if (client->dataset[cursor].begin_position < 0 ||
|
||||
client->dataset[cursor].total_size < 0 ||
|
||||
client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size - 1 > offset ||
|
||||
client->dataset[cursor].total_size > offset ||
|
||||
cursor + 1 >= client->nodes)
|
||||
break;
|
||||
r = client->dataset[cursor].begin_position +
|
||||
@@ -1719,12 +1740,13 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
while (1) {
|
||||
r = client_switch_proxy(f, cursor);
|
||||
if (r != ARCHIVE_OK)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
if ((r = client_seek_proxy(f, 0, SEEK_END)) < 0)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
sought = 1;
|
||||
client->dataset[cursor].total_size = r;
|
||||
if (client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size - 1 > offset ||
|
||||
client->dataset[cursor].total_size > offset ||
|
||||
cursor + 1 >= client->nodes)
|
||||
break;
|
||||
r = client->dataset[cursor].begin_position +
|
||||
@@ -1733,10 +1755,13 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
}
|
||||
offset -= client->dataset[cursor].begin_position;
|
||||
if (offset < 0
|
||||
|| offset > client->dataset[cursor].total_size)
|
||||
return ARCHIVE_FATAL;
|
||||
|| offset > client->dataset[cursor].total_size) {
|
||||
r = ARCHIVE_FATAL;
|
||||
goto clear_buffer;
|
||||
}
|
||||
if ((r = client_seek_proxy(f, offset, SEEK_SET)) < 0)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
sought = 1;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
@@ -1753,9 +1778,10 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
while (1) {
|
||||
r = client_switch_proxy(f, cursor);
|
||||
if (r != ARCHIVE_OK)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
if ((r = client_seek_proxy(f, 0, SEEK_END)) < 0)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
sought = 1;
|
||||
client->dataset[cursor].total_size = r;
|
||||
r = client->dataset[cursor].begin_position +
|
||||
client->dataset[cursor].total_size;
|
||||
@@ -1776,10 +1802,11 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
}
|
||||
offset = (r + offset) - client->dataset[cursor].begin_position;
|
||||
if ((r = client_switch_proxy(f, cursor)) != ARCHIVE_OK)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
r = client_seek_proxy(f, offset, SEEK_SET);
|
||||
if (r < ARCHIVE_OK)
|
||||
return r;
|
||||
goto clear_buffer;
|
||||
sought = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1787,28 +1814,36 @@ __archive_read_filter_seek(struct archive_read_filter *f, int64_t offset,
|
||||
}
|
||||
r += client->dataset[cursor].begin_position;
|
||||
|
||||
clear_buffer:
|
||||
if (r == ARCHIVE_FAILED && !sought && old_cursor == client->cursor) {
|
||||
/* Seek failed without moving position: keep buffer */
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ouch. Clearing the buffer like this hurts, especially
|
||||
* at bid time. A lot of our efficiency at bid time comes
|
||||
* from having bidders reuse the data we've already read.
|
||||
*
|
||||
* TODO: If the seek request is in data we already
|
||||
* have, then don't call the seek callback.
|
||||
*
|
||||
* TODO: Zip seeks to end-of-file at bid time. If
|
||||
* other formats also start doing this, we may need to
|
||||
* find a way for clients to fudge the seek offset to
|
||||
* a block boundary.
|
||||
*
|
||||
* Hmmm... If whence was SEEK_END, we know the file
|
||||
* size is (r - offset). Can we use that to simplify
|
||||
* the TODO items above?
|
||||
*/
|
||||
f->avail = f->client_avail = 0;
|
||||
f->next = f->buffer;
|
||||
if (r >= 0) {
|
||||
/*
|
||||
* Ouch. Clearing the buffer like this hurts, especially
|
||||
* at bid time. A lot of our efficiency at bid time comes
|
||||
* from having bidders reuse the data we've already read.
|
||||
*
|
||||
* TODO: If the seek request is in data we already
|
||||
* have, then don't call the seek callback.
|
||||
*
|
||||
* TODO: Zip seeks to end-of-file at bid time. If
|
||||
* other formats also start doing this, we may need to
|
||||
* find a way for clients to fudge the seek offset to
|
||||
* a block boundary.
|
||||
*
|
||||
* Hmmm... If whence was SEEK_END, we know the file
|
||||
* size is (r - offset). Can we use that to simplify
|
||||
* the TODO items above?
|
||||
*/
|
||||
f->avail = f->client_avail = 0;
|
||||
f->next = f->buffer;
|
||||
f->position = r;
|
||||
f->end_of_file = 0;
|
||||
}
|
||||
} else
|
||||
f->fatal = 1;
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -width indent
|
||||
.It Fn archive_read_add_passphrase
|
||||
Register passphrases for reading an encryption archive.
|
||||
Register passphrases for reading an encrypted archive.
|
||||
If
|
||||
.Ar passphrase
|
||||
is
|
||||
@@ -59,7 +59,7 @@ Otherwise,
|
||||
.Cm ARCHIVE_OK
|
||||
will be returned.
|
||||
.It Fn archive_read_set_passphrase_callback
|
||||
Register a callback function that will be invoked to get a passphrase
|
||||
Register a callback function that will be invoked to get a passphrase
|
||||
for decryption after trying all the passphrases registered by the
|
||||
.Fn archive_read_add_passphrase
|
||||
function failed.
|
||||
|
||||
@@ -33,14 +33,25 @@
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
static struct archive_read_filter_bidder *
|
||||
get_last_bidder(struct archive_read *a)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(a->bidders) / sizeof(a->bidders[0]); i++)
|
||||
{
|
||||
if (a->bidders[i].vtable == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
return a->bidders + (i - 1);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_append_filter(struct archive *_a, int code)
|
||||
{
|
||||
int r1, r2, number_bidders, i;
|
||||
const char *str;
|
||||
struct archive_read_filter_bidder *b;
|
||||
struct archive_read_filter *f;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r1, r2;
|
||||
|
||||
r2 = (ARCHIVE_OK);
|
||||
switch (code)
|
||||
@@ -53,15 +64,12 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
r1 = (ARCHIVE_OK);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GZIP:
|
||||
str = "gzip";
|
||||
r1 = archive_read_support_filter_gzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_BZIP2:
|
||||
str = "bzip2";
|
||||
r1 = archive_read_support_filter_bzip2(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_COMPRESS:
|
||||
str = "compress (.Z)";
|
||||
r1 = archive_read_support_filter_compress(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_PROGRAM:
|
||||
@@ -69,43 +77,33 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
"Cannot append program filter using archive_read_append_filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
case ARCHIVE_FILTER_LZMA:
|
||||
str = "lzma";
|
||||
r1 = archive_read_support_filter_lzma(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_XZ:
|
||||
str = "xz";
|
||||
r1 = archive_read_support_filter_xz(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_UU:
|
||||
str = "uu";
|
||||
r1 = archive_read_support_filter_uu(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_RPM:
|
||||
str = "rpm";
|
||||
r1 = archive_read_support_filter_rpm(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZ4:
|
||||
str = "lz4";
|
||||
r1 = archive_read_support_filter_lz4(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_ZSTD:
|
||||
str = "zstd";
|
||||
r1 = archive_read_support_filter_zstd(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZIP:
|
||||
str = "lzip";
|
||||
r1 = archive_read_support_filter_lzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZOP:
|
||||
str = "lzop";
|
||||
r1 = archive_read_support_filter_lzop(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LRZIP:
|
||||
str = "lrzip";
|
||||
r1 = archive_read_support_filter_lrzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GRZIP:
|
||||
str = "grzip";
|
||||
r1 = archive_read_support_filter_grzip(_a);
|
||||
break;
|
||||
default:
|
||||
@@ -114,22 +112,10 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (code != ARCHIVE_FILTER_NONE)
|
||||
if (r1 > ARCHIVE_FATAL && code != ARCHIVE_FILTER_NONE)
|
||||
{
|
||||
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
|
||||
|
||||
b = a->bidders;
|
||||
for (i = 1; i < number_bidders; i++, b++)
|
||||
{
|
||||
if (!b->name || !strcmp(b->name, str))
|
||||
break;
|
||||
}
|
||||
if (!b->name || strcmp(b->name, str))
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: Unable to append filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
struct archive_read_filter_bidder *b;
|
||||
struct archive_read_filter *f;
|
||||
|
||||
f = calloc(1, sizeof(*f));
|
||||
if (f == NULL)
|
||||
@@ -137,6 +123,7 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
b = get_last_bidder(a);
|
||||
f->bidder = b;
|
||||
f->archive = a;
|
||||
f->upstream = a->filter;
|
||||
@@ -162,37 +149,22 @@ int
|
||||
archive_read_append_filter_program_signature(struct archive *_a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
int r, number_bidders, i;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *b;
|
||||
struct archive_read_filter *f;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r;
|
||||
|
||||
if (archive_read_support_filter_program_signature(_a, cmd, signature,
|
||||
signature_len) != (ARCHIVE_OK))
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
|
||||
|
||||
b = a->bidders;
|
||||
for (i = 0; i < number_bidders; i++, b++)
|
||||
{
|
||||
/* Program bidder name set to filter name after initialization */
|
||||
if (b->data && !b->name)
|
||||
break;
|
||||
}
|
||||
if (!b->data)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Internal error: Unable to append program filter");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
f = calloc(1, sizeof(*f));
|
||||
if (f == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
b = get_last_bidder(a);
|
||||
f->bidder = b;
|
||||
f->archive = a;
|
||||
f->upstream = a->filter;
|
||||
@@ -202,7 +174,6 @@ archive_read_append_filter_program_signature(struct archive *_a,
|
||||
__archive_read_free_filters(a);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
b->name = a->filter->name;
|
||||
|
||||
a->bypass_filter_bidding = 1;
|
||||
return r;
|
||||
|
||||
@@ -70,6 +70,21 @@ will not overlap.
|
||||
Note that the blocks returned from this function can be much larger
|
||||
than the block size read from disk, due to compression
|
||||
and internal buffer optimizations.
|
||||
All three of
|
||||
.Fa buff ,
|
||||
.Fa len
|
||||
and
|
||||
.Fa offset
|
||||
are written whenever the function returns
|
||||
.Cm ARCHIVE_OK
|
||||
or
|
||||
.Cm ARCHIVE_EOF .
|
||||
At the end of an entry
|
||||
.Fa len
|
||||
is zero and
|
||||
.Fa offset
|
||||
is the end of the entry's data, which is how a trailing sparse hole is
|
||||
reported.
|
||||
.It Fn archive_read_data_skip
|
||||
A convenience function that repeatedly calls
|
||||
.Fn archive_read_data_block
|
||||
|
||||
@@ -96,7 +96,7 @@ archive_read_data_into_fd(struct archive *a, int fd)
|
||||
size_t size, bytes_to_write;
|
||||
ssize_t bytes_written;
|
||||
int64_t fd_offset;
|
||||
int64_t target_offset;
|
||||
int64_t target_offset = 0;
|
||||
int64_t actual_offset = 0;
|
||||
int64_t declared_size;
|
||||
int can_lseek;
|
||||
|
||||
@@ -56,7 +56,7 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Ft int
|
||||
.Fn archive_read_disk_open "struct archive *" "const char *"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_open_w "struct archive *" "const wchar_t *"
|
||||
.Fn archive_read_disk_open_w "struct archive *" "const wchar_t *"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_set_behavior "struct archive *" "int"
|
||||
.Ft int
|
||||
@@ -109,7 +109,7 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Fa "void (*excluded_func)(struct archive *, void *, struct archive entry *)"
|
||||
.Fa "void *"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Ft int
|
||||
.Fo archive_read_disk_set_metadata_filter_callback
|
||||
.Fa "struct archive *"
|
||||
.Fa "int (*metadata_filter_func)(struct archive *, void*, struct archive_entry *)"
|
||||
@@ -191,15 +191,19 @@ By default, sparse file information is read from disk.
|
||||
This sets the mode used for handling symbolic links.
|
||||
The
|
||||
.Dq logical
|
||||
mode follows all symbolic links.
|
||||
mode follows all symbolic links, except that a symbolic link whose
|
||||
target is an ancestor directory of the link is archived as a symbolic
|
||||
link rather than being followed, to avoid loops.
|
||||
The
|
||||
.Dq physical
|
||||
mode does not follow any symbolic links.
|
||||
The
|
||||
.Dq hybrid
|
||||
mode currently behaves identically to the
|
||||
.Dq logical
|
||||
mode.
|
||||
mode follows symbolic links specified as the target of
|
||||
.Fn archive_read_disk_open
|
||||
or
|
||||
.Fn archive_read_disk_open_w
|
||||
but does not follow symbolic links anywhere else.
|
||||
.It Xo
|
||||
.Fn archive_read_disk_gname ,
|
||||
.Fn archive_read_disk_uname
|
||||
@@ -267,13 +271,13 @@ This affects the file ownership fields and ACL values in the
|
||||
.Tn struct archive_entry
|
||||
object.
|
||||
.It Fn archive_read_disk_descend
|
||||
If the current entry can be descended, this function will mark the directory as the next entry for
|
||||
If the current entry can be descended, this function will mark the directory as the next entry for
|
||||
.Xr archive_read_header 3
|
||||
to visit.
|
||||
.It Fn archive_read_disk_can_descend
|
||||
Returns 1 if the current entry is an unvisited directory and 0 otherwise.
|
||||
.It Fn archive_read_disk_current_filesystem
|
||||
Returns the index of the most recent filesystem entry that has been visited through archive_read_disk
|
||||
Returns the index of the most recent filesystem entry that has been visited through archive_read_disk.
|
||||
.It Fn archive_read_disk_current_filesystem_is_synthetic
|
||||
Returns 1 if the current filesystem is a virtual filesystem. Returns 0 if the current filesystem is not a virtual filesystem. Returns -1 if it is unknown.
|
||||
.It Fn archive_read_disk_current_filesystem_is_remote
|
||||
@@ -294,7 +298,7 @@ Allows the caller to set a callback function during calls to
|
||||
.Xr archive_read_header 3
|
||||
to filter out metadata for each entry. The callback function receives the
|
||||
.Tn struct archive
|
||||
object, void* custom filter data, and the
|
||||
object, void* custom filter data, and the
|
||||
.Tn struct archive_entry .
|
||||
If the callback function returns an error, ARCHIVE_RETRY will be returned and the entry will not be further processed.
|
||||
.El
|
||||
@@ -316,12 +320,12 @@ file_to_archive(struct archive *a, const char *name)
|
||||
struct archive_entry *entry;
|
||||
int fd;
|
||||
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
ard = archive_read_disk_new();
|
||||
archive_read_disk_set_standard_lookup(ard);
|
||||
entry = archive_entry_new();
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
archive_entry_copy_pathname(entry, name);
|
||||
archive_read_disk_entry_from_file(ard, entry, fd, NULL);
|
||||
archive_write_header(a, entry);
|
||||
|
||||
@@ -97,9 +97,6 @@
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_disk_private.h"
|
||||
|
||||
#ifndef HAVE_FCHDIR
|
||||
#error fchdir function required.
|
||||
#endif
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
@@ -114,6 +111,18 @@
|
||||
#define HAVE_DIRFD
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FCHDIR
|
||||
/*
|
||||
* Stub function for platforms that do not support fchdir. This is OK on
|
||||
* platforms with newer *at functions as fchdir isn't used there (e.g. WASI).
|
||||
*/
|
||||
static int fchdir(int fd)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* This is a new directory-walking system that addresses a number
|
||||
* of problems I've had with fts(3). In particular, it has no
|
||||
|
||||
@@ -47,11 +47,11 @@
|
||||
#include "archive.h"
|
||||
#include "archive_integer.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) || defined(__wasi__)
|
||||
int
|
||||
archive_read_disk_set_standard_lookup(struct archive *a)
|
||||
{
|
||||
archive_set_error(a, -1, "Standard lookups not available on Windows");
|
||||
archive_set_error(a, -1, "Standard lookups not available on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else /* ! (_WIN32 && !__CYGWIN__) */
|
||||
@@ -312,4 +312,4 @@ lookup_gname_helper(struct name_cache *cache, id_t id)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! (_WIN32 && !__CYGWIN__) */
|
||||
#endif /* ! (_WIN32 && !__CYGWIN__ || __wasi__) */
|
||||
@@ -2056,11 +2056,11 @@ entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
|
||||
uint32_t nsecs;
|
||||
mode_t mode;
|
||||
|
||||
ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
|
||||
archive_entry_set_atime(entry, secs, nsecs);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
|
||||
archive_entry_set_mtime(entry, secs, nsecs);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
|
||||
__archive_ntfs_to_unix(__archive_FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
|
||||
archive_entry_set_birthtime(entry, secs, nsecs);
|
||||
archive_entry_set_ctime(entry, secs, nsecs);
|
||||
archive_entry_set_dev(entry, bhfi_dev(bhfi));
|
||||
|
||||
@@ -59,7 +59,7 @@ than 2013.
|
||||
.It Fn archive_read_free
|
||||
Invokes
|
||||
.Fn archive_read_close
|
||||
if it was not invoked manually, then release all resources.
|
||||
if it was not invoked manually, then releases all resources.
|
||||
Note: In libarchive 1.x, this function was declared to return
|
||||
.Ft void ,
|
||||
which made it impossible to detect certain errors when
|
||||
|
||||
@@ -166,7 +166,7 @@ The callback functions must match the following prototypes:
|
||||
.El
|
||||
.Pp
|
||||
The open callback is invoked by
|
||||
.Fn archive_open .
|
||||
.Fn archive_read_open .
|
||||
It should return
|
||||
.Cm ARCHIVE_OK
|
||||
if the underlying file or data source is successfully
|
||||
@@ -210,7 +210,7 @@ performance gains when reading uncompressed
|
||||
archives from slow disk drives or other media
|
||||
that can skip quickly.
|
||||
.Pp
|
||||
The close callback is invoked by archive_close when
|
||||
The close callback is invoked by archive_read_close when
|
||||
the archive processing is complete.
|
||||
The callback should return
|
||||
.Cm ARCHIVE_OK
|
||||
|
||||
@@ -109,8 +109,11 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
|
||||
archive_read_set_seek_callback(a, file_seek);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
r = archive_read_set_callback_data(a, mine);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
free(mine->buffer);
|
||||
free(mine);
|
||||
return (r);
|
||||
}
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
|
||||
@@ -106,8 +106,11 @@ archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
archive_read_set_seek_callback(a, FILE_seek);
|
||||
archive_read_set_close_callback(a, FILE_close);
|
||||
r = archive_read_set_callback_data(a, mine);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
free(mine->buffer);
|
||||
free(mine);
|
||||
return (r);
|
||||
}
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
|
||||
@@ -84,8 +84,10 @@ archive_read_open_memory2(struct archive *a, const void *buff,
|
||||
archive_read_set_skip_callback(a, memory_read_skip);
|
||||
archive_read_set_close_callback(a, memory_read_close);
|
||||
r = archive_read_set_callback_data(a, mine);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
free(mine);
|
||||
return (r);
|
||||
}
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
@@ -149,29 +151,27 @@ static int64_t
|
||||
memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whence)
|
||||
{
|
||||
struct read_memory_data *mine = (struct read_memory_data *)client_data;
|
||||
const unsigned char *p;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
mine->p = mine->start + offset;
|
||||
p = mine->start + offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
mine->p += offset;
|
||||
p = mine->p + offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
mine->p = mine->end + offset;
|
||||
p = mine->end + offset;
|
||||
break;
|
||||
default:
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
if (mine->p < mine->start) {
|
||||
mine->p = mine->start;
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
if (mine->p > mine->end) {
|
||||
mine->p = mine->end;
|
||||
if (p < mine->start)
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
if (p > mine->end)
|
||||
return ARCHIVE_FAILED;
|
||||
mine->p = p;
|
||||
return (mine->p - mine->start);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,8 +68,6 @@ struct archive_read_filter_bidder_vtable {
|
||||
struct archive_read_filter_bidder {
|
||||
/* Configuration data for the bidder. */
|
||||
void *data;
|
||||
/* Name of the filter */
|
||||
const char *name;
|
||||
const struct archive_read_filter_bidder_vtable *vtable;
|
||||
};
|
||||
|
||||
@@ -189,10 +187,6 @@ struct archive_read {
|
||||
*/
|
||||
int64_t entry_bytes_declared;
|
||||
|
||||
/* Nodes and offsets of compressed data block */
|
||||
unsigned int data_start_node;
|
||||
unsigned int data_end_node;
|
||||
|
||||
/*
|
||||
* Format detection is mostly the same as compression
|
||||
* detection, with one significant difference: The bidders
|
||||
@@ -250,7 +244,6 @@ int __archive_read_register_format(struct archive_read *a,
|
||||
|
||||
int __archive_read_register_bidder(struct archive_read *a,
|
||||
void *bidder_data,
|
||||
const char *name,
|
||||
const struct archive_read_filter_bidder_vtable *vtable);
|
||||
|
||||
const void *__archive_read_ahead(struct archive_read *, size_t, ssize_t *);
|
||||
|
||||
@@ -134,7 +134,7 @@ If either function returns
|
||||
.Cm ARCHIVE_FATAL
|
||||
will be returned
|
||||
immediately.
|
||||
Otherwise, greater of the two values will be returned.
|
||||
Otherwise, the greater of the two values will be returned.
|
||||
.\"
|
||||
.It Xo
|
||||
.Fn archive_read_set_options
|
||||
|
||||
@@ -91,7 +91,7 @@ archive_read_support_filter_bzip2(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "bzip2",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&bzip2_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ archive_read_support_filter_compress(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
return __archive_read_register_bidder(a, NULL, "compress (.Z)",
|
||||
return __archive_read_register_bidder(a, NULL,
|
||||
&compress_bidder_vtable);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ archive_read_support_filter_grzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "grzip",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&grzip_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ archive_read_support_filter_gzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "gzip",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&gzip_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -344,7 +344,7 @@ consume_header(struct archive_read_filter *f)
|
||||
__archive_read_filter_consume(f->upstream, len);
|
||||
|
||||
/* Initialize CRC accumulator. */
|
||||
gzip->crc = crc32(0L, NULL, 0);
|
||||
gzip->crc = __archive_crc32(0L, NULL, 0);
|
||||
|
||||
/* Initialize compression library. */
|
||||
gzip->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
@@ -416,8 +416,12 @@ consume_trailer(struct archive_read_filter *f)
|
||||
|
||||
/* GZip trailer is a fixed 8 byte structure. */
|
||||
p = __archive_read_filter_ahead(f->upstream, 8, NULL);
|
||||
if (p == NULL)
|
||||
if (p == NULL) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Truncated gzip input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* XXX TODO: Verify the length and CRC. */
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ archive_read_support_filter_lrzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "lrzip",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&lrzip_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -79,14 +79,12 @@ lrzip_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
struct archive_read_filter *f)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t len;
|
||||
int i;
|
||||
|
||||
(void)b; /* UNUSED */
|
||||
/* Start by looking at the first six bytes of the header, which
|
||||
* is all fixed layout. */
|
||||
len = 6;
|
||||
p = __archive_read_filter_ahead(f, len, NULL);
|
||||
p = __archive_read_filter_ahead(f, 6, NULL);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
|
||||
@@ -101,7 +99,7 @@ lrzip_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
if ((i < 6) || (i > 10))
|
||||
return 0;
|
||||
|
||||
return (int)len;
|
||||
return (48);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -73,7 +73,6 @@ struct lz4 {
|
||||
int block_maximum_size;
|
||||
} flags;
|
||||
int64_t stream_size;
|
||||
uint32_t dict_id;
|
||||
char *out_block;
|
||||
size_t out_block_size;
|
||||
|
||||
@@ -82,7 +81,6 @@ struct lz4 {
|
||||
size_t decoded_size;
|
||||
void *xxh32_state;
|
||||
|
||||
char valid; /* True = decompressor is initialized */
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
@@ -118,7 +116,7 @@ archive_read_support_filter_lz4(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "lz4",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&lz4_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -180,6 +178,7 @@ lz4_reader_bid(struct archive_read_filter_bidder *b,
|
||||
uint32_t frame_data_size;
|
||||
|
||||
/* Skip over the magic number */
|
||||
bits_checked += 28;
|
||||
offset_in_buffer += 4;
|
||||
|
||||
/* Ensure that we can read another 4 bytes. */
|
||||
@@ -205,13 +204,11 @@ lz4_reader_bid(struct archive_read_filter_bidder *b,
|
||||
* if this is LZ4 data.
|
||||
*/
|
||||
if (archive_ckd_add_size(&min,
|
||||
offset_in_buffer, min_lz4_frame_size))
|
||||
offset_in_buffer, min_lz4_frame_size) ||
|
||||
min > max_lookahead)
|
||||
return (0);
|
||||
/* TODO: should this be >= ? */
|
||||
if (min > (size_t)avail) {
|
||||
if (min > max_lookahead)
|
||||
return (0);
|
||||
|
||||
buffer = __archive_read_filter_ahead(f,
|
||||
min, &avail);
|
||||
if (buffer == NULL)
|
||||
@@ -226,7 +223,6 @@ lz4_reader_bid(struct archive_read_filter_bidder *b,
|
||||
* follows, or this isn't LZ4 data.
|
||||
*/
|
||||
|
||||
bits_checked = offset_in_buffer;
|
||||
buffer = buffer + offset_in_buffer;
|
||||
|
||||
if (magic_number == LZ4_MAGICNUMBER) {
|
||||
|
||||
@@ -109,7 +109,7 @@ archive_read_support_filter_lzop(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "lzop",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&lzop_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -274,7 +274,7 @@ consume_header(struct archive_read_filter *f)
|
||||
if (p == NULL)
|
||||
goto truncated;
|
||||
if (flags & CRC32_HEADER)
|
||||
checksum = crc32(crc32(0, NULL, 0), p, len);
|
||||
checksum = __archive_crc32(__archive_crc32(0, NULL, 0), p, len);
|
||||
else
|
||||
checksum = adler32(adler32(0, NULL, 0), p, len);
|
||||
#ifndef DONT_FAIL_ON_CRC_ERROR
|
||||
@@ -414,7 +414,7 @@ lzop_filter_read(struct archive_read_filter *f, const void **p)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (lzop->flags & CRC32_COMPRESSED)
|
||||
cksum = crc32(crc32(0, NULL, 0), b, lzop->compressed_size);
|
||||
cksum = __archive_crc32(__archive_crc32(0, NULL, 0), b, lzop->compressed_size);
|
||||
else if (lzop->flags & ADLER32_COMPRESSED)
|
||||
cksum = adler32(adler32(0, NULL, 0), b, lzop->compressed_size);
|
||||
else
|
||||
@@ -459,7 +459,7 @@ lzop_filter_read(struct archive_read_filter *f, const void **p)
|
||||
}
|
||||
|
||||
if (lzop->flags & CRC32_UNCOMPRESSED)
|
||||
cksum = crc32(crc32(0, NULL, 0), lzop->out_block,
|
||||
cksum = __archive_crc32(__archive_crc32(0, NULL, 0), lzop->out_block,
|
||||
lzop->uncompressed_size);
|
||||
else if (lzop->flags & ADLER32_UNCOMPRESSED)
|
||||
cksum = adler32(adler32(0, NULL, 0), lzop->out_block,
|
||||
|
||||
@@ -81,6 +81,8 @@ archive_read_support_filter_program(struct archive *a, const char *cmd)
|
||||
return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAITPID
|
||||
|
||||
/*
|
||||
* The bidder object stores the command and the signature to watch for.
|
||||
* The 'inhibit' entry here is used to ensure that unchecked filters never
|
||||
@@ -149,6 +151,11 @@ archive_read_support_filter_program_signature(struct archive *_a,
|
||||
archive_strcat(&state->description, cmd);
|
||||
|
||||
if (signature != NULL && signature_len > 0) {
|
||||
if (signature_len > (size_t)INT_MAX / 8) {
|
||||
free_state(state);
|
||||
archive_set_error(_a, EINVAL, "Signature too large");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->signature_len = signature_len;
|
||||
state->signature = malloc(signature_len);
|
||||
if (state->signature == NULL)
|
||||
@@ -156,7 +163,7 @@ archive_read_support_filter_program_signature(struct archive *_a,
|
||||
memcpy(state->signature, signature, signature_len);
|
||||
}
|
||||
|
||||
if (__archive_read_register_bidder(a, state, NULL,
|
||||
if (__archive_read_register_bidder(a, state,
|
||||
&program_bidder_vtable) != ARCHIVE_OK) {
|
||||
free_state(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -257,7 +264,7 @@ child_stop(struct archive_read_filter *f, struct program *program)
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#ifdef WIFSIGNALED
|
||||
if (WIFSIGNALED(program->exit_status)) {
|
||||
#ifdef SIGPIPE
|
||||
/* If the child died because we stopped reading before
|
||||
@@ -274,7 +281,7 @@ child_stop(struct archive_read_filter *f, struct program *program)
|
||||
WTERMSIG(program->exit_status));
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
#endif /* !_WIN32 || __CYGWIN__ */
|
||||
#endif /* WIFSIGNALED */
|
||||
|
||||
if (WIFEXITED(program->exit_status)) {
|
||||
if (WEXITSTATUS(program->exit_status) == 0)
|
||||
@@ -495,3 +502,26 @@ program_filter_close(struct archive_read_filter *f)
|
||||
|
||||
return (e);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
archive_read_support_filter_program_signature(struct archive *a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
(void)cmd; /* UNUSED */
|
||||
(void)signature; /* UNUSED */
|
||||
(void)signature_len; /* UNUSED */
|
||||
archive_set_error(a, ENOSYS, "Processes not supported");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
__archive_read_program(struct archive_read_filter *f, const char *cmd)
|
||||
{
|
||||
(void)f; /* UNUSED */
|
||||
(void)cmd; /* UNUSED */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -71,7 +71,7 @@ archive_read_support_filter_rpm(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
return __archive_read_register_bidder(a, NULL, "rpm",
|
||||
return __archive_read_register_bidder(a, NULL,
|
||||
&rpm_bidder_vtable);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,18 +37,14 @@
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
/* Maximum lookahead during bid phase */
|
||||
#define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */
|
||||
#define MAX_LINE_LENGTH 128*1024 /* in bytes */
|
||||
|
||||
struct uu {
|
||||
int64_t total;
|
||||
unsigned char *in_buff;
|
||||
#define IN_BUFF_SIZE (1024)
|
||||
ssize_t in_cnt;
|
||||
size_t in_allocated;
|
||||
unsigned char *out_buff;
|
||||
#define OUT_BUFF_SIZE (64 * 1024)
|
||||
int state;
|
||||
@@ -92,29 +88,10 @@ archive_read_support_filter_uu(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
return __archive_read_register_bidder(a, NULL, "uu",
|
||||
return __archive_read_register_bidder(a, NULL,
|
||||
&uudecode_bidder_vtable);
|
||||
}
|
||||
|
||||
static const unsigned char ascii[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, '\r', 0, 0, /* 00 - 0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
|
||||
};
|
||||
|
||||
static const unsigned char uuchar[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
|
||||
@@ -172,143 +149,157 @@ static const int base64num[128] = {
|
||||
49, 50, 51, 0, 0, 0, 0, 0, /* 70 - 7F */
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
get_line(const unsigned char *b, ssize_t avail, ssize_t *nlsize)
|
||||
/*
|
||||
* Read the next line from upstream beginning at given offset. No more than
|
||||
* MAX_LINE_LENGTH bytes will be read into stream. Bytes won't be consumed.
|
||||
* The length of the line excluding the newline is stored in len.
|
||||
*
|
||||
* If parsed is non-zero, only already available bytes are considered.
|
||||
* This option is supposed to be used with a 0 offset.
|
||||
*
|
||||
* Amount of unconsumed bytes, including newline character(s), or up to
|
||||
* MAX_LINE_LENGTH if no newline was found, is stored in unconsumed.
|
||||
*
|
||||
* If a line is found, pointer to beginning of line is returned.
|
||||
*/
|
||||
static const unsigned char *
|
||||
read_line_ahead(struct archive_read_filter *f, ssize_t parsed,
|
||||
size_t offset, size_t *len, ssize_t *unconsumed)
|
||||
{
|
||||
ssize_t len;
|
||||
/* Read approximately two new lines each iteration. */
|
||||
size_t step = 160;
|
||||
const unsigned char *line;
|
||||
ssize_t avail;
|
||||
size_t request, start;
|
||||
|
||||
len = 0;
|
||||
while (len < avail) {
|
||||
switch (ascii[*b]) {
|
||||
case 0: /* Non-ascii character or control character. */
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 0;
|
||||
return (-1);
|
||||
case '\r':
|
||||
if (avail-len > 1 && b[1] == '\n') {
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 2;
|
||||
return (len+2);
|
||||
start = offset;
|
||||
line = NULL;
|
||||
*len = 0;
|
||||
*unconsumed = 0;
|
||||
request = offset == 0 ? 1 : offset + step;
|
||||
do {
|
||||
size_t remaining, nl = 1;
|
||||
const unsigned char *b, *p;
|
||||
|
||||
/* Read bytes from upstream filter. */
|
||||
b = __archive_read_filter_ahead(f, request, &avail);
|
||||
if (avail > MAX_LINE_LENGTH)
|
||||
avail = MAX_LINE_LENGTH;
|
||||
*unconsumed = avail;
|
||||
if (b == NULL) {
|
||||
if (avail > 0 && (size_t)avail > offset)
|
||||
b = __archive_read_filter_ahead(f, avail,
|
||||
&avail);
|
||||
if (b == NULL)
|
||||
break;
|
||||
}
|
||||
remaining = avail - offset;
|
||||
/* Locate end of line (\r, \n, \r\n). */
|
||||
p = memchr(b + offset, '\n', remaining);
|
||||
if (p == NULL) {
|
||||
p = memchr(b + offset, '\r', remaining);
|
||||
if (p == b + avail - 1 && step > 1) {
|
||||
/* Is it \r or \r\n, missing one byte? */
|
||||
p = NULL;
|
||||
step = 1;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case '\n':
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 1;
|
||||
return (len+1);
|
||||
case 1:
|
||||
b++;
|
||||
len++;
|
||||
break;
|
||||
} else if (p > b + start && p[-1] == '\r') {
|
||||
/* "\r\n" takes two bytes. */
|
||||
nl++;
|
||||
--p;
|
||||
}
|
||||
}
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 0;
|
||||
return (avail);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bid_get_line(struct archive_read_filter *f,
|
||||
const unsigned char **b, ssize_t *avail, ssize_t *ravail,
|
||||
ssize_t *nl, size_t* nbytes_read)
|
||||
{
|
||||
ssize_t len;
|
||||
int quit;
|
||||
|
||||
quit = 0;
|
||||
if (*avail == 0) {
|
||||
*nl = 0;
|
||||
len = 0;
|
||||
} else
|
||||
len = get_line(*b, *avail, nl);
|
||||
|
||||
/*
|
||||
* Read more bytes while it does not reach the end of line.
|
||||
*/
|
||||
while (*nl == 0 && len == *avail && !quit &&
|
||||
*nbytes_read < UUENCODE_BID_MAX_READ) {
|
||||
ssize_t diff = *ravail - *avail;
|
||||
size_t nbytes_req = (*ravail+1023) & ~1023U;
|
||||
ssize_t tested;
|
||||
|
||||
/* Increase reading bytes if it is not enough for at least
|
||||
* two new lines. */
|
||||
if (nbytes_req < (size_t)*ravail + 160)
|
||||
nbytes_req <<= 1;
|
||||
|
||||
*b = __archive_read_filter_ahead(f, nbytes_req, avail);
|
||||
if (*b == NULL) {
|
||||
if (*ravail >= *avail)
|
||||
return (0);
|
||||
/* Reading bytes reaches the end of a stream. */
|
||||
*b = __archive_read_filter_ahead(f, *avail, avail);
|
||||
quit = 1;
|
||||
/* Return line or prepare to read more bytes. */
|
||||
if (p != NULL) {
|
||||
line = b + start;
|
||||
*len = p - line;
|
||||
*unconsumed = *len + nl;
|
||||
} else {
|
||||
/* Keep offset for check of possibly missing \n in \r\n. */
|
||||
if (step != 1)
|
||||
offset = avail;
|
||||
if (archive_ckd_add_size(&request, avail, step))
|
||||
break;
|
||||
if (request > MAX_LINE_LENGTH)
|
||||
request = MAX_LINE_LENGTH;
|
||||
}
|
||||
*nbytes_read = *avail;
|
||||
*ravail = *avail;
|
||||
*b += diff;
|
||||
*avail -= diff;
|
||||
tested = len;/* Skip some bytes we already determined. */
|
||||
len = get_line(*b + tested, *avail - tested, nl);
|
||||
if (len >= 0)
|
||||
len += tested;
|
||||
}
|
||||
return (len);
|
||||
} while (line == NULL && avail < MAX_LINE_LENGTH && !parsed);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
|
||||
|
||||
/*
|
||||
* Parses the header line of a uuencoded file, "begin <mode> <name>", or of
|
||||
* a base64 encoded file, "begin-base64 <mode> <name>". The mode is a
|
||||
* sequence of at least three octal digits: encoders don't all write the same
|
||||
* number of them, for example 644, 0644 or 4755 for the same kind of file.
|
||||
*
|
||||
* Returns the length of the "begin " or "begin-base64 " prefix, or 0 if the
|
||||
* line is not a header. Stores the permission bits of the mode in *mode and
|
||||
* the offset of the name in *name_offset, unless they are NULL.
|
||||
*/
|
||||
static size_t
|
||||
parse_header(const unsigned char *p, size_t len, mode_t *mode,
|
||||
size_t *name_offset)
|
||||
{
|
||||
size_t i, l;
|
||||
mode_t m;
|
||||
|
||||
if (len >= 6 && memcmp(p, "begin ", 6) == 0)
|
||||
l = 6;
|
||||
else if (len >= 13 && memcmp(p, "begin-base64 ", 13) == 0)
|
||||
l = 13;
|
||||
else
|
||||
return (0);
|
||||
|
||||
m = 0;
|
||||
for (i = l; i < len && p[i] >= '0' && p[i] <= '7'; i++)
|
||||
m = ((m << 3) | (p[i] - '0')) & 0777;
|
||||
/*
|
||||
* Need at least three digits, as too lenient a check would have
|
||||
* the bidder take other kinds of data for a header. Then a space and
|
||||
* a one character name.
|
||||
*/
|
||||
if (i - l < 3 || i + 1 >= len || p[i] != ' ')
|
||||
return (0);
|
||||
|
||||
if (mode != NULL)
|
||||
*mode = m;
|
||||
if (name_offset != NULL)
|
||||
*name_offset = i + 1;
|
||||
return (l);
|
||||
}
|
||||
|
||||
static int
|
||||
uudecode_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
struct archive_read_filter *f)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t avail, ravail;
|
||||
ssize_t len, nl;
|
||||
int l;
|
||||
size_t l;
|
||||
int firstline;
|
||||
size_t nbytes_read;
|
||||
size_t len, offset;
|
||||
ssize_t unconsumed;
|
||||
|
||||
(void)b; /* UNUSED */
|
||||
|
||||
p = __archive_read_filter_ahead(f, 1, &avail);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
|
||||
offset = 0;
|
||||
firstline = 20;
|
||||
ravail = avail;
|
||||
nbytes_read = avail;
|
||||
for (;;) {
|
||||
len = bid_get_line(f, &p, &avail, &ravail, &nl, &nbytes_read);
|
||||
if (len < 0 || nl == 0)
|
||||
p = read_line_ahead(f, 0, offset, &len, &unconsumed);
|
||||
if (p == NULL)
|
||||
return (0); /* No match found. */
|
||||
if (len - nl >= 11 && memcmp(p, "begin ", 6) == 0)
|
||||
l = 6;
|
||||
else if (len -nl >= 18 && memcmp(p, "begin-base64 ", 13) == 0)
|
||||
l = 13;
|
||||
else
|
||||
l = 0;
|
||||
offset += unconsumed;
|
||||
|
||||
if (l > 0 && (p[l] < '0' || p[l] > '7' ||
|
||||
p[l+1] < '0' || p[l+1] > '7' ||
|
||||
p[l+2] < '0' || p[l+2] > '7' || p[l+3] != ' '))
|
||||
l = 0;
|
||||
|
||||
p += len;
|
||||
avail -= len;
|
||||
if (l)
|
||||
l = parse_header(p, len, NULL, NULL);
|
||||
if (l != 0)
|
||||
break;
|
||||
firstline = 0;
|
||||
|
||||
/* Do not read more than UUENCODE_BID_MAX_READ bytes */
|
||||
if (nbytes_read >= UUENCODE_BID_MAX_READ)
|
||||
return (0);
|
||||
}
|
||||
if (!avail)
|
||||
return (0);
|
||||
len = bid_get_line(f, &p, &avail, &ravail, &nl, &nbytes_read);
|
||||
if (len < 0 || nl == 0)
|
||||
return (0);/* There are non-ascii characters. */
|
||||
avail -= len;
|
||||
p = read_line_ahead(f, 0, offset, &len, &unconsumed);
|
||||
if (p == NULL)
|
||||
return (0); /* No match found. */
|
||||
|
||||
if (l == 6) {
|
||||
/* "begin " */
|
||||
@@ -316,10 +307,13 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
return (0);
|
||||
/* Get a length of decoded bytes. */
|
||||
l = UUDECODE(*p++); len--;
|
||||
if (l == 0)
|
||||
/* empty encoded file */
|
||||
return (firstline+30);
|
||||
if (l > 45)
|
||||
/* Normally, maximum length is 45(character 'M'). */
|
||||
return (0);
|
||||
if (l > len - nl)
|
||||
if (l > len)
|
||||
return (0); /* Line too short. */
|
||||
while (l) {
|
||||
if (!uuchar[*p++])
|
||||
@@ -327,30 +321,27 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
--len;
|
||||
--l;
|
||||
}
|
||||
if (len-nl == 1 &&
|
||||
if (len == 1 &&
|
||||
(uuchar[*p] || /* Check sum. */
|
||||
(*p >= 'a' && *p <= 'z'))) {/* Padding data(MINIX). */
|
||||
++p;
|
||||
--len;
|
||||
}
|
||||
p += nl;
|
||||
if (avail && uuchar[*p])
|
||||
offset += unconsumed;
|
||||
p = read_line_ahead(f, 0, offset, &len, &unconsumed);
|
||||
if (p != NULL && uuchar[*p])
|
||||
return (firstline+30);
|
||||
} else if (l == 13) {
|
||||
/* "begin-base64 " */
|
||||
while (len-nl > 0) {
|
||||
while (len > 0) {
|
||||
if (!base64[*p++])
|
||||
return (0);
|
||||
--len;
|
||||
len--;
|
||||
}
|
||||
p += nl;
|
||||
|
||||
if (avail >= 5 && memcmp(p, "====\n", 5) == 0)
|
||||
return (firstline+40);
|
||||
if (avail >= 6 && memcmp(p, "====\r\n", 6) == 0)
|
||||
return (firstline+40);
|
||||
if (avail > 0 && base64[*p])
|
||||
if (len == 0)
|
||||
return (firstline+30);
|
||||
if (len == 4 && memcmp(p, "====", 4) == 0)
|
||||
return (firstline+40);
|
||||
}
|
||||
|
||||
return (0);
|
||||
@@ -366,29 +357,23 @@ uudecode_reader_vtable = {
|
||||
static int
|
||||
uudecode_bidder_init(struct archive_read_filter *f)
|
||||
{
|
||||
struct uu *uu;
|
||||
struct uu *uu;
|
||||
void *out_buff;
|
||||
void *in_buff;
|
||||
|
||||
f->code = ARCHIVE_FILTER_UU;
|
||||
f->name = "uu";
|
||||
|
||||
uu = calloc(1, sizeof(*uu));
|
||||
out_buff = malloc(OUT_BUFF_SIZE);
|
||||
in_buff = malloc(IN_BUFF_SIZE);
|
||||
if (uu == NULL || out_buff == NULL || in_buff == NULL) {
|
||||
if (uu == NULL || out_buff == NULL) {
|
||||
archive_set_error(&f->archive->archive, ENOMEM,
|
||||
"Can't allocate data for uudecode");
|
||||
free(uu);
|
||||
free(out_buff);
|
||||
free(in_buff);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
f->data = uu;
|
||||
uu->in_buff = in_buff;
|
||||
uu->in_cnt = 0;
|
||||
uu->in_allocated = IN_BUFF_SIZE;
|
||||
uu->out_buff = out_buff;
|
||||
uu->state = ST_FIND_HEAD;
|
||||
uu->mode_set = 0;
|
||||
@@ -398,45 +383,6 @@ uudecode_bidder_init(struct archive_read_filter *f)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
ensure_in_buff_size(struct archive_read_filter *f,
|
||||
struct uu *uu, size_t size)
|
||||
{
|
||||
|
||||
if (size > uu->in_allocated) {
|
||||
unsigned char *ptr;
|
||||
size_t newsize;
|
||||
|
||||
/*
|
||||
* Calculate a new buffer size for in_buff.
|
||||
* Increase its value until it is enough for our needs.
|
||||
*/
|
||||
newsize = uu->in_allocated;
|
||||
do {
|
||||
if (newsize < IN_BUFF_SIZE*32)
|
||||
newsize <<= 1;
|
||||
else
|
||||
newsize += IN_BUFF_SIZE;
|
||||
} while (size > newsize);
|
||||
/* Allocate the new buffer. */
|
||||
ptr = malloc(newsize);
|
||||
if (ptr == NULL) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ENOMEM,
|
||||
"Can't allocate data for uudecode");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Move the remaining data in in_buff into the new buffer. */
|
||||
if (uu->in_cnt)
|
||||
memmove(ptr, uu->in_buff, uu->in_cnt);
|
||||
/* Replace in_buff with the new buffer. */
|
||||
free(uu->in_buff);
|
||||
uu->in_buff = ptr;
|
||||
uu->in_allocated = newsize;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
uudecode_read_header(struct archive_read_filter *f, struct archive_entry *entry)
|
||||
{
|
||||
@@ -455,138 +401,59 @@ static ssize_t
|
||||
uudecode_filter_read(struct archive_read_filter *f, const void **buff)
|
||||
{
|
||||
struct uu *uu = f->data;
|
||||
const unsigned char *b, *d;
|
||||
unsigned char *out;
|
||||
ssize_t avail_in, ravail;
|
||||
ssize_t used;
|
||||
ssize_t total;
|
||||
ssize_t len, llen, nl, namelen;
|
||||
|
||||
read_more:
|
||||
d = __archive_read_filter_ahead(f->upstream, 1, &avail_in);
|
||||
if (d == NULL && avail_in < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
/* Quiet a code analyzer; make sure avail_in must be zero
|
||||
* when d is NULL. */
|
||||
if (d == NULL)
|
||||
avail_in = 0;
|
||||
used = 0;
|
||||
total = 0;
|
||||
out = uu->out_buff;
|
||||
if (avail_in > 2 * UUENCODE_BID_MAX_READ)
|
||||
avail_in = 2 * UUENCODE_BID_MAX_READ;
|
||||
ravail = avail_in;
|
||||
if (uu->state == ST_IGNORE) {
|
||||
used = avail_in;
|
||||
goto finish;
|
||||
}
|
||||
if (uu->in_cnt) {
|
||||
if (uu->in_cnt > UUENCODE_BID_MAX_READ) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid format data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/*
|
||||
* If there is remaining data which is saved by
|
||||
* a previous call, use it first.
|
||||
*/
|
||||
if (ensure_in_buff_size(f, uu,
|
||||
avail_in + uu->in_cnt) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (avail_in > 0)
|
||||
memcpy(uu->in_buff + uu->in_cnt,
|
||||
d, avail_in);
|
||||
d = uu->in_buff;
|
||||
avail_in += uu->in_cnt;
|
||||
uu->in_cnt = 0;
|
||||
}
|
||||
for (;used < avail_in; d += llen, used += llen) {
|
||||
ssize_t l, body;
|
||||
total = 0;
|
||||
|
||||
b = d;
|
||||
len = get_line(b, avail_in - used, &nl);
|
||||
if (len < 0) {
|
||||
/* Non-ascii character is found. */
|
||||
if (uu->state == ST_FIND_HEAD &&
|
||||
(uu->total > 0 || total > 0)) {
|
||||
uu->state = ST_IGNORE;
|
||||
used = avail_in;
|
||||
goto finish;
|
||||
}
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (len > UUENCODE_BID_MAX_READ) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid format data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
llen = len;
|
||||
if ((nl == 0) && (uu->state != ST_UUEND)) {
|
||||
if (total == 0 && ravail <= 0) {
|
||||
/* There is nothing more to read, fail */
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Missing format data");
|
||||
while (uu->state != ST_IGNORE) {
|
||||
const unsigned char *b;
|
||||
ssize_t unconsumed;
|
||||
ssize_t l, body;
|
||||
ssize_t namelen;
|
||||
size_t len, name_offset;
|
||||
mode_t mode;
|
||||
|
||||
b = read_line_ahead(f->upstream, total, 0,
|
||||
&len, &unconsumed);
|
||||
if (b == NULL) {
|
||||
if (unconsumed < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/*
|
||||
* Save remaining data which does not contain
|
||||
* NL('\n','\r').
|
||||
*/
|
||||
if (ensure_in_buff_size(f, uu, len)
|
||||
!= ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (uu->in_buff != b)
|
||||
memmove(uu->in_buff, b, len);
|
||||
uu->in_cnt = len;
|
||||
if (total == 0) {
|
||||
/* Do not return 0; it means end-of-file.
|
||||
* We should try to read more bytes. */
|
||||
__archive_read_filter_consume(
|
||||
f->upstream, ravail);
|
||||
goto read_more;
|
||||
}
|
||||
used += len;
|
||||
break;
|
||||
}
|
||||
switch (uu->state) {
|
||||
default:
|
||||
case ST_FIND_HEAD:
|
||||
/* Do not read more than UUENCODE_BID_MAX_READ bytes */
|
||||
if (total + len >= UUENCODE_BID_MAX_READ) {
|
||||
if (unconsumed == MAX_LINE_LENGTH) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid format data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0)
|
||||
l = 6;
|
||||
else if (len - nl >= 18 &&
|
||||
memcmp(b, "begin-base64 ", 13) == 0)
|
||||
l = 13;
|
||||
else
|
||||
l = 0;
|
||||
if (l != 0 && b[l] >= '0' && b[l] <= '7' &&
|
||||
b[l+1] >= '0' && b[l+1] <= '7' &&
|
||||
b[l+2] >= '0' && b[l+2] <= '7' && b[l+3] == ' ') {
|
||||
if (total != 0)
|
||||
break;
|
||||
if (uu->state != ST_FIND_HEAD) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Non-ascii character or end of stream is found. */
|
||||
uu->state = ST_IGNORE;
|
||||
}
|
||||
|
||||
switch (uu->state) {
|
||||
case ST_IGNORE:
|
||||
default:
|
||||
break;
|
||||
case ST_FIND_HEAD:
|
||||
l = parse_header(b, len, &mode, &name_offset);
|
||||
if (l != 0) {
|
||||
if (l == 6)
|
||||
uu->state = ST_READ_UU;
|
||||
else
|
||||
uu->state = ST_READ_BASE64;
|
||||
uu->mode = (mode_t)(
|
||||
((int)(b[l] - '0') * 64) +
|
||||
((int)(b[l+1] - '0') * 8) +
|
||||
(int)(b[l+2] - '0'));
|
||||
uu->mode = mode;
|
||||
uu->mode_set = 1;
|
||||
namelen = len - nl - 4 - l;
|
||||
namelen = len - name_offset;
|
||||
if (namelen > 1) {
|
||||
if (uu->name != NULL)
|
||||
free(uu->name);
|
||||
free(uu->name);
|
||||
uu->name = malloc(namelen + 1);
|
||||
if (uu->name == NULL) {
|
||||
archive_set_error(
|
||||
@@ -596,7 +463,7 @@ read_more:
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
strncpy(uu->name,
|
||||
(const char *)(b + l + 4),
|
||||
(const char *)(b + name_offset),
|
||||
namelen);
|
||||
uu->name[namelen] = '\0';
|
||||
}
|
||||
@@ -605,7 +472,7 @@ read_more:
|
||||
case ST_READ_UU:
|
||||
if (total + len * 2 > OUT_BUFF_SIZE)
|
||||
goto finish;
|
||||
body = len - nl;
|
||||
body = len;
|
||||
if (!uuchar[*b] || body <= 0) {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
@@ -658,8 +525,8 @@ read_more:
|
||||
}
|
||||
break;
|
||||
case ST_UUEND:
|
||||
if (len - nl == 3 && memcmp(b, "end ", 3) == 0)
|
||||
uu->state = ST_FIND_HEAD;
|
||||
if (len == 3 && memcmp(b, "end", 3) == 0)
|
||||
uu->state = ST_IGNORE;
|
||||
else {
|
||||
archive_set_error(&f->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
@@ -670,10 +537,10 @@ read_more:
|
||||
case ST_READ_BASE64:
|
||||
if (total + len * 2 > OUT_BUFF_SIZE)
|
||||
goto finish;
|
||||
l = len - nl;
|
||||
l = len;
|
||||
if (l >= 3 && b[0] == '=' && b[1] == '=' &&
|
||||
b[2] == '=') {
|
||||
uu->state = ST_FIND_HEAD;
|
||||
uu->state = ST_IGNORE;
|
||||
break;
|
||||
}
|
||||
while (l > 0) {
|
||||
@@ -713,14 +580,10 @@ read_more:
|
||||
}
|
||||
break;
|
||||
}
|
||||
__archive_read_filter_consume(f->upstream, unconsumed);
|
||||
}
|
||||
finish:
|
||||
if (ravail < avail_in)
|
||||
used -= avail_in - ravail;
|
||||
__archive_read_filter_consume(f->upstream, used);
|
||||
|
||||
*buff = uu->out_buff;
|
||||
uu->total += total;
|
||||
return (total);
|
||||
}
|
||||
|
||||
@@ -729,7 +592,6 @@ uudecode_filter_close(struct archive_read_filter *f)
|
||||
{
|
||||
struct uu *uu = f->data;
|
||||
|
||||
free(uu->in_buff);
|
||||
free(uu->out_buff);
|
||||
free(uu->name);
|
||||
free(uu);
|
||||
|
||||
@@ -115,7 +115,7 @@ archive_read_support_filter_xz(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "xz",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&xz_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -147,7 +147,7 @@ archive_read_support_filter_lzma(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "lzma",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&lzma_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -180,7 +180,7 @@ archive_read_support_filter_lzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "lzip",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&lzip_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
@@ -87,7 +83,7 @@ archive_read_support_filter_zstd(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
if (__archive_read_register_bidder(a, NULL, "zstd",
|
||||
if (__archive_read_register_bidder(a, NULL,
|
||||
&zstd_bidder_vtable) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
@@ -109,6 +105,7 @@ zstd_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
int bits_checked = 0;
|
||||
/*
|
||||
* Zstandard skippable frames contain a 4 byte magic number followed
|
||||
* by a 4 byte frame data size, then that number of bytes of data.
|
||||
@@ -147,6 +144,7 @@ zstd_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
uint32_t frame_data_size;
|
||||
|
||||
/* Skip over the magic number */
|
||||
bits_checked += 28;
|
||||
offset_in_buffer += 4;
|
||||
|
||||
/* Ensure that we can read another 4 bytes. */
|
||||
@@ -172,12 +170,10 @@ zstd_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
* if this is zstd data.
|
||||
*/
|
||||
if (archive_ckd_add_size(&min,
|
||||
offset_in_buffer, min_zstd_frame_size))
|
||||
offset_in_buffer, min_zstd_frame_size) ||
|
||||
min > max_lookahead)
|
||||
return (0);
|
||||
if (min > (size_t)avail) {
|
||||
if (min > max_lookahead)
|
||||
return (0);
|
||||
|
||||
buffer = __archive_read_filter_ahead(f,
|
||||
min, &avail);
|
||||
if (buffer == NULL)
|
||||
@@ -193,7 +189,7 @@ zstd_bidder_bid(struct archive_read_filter_bidder *b,
|
||||
*/
|
||||
|
||||
if (magic_number == zstd_magic)
|
||||
return (offset_in_buffer + 4);
|
||||
return (bits_checked + 32);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -60,13 +60,11 @@
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_endian.h"
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
#include "archive_crc32.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define _7ZIP_SIGNATURE "7z\xBC\xAF\x27\x1C"
|
||||
#define SFX_MIN_ADDR 0x27000
|
||||
#define SFX_MAX_ADDR 0x60000
|
||||
#define SFX_MAX_ADDR 0x80000
|
||||
#define SFX_MAX_OFFSET (SFX_MAX_ADDR - SFX_MIN_ADDR)
|
||||
#define SFX_MAX_SEEK 0x800000
|
||||
|
||||
@@ -353,13 +351,21 @@ struct _7zip {
|
||||
|
||||
/* Decoding BCJ and BCJ2 data. */
|
||||
uint32_t bcj_state;
|
||||
size_t odd_bcj_size;
|
||||
unsigned char odd_bcj[4];
|
||||
size_t odd_bcj_size; /* Number of bytes currently stashed in odd_bcj. */
|
||||
/* Bytes that a filter didn't have enough lookahead to transform yet.
|
||||
* Big enough to hold the largest lookahead (IA64). */
|
||||
unsigned char odd_bcj[16];
|
||||
|
||||
/* Decoding BCJ data. */
|
||||
size_t bcj_prevPosT;
|
||||
uint32_t bcj_prevMask;
|
||||
uint32_t bcj_ip;
|
||||
|
||||
/* Decoding Delta data. */
|
||||
unsigned delta_dist;
|
||||
uint8_t delta_pos;
|
||||
uint8_t delta_history[256];
|
||||
|
||||
/* Decoding BCJ2 data. */
|
||||
int64_t main_stream_bytes_remaining;
|
||||
unsigned char *sub_stream_buff[3];
|
||||
@@ -459,10 +465,17 @@ static void x86_Init(struct _7zip *);
|
||||
static size_t x86_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static void arm_Init(struct _7zip *);
|
||||
static size_t arm_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static void armthumb_Init(struct _7zip *);
|
||||
static size_t armthumb_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t sparc_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t powerpc_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t riscv_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t ia64_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static void delta_Init(struct _7zip *, unsigned);
|
||||
static void delta_Decode(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t bcj_lookahead(int64_t);
|
||||
static int64_t seek_compat(struct archive_read *, int64_t, int, int);
|
||||
|
||||
|
||||
@@ -478,8 +491,7 @@ archive_read_support_format_7zip(struct archive *_a)
|
||||
|
||||
zip = calloc(1, sizeof(*zip));
|
||||
if (zip == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate 7zip data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate 7zip data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -489,7 +501,6 @@ archive_read_support_format_7zip(struct archive *_a)
|
||||
*/
|
||||
zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
||||
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
zip,
|
||||
"7zip",
|
||||
@@ -505,7 +516,7 @@ archive_read_support_format_7zip(struct archive *_a)
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(zip);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -531,11 +542,11 @@ archive_read_format_7zip_has_encrypted_entries(struct archive_read *a)
|
||||
static int
|
||||
get_data_offset(struct archive_read *a, int64_t *data_offset, int compat)
|
||||
{
|
||||
const unsigned char *p;
|
||||
const unsigned char *h;
|
||||
int64_t offset, sfx_offset;
|
||||
int r, window;
|
||||
|
||||
if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) {
|
||||
if ((h = __archive_read_ahead(a, 6, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated 7-Zip file body");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -543,7 +554,7 @@ get_data_offset(struct archive_read *a, int64_t *data_offset, int compat)
|
||||
|
||||
/* If first six bytes are the 7-Zip signature,
|
||||
* return the offset right now. */
|
||||
if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) {
|
||||
if (memcmp(h, _7ZIP_SIGNATURE, 6) == 0) {
|
||||
*data_offset = 0;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@@ -556,9 +567,9 @@ get_data_offset(struct archive_read *a, int64_t *data_offset, int compat)
|
||||
* performing a seek, get_elf_sfx_offset requires one,
|
||||
* thus a performance difference between the two is expected.
|
||||
*/
|
||||
if ((p[0] == 'M' && p[1] == 'Z'))
|
||||
if ((h[0] == 'M' && h[1] == 'Z'))
|
||||
r = get_pe_sfx_offset(a, &sfx_offset);
|
||||
else if (memcmp(p, "\x7F\x45LF", 4) == 0)
|
||||
else if (memcmp(h, "\x7F\x45LF", 4) == 0)
|
||||
r = get_elf_sfx_offset(a, &sfx_offset, compat);
|
||||
else
|
||||
r = ARCHIVE_FATAL;
|
||||
@@ -567,27 +578,29 @@ get_data_offset(struct archive_read *a, int64_t *data_offset, int compat)
|
||||
|
||||
offset = sfx_offset;
|
||||
window = 4096;
|
||||
while (offset + window <= (sfx_offset + SFX_MAX_OFFSET)) {
|
||||
#define SFX_MAX_READAHEAD (sfx_offset + SFX_MAX_OFFSET)
|
||||
while (offset + window <= SFX_MAX_READAHEAD) {
|
||||
ssize_t bytes_avail;
|
||||
const unsigned char *buff = __archive_read_ahead(a,
|
||||
offset + window, &bytes_avail);
|
||||
if (buff == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window >>= 1;
|
||||
if (window < 0x40)
|
||||
goto fail;
|
||||
continue;
|
||||
|
||||
h = __archive_read_ahead(a, offset + window, &bytes_avail);
|
||||
if (h == NULL) {
|
||||
if (bytes_avail >= offset + 32) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window = bytes_avail - offset;
|
||||
continue;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
p = buff + offset;
|
||||
while (buff + bytes_avail - p >= 32) {
|
||||
size_t step = check_7zip_header_in_sfx(p);
|
||||
if (bytes_avail > SFX_MAX_READAHEAD)
|
||||
bytes_avail = SFX_MAX_READAHEAD;
|
||||
while (offset <= bytes_avail - 32) {
|
||||
size_t step = check_7zip_header_in_sfx(h + offset);
|
||||
if (step == 0) {
|
||||
*data_offset = p - buff;
|
||||
*data_offset = offset;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
p += step;
|
||||
offset += step;
|
||||
}
|
||||
offset = p - buff;
|
||||
}
|
||||
fail:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@@ -600,9 +613,9 @@ archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
int64_t data_offset;
|
||||
|
||||
/* If someone has already bid more than 32, then avoid
|
||||
/* If someone has already bid more than 48, then avoid
|
||||
trashing the look-ahead buffers with a seek. */
|
||||
if (best_bid > 32)
|
||||
if (best_bid > 48)
|
||||
return (-1);
|
||||
|
||||
if (get_data_offset(a, &data_offset, 0) < 0)
|
||||
@@ -623,7 +636,7 @@ check_7zip_header_in_sfx(const unsigned char *p)
|
||||
* Magic Code, so we should do this in order not to
|
||||
* make a mis-detection.
|
||||
*/
|
||||
if (crc32(0, p + 12, 20) != archive_le32dec(p + 8))
|
||||
if (__archive_crc32(0, p + 12, 20) != archive_le32dec(p + 8))
|
||||
return (6);
|
||||
/* Hit the header! */
|
||||
return (0);
|
||||
@@ -965,7 +978,13 @@ archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
}
|
||||
}
|
||||
|
||||
if (archive_entry_copy_pathname_l(entry,
|
||||
if (zip_entry->utf16name == NULL) {
|
||||
/*
|
||||
* No kName property (eg from`7z a -si`): 7-Zip derives the
|
||||
* name from the archive filename, which we don't know.
|
||||
*/
|
||||
archive_entry_set_pathname(entry, "data");
|
||||
} else if (archive_entry_copy_pathname_l(entry,
|
||||
(const char *)zip_entry->utf16name,
|
||||
zip_entry->name_len, zip->sconv) != 0) {
|
||||
if (errno == ENOMEM) {
|
||||
@@ -1135,7 +1154,7 @@ archive_read_format_7zip_read_data(struct archive_read *a,
|
||||
|
||||
/* Update checksum */
|
||||
if ((zip->entry->flg & CRC32_IS_SET) && bytes)
|
||||
zip->entry_crc32 = crc32(zip->entry_crc32, *buff,
|
||||
zip->entry_crc32 = __archive_crc32(zip->entry_crc32, *buff,
|
||||
(unsigned)bytes);
|
||||
|
||||
/* If we hit the end, swallow any end-of-data marker. */
|
||||
@@ -1302,6 +1321,15 @@ ppmd_read(void *p)
|
||||
* and we are on boundary;
|
||||
* last resort to read using __archive_read_ahead.
|
||||
*/
|
||||
if (zip->pack_stream_inbytes_remaining <= 0 ||
|
||||
zip->ppstream.stream_in >=
|
||||
(uint64_t)zip->pack_stream_inbytes_remaining) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated 7z file data");
|
||||
zip->ppstream.overconsumed = 1;
|
||||
return (0);
|
||||
}
|
||||
const uint8_t *data = __archive_read_ahead(a,
|
||||
zip->ppstream.stream_in + 1, NULL);
|
||||
if (data == NULL) {
|
||||
@@ -1339,9 +1367,13 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
if (coder2->codec != _7Z_X86 &&
|
||||
coder2->codec != _7Z_X86_BCJ2 &&
|
||||
coder2->codec != _7Z_ARM &&
|
||||
coder2->codec != _7Z_ARMTHUMB &&
|
||||
coder2->codec != _7Z_ARM64 &&
|
||||
coder2->codec != _7Z_IA64 &&
|
||||
coder2->codec != _7Z_POWERPC &&
|
||||
coder2->codec != _7Z_SPARC) {
|
||||
coder2->codec != _7Z_RISCV &&
|
||||
coder2->codec != _7Z_SPARC &&
|
||||
coder2->codec != _7Z_DELTA) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Unsupported filter %jx for %jx",
|
||||
@@ -1349,12 +1381,29 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
(uintmax_t)coder1->codec);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
if (coder2->codec == _7Z_DELTA &&
|
||||
coder2->propertiesSize != 1) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Delta parameter");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
zip->codec2 = coder2->codec;
|
||||
zip->bcj_state = 0;
|
||||
if (coder2->codec == _7Z_X86)
|
||||
x86_Init(zip);
|
||||
else if (coder2->codec == _7Z_ARM)
|
||||
arm_Init(zip);
|
||||
else if (coder2->codec == _7Z_ARMTHUMB)
|
||||
armthumb_Init(zip);
|
||||
else if (coder2->codec == _7Z_ARM64 ||
|
||||
coder2->codec == _7Z_IA64 ||
|
||||
coder2->codec == _7Z_POWERPC ||
|
||||
coder2->codec == _7Z_RISCV ||
|
||||
coder2->codec == _7Z_SPARC)
|
||||
zip->bcj_ip = 0;
|
||||
else if (coder2->codec == _7Z_DELTA)
|
||||
delta_Init(zip, coder2->properties[0] + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1407,73 +1456,86 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
zip->codec2 = coder2->codec;
|
||||
|
||||
filters[fi].options = NULL;
|
||||
switch (zip->codec2) {
|
||||
case _7Z_X86:
|
||||
if (zip->codec == _7Z_LZMA2) {
|
||||
/*
|
||||
* Only LZMA2 gets liblzma's branch filters; for LZMA1
|
||||
* we run our own instead, for the reason given above.
|
||||
*/
|
||||
if (zip->codec != _7Z_LZMA2 &&
|
||||
bcj_lookahead(zip->codec2) != 0) {
|
||||
/* Use our filter. */
|
||||
if (zip->codec2 == _7Z_X86)
|
||||
x86_Init(zip);
|
||||
else if (zip->codec2 == _7Z_ARM)
|
||||
arm_Init(zip);
|
||||
else if (zip->codec2 == _7Z_ARMTHUMB)
|
||||
armthumb_Init(zip);
|
||||
else /* ARM64, IA64, POWERPC, RISCV, SPARC. */
|
||||
zip->bcj_ip = 0;
|
||||
} else {
|
||||
switch (zip->codec2) {
|
||||
case _7Z_X86:
|
||||
filters[fi].id = LZMA_FILTER_X86;
|
||||
fi++;
|
||||
} else
|
||||
break;
|
||||
case _7Z_X86_BCJ2:
|
||||
/* Use our filter. */
|
||||
x86_Init(zip);
|
||||
break;
|
||||
case _7Z_X86_BCJ2:
|
||||
/* Use our filter. */
|
||||
zip->bcj_state = 0;
|
||||
break;
|
||||
case _7Z_DELTA:
|
||||
if (coder2->propertiesSize != 1) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Delta parameter");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
filters[fi].id = LZMA_FILTER_DELTA;
|
||||
memset(&delta_opt, 0, sizeof(delta_opt));
|
||||
delta_opt.type = LZMA_DELTA_TYPE_BYTE;
|
||||
delta_opt.dist =
|
||||
coder2->properties[0] + 1;
|
||||
filters[fi].options = &delta_opt;
|
||||
fi++;
|
||||
break;
|
||||
/* Following filters have not been tested yet. */
|
||||
case _7Z_POWERPC:
|
||||
filters[fi].id = LZMA_FILTER_POWERPC;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_IA64:
|
||||
filters[fi].id = LZMA_FILTER_IA64;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_ARM:
|
||||
filters[fi].id = LZMA_FILTER_ARM;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_ARMTHUMB:
|
||||
filters[fi].id = LZMA_FILTER_ARMTHUMB;
|
||||
fi++;
|
||||
break;
|
||||
zip->bcj_state = 0;
|
||||
break;
|
||||
case _7Z_DELTA:
|
||||
if (coder2->propertiesSize != 1) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Invalid Delta parameter");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
filters[fi].id = LZMA_FILTER_DELTA;
|
||||
memset(&delta_opt, 0, sizeof(delta_opt));
|
||||
delta_opt.type = LZMA_DELTA_TYPE_BYTE;
|
||||
delta_opt.dist =
|
||||
coder2->properties[0] + 1;
|
||||
filters[fi].options = &delta_opt;
|
||||
fi++;
|
||||
break;
|
||||
/* Following filters have not been tested yet. */
|
||||
case _7Z_POWERPC:
|
||||
filters[fi].id = LZMA_FILTER_POWERPC;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_IA64:
|
||||
filters[fi].id = LZMA_FILTER_IA64;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_ARM:
|
||||
filters[fi].id = LZMA_FILTER_ARM;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_ARMTHUMB:
|
||||
filters[fi].id = LZMA_FILTER_ARMTHUMB;
|
||||
fi++;
|
||||
break;
|
||||
#ifdef LZMA_FILTER_ARM64
|
||||
case _7Z_ARM64:
|
||||
filters[fi].id = LZMA_FILTER_ARM64;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_ARM64:
|
||||
filters[fi].id = LZMA_FILTER_ARM64;
|
||||
fi++;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LZMA_FILTER_RISCV
|
||||
case _7Z_RISCV:
|
||||
filters[fi].id = LZMA_FILTER_RISCV;
|
||||
fi++;
|
||||
break;
|
||||
case _7Z_RISCV:
|
||||
filters[fi].id = LZMA_FILTER_RISCV;
|
||||
fi++;
|
||||
break;
|
||||
#endif
|
||||
case _7Z_SPARC:
|
||||
filters[fi].id = LZMA_FILTER_SPARC;
|
||||
fi++;
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Unexpected codec ID: %jX",
|
||||
(uintmax_t)zip->codec2);
|
||||
return (ARCHIVE_FAILED);
|
||||
case _7Z_SPARC:
|
||||
filters[fi].id = LZMA_FILTER_SPARC;
|
||||
fi++;
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Unexpected codec ID: %jX",
|
||||
(uintmax_t)zip->codec2);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1672,6 +1734,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
size_t t_avail_in, t_avail_out;
|
||||
uint8_t *bcj2_next_out;
|
||||
size_t bcj2_avail_out;
|
||||
size_t odd_bcj_out = 0;
|
||||
int r, ret = ARCHIVE_OK;
|
||||
|
||||
t_avail_in = o_avail_in = *used;
|
||||
@@ -1679,12 +1742,14 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
t_next_in = b;
|
||||
t_next_out = buff;
|
||||
|
||||
if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) {
|
||||
if (zip->codec != _7Z_LZMA2 && bcj_lookahead(zip->codec2) != 0) {
|
||||
int i;
|
||||
size_t min_out = bcj_lookahead(zip->codec2);
|
||||
|
||||
/* Do not copy out the BCJ remaining bytes when the output
|
||||
* buffer size is less than five bytes. */
|
||||
if (o_avail_in != 0 && t_avail_out < 5 && zip->odd_bcj_size) {
|
||||
* buffer size is less than the filter's lookahead size. */
|
||||
if (o_avail_in != 0 && t_avail_out < min_out &&
|
||||
zip->odd_bcj_size) {
|
||||
*used = 0;
|
||||
*outbytes = 0;
|
||||
return (ret);
|
||||
@@ -1693,8 +1758,17 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
*t_next_out++ = zip->odd_bcj[i];
|
||||
t_avail_out--;
|
||||
zip->odd_bcj_size--;
|
||||
odd_bcj_out++;
|
||||
}
|
||||
if (o_avail_in == 0 || t_avail_out == 0) {
|
||||
/*
|
||||
* PPMd is the only codec which can still produce output
|
||||
* after its packed stream has been consumed: it is asked
|
||||
* to flush the rest of the folder when called with no
|
||||
* input. Returning here would skip that flush and leave
|
||||
* the folder short, so let it through.
|
||||
*/
|
||||
if ((o_avail_in == 0 && zip->codec != _7Z_PPMD) ||
|
||||
t_avail_out == 0) {
|
||||
*used = o_avail_in - t_avail_in;
|
||||
*outbytes = o_avail_out - t_avail_out;
|
||||
if (o_avail_in == 0)
|
||||
@@ -1898,10 +1972,20 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
zip->ppmd7_stat = 1;
|
||||
}
|
||||
|
||||
if (t_avail_in == 0)
|
||||
/* XXX Flush out remaining decoded data XXX */
|
||||
flush_bytes = zip->folder_outbytes_remaining;
|
||||
else
|
||||
if (t_avail_in == 0) {
|
||||
/* XXX Flush out remaining decoded data XXX
|
||||
*
|
||||
* The bytes a BCJ filter parked on the previous call
|
||||
* have just been written to the output buffer, and
|
||||
* count towards what the folder still owes. Asking
|
||||
* PPMd to decode them a second time would run the
|
||||
* range decoder off the end of the packed stream. */
|
||||
flush_bytes = zip->folder_outbytes_remaining -
|
||||
(int64_t)odd_bcj_out;
|
||||
/* Those bytes were all that was left of the folder. */
|
||||
if (flush_bytes <= 0)
|
||||
break;
|
||||
} else
|
||||
flush_bytes = 0;
|
||||
|
||||
do {
|
||||
@@ -1939,34 +2023,64 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF)
|
||||
return (ret);
|
||||
|
||||
*used = o_avail_in - t_avail_in;
|
||||
if (zip->codec == _7Z_PPMD)
|
||||
*used = zip->ppstream.stream_in;
|
||||
else
|
||||
*used = o_avail_in - t_avail_in;
|
||||
*outbytes = o_avail_out - t_avail_out;
|
||||
|
||||
/*
|
||||
* Decode BCJ.
|
||||
*/
|
||||
if (zip->codec != _7Z_LZMA2) {
|
||||
if (zip->codec2 == _7Z_X86) {
|
||||
size_t l = x86_Convert(zip, buff, *outbytes);
|
||||
if (zip->codec != _7Z_LZMA2 && bcj_lookahead(zip->codec2) != 0) {
|
||||
size_t l;
|
||||
|
||||
zip->odd_bcj_size = *outbytes - l;
|
||||
if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 &&
|
||||
o_avail_in && ret != ARCHIVE_EOF) {
|
||||
memcpy(zip->odd_bcj,
|
||||
((unsigned char *)buff) + l,
|
||||
zip->odd_bcj_size);
|
||||
*outbytes = l;
|
||||
} else
|
||||
zip->odd_bcj_size = 0;
|
||||
} else if (zip->codec2 == _7Z_ARM) {
|
||||
*outbytes = arm_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_ARM64) {
|
||||
*outbytes = arm64_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_SPARC) {
|
||||
*outbytes = sparc_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_POWERPC) {
|
||||
*outbytes = powerpc_Convert(zip, buff, *outbytes);
|
||||
switch (zip->codec2) {
|
||||
case _7Z_X86:
|
||||
l = x86_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_ARM:
|
||||
l = arm_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_ARMTHUMB:
|
||||
l = armthumb_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_ARM64:
|
||||
l = arm64_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_SPARC:
|
||||
l = sparc_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_POWERPC:
|
||||
l = powerpc_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_RISCV:
|
||||
l = riscv_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
case _7Z_IA64:
|
||||
l = ia64_Convert(zip, buff, *outbytes);
|
||||
break;
|
||||
default:
|
||||
/* Unreachable: bcj_lookahead() returns non-zero only
|
||||
* for the codecs handled above. Guards against the two
|
||||
* lists drifting apart. */
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"BCJ filter internal error");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
/* Keep the bytes which could not be converted yet, they are
|
||||
* prepended to the output buffer on the next call. */
|
||||
zip->odd_bcj_size = *outbytes - l;
|
||||
if (zip->odd_bcj_size > 0 &&
|
||||
zip->odd_bcj_size <= sizeof(zip->odd_bcj) &&
|
||||
o_avail_in && ret != ARCHIVE_EOF) {
|
||||
memcpy(zip->odd_bcj,
|
||||
((unsigned char *)buff) + l,
|
||||
zip->odd_bcj_size);
|
||||
*outbytes = l;
|
||||
} else
|
||||
zip->odd_bcj_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1995,6 +2109,13 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
*outbytes = o_avail_out - bcj2_avail_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode Delta. LZMA1 and LZMA2 use liblzma's Delta filter instead.
|
||||
*/
|
||||
if (zip->codec2 == _7Z_DELTA &&
|
||||
zip->codec != _7Z_LZMA && zip->codec != _7Z_LZMA2)
|
||||
delta_Decode(zip, buff, *outbytes);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -3176,19 +3297,19 @@ read_Times(struct archive_read *a, int type)
|
||||
goto failed;
|
||||
switch (type) {
|
||||
case kCTime:
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
__archive_ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].ctime),
|
||||
&(entries[i].ctime_ns));
|
||||
entries[i].flg |= CTIME_IS_SET;
|
||||
break;
|
||||
case kATime:
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
__archive_ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].atime),
|
||||
&(entries[i].atime_ns));
|
||||
entries[i].flg |= ATIME_IS_SET;
|
||||
break;
|
||||
case kMTime:
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
__archive_ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].mtime),
|
||||
&(entries[i].mtime_ns));
|
||||
entries[i].flg |= MTIME_IS_SET;
|
||||
@@ -3267,7 +3388,7 @@ header_bytes(struct archive_read *a, size_t rbytes)
|
||||
}
|
||||
|
||||
/* Update checksum */
|
||||
zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes);
|
||||
zip->header_crc32 = __archive_crc32(zip->header_crc32, p, (unsigned)rbytes);
|
||||
return (p);
|
||||
}
|
||||
|
||||
@@ -3306,7 +3427,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
|
||||
}
|
||||
|
||||
/* CRC check. */
|
||||
if (crc32(0, p + 12, 20)
|
||||
if (__archive_crc32(0, p + 12, 20)
|
||||
!= archive_le32dec(p + 8)) {
|
||||
#ifndef DONT_FAIL_ON_CRC_ERROR
|
||||
archive_set_error(&a->archive, -1, "Header CRC error");
|
||||
@@ -3650,8 +3771,9 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
|
||||
if (zip->uncompressed_buffer_bytes_remaining ==
|
||||
zip->uncompressed_buffer_size)
|
||||
break;
|
||||
if (zip->codec2 == _7Z_X86 && zip->odd_bcj_size &&
|
||||
zip->uncompressed_buffer_bytes_remaining + 5 >
|
||||
if (zip->odd_bcj_size &&
|
||||
zip->uncompressed_buffer_bytes_remaining +
|
||||
bcj_lookahead(zip->codec2) >
|
||||
zip->uncompressed_buffer_size)
|
||||
break;
|
||||
if (zip->pack_stream_inbytes_remaining == 0 &&
|
||||
@@ -4280,6 +4402,54 @@ arm_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
armthumb_Init(struct _7zip *zip)
|
||||
{
|
||||
zip->bcj_ip = 4;
|
||||
}
|
||||
|
||||
static size_t
|
||||
armthumb_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
// in https://git.tukaani.org/xz-embedded.git
|
||||
|
||||
/*
|
||||
* Branch/Call/Jump (BCJ) filter decoders
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <https://7-zip.org/>
|
||||
*
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
size_t i;
|
||||
uint32_t addr;
|
||||
|
||||
for (i = 0; i + 4 <= size; i += 2) {
|
||||
if ((buf[i + 1] & 0xF8) == 0xF0
|
||||
&& (buf[i + 3] & 0xF8) == 0xF8) {
|
||||
addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
|
||||
| ((uint32_t)buf[i] << 11)
|
||||
| (((uint32_t)buf[i + 3] & 0x07) << 8)
|
||||
| (uint32_t)buf[i + 2];
|
||||
addr <<= 1;
|
||||
addr -= zip->bcj_ip + (uint32_t)i;
|
||||
addr >>= 1;
|
||||
buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
|
||||
buf[i] = (uint8_t)(addr >> 11);
|
||||
buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
|
||||
buf[i + 2] = (uint8_t)addr;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
@@ -4443,6 +4613,260 @@ powerpc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
riscv_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t bcj_riscv(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
// in https://git.tukaani.org/xz-embedded.git
|
||||
|
||||
/*
|
||||
* Branch/Call/Jump (BCJ) filter decoders
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <https://7-zip.org/>
|
||||
*
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
if (size < 8)
|
||||
return 0;
|
||||
size -= 8;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i <= size; i += 2) {
|
||||
uint32_t inst = buf[i];
|
||||
|
||||
if (inst == 0xEF) {
|
||||
// JAL. Only filter rd=x1(ra) and rd=x5(t0).
|
||||
const uint32_t b1 = buf[i + 1];
|
||||
|
||||
if ((b1 & 0x0D) != 0)
|
||||
continue;
|
||||
|
||||
const uint32_t b2 = buf[i + 2];
|
||||
const uint32_t b3 = buf[i + 3];
|
||||
|
||||
uint32_t addr = ((b1 & 0xF0) << 13)
|
||||
| (b2 << 9) | (b3 << 1);
|
||||
addr -= zip->bcj_ip + (uint32_t)i;
|
||||
|
||||
buf[i + 1] = (uint8_t)((b1 & 0x0F)
|
||||
| ((addr >> 8) & 0xF0));
|
||||
buf[i + 2] = (uint8_t)(((addr >> 16) & 0x0F)
|
||||
| ((addr >> 7) & 0x10)
|
||||
| ((addr << 4) & 0xE0));
|
||||
buf[i + 3] = (uint8_t)(((addr >> 4) & 0x7F)
|
||||
| ((addr >> 13) & 0x80));
|
||||
|
||||
i += 4 - 2;
|
||||
} else if ((inst & 0x7F) == 0x17) {
|
||||
// AUIPC, paired with a second instruction (inst2)
|
||||
// that is within the next four bytes.
|
||||
uint32_t inst2;
|
||||
|
||||
inst |= (uint32_t)buf[i + 1] << 8;
|
||||
inst |= (uint32_t)buf[i + 2] << 16;
|
||||
inst |= (uint32_t)buf[i + 3] << 24;
|
||||
|
||||
if (inst & 0xE80) {
|
||||
// AUIPC's rd doesn't equal x0 or x2.
|
||||
inst2 = archive_le32dec(buf + i + 4);
|
||||
|
||||
if (((inst << 8) ^ (inst2 - 3)) & 0xF8003) {
|
||||
i += 6 - 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t addr = (inst & 0xFFFFF000)
|
||||
+ (inst2 >> 20);
|
||||
|
||||
inst = 0x17 | (2 << 7) | (inst2 << 12);
|
||||
inst2 = addr;
|
||||
} else {
|
||||
// AUIPC's rd equals x0 or x2.
|
||||
const uint32_t inst2_rs1 = inst >> 27;
|
||||
|
||||
if ((uint32_t)((inst - 0x3117) << 18)
|
||||
>= (inst2_rs1 & 0x1D)) {
|
||||
i += 4 - 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t addr = archive_be32dec(buf + i + 4);
|
||||
addr -= zip->bcj_ip + (uint32_t)i;
|
||||
|
||||
inst2 = (inst >> 12) | (addr << 20);
|
||||
inst = 0x17 | (inst2_rs1 << 7)
|
||||
| ((addr + 0x800) & 0xFFFFF000);
|
||||
}
|
||||
|
||||
archive_le32enc(buf + i, inst);
|
||||
archive_le32enc(buf + i + 4, inst2);
|
||||
|
||||
i += 8 - 2;
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
ia64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
// in https://git.tukaani.org/xz-embedded.git
|
||||
|
||||
/*
|
||||
* Branch/Call/Jump (BCJ) filter decoders
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <https://7-zip.org/>
|
||||
*
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
static const uint8_t branch_table[32] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 4, 6, 6, 0, 0, 7, 7,
|
||||
4, 4, 0, 0, 4, 4, 0, 0
|
||||
};
|
||||
|
||||
/* Loop counters */
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
/* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
|
||||
uint32_t slot;
|
||||
|
||||
/* Bitwise offset of the instruction indicated by slot */
|
||||
uint32_t bit_pos;
|
||||
|
||||
/* bit_pos split into byte and bit parts */
|
||||
uint32_t byte_pos;
|
||||
uint32_t bit_res;
|
||||
|
||||
/* Address part of an instruction */
|
||||
uint32_t addr;
|
||||
|
||||
/* Mask used to detect which instructions to convert */
|
||||
uint32_t mask;
|
||||
|
||||
/* 41-bit instruction stored somewhere in the lowest 48 bits */
|
||||
uint64_t instr;
|
||||
|
||||
/* Instruction normalized with bit_res for easier manipulation */
|
||||
uint64_t norm;
|
||||
|
||||
size &= ~(size_t)15;
|
||||
|
||||
for (i = 0; i < size; i += 16) {
|
||||
mask = branch_table[buf[i] & 0x1F];
|
||||
for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
|
||||
if (((mask >> slot) & 1) == 0)
|
||||
continue;
|
||||
|
||||
byte_pos = bit_pos >> 3;
|
||||
bit_res = bit_pos & 7;
|
||||
instr = 0;
|
||||
for (j = 0; j < 6; ++j)
|
||||
instr |= (uint64_t)(buf[i + j + byte_pos])
|
||||
<< (8 * j);
|
||||
|
||||
norm = instr >> bit_res;
|
||||
|
||||
if (((norm >> 37) & 0x0F) == 0x05
|
||||
&& ((norm >> 9) & 0x07) == 0) {
|
||||
addr = (norm >> 13) & 0x0FFFFF;
|
||||
addr |= ((uint32_t)(norm >> 36) & 1) << 20;
|
||||
addr <<= 4;
|
||||
addr -= zip->bcj_ip + (uint32_t)i;
|
||||
addr >>= 4;
|
||||
|
||||
norm &= ~((uint64_t)0x8FFFFF << 13);
|
||||
norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
|
||||
norm |= (uint64_t)(addr & 0x100000)
|
||||
<< (36 - 20);
|
||||
|
||||
instr &= (1U << bit_res) - 1;
|
||||
instr |= norm << bit_res;
|
||||
|
||||
for (j = 0; j < 6; j++)
|
||||
buf[i + j + byte_pos]
|
||||
= (uint8_t)(instr >> (8 * j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
delta_Init(struct _7zip *zip, unsigned dist)
|
||||
{
|
||||
zip->delta_dist = dist;
|
||||
zip->delta_pos = 0;
|
||||
memset(zip->delta_history, 0, sizeof(zip->delta_history));
|
||||
}
|
||||
|
||||
static void
|
||||
delta_Decode(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This was adapted from src/liblzma/delta/delta_decoder.c's
|
||||
// static void decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
|
||||
// function in https://github.com/tukaani-project/xz.git
|
||||
|
||||
/*
|
||||
* Delta filter decoder
|
||||
*
|
||||
* Author: Lasse Collin
|
||||
*
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
buf[i] += zip->delta_history[
|
||||
(zip->delta_dist + zip->delta_pos) & 0xFF];
|
||||
zip->delta_history[zip->delta_pos--] = buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The widest instruction the BCJ filters rewrite, and the smallest output
|
||||
* buffer that those filters can make progress with. Filters leave up to one
|
||||
* byte less than this unconverted at the end of a buffer (when they don't
|
||||
* have enough data to continue). Returns 0 for codecs we do not filter
|
||||
* ourselves.
|
||||
*/
|
||||
static size_t
|
||||
bcj_lookahead(int64_t codec2)
|
||||
{
|
||||
switch (codec2) {
|
||||
case _7Z_X86:
|
||||
return (5);
|
||||
case _7Z_RISCV:
|
||||
return (8);
|
||||
case _7Z_IA64:
|
||||
return (16);
|
||||
case _7Z_ARM:
|
||||
case _7Z_ARMTHUMB:
|
||||
case _7Z_ARM64:
|
||||
case _7Z_POWERPC:
|
||||
case _7Z_SPARC:
|
||||
return (4);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Brought from LZMA SDK.
|
||||
*
|
||||
|
||||
@@ -106,8 +106,7 @@ archive_read_support_format_ar(struct archive *_a)
|
||||
|
||||
ar = calloc(1, sizeof(*ar));
|
||||
if (ar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate ar data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate ar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ar->strtab = NULL;
|
||||
@@ -125,11 +124,9 @@ archive_read_support_format_ar(struct archive *_a)
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
if (r != ARCHIVE_OK)
|
||||
free(ar);
|
||||
return (r);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -251,56 +248,66 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
*/
|
||||
ar_parse_common_header(ar, entry, h);
|
||||
|
||||
/*
|
||||
* '/' is the ranlib index.
|
||||
* Ignore it since it contains linker information.
|
||||
*/
|
||||
if (strcmp(filename, "/") == 0) {
|
||||
/* This is not a file entry. Ignore. */
|
||||
archive_entry_copy_pathname(entry, NULL);
|
||||
|
||||
/* Skip special file entry. */
|
||||
return (archive_read_format_ar_skip(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* '//' is the GNU filename table.
|
||||
* Later entries can refer to names in this table.
|
||||
*/
|
||||
if (strcmp(filename, "//") == 0) {
|
||||
char *st;
|
||||
size_t entry_size;
|
||||
int64_t entry_size;
|
||||
size_t strtab_size;
|
||||
|
||||
/* This is not a file entry. Ignore. */
|
||||
archive_entry_copy_pathname(entry, NULL);
|
||||
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
/* Get the size of the filename table. */
|
||||
number = ar_atol10(h + AR_size_offset, AR_size_size);
|
||||
if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
|
||||
entry_size = archive_entry_size(entry);
|
||||
if (entry_size == 0 || entry_size > 1024 * 1024 * 1024) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Filename table too large");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
entry_size = (size_t)number;
|
||||
if (entry_size == 0) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid string table");
|
||||
"Invalid filename table size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
strtab_size = (size_t)entry_size;
|
||||
if (ar->strtab != NULL) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"More than one string table exists");
|
||||
"More than one filename table exists");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Read the filename table into memory. */
|
||||
st = malloc(entry_size);
|
||||
st = malloc(strtab_size);
|
||||
if (st == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate filename table buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ar->strtab = st;
|
||||
ar->strtab_size = entry_size;
|
||||
ar->strtab_size = strtab_size;
|
||||
|
||||
if (*unconsumed) {
|
||||
__archive_read_consume(a, *unconsumed);
|
||||
*unconsumed = 0;
|
||||
}
|
||||
|
||||
if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL)
|
||||
if ((b = __archive_read_ahead(a, strtab_size, NULL)) == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
memcpy(st, b, strtab_size);
|
||||
|
||||
/* Skip special file entry. */
|
||||
if (archive_read_format_ar_skip(a) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
memcpy(st, b, entry_size);
|
||||
__archive_read_consume(a, entry_size);
|
||||
/* All contents are consumed. */
|
||||
ar->entry_bytes_remaining = 0;
|
||||
archive_entry_set_size(entry, ar->entry_bytes_remaining);
|
||||
|
||||
/* Parse the filename table. */
|
||||
return (ar_parse_gnu_filename_table(a));
|
||||
@@ -415,17 +422,20 @@ archive_read_format_ar_read_header(struct archive_read *a,
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_AR;
|
||||
}
|
||||
|
||||
/* Read the header for the next file entry. */
|
||||
if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL)
|
||||
/* Broken header. */
|
||||
return (ARCHIVE_EOF);
|
||||
do {
|
||||
/* Read the header for the next file entry. */
|
||||
if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL)
|
||||
/* Broken header. */
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
unconsumed = 60;
|
||||
unconsumed = 60;
|
||||
|
||||
ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed);
|
||||
ret = _ar_read_header(a, entry, ar, (const char *)header_data,
|
||||
&unconsumed);
|
||||
|
||||
if (unconsumed)
|
||||
__archive_read_consume(a, unconsumed);
|
||||
if (unconsumed)
|
||||
__archive_read_consume(a, unconsumed);
|
||||
} while (ret == ARCHIVE_OK && archive_entry_pathname(entry) == NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -522,18 +532,20 @@ ar_parse_gnu_filename_table(struct archive_read *a)
|
||||
size = ar->strtab_size;
|
||||
|
||||
for (p = ar->strtab; p < ar->strtab + size - 1; ++p) {
|
||||
if (*p == '/') {
|
||||
/* Normalize backslash, even before separator check. */
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
if (*p == '/' && *(p + 1) == '\n') {
|
||||
*p++ = '\0';
|
||||
if (*p != '\n')
|
||||
goto bad_string_table;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* GNU ar always pads the table to an even size.
|
||||
* The pad character is either '\n' or '`'.
|
||||
* For Windows Archive files, the pad character can be '\0'.
|
||||
*/
|
||||
if (p != ar->strtab + size && *p != '\n' && *p != '`')
|
||||
if (p != ar->strtab + size && *p != '\n' && *p != '`' && *p != '\0')
|
||||
goto bad_string_table;
|
||||
|
||||
/* Enforce zero termination. */
|
||||
|
||||
@@ -187,6 +187,8 @@ struct lzx_dec {
|
||||
uint8_t *w_buff;
|
||||
/* The insert position to the window. */
|
||||
size_t w_pos;
|
||||
/* The number of initialized bytes in the window. */
|
||||
size_t w_filled;
|
||||
/* The position where we can copy decoded code from the window. */
|
||||
size_t copy_pos;
|
||||
/* The length how many bytes we can copy decoded code from
|
||||
@@ -284,6 +286,7 @@ struct lzx_stream {
|
||||
#define MAX_UNCOMPRESS_SIZE 0x8000
|
||||
#define MAX_FILE_SIZE (UINT16_MAX * MAX_UNCOMPRESS_SIZE)
|
||||
#define MAX_E8_TRANSLATION (0x8000 * MAX_UNCOMPRESS_SIZE)
|
||||
#define SFX_MAX_READAHEAD (1024 * 512)
|
||||
|
||||
static const char * const compression_name[] = {
|
||||
"NONE",
|
||||
@@ -459,14 +462,13 @@ archive_read_support_format_cab(struct archive *_a)
|
||||
|
||||
cab = calloc(1, sizeof(*cab));
|
||||
if (cab == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
archive_set_error(_a, ENOMEM,
|
||||
"Can't allocate CAB data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_string_init(&cab->ws);
|
||||
if (archive_wstring_ensure(&cab->ws, 256) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate memory");
|
||||
free(cab);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@@ -488,10 +490,10 @@ archive_read_support_format_cab(struct archive *_a)
|
||||
archive_wstring_free(&cab->ws);
|
||||
free(cab);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
static size_t
|
||||
find_cab_magic(const char *p)
|
||||
{
|
||||
switch (p[4]) {
|
||||
@@ -517,46 +519,54 @@ find_cab_magic(const char *p)
|
||||
static int
|
||||
archive_read_format_cab_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *p;
|
||||
ssize_t bytes_avail, offset, window;
|
||||
const char *h;
|
||||
|
||||
/* If there's already a better bid than we can ever
|
||||
make, don't bother testing. */
|
||||
if (best_bid > 64)
|
||||
return (-1);
|
||||
|
||||
if ((p = __archive_read_ahead(a, 8, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, 16, NULL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (memcmp(p, "MSCF\0\0\0\0", 8) == 0)
|
||||
return (64);
|
||||
if (memcmp(h, "MSCF", 4) == 0) {
|
||||
if (memcmp(h + 4, "\0\0\0\0", 4) == 0)
|
||||
return (64);
|
||||
/* Some archives do not have all reserved bits set to zero. */
|
||||
if (memcmp(h + 12, "\0\0\0\0", 4) == 0)
|
||||
return (32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to handle self-extracting archives
|
||||
* by noting a PE header and searching forward
|
||||
* up to 128k for an 'MSCF' marker.
|
||||
*/
|
||||
if (p[0] == 'M' && p[1] == 'Z') {
|
||||
if (h[0] == 'M' && h[1] == 'Z') {
|
||||
ssize_t bytes_avail;
|
||||
ssize_t offset, window;
|
||||
|
||||
offset = 0;
|
||||
window = 4096;
|
||||
while (offset < (1024 * 128)) {
|
||||
const char *h = __archive_read_ahead(a, offset + window,
|
||||
while (offset + window <= SFX_MAX_READAHEAD) {
|
||||
h = __archive_read_ahead(a, offset + window,
|
||||
&bytes_avail);
|
||||
if (h == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window >>= 1;
|
||||
if (window < 128)
|
||||
return (0);
|
||||
continue;
|
||||
if (bytes_avail >= offset + 8) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window = bytes_avail - offset;
|
||||
continue;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
p = h + offset;
|
||||
while (p + 8 < h + bytes_avail) {
|
||||
int next;
|
||||
if ((next = find_cab_magic(p)) == 0)
|
||||
if (bytes_avail > SFX_MAX_READAHEAD)
|
||||
bytes_avail = SFX_MAX_READAHEAD;
|
||||
while (offset <= bytes_avail - 8) {
|
||||
size_t next = find_cab_magic(h + offset);
|
||||
if (next == 0)
|
||||
return (64);
|
||||
p += next;
|
||||
offset += next;
|
||||
}
|
||||
offset = p - h;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
@@ -619,8 +629,8 @@ cab_skip_sfx(struct archive_read *a)
|
||||
* like the cab header.
|
||||
*/
|
||||
while (p + 8 < q) {
|
||||
int next;
|
||||
if ((next = find_cab_magic(p)) == 0) {
|
||||
size_t next = find_cab_magic(p);
|
||||
if (next == 0) {
|
||||
skip = p - h;
|
||||
__archive_read_consume(a, skip);
|
||||
return (ARCHIVE_OK);
|
||||
@@ -1048,8 +1058,16 @@ archive_read_format_cab_read_header(struct archive_read *a,
|
||||
}
|
||||
/* If a cffolder of this file is changed, reset a cfdata to read
|
||||
* file contents from next cfdata. */
|
||||
if (prev_folder != cab->entry_cffolder)
|
||||
if (prev_folder != cab->entry_cffolder) {
|
||||
cab->entry_cfdata = NULL;
|
||||
/*
|
||||
* Bytes of files we skipped so far belong to folders we
|
||||
* are done with; reading this file will seek directly to
|
||||
* the data of the new folder, so we must not charge the
|
||||
* skipped bytes against the new folder's data.
|
||||
*/
|
||||
cab->bytes_skipped = 0;
|
||||
}
|
||||
|
||||
/* If a pathname is UTF-8, prepare a string conversion object
|
||||
* for UTF-8 and use it. */
|
||||
@@ -2252,6 +2270,7 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
|
||||
}
|
||||
|
||||
ds->w_pos = 0;
|
||||
ds->w_filled = 0;
|
||||
ds->state = ST_RD_TRANSLATION;
|
||||
ds->br.cache_buffer = 0;
|
||||
ds->br.cache_avail = 0;
|
||||
@@ -2707,6 +2726,11 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
|
||||
strm->avail_out -= l;
|
||||
strm->total_out += l;
|
||||
ds->w_pos = (ds->w_pos + l) & ds->w_mask;
|
||||
if (ds->w_filled < ds->w_size) {
|
||||
ds->w_filled += l;
|
||||
if (ds->w_filled > ds->w_size)
|
||||
ds->w_filled = ds->w_size;
|
||||
}
|
||||
ds->block_bytes_avail -= l;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
@@ -2753,7 +2777,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
|
||||
/*
|
||||
* Read Pre-tree for first 256 elements of main tree.
|
||||
*/
|
||||
if (lzx_read_pre_tree(strm) < 0) {
|
||||
if (lzx_read_pre_tree(strm) == ARCHIVE_EOF) {
|
||||
ds->state = ST_RD_PRE_MAIN_TREE_256;
|
||||
if (last)
|
||||
goto failed;
|
||||
@@ -2781,7 +2805,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
|
||||
/*
|
||||
* Read Pre-tree for remaining elements of main tree.
|
||||
*/
|
||||
if (lzx_read_pre_tree(strm) < 0) {
|
||||
if (lzx_read_pre_tree(strm) == ARCHIVE_EOF) {
|
||||
ds->state = ST_RD_PRE_MAIN_TREE_REM;
|
||||
if (last)
|
||||
goto failed;
|
||||
@@ -2811,7 +2835,7 @@ lzx_read_blocks(struct lzx_stream *strm, int last)
|
||||
/*
|
||||
* Read Pre-tree for remaining elements of main tree.
|
||||
*/
|
||||
if (lzx_read_pre_tree(strm) < 0) {
|
||||
if (lzx_read_pre_tree(strm) == ARCHIVE_EOF) {
|
||||
ds->state = ST_RD_PRE_LENGTH_TREE;
|
||||
if (last)
|
||||
goto failed;
|
||||
@@ -2862,6 +2886,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
uint8_t mt_lookup_bits = mt->lookup_bits;
|
||||
size_t copy_len = ds->copy_len, copy_pos = ds->copy_pos;
|
||||
size_t w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size;
|
||||
size_t w_filled = ds->w_filled;
|
||||
uint8_t length_header = ds->length_header;
|
||||
uint8_t offset_bits = ds->offset_bits;
|
||||
uint16_t position_slot = ds->position_slot;
|
||||
@@ -2886,6 +2911,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
ds->position_slot = position_slot;
|
||||
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
|
||||
ds->w_pos = w_pos;
|
||||
ds->w_filled = w_filled;
|
||||
strm->avail_out = endp - noutp;
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
@@ -2922,6 +2948,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
* afterward. */
|
||||
w_buff[w_pos] = c;
|
||||
w_pos = (w_pos + 1) & w_mask;
|
||||
if (w_filled < w_size)
|
||||
w_filled++;
|
||||
/* Store the decoded code to output buffer. */
|
||||
*noutp++ = c;
|
||||
block_bytes_avail--;
|
||||
@@ -3049,6 +3077,8 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
/*
|
||||
* Compute a real position in window.
|
||||
*/
|
||||
if (copy_pos == 0 || copy_pos > w_filled)
|
||||
goto failed;
|
||||
copy_pos = (w_pos - copy_pos) & w_mask;
|
||||
/* FALL THROUGH */
|
||||
case ST_COPY:
|
||||
@@ -3086,6 +3116,11 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
noutp += l;
|
||||
copy_pos = (copy_pos + l) & w_mask;
|
||||
w_pos = (w_pos + l) & w_mask;
|
||||
if (w_filled < w_size) {
|
||||
w_filled += l;
|
||||
if (w_filled > w_size)
|
||||
w_filled = w_size;
|
||||
}
|
||||
block_bytes_avail -= l;
|
||||
if (copy_len <= l)
|
||||
/* A copy of current pattern ended. */
|
||||
@@ -3114,6 +3149,7 @@ next_data:
|
||||
ds->r0 = r0; ds->r1 = r1; ds->r2 = r2;
|
||||
ds->state = state;
|
||||
ds->w_pos = w_pos;
|
||||
ds->w_filled = w_filled;
|
||||
strm->avail_out = endp - noutp;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@@ -3240,7 +3276,8 @@ lzx_huffman_init(struct huffman *hf, uint16_t symbol_count, uint8_t tbl_bits)
|
||||
return (ARCHIVE_FATAL);
|
||||
hf->tbl_bits = tbl_bits;
|
||||
} else
|
||||
memset(hf->tbl, 0, tbl_size * sizeof(hf->bitlen[0]));
|
||||
memset(hf->tbl, 0,
|
||||
((size_t)1 << hf->tbl_bits) * sizeof(hf->tbl[0]));
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,9 +173,7 @@ struct links_entry {
|
||||
char *name;
|
||||
};
|
||||
|
||||
#define CPIO_MAGIC 0x13141516
|
||||
struct cpio {
|
||||
int magic;
|
||||
int (*read_header)(struct archive_read *, struct cpio *,
|
||||
struct archive_entry *, size_t *, size_t *);
|
||||
struct links_entry *links_head;
|
||||
@@ -234,10 +232,9 @@ archive_read_support_format_cpio(struct archive *_a)
|
||||
|
||||
cpio = calloc(1, sizeof(*cpio));
|
||||
if (cpio == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate cpio data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
cpio->magic = CPIO_MAGIC;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
cpio,
|
||||
@@ -254,7 +251,7 @@ archive_read_support_format_cpio(struct archive *_a)
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(cpio);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
@@ -262,16 +259,16 @@ static int
|
||||
archive_read_format_cpio_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
struct cpio *cpio = a->format->data;
|
||||
const unsigned char *p;
|
||||
const void *h;
|
||||
int bid;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
if ((p = __archive_read_ahead(a, 6, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, 6, NULL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
bid = 0;
|
||||
if (memcmp(p, "070707", 6) == 0) {
|
||||
if (memcmp(h, "070707", 6) == 0) {
|
||||
/* ASCII cpio archive (odc, POSIX.1) */
|
||||
cpio->read_header = header_odc;
|
||||
bid += 48;
|
||||
@@ -279,7 +276,7 @@ archive_read_format_cpio_bid(struct archive_read *a, int best_bid)
|
||||
* XXX TODO: More verification; Could check that only octal
|
||||
* digits appear in appropriate header locations. XXX
|
||||
*/
|
||||
} else if (memcmp(p, "070727", 6) == 0) {
|
||||
} else if (memcmp(h, "070727", 6) == 0) {
|
||||
/* afio large ASCII cpio archive */
|
||||
cpio->read_header = header_odc;
|
||||
bid += 48;
|
||||
@@ -287,7 +284,7 @@ archive_read_format_cpio_bid(struct archive_read *a, int best_bid)
|
||||
* XXX TODO: More verification; Could check that almost hex
|
||||
* digits appear in appropriate header locations. XXX
|
||||
*/
|
||||
} else if (memcmp(p, "070701", 6) == 0) {
|
||||
} else if (memcmp(h, "070701", 6) == 0) {
|
||||
/* ASCII cpio archive (SVR4 without CRC) */
|
||||
cpio->read_header = header_newc;
|
||||
bid += 48;
|
||||
@@ -295,7 +292,7 @@ archive_read_format_cpio_bid(struct archive_read *a, int best_bid)
|
||||
* XXX TODO: More verification; Could check that only hex
|
||||
* digits appear in appropriate header locations. XXX
|
||||
*/
|
||||
} else if (memcmp(p, "070702", 6) == 0) {
|
||||
} else if (memcmp(h, "070702", 6) == 0) {
|
||||
/* ASCII cpio archive (SVR4 with CRC) */
|
||||
/* XXX TODO: Flag that we should check the CRC. XXX */
|
||||
cpio->read_header = header_newc;
|
||||
@@ -304,12 +301,12 @@ archive_read_format_cpio_bid(struct archive_read *a, int best_bid)
|
||||
* XXX TODO: More verification; Could check that only hex
|
||||
* digits appear in appropriate header locations. XXX
|
||||
*/
|
||||
} else if (archive_be16dec(p) == 070707) {
|
||||
} else if (archive_be16dec(h) == 070707) {
|
||||
/* big-endian binary cpio archives */
|
||||
cpio->read_header = header_bin_be;
|
||||
bid += 16;
|
||||
/* Is more verification possible here? */
|
||||
} else if (archive_le16dec(p) == 070707) {
|
||||
} else if (archive_le16dec(h) == 070707) {
|
||||
/* little-endian binary cpio archives */
|
||||
cpio->read_header = header_bin_le;
|
||||
bid += 16;
|
||||
|
||||
@@ -87,9 +87,10 @@ archive_read_format_empty_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, int64_t *offset)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)buff; /* UNUSED */
|
||||
(void)size; /* UNUSED */
|
||||
(void)offset; /* UNUSED */
|
||||
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
*offset = 0;
|
||||
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
@@ -320,9 +320,6 @@ struct heap_queue {
|
||||
};
|
||||
|
||||
struct iso9660 {
|
||||
int magic;
|
||||
#define ISO9660_MAGIC 0x96609660
|
||||
|
||||
int opt_support_joliet;
|
||||
int opt_support_rockridge;
|
||||
|
||||
@@ -423,7 +420,7 @@ static struct file_info *
|
||||
static int parse_rockridge(struct archive_read *a,
|
||||
struct file_info *file, const unsigned char *start,
|
||||
const unsigned char *end);
|
||||
static int register_CE(struct archive_read *a, int32_t location,
|
||||
static int register_CE(struct archive_read *a, uint32_t location,
|
||||
struct file_info *file);
|
||||
static int read_CE(struct archive_read *a, struct iso9660 *iso9660);
|
||||
static void parse_rockridge_NM1(struct file_info *,
|
||||
@@ -464,11 +461,9 @@ archive_read_support_format_iso9660(struct archive *_a)
|
||||
|
||||
iso9660 = calloc(1, sizeof(*iso9660));
|
||||
if (iso9660 == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate iso9660 data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate iso9660 data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
iso9660->magic = ISO9660_MAGIC;
|
||||
iso9660->cache_files.first = NULL;
|
||||
iso9660->cache_files.last = &(iso9660->cache_files.first);
|
||||
iso9660->re_files.first = NULL;
|
||||
@@ -491,11 +486,9 @@ archive_read_support_format_iso9660(struct archive *_a)
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
if (r != ARCHIVE_OK)
|
||||
free(iso9660);
|
||||
return (r);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
@@ -504,7 +497,7 @@ archive_read_format_iso9660_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
struct iso9660 *iso9660 = a->format->data;
|
||||
ssize_t bytes_read;
|
||||
const unsigned char *p;
|
||||
const unsigned char *h;
|
||||
int seenTerminator;
|
||||
|
||||
/* If there's already a better bid than we can ever
|
||||
@@ -518,41 +511,41 @@ archive_read_format_iso9660_bid(struct archive_read *a, int best_bid)
|
||||
* if the I/O layer gives us more, we'll take it.
|
||||
*/
|
||||
#define RESERVED_AREA (SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE)
|
||||
p = __archive_read_ahead(a,
|
||||
h = __archive_read_ahead(a,
|
||||
RESERVED_AREA + 8 * LOGICAL_BLOCK_SIZE,
|
||||
&bytes_read);
|
||||
if (p == NULL)
|
||||
if (h == NULL)
|
||||
return (-1);
|
||||
|
||||
/* Skip the reserved area. */
|
||||
bytes_read -= RESERVED_AREA;
|
||||
p += RESERVED_AREA;
|
||||
h += RESERVED_AREA;
|
||||
|
||||
/* Check each volume descriptor. */
|
||||
seenTerminator = 0;
|
||||
for (; bytes_read > LOGICAL_BLOCK_SIZE;
|
||||
bytes_read -= LOGICAL_BLOCK_SIZE, p += LOGICAL_BLOCK_SIZE) {
|
||||
bytes_read -= LOGICAL_BLOCK_SIZE, h += LOGICAL_BLOCK_SIZE) {
|
||||
/* Do not handle undefined Volume Descriptor Type. */
|
||||
if (p[0] >= 4 && p[0] <= 254)
|
||||
if (h[0] >= 4 && h[0] <= 254)
|
||||
return (0);
|
||||
/* Standard Identifier must be "CD001" */
|
||||
if (memcmp(p + 1, "CD001", 5) != 0)
|
||||
if (memcmp(h + 1, "CD001", 5) != 0)
|
||||
return (0);
|
||||
if (isPVD(iso9660, p))
|
||||
if (isPVD(iso9660, h))
|
||||
continue;
|
||||
if (!iso9660->joliet.location) {
|
||||
if (isJolietSVD(iso9660, p))
|
||||
if (isJolietSVD(iso9660, h))
|
||||
continue;
|
||||
}
|
||||
if (isBootRecord(p))
|
||||
if (isBootRecord(h))
|
||||
continue;
|
||||
if (isEVD(p))
|
||||
if (isEVD(h))
|
||||
continue;
|
||||
if (isSVD(p))
|
||||
if (isSVD(h))
|
||||
continue;
|
||||
if (isVolumePartition(iso9660, p))
|
||||
if (isVolumePartition(iso9660, h))
|
||||
continue;
|
||||
if (isVDSetTerminator(p)) {
|
||||
if (isVDSetTerminator(h)) {
|
||||
seenTerminator = 1;
|
||||
break;
|
||||
}
|
||||
@@ -1517,8 +1510,7 @@ zisofs_read_data(struct archive_read *a,
|
||||
if (zisofs->block_pointers_alloc < xsize) {
|
||||
size_t alloc;
|
||||
|
||||
if (zisofs->block_pointers != NULL)
|
||||
free(zisofs->block_pointers);
|
||||
free(zisofs->block_pointers);
|
||||
alloc = ((xsize >> 10) + 1) << 10;
|
||||
zisofs->block_pointers = malloc(alloc);
|
||||
if (zisofs->block_pointers == NULL) {
|
||||
@@ -1533,8 +1525,7 @@ zisofs_read_data(struct archive_read *a,
|
||||
/* Allocate uncompressed data buffer. */
|
||||
xsize = (size_t)1UL << zisofs->pz_log2_bs;
|
||||
if (zisofs->uncompressed_buffer_size < xsize) {
|
||||
if (zisofs->uncompressed_buffer != NULL)
|
||||
free(zisofs->uncompressed_buffer);
|
||||
free(zisofs->uncompressed_buffer);
|
||||
zisofs->uncompressed_buffer = malloc(xsize);
|
||||
if (zisofs->uncompressed_buffer == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
@@ -2194,7 +2185,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
* 8 byte offset w/in above sector
|
||||
* 8 byte length of continuation
|
||||
*/
|
||||
int32_t location =
|
||||
uint32_t location =
|
||||
archive_le32dec(data);
|
||||
file->ce_offset =
|
||||
archive_le32dec(data+8);
|
||||
@@ -2341,22 +2332,24 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
||||
}
|
||||
|
||||
static int
|
||||
register_CE(struct archive_read *a, int32_t location,
|
||||
register_CE(struct archive_read *a, uint32_t location,
|
||||
struct file_info *file)
|
||||
{
|
||||
struct iso9660 *iso9660 = a->format->data;
|
||||
struct read_ce_queue *heap;
|
||||
uint64_t offset, parent_offset;
|
||||
uint64_t offset, parent_offset, ce_end;
|
||||
size_t hole, parent;
|
||||
|
||||
offset = ((uint64_t)location) * (uint64_t)iso9660->logical_block_size;
|
||||
if (((file->mode & AE_IFMT) == AE_IFREG &&
|
||||
if (archive_ckd_mul_u64(&offset, (uint64_t)location,
|
||||
(uint64_t)iso9660->logical_block_size) ||
|
||||
archive_ckd_add_u64(&ce_end, offset,
|
||||
((uint64_t)file->ce_offset) + file->ce_size) ||
|
||||
((file->mode & AE_IFMT) == AE_IFREG &&
|
||||
offset >= file->offset) ||
|
||||
offset < iso9660->current_position ||
|
||||
(((uint64_t)file->ce_offset) + file->ce_size)
|
||||
> (uint64_t)iso9660->logical_block_size ||
|
||||
offset + file->ce_offset + file->ce_size
|
||||
> iso9660->volume_size) {
|
||||
ce_end > iso9660->volume_size) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid parameter in SUSP \"CE\" extension");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -3061,14 +3054,28 @@ re_get_entry(struct iso9660 *iso9660)
|
||||
static inline int
|
||||
rede_add_entry(struct file_info *file)
|
||||
{
|
||||
struct file_info *re;
|
||||
struct file_info *re, *slow;
|
||||
int slow_turn = 0;
|
||||
|
||||
/*
|
||||
* Find "RE" entry.
|
||||
*
|
||||
* A malformed image can chain "CL"/"RE" reparenting so that the
|
||||
* parent pointers form a cycle in which no node carries the "re"
|
||||
* flag. Advance a second pointer at half speed (Floyd's cycle
|
||||
* detection) so such a loop is reported as a malformed archive
|
||||
* instead of spinning forever.
|
||||
*/
|
||||
re = file->parent;
|
||||
while (re != NULL && !re->re)
|
||||
re = slow = file->parent;
|
||||
while (re != NULL && !re->re) {
|
||||
re = re->parent;
|
||||
if (slow_turn) {
|
||||
slow = slow->parent;
|
||||
if (re == slow)
|
||||
return (-1); /* Cyclic parent chain. */
|
||||
}
|
||||
slow_turn = !slow_turn;
|
||||
}
|
||||
if (re == NULL)
|
||||
return (-1);
|
||||
|
||||
|
||||
@@ -206,10 +206,12 @@ struct lha {
|
||||
* LHA header common member offset.
|
||||
*/
|
||||
#define H_METHOD_OFFSET 2 /* Compress type. */
|
||||
#define H_ATTR_OFFSET 19 /* DOS attribute. */
|
||||
#define H_ATTR_OFFSET 19 /* AmigaDOS or DOS attributes. */
|
||||
#define H_LEVEL_OFFSET 20 /* Header Level. */
|
||||
#define H_SIZE 22 /* Minimum header size. */
|
||||
|
||||
#define SFX_MAX_READAHEAD (1024 * 512)
|
||||
|
||||
static int archive_read_format_lha_bid(struct archive_read *, int);
|
||||
static int archive_read_format_lha_options(struct archive_read *,
|
||||
const char *, const char *);
|
||||
@@ -228,7 +230,7 @@ static int lha_read_file_header_2(struct archive_read *, struct lha *);
|
||||
static int lha_read_file_header_3(struct archive_read *, struct lha *);
|
||||
static int lha_read_file_extended_header(struct archive_read *,
|
||||
struct lha *, uint16_t *, int, uint64_t, size_t *);
|
||||
static size_t lha_check_header_format(const void *);
|
||||
static size_t lha_check_header_format(const char *);
|
||||
static int lha_skip_sfx(struct archive_read *);
|
||||
static unsigned char lha_calcsum(unsigned char, const void *,
|
||||
int, size_t);
|
||||
@@ -264,8 +266,7 @@ archive_read_support_format_lha(struct archive *_a)
|
||||
|
||||
lha = calloc(1, sizeof(*lha));
|
||||
if (lha == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate lha data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate lha data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_string_init(&lha->ws);
|
||||
@@ -285,16 +286,15 @@ archive_read_support_format_lha(struct archive *_a)
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(lha);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static size_t
|
||||
lha_check_header_format(const void *h)
|
||||
lha_check_header_format(const char *h)
|
||||
{
|
||||
const unsigned char *p = h;
|
||||
size_t next_skip_bytes;
|
||||
|
||||
switch (p[H_METHOD_OFFSET+3]) {
|
||||
switch (h[H_METHOD_OFFSET + 3]) {
|
||||
/*
|
||||
* "-lh0-" ... "-lh7-" "-lhd-"
|
||||
* "-lzs-" "-lz5-"
|
||||
@@ -305,29 +305,27 @@ lha_check_header_format(const void *h)
|
||||
case 's':
|
||||
next_skip_bytes = 4;
|
||||
|
||||
/* b0 == 0 means the end of an LHa archive file. */
|
||||
if (p[0] == 0)
|
||||
/* 0 means the end of an LHa archive file. */
|
||||
if (h[0] == 0)
|
||||
break;
|
||||
if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l'
|
||||
|| p[H_METHOD_OFFSET+4] != '-')
|
||||
if (h[H_METHOD_OFFSET] != '-' || h[H_METHOD_OFFSET + 1] != 'l'
|
||||
|| h[H_METHOD_OFFSET + 4] != '-')
|
||||
break;
|
||||
|
||||
if (p[H_METHOD_OFFSET+2] == 'h') {
|
||||
if (h[H_METHOD_OFFSET + 2] == 'h') {
|
||||
/* "-lh?-" */
|
||||
if (p[H_METHOD_OFFSET+3] == 's')
|
||||
if (h[H_METHOD_OFFSET + 3] == 's')
|
||||
break;
|
||||
if (p[H_LEVEL_OFFSET] == 0)
|
||||
return (0);
|
||||
if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20)
|
||||
if (h[H_LEVEL_OFFSET] <= 3)
|
||||
return (0);
|
||||
}
|
||||
if (p[H_METHOD_OFFSET+2] == 'z') {
|
||||
if (h[H_METHOD_OFFSET + 2] == 'z') {
|
||||
/* LArc extensions: -lzs-,-lz4- and -lz5- */
|
||||
if (p[H_LEVEL_OFFSET] != 0)
|
||||
if (h[H_LEVEL_OFFSET] != 0)
|
||||
break;
|
||||
if (p[H_METHOD_OFFSET+3] == 's'
|
||||
|| p[H_METHOD_OFFSET+3] == '4'
|
||||
|| p[H_METHOD_OFFSET+3] == '5')
|
||||
if (h[H_METHOD_OFFSET + 3] == 's'
|
||||
|| h[H_METHOD_OFFSET + 3] == '4'
|
||||
|| h[H_METHOD_OFFSET + 3] == '5')
|
||||
return (0);
|
||||
}
|
||||
break;
|
||||
@@ -344,43 +342,46 @@ lha_check_header_format(const void *h)
|
||||
static int
|
||||
archive_read_format_lha_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *p;
|
||||
const void *buff;
|
||||
ssize_t bytes_avail, offset, window;
|
||||
size_t next;
|
||||
const char *h;
|
||||
|
||||
/* If there's already a better bid than we can ever
|
||||
make, don't bother testing. */
|
||||
if (best_bid > 30)
|
||||
return (-1);
|
||||
|
||||
if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, H_SIZE, NULL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (lha_check_header_format(p) == 0)
|
||||
if (lha_check_header_format(h) == 0)
|
||||
return (30);
|
||||
|
||||
if (p[0] == 'M' && p[1] == 'Z') {
|
||||
if (h[0] == 'M' && h[1] == 'Z') {
|
||||
ssize_t offset, window;
|
||||
|
||||
/* PE file */
|
||||
offset = 0;
|
||||
window = 4096;
|
||||
while (offset < (1024 * 20)) {
|
||||
buff = __archive_read_ahead(a, offset + window,
|
||||
while (offset + window <= SFX_MAX_READAHEAD) {
|
||||
ssize_t bytes_avail;
|
||||
|
||||
h = __archive_read_ahead(a, offset + window,
|
||||
&bytes_avail);
|
||||
if (buff == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window >>= 1;
|
||||
if (window < (H_SIZE + 3))
|
||||
return (0);
|
||||
continue;
|
||||
if (h == NULL) {
|
||||
if (bytes_avail >= offset + H_SIZE) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window = bytes_avail - offset;
|
||||
continue;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
p = (const char *)buff + offset;
|
||||
while (p + H_SIZE < (const char *)buff + bytes_avail) {
|
||||
if ((next = lha_check_header_format(p)) == 0)
|
||||
if (bytes_avail > SFX_MAX_READAHEAD)
|
||||
bytes_avail = SFX_MAX_READAHEAD;
|
||||
while (offset <= bytes_avail - H_SIZE) {
|
||||
size_t next = lha_check_header_format(h + offset);
|
||||
if (next == 0)
|
||||
return (30);
|
||||
p += next;
|
||||
offset += next;
|
||||
}
|
||||
offset = p - (const char *)buff;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
@@ -474,7 +475,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
|
||||
struct lha *lha = a->format->data;
|
||||
struct archive_wstring linkname;
|
||||
struct archive_wstring pathname;
|
||||
const unsigned char *p;
|
||||
const char *p;
|
||||
const char *signature;
|
||||
int err;
|
||||
struct archive_mstring conv_buffer;
|
||||
@@ -500,7 +501,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
|
||||
return (truncated_error(a));
|
||||
}
|
||||
|
||||
signature = (const char *)p;
|
||||
signature = p;
|
||||
if (lha->found_first_header == 0 &&
|
||||
signature[0] == 'M' && signature[1] == 'Z') {
|
||||
/* This is an executable? Must be self-extracting... */
|
||||
@@ -510,7 +511,7 @@ archive_read_format_lha_read_header(struct archive_read *a,
|
||||
|
||||
if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL)
|
||||
return (truncated_error(a));
|
||||
signature = (const char *)p;
|
||||
signature = p;
|
||||
}
|
||||
/* signature[0] == 0 means the end of an LHa archive file. */
|
||||
if (signature[0] == 0)
|
||||
@@ -588,6 +589,9 @@ archive_read_format_lha_read_header(struct archive_read *a,
|
||||
if (err < ARCHIVE_WARN)
|
||||
return (err);
|
||||
|
||||
if (!lha->directory && archive_strlen(&lha->filename) == 0)
|
||||
if (memcmp(lha->method, "lh0", 3) == 0 && archive_strlen(&lha->dirname) > 0)
|
||||
lha->directory = 1; /* empty directory entry */
|
||||
|
||||
if (!lha->directory && archive_strlen(&lha->filename) == 0)
|
||||
/* The filename has not been set */
|
||||
@@ -812,7 +816,7 @@ lha_read_file_header_0(struct archive_read *a, struct lha *lha)
|
||||
headersum = p[H0_HEADER_SUM_OFFSET];
|
||||
lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
|
||||
lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
|
||||
lha->mtime = dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET));
|
||||
lha->mtime = __archive_dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET));
|
||||
namelen = p[H0_NAME_LEN_OFFSET];
|
||||
extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
|
||||
if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
|
||||
@@ -912,7 +916,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha)
|
||||
/* Note: An extended header size is included in a compsize. */
|
||||
lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
|
||||
lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
|
||||
lha->mtime = dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET));
|
||||
lha->mtime = __archive_dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET));
|
||||
namelen = p[H1_NAME_LEN_OFFSET];
|
||||
/* Calculate a padding size. The result will be normally 0 only(?) */
|
||||
padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
|
||||
@@ -1325,15 +1329,15 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
|
||||
break;
|
||||
case EXT_TIMESTAMP:
|
||||
if (datasize == (sizeof(uint64_t) * 3)) {
|
||||
ntfs_to_unix(archive_le64dec(extdheader),
|
||||
__archive_ntfs_to_unix(archive_le64dec(extdheader),
|
||||
&lha->birthtime,
|
||||
&lha->birthtime_tv_nsec);
|
||||
extdheader += sizeof(uint64_t);
|
||||
ntfs_to_unix(archive_le64dec(extdheader),
|
||||
__archive_ntfs_to_unix(archive_le64dec(extdheader),
|
||||
&lha->mtime,
|
||||
&lha->mtime_tv_nsec);
|
||||
extdheader += sizeof(uint64_t);
|
||||
ntfs_to_unix(archive_le64dec(extdheader),
|
||||
__archive_ntfs_to_unix(archive_le64dec(extdheader),
|
||||
&lha->atime,
|
||||
&lha->atime_tv_nsec);
|
||||
lha->setflag |= BIRTHTIME_IS_SET |
|
||||
@@ -1342,11 +1346,19 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
|
||||
break;
|
||||
case EXT_FILESIZE:
|
||||
if (datasize == sizeof(uint64_t) * 2) {
|
||||
lha->compsize = archive_le64dec(extdheader);
|
||||
uint64_t compsize, origsize;
|
||||
|
||||
/* Range-check before the conversion to the
|
||||
* signed type rather than relying on the
|
||||
* implementation-defined result of it. */
|
||||
compsize = archive_le64dec(extdheader);
|
||||
extdheader += sizeof(uint64_t);
|
||||
lha->origsize = archive_le64dec(extdheader);
|
||||
if (lha->compsize < 0 || lha->origsize < 0)
|
||||
origsize = archive_le64dec(extdheader);
|
||||
if (compsize > INT64_MAX ||
|
||||
origsize > INT64_MAX)
|
||||
goto invalid;
|
||||
lha->compsize = (int64_t)compsize;
|
||||
lha->origsize = (int64_t)origsize;
|
||||
}
|
||||
break;
|
||||
case EXT_CODEPAGE:
|
||||
@@ -1551,7 +1563,7 @@ lha_read_data_lzh(struct archive_read *a, const void **buff,
|
||||
size_t *size, int64_t *offset)
|
||||
{
|
||||
struct lha *lha = a->format->data;
|
||||
ssize_t bytes_avail;
|
||||
ssize_t bytes_avail, max_in;
|
||||
int r;
|
||||
|
||||
/* If we haven't yet read any data, initialize the decompressor. */
|
||||
@@ -1598,6 +1610,17 @@ lha_read_data_lzh(struct archive_read *a, const void **buff,
|
||||
if (bytes_avail > lha->entry_bytes_remaining)
|
||||
bytes_avail = (ssize_t)lha->entry_bytes_remaining;
|
||||
|
||||
/* Setup buffer boundaries. strm.avail_in is an int, and the
|
||||
* compressed size it is bounded by comes straight from the LHa
|
||||
* header, so clamp the available byte count before the
|
||||
* assignment. */
|
||||
if (INT_MAX >= SSIZE_MAX)
|
||||
max_in = SSIZE_MAX;
|
||||
else
|
||||
max_in = INT_MAX;
|
||||
if (bytes_avail > max_in)
|
||||
bytes_avail = max_in;
|
||||
|
||||
lha->strm.avail_in = (int)bytes_avail;
|
||||
lha->strm.total_in = 0;
|
||||
lha->strm.avail_out = 0;
|
||||
|
||||
@@ -91,6 +91,7 @@ struct mtree_option {
|
||||
struct mtree_entry {
|
||||
struct archive_rb_node rbnode;
|
||||
struct mtree_entry *next_dup;
|
||||
struct mtree_entry *last_dup;
|
||||
struct mtree_entry *next;
|
||||
struct mtree_option *options;
|
||||
char *name;
|
||||
@@ -108,7 +109,6 @@ struct mtree {
|
||||
const char *archive_format_name;
|
||||
struct mtree_entry *entries;
|
||||
struct mtree_entry *this_entry;
|
||||
struct archive_rb_tree entry_rbtree;
|
||||
struct archive_string current_dir;
|
||||
struct archive_string contents_name;
|
||||
|
||||
@@ -224,8 +224,7 @@ archive_read_support_format_mtree(struct archive *_a)
|
||||
|
||||
mtree = calloc(1, sizeof(*mtree));
|
||||
if (mtree == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate mtree data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate mtree data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
mtree->checkfs = 0;
|
||||
@@ -233,12 +232,22 @@ archive_read_support_format_mtree(struct archive *_a)
|
||||
|
||||
__archive_rb_tree_init(&mtree->rbtree, &rb_ops);
|
||||
|
||||
r = __archive_read_register_format(a, mtree, "mtree",
|
||||
mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
|
||||
r = __archive_read_register_format(a,
|
||||
mtree,
|
||||
"mtree",
|
||||
mtree_bid,
|
||||
archive_read_format_mtree_options,
|
||||
read_header,
|
||||
read_data,
|
||||
skip,
|
||||
NULL,
|
||||
cleanup,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(mtree);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -620,16 +629,16 @@ static int
|
||||
mtree_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *signature = "#mtree";
|
||||
const char *p;
|
||||
const void *h;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
/* Now let's look at the actual header and see if it matches. */
|
||||
p = __archive_read_ahead(a, strlen(signature), NULL);
|
||||
if (p == NULL)
|
||||
h = __archive_read_ahead(a, strlen(signature), NULL);
|
||||
if (h == NULL)
|
||||
return (-1);
|
||||
|
||||
if (memcmp(p, signature, strlen(signature)) == 0)
|
||||
if (memcmp(h, signature, strlen(signature)) == 0)
|
||||
return (8 * (int)strlen(signature));
|
||||
|
||||
/*
|
||||
@@ -940,15 +949,15 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
||||
parse_escapes(entry->name, entry);
|
||||
|
||||
entry->next_dup = NULL;
|
||||
entry->last_dup = entry;
|
||||
if (entry->full) {
|
||||
if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
|
||||
struct mtree_entry *alt;
|
||||
alt = (struct mtree_entry *)__archive_rb_tree_find_node(
|
||||
&mtree->rbtree, entry->name);
|
||||
if (alt != NULL) {
|
||||
while (alt->next_dup)
|
||||
alt = alt->next_dup;
|
||||
alt->next_dup = entry;
|
||||
alt->last_dup->next_dup = entry;
|
||||
alt->last_dup = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1067,7 +1076,6 @@ static int
|
||||
read_header(struct archive_read *a, struct archive_entry *entry)
|
||||
{
|
||||
struct mtree *mtree = a->format->data;
|
||||
char *p;
|
||||
int r, use_next;
|
||||
|
||||
if (mtree->fd >= 0) {
|
||||
@@ -1096,14 +1104,9 @@ read_header(struct archive_read *a, struct archive_entry *entry)
|
||||
mtree->this_entry->used = 1;
|
||||
if (archive_strlen(&mtree->current_dir) > 0) {
|
||||
/* Roll back current path. */
|
||||
p = mtree->current_dir.s
|
||||
+ mtree->current_dir.length - 1;
|
||||
while (p >= mtree->current_dir.s && *p != '/')
|
||||
--p;
|
||||
if (p >= mtree->current_dir.s)
|
||||
--p;
|
||||
mtree->current_dir.length
|
||||
= p - mtree->current_dir.s + 1;
|
||||
archive_string_dirname(&mtree->current_dir);
|
||||
if (strcmp(mtree->current_dir.s, ".") == 0)
|
||||
archive_string_empty(&mtree->current_dir);
|
||||
}
|
||||
}
|
||||
if (!mtree->this_entry->used) {
|
||||
@@ -1429,7 +1432,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val)
|
||||
* Decode and pack it accordingly.
|
||||
*/
|
||||
*dev++ = '\0';
|
||||
if ((pack = pack_find(val)) == NULL) {
|
||||
if ((pack = __archive_pack_find(val)) == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unknown format `%s'", val);
|
||||
return ARCHIVE_WARN;
|
||||
@@ -1709,6 +1712,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
||||
ARCHIVE_ENTRY_DIGEST_SHA512);
|
||||
}
|
||||
if (strcmp(key, "size") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_SIZE;
|
||||
archive_entry_set_size(entry, mtree_atol(&val, 10));
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,7 @@
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#ifndef HAVE_ZLIB_H
|
||||
#include "archive_crc32.h"
|
||||
#endif
|
||||
|
||||
#include "archive_endian.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_locale.h"
|
||||
@@ -136,6 +134,8 @@
|
||||
#define MAX_SYMBOL_LENGTH 0xF
|
||||
#define MAX_SYMBOLS 20
|
||||
|
||||
#define SFX_MAX_READAHEAD (1024 * 512)
|
||||
|
||||
/* Virtual Machine Properties */
|
||||
#define VM_MEMORY_SIZE 0x40000
|
||||
#define VM_MEMORY_MASK (VM_MEMORY_SIZE - 1)
|
||||
@@ -328,7 +328,6 @@ struct rar
|
||||
unsigned int unp_buffer_size;
|
||||
unsigned char *unp_buffer;
|
||||
unsigned int dictionary_size;
|
||||
char start_new_block;
|
||||
char entry_eof;
|
||||
unsigned long crc_calculated;
|
||||
int found_first_header;
|
||||
@@ -736,7 +735,7 @@ archive_read_support_format_rar(struct archive *_a)
|
||||
rar = calloc(1, sizeof(*rar));
|
||||
if (rar == NULL)
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate rar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -747,17 +746,17 @@ archive_read_support_format_rar(struct archive *_a)
|
||||
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
rar,
|
||||
"rar",
|
||||
archive_read_format_rar_bid,
|
||||
archive_read_format_rar_options,
|
||||
archive_read_format_rar_read_header,
|
||||
archive_read_format_rar_read_data,
|
||||
archive_read_format_rar_read_data_skip,
|
||||
archive_read_format_rar_seek_data,
|
||||
archive_read_format_rar_cleanup,
|
||||
archive_read_support_format_rar_capabilities,
|
||||
archive_read_format_rar_has_encrypted_entries);
|
||||
rar,
|
||||
"rar",
|
||||
archive_read_format_rar_bid,
|
||||
archive_read_format_rar_options,
|
||||
archive_read_format_rar_read_header,
|
||||
archive_read_format_rar_read_data,
|
||||
archive_read_format_rar_read_data_skip,
|
||||
archive_read_format_rar_seek_data,
|
||||
archive_read_format_rar_cleanup,
|
||||
archive_read_support_format_rar_capabilities,
|
||||
archive_read_format_rar_has_encrypted_entries);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(rar);
|
||||
@@ -788,39 +787,41 @@ archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
|
||||
static int
|
||||
archive_read_format_rar_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *p;
|
||||
const char *h;
|
||||
|
||||
/* If there's already a bid > 30, we'll never win. */
|
||||
if (best_bid > 30)
|
||||
return (-1);
|
||||
|
||||
if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
if (memcmp(p, RAR_SIGNATURE, 7) == 0)
|
||||
if (memcmp(h, RAR_SIGNATURE, 7) == 0)
|
||||
return (30);
|
||||
|
||||
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
|
||||
if ((h[0] == 'M' && h[1] == 'Z') || memcmp(h, "\x7F\x45LF", 4) == 0) {
|
||||
/* This is a PE file */
|
||||
ssize_t offset = 0x10000;
|
||||
ssize_t window = 4096;
|
||||
ssize_t bytes_avail;
|
||||
while (offset + window <= (1024 * 128)) {
|
||||
const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail);
|
||||
if (buff == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window >>= 1;
|
||||
if (window < 0x40)
|
||||
return (0);
|
||||
continue;
|
||||
|
||||
while (offset + window <= SFX_MAX_READAHEAD) {
|
||||
h = __archive_read_ahead(a, offset + window, &bytes_avail);
|
||||
if (h == NULL) {
|
||||
if (bytes_avail >= offset + 0x10) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window = bytes_avail - offset;
|
||||
continue;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
p = buff + offset;
|
||||
while (p + 7 < buff + bytes_avail) {
|
||||
if (memcmp(p, RAR_SIGNATURE, 7) == 0)
|
||||
if (bytes_avail > SFX_MAX_READAHEAD)
|
||||
bytes_avail = SFX_MAX_READAHEAD;
|
||||
while (offset <= bytes_avail - 7) {
|
||||
if (memcmp(h + offset, RAR_SIGNATURE, 7) == 0)
|
||||
return (30);
|
||||
p += 0x10;
|
||||
offset += 0x10;
|
||||
}
|
||||
offset = p - buff;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
@@ -836,7 +837,7 @@ skip_sfx(struct archive_read *a)
|
||||
|
||||
total = 0;
|
||||
window = 4096;
|
||||
while (total + window <= (1024 * 128)) {
|
||||
while (total + window <= SFX_MAX_READAHEAD) {
|
||||
h = __archive_read_ahead(a, window, &bytes);
|
||||
if (h == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
@@ -1005,7 +1006,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
|
||||
crc32_val = __archive_crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
|
||||
if ((crc32_val & 0xffff) != archive_le16dec(p)) {
|
||||
#ifndef DONT_FAIL_ON_CRC_ERROR
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@@ -1064,7 +1065,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
|
||||
crc32_val = __archive_crc32(crc32_val, (const unsigned char *)p, to_read);
|
||||
__archive_read_consume(a, to_read);
|
||||
skip -= to_read;
|
||||
}
|
||||
@@ -1403,7 +1404,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
"Invalid header size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
crc32_computed = crc32(0, (const unsigned char *)p + 2, 7 - 2);
|
||||
crc32_computed = __archive_crc32(0, (const unsigned char *)p + 2, 7 - 2);
|
||||
__archive_read_consume(a, 7);
|
||||
|
||||
if (!(rar->file_flags & FHD_SOLID))
|
||||
@@ -1441,7 +1442,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
|
||||
/* File Header CRC check. */
|
||||
crc32_computed = crc32(crc32_computed, h, (unsigned)(header_size - 7));
|
||||
crc32_computed = __archive_crc32(crc32_computed, h, (unsigned)(header_size - 7));
|
||||
crc32_read = archive_le16dec(rar_header.crc);
|
||||
if ((crc32_computed & 0xffff) != crc32_read) {
|
||||
#ifndef DONT_FAIL_ON_CRC_ERROR
|
||||
@@ -1510,12 +1511,14 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
* consumed at the end.
|
||||
*/
|
||||
if (head_type == NEWSUB_HEAD) {
|
||||
if (rar->packed_size > INT64_MAX - header_size) {
|
||||
int64_t skip;
|
||||
if (archive_ckd_add_i64(&skip, rar->packed_size, header_size) ||
|
||||
skip < 7) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid RAR file: Overlarge extended header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (__archive_read_consume(a, header_size + rar->packed_size - 7) < 0) {
|
||||
if (__archive_read_consume(a, skip - 7) < 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid RAR file: Cannot read extended header data");
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1866,7 +1869,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
static time_t
|
||||
get_time(int ttime)
|
||||
{
|
||||
struct tm tm;
|
||||
struct tm tm = { 0 };
|
||||
tm.tm_sec = 2 * (ttime & 0x1f);
|
||||
tm.tm_min = (ttime >> 5) & 0x3f;
|
||||
tm.tm_hour = (ttime >> 11) & 0x1f;
|
||||
@@ -2037,7 +2040,7 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size,
|
||||
rar->bytes_remaining -= bytes_avail;
|
||||
rar->bytes_unconsumed = bytes_avail;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
|
||||
rar->crc_calculated = __archive_crc32(rar->crc_calculated, *buff,
|
||||
(unsigned)bytes_avail);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
@@ -2096,7 +2099,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
*offset = rar->offset_outgoing;
|
||||
rar->offset_outgoing += *size;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
|
||||
rar->crc_calculated = __archive_crc32(rar->crc_calculated, *buff,
|
||||
(unsigned)*size);
|
||||
rar->unp_offset = 0;
|
||||
return (ARCHIVE_OK);
|
||||
@@ -2132,7 +2135,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
*offset = rar->offset_outgoing;
|
||||
rar->offset_outgoing += *size;
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff,
|
||||
rar->crc_calculated = __archive_crc32(rar->crc_calculated, *buff,
|
||||
(unsigned)*size);
|
||||
return (ret);
|
||||
}
|
||||
@@ -2291,7 +2294,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
|
||||
rar->offset_outgoing += *size;
|
||||
ending_block:
|
||||
/* Calculate File CRC. */
|
||||
rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
|
||||
rar->crc_calculated = __archive_crc32(rar->crc_calculated, *buff, (unsigned)*size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2993,7 +2996,6 @@ expand(struct archive_read *a, int64_t *end)
|
||||
|
||||
if(newfile)
|
||||
{
|
||||
rar->start_new_block = 1;
|
||||
if (!rar_br_read_ahead(a, br, 1))
|
||||
goto truncated_data;
|
||||
rar->start_new_table = rar_br_bits(br, 1);
|
||||
@@ -3477,8 +3479,11 @@ run_filters(struct archive_read *a)
|
||||
if (tend < 0)
|
||||
return 0;
|
||||
end = (size_t)tend;
|
||||
if (end != start + filter->blocklength)
|
||||
if (end != start + filter->blocklength) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad RAR file data: filter block was not fully decompressed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!filters->vm)
|
||||
{
|
||||
@@ -3554,7 +3559,7 @@ compile_program(const uint8_t *bytes, size_t length)
|
||||
prog = calloc(1, sizeof(*prog));
|
||||
if (!prog)
|
||||
return NULL;
|
||||
prog->fingerprint = crc32(0, bytes, (unsigned int)length) | ((uint64_t)length << 32);
|
||||
prog->fingerprint = __archive_crc32(0, bytes, (unsigned int)length) | ((uint64_t)length << 32);
|
||||
|
||||
if (membr_bits(&br, 1))
|
||||
{
|
||||
@@ -3712,7 +3717,9 @@ execute_filter_delta(struct rar_filter *filter, struct rar_virtual_machine *vm)
|
||||
uint8_t *src, *dst;
|
||||
uint32_t i, idx;
|
||||
|
||||
if (length > PROGRAM_WORK_SIZE / 2)
|
||||
if (length > PROGRAM_WORK_SIZE / 2 ||
|
||||
numchannels == 0 ||
|
||||
numchannels > 128)
|
||||
return 0;
|
||||
|
||||
src = &vm->memory[0];
|
||||
@@ -3827,7 +3834,9 @@ execute_filter_audio(struct rar_filter *filter, struct rar_virtual_machine *vm)
|
||||
uint8_t *src, *dst;
|
||||
uint32_t i, j;
|
||||
|
||||
if (length > PROGRAM_WORK_SIZE / 2)
|
||||
if (length > PROGRAM_WORK_SIZE / 2 ||
|
||||
numchannels == 0 ||
|
||||
numchannels > 128)
|
||||
return 0;
|
||||
|
||||
src = &vm->memory[0];
|
||||
|
||||
@@ -38,9 +38,7 @@
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#ifndef HAVE_ZLIB_H
|
||||
#include "archive_crc32.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_locale.h"
|
||||
@@ -87,11 +85,24 @@ static const unsigned char rar5_signature_xor[] = {
|
||||
};
|
||||
static const size_t g_unpack_window_size = 0x20000;
|
||||
|
||||
/* Bid returned when the RAR5 signature is found at offset 0. Bidders
|
||||
* conventionally return the number of bits they verified, so an exact
|
||||
* match of the 8-byte signature bids 64 (like the ar and warc readers
|
||||
* do for their 8-byte magics). This must stay above the seekable Zip
|
||||
* bidder's 32 so that a RAR archive which merely stores an uncompressed
|
||||
* Zip is still recognized as RAR (see issue #2249). The weaker SFX
|
||||
* heuristic, which only scans for the signature somewhere inside an
|
||||
* executable, deliberately keeps its lower bid of 30. */
|
||||
#define RAR5_SIGNATURE_BID ((int)(8 * sizeof(rar5_signature_xor)))
|
||||
|
||||
/* These could have been static const's, but they aren't, because of
|
||||
* Visual Studio. */
|
||||
#define MAX_NAME_IN_CHARS 2048
|
||||
#define MAX_NAME_IN_BYTES (4 * MAX_NAME_IN_CHARS)
|
||||
|
||||
/* maximum header size for RAR5 is 2MB */
|
||||
#define MAX_HEADER_SIZE (2 * 1024 * 1024)
|
||||
|
||||
struct file_header {
|
||||
ssize_t bytes_remaining;
|
||||
ssize_t unpacked_size;
|
||||
@@ -152,6 +163,8 @@ enum REDIR_TYPE {
|
||||
#define OWNER_GROUP_GID 0x08
|
||||
#define OWNER_MAXNAMELEN 256
|
||||
|
||||
#define SFX_MAX_READAHEAD (1024 * 512)
|
||||
|
||||
enum FILTER_TYPE {
|
||||
FILTER_DELTA = 0, /* Generic pattern. */
|
||||
FILTER_E8 = 1, /* Intel x86 code. */
|
||||
@@ -404,7 +417,7 @@ static int cdeque_init(struct cdeque* d, int max_capacity_power_of_2) {
|
||||
return CDE_PARAM;
|
||||
|
||||
cdeque_clear(d);
|
||||
d->arr = malloc(sizeof(void*) * max_capacity_power_of_2);
|
||||
d->arr = malloc(sizeof(size_t*) * max_capacity_power_of_2);
|
||||
|
||||
return d->arr ? CDE_OK : CDE_ALLOC;
|
||||
}
|
||||
@@ -889,16 +902,6 @@ static void reset_file_context(struct rar5 *rar5) {
|
||||
free_filters(rar5);
|
||||
}
|
||||
|
||||
static inline int get_archive_read(struct archive* a,
|
||||
struct archive_read** ar)
|
||||
{
|
||||
*ar = (struct archive_read*) a;
|
||||
archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_support_format_rar5");
|
||||
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static int read_ahead(struct archive_read* a, size_t how_many,
|
||||
const uint8_t** ptr)
|
||||
{
|
||||
@@ -914,13 +917,10 @@ static int read_ahead(struct archive_read* a, size_t how_many,
|
||||
}
|
||||
|
||||
static int consume(struct archive_read* a, int64_t how_many) {
|
||||
int ret;
|
||||
if(__archive_read_consume(a, how_many) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
ret = how_many == __archive_read_consume(a, how_many)
|
||||
? ARCHIVE_OK
|
||||
: ARCHIVE_FATAL;
|
||||
|
||||
return ret;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -935,9 +935,11 @@ static int consume(struct archive_read* a, int64_t how_many) {
|
||||
* the number of bytes that `pvalue_len` value contains. If the `pvalue_len`
|
||||
* is NULL, this consuming operation is done automatically.
|
||||
*
|
||||
* Returns 1 if *pvalue was successfully read.
|
||||
* Returns 0 if there was an error. In this case, *pvalue contains an
|
||||
* invalid value.
|
||||
* In case of error (!ARCHIVE_OK), *pvalue contains an invalid value.
|
||||
*
|
||||
* Returns ARCHIVE_OK if *pvalue was successfully read.
|
||||
* Returns ARCHIVE_FATAL if there was an error.
|
||||
* Returns ARCHIVE_EOF if end of file was reached.
|
||||
*/
|
||||
|
||||
static int read_var(struct archive_read* a, uint64_t* pvalue,
|
||||
@@ -945,16 +947,36 @@ static int read_var(struct archive_read* a, uint64_t* pvalue,
|
||||
{
|
||||
uint64_t multiplier;
|
||||
uint64_t result = 0;
|
||||
size_t i;
|
||||
size_t i, max_bytes;
|
||||
ssize_t avail;
|
||||
const uint8_t* p;
|
||||
|
||||
/* We will read maximum of 10 bytes. We don't have to handle the
|
||||
* situation to read the RAR5 variable-sized value stored at the end of
|
||||
* the file, because such situation will never happen. */
|
||||
if(!read_ahead(a, 10, &p))
|
||||
return 0;
|
||||
/* We will read a maximum of 10 bytes, since that's the longest a
|
||||
* RAR5 varint can legally be. Ask for a full 10-byte lookahead
|
||||
* first, since that's the common case. However, a varint is
|
||||
* self-terminating (a byte with the MSB clear ends the value, so
|
||||
* most varints take far fewer than 10 bytes), and it's legal for
|
||||
* one to end fewer than 10 bytes before the end of the archive --
|
||||
* e.g. a file header's extra field butting up against ENDARC with
|
||||
* no padding. If a full 10-byte lookahead isn't available, fall
|
||||
* back to however many bytes actually remain and decode within
|
||||
* that instead of failing outright; only reaching the real end of
|
||||
* the archive with zero bytes left, or exhausting the available
|
||||
* bytes without hitting a terminator, is a genuine error. */
|
||||
max_bytes = 10;
|
||||
p = __archive_read_ahead(a, max_bytes, &avail);
|
||||
if(p == NULL) {
|
||||
if(avail == 0)
|
||||
return ARCHIVE_EOF;
|
||||
if(avail < 1)
|
||||
return ARCHIVE_FATAL;
|
||||
max_bytes = (size_t)avail;
|
||||
p = __archive_read_ahead(a, max_bytes, NULL);
|
||||
if(p == NULL)
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
for(multiplier = 1, i = 0; i < 10; i++, multiplier *= 128) {
|
||||
for(multiplier = 1, i = 0; i < max_bytes; i++, multiplier *= 128) {
|
||||
uint64_t val;
|
||||
uint8_t b;
|
||||
|
||||
@@ -965,7 +987,9 @@ static int read_var(struct archive_read* a, uint64_t* pvalue,
|
||||
if(archive_ckd_mul_u64(&val, b & 0x7F, multiplier) ||
|
||||
archive_ckd_add_u64(&result, result, val)) {
|
||||
/* Integer overflow occurred. */
|
||||
return 0;
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Number too large");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
/* MSB set to 1 means we need to continue decoding process.
|
||||
@@ -991,17 +1015,19 @@ static int read_var(struct archive_read* a, uint64_t* pvalue,
|
||||
* needs to consume. This is why we handle
|
||||
* such situation here automatically. */
|
||||
if(ARCHIVE_OK != consume(a, 1 + i)) {
|
||||
return 0;
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of decoding process, return success. */
|
||||
return 1;
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* All continuation bits were set. This is an error. */
|
||||
return 0;
|
||||
/* Either all 10 bytes had their continuation bit set (a malformed
|
||||
* varint), or fewer than 10 bytes were available and none of them
|
||||
* terminated the value (a truncated archive). Both are errors. */
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
static int read_var_sized(struct archive_read* a, size_t* pvalue,
|
||||
@@ -1010,10 +1036,17 @@ static int read_var_sized(struct archive_read* a, size_t* pvalue,
|
||||
uint64_t v;
|
||||
uint64_t v_size = 0;
|
||||
|
||||
const int ret = pvalue_len ? read_var(a, &v, &v_size)
|
||||
: read_var(a, &v, NULL);
|
||||
int ret = pvalue_len ? read_var(a, &v, &v_size)
|
||||
: read_var(a, &v, NULL);
|
||||
#if UINT64_MAX > SIZE_MAX
|
||||
if(ret == ARCHIVE_OK && v > SIZE_MAX) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Number too large");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ret == 1 && pvalue) {
|
||||
if(ret == ARCHIVE_OK && pvalue) {
|
||||
*pvalue = (size_t) v;
|
||||
}
|
||||
|
||||
@@ -1111,52 +1144,55 @@ static char read_u64(struct archive_read* a, uint64_t* pvalue) {
|
||||
}
|
||||
|
||||
static int bid_standard(struct archive_read* a) {
|
||||
const uint8_t* p;
|
||||
const uint8_t* h;
|
||||
char signature[sizeof(rar5_signature_xor)];
|
||||
|
||||
rar5_signature(signature);
|
||||
|
||||
if(!read_ahead(a, sizeof(rar5_signature_xor), &p))
|
||||
if(!read_ahead(a, sizeof(rar5_signature_xor), &h))
|
||||
return -1;
|
||||
|
||||
if(!memcmp(signature, p, sizeof(rar5_signature_xor)))
|
||||
return 30;
|
||||
if(!memcmp(h, signature, sizeof(rar5_signature_xor)))
|
||||
return RAR5_SIGNATURE_BID;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int bid_sfx(struct archive_read *a)
|
||||
{
|
||||
const char *p;
|
||||
const char *h;
|
||||
|
||||
if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
|
||||
return -1;
|
||||
|
||||
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
|
||||
if ((h[0] == 'M' && h[1] == 'Z') || memcmp(h, "\x7F\x45LF", 4) == 0) {
|
||||
/* This is a PE file */
|
||||
char signature[sizeof(rar5_signature_xor)];
|
||||
ssize_t offset = 0x10000;
|
||||
ssize_t window = 4096;
|
||||
ssize_t bytes_avail;
|
||||
|
||||
rar5_signature(signature);
|
||||
|
||||
while (offset + window <= (1024 * 512)) {
|
||||
const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail);
|
||||
if (buff == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window >>= 1;
|
||||
if (window < 0x40)
|
||||
return 0;
|
||||
continue;
|
||||
while (offset + window <= SFX_MAX_READAHEAD) {
|
||||
ssize_t bytes_avail;
|
||||
|
||||
h = __archive_read_ahead(a, offset + window, &bytes_avail);
|
||||
if (h == NULL) {
|
||||
if (bytes_avail >= offset + 0x10) {
|
||||
/* Remaining bytes are less than window. */
|
||||
window = bytes_avail - offset;
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
p = buff + offset;
|
||||
while (p + 8 < buff + bytes_avail) {
|
||||
if (memcmp(p, signature, sizeof(signature)) == 0)
|
||||
if (bytes_avail > SFX_MAX_READAHEAD)
|
||||
bytes_avail = SFX_MAX_READAHEAD;
|
||||
while (offset <= bytes_avail - 8) {
|
||||
if (memcmp(h + offset, signature,
|
||||
sizeof(signature)) == 0)
|
||||
return 30;
|
||||
p += 0x10;
|
||||
offset += 0x10;
|
||||
}
|
||||
offset = p - buff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1166,7 +1202,7 @@ static int bid_sfx(struct archive_read *a)
|
||||
static int rar5_bid(struct archive_read* a, int best_bid) {
|
||||
int my_bid;
|
||||
|
||||
if(best_bid > 30)
|
||||
if(best_bid >= RAR5_SIGNATURE_BID)
|
||||
return -1;
|
||||
|
||||
my_bid = bid_standard(a);
|
||||
@@ -1220,26 +1256,30 @@ static int process_main_locator_extra_block(struct archive_read* a,
|
||||
struct rar5 *rar5)
|
||||
{
|
||||
uint64_t locator_flags;
|
||||
int r;
|
||||
|
||||
enum LOCATOR_FLAGS {
|
||||
QLIST = 0x01, RECOVERY = 0x02,
|
||||
};
|
||||
|
||||
if(!read_var(a, &locator_flags, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &locator_flags, NULL);
|
||||
if(r != ARCHIVE_OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if(locator_flags & QLIST) {
|
||||
if(!read_var(a, &rar5->qlist_offset, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &rar5->qlist_offset, NULL);
|
||||
if(r != ARCHIVE_OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* qlist is not used */
|
||||
}
|
||||
|
||||
if(locator_flags & RECOVERY) {
|
||||
if(!read_var(a, &rar5->rr_offset, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &rar5->rr_offset, NULL);
|
||||
if(r != ARCHIVE_OK) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* rr is not used */
|
||||
@@ -1253,13 +1293,15 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5 *rar5,
|
||||
{
|
||||
size_t hash_type = 0;
|
||||
size_t value_len;
|
||||
int r;
|
||||
|
||||
enum HASH_TYPE {
|
||||
BLAKE2sp = 0x00
|
||||
};
|
||||
|
||||
if(!read_var_sized(a, &hash_type, &value_len))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &hash_type, &value_len);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
*extra_data_size -= value_len;
|
||||
if(ARCHIVE_OK != consume(a, value_len)) {
|
||||
@@ -1307,7 +1349,7 @@ static int parse_htime_item(struct archive_read* a, char unix_time,
|
||||
if(!read_u64(a, &windows_time))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
ntfs_to_unix(windows_time, sec, nsec);
|
||||
__archive_ntfs_to_unix(windows_time, sec, nsec);
|
||||
*extra_data_size -= 8;
|
||||
}
|
||||
|
||||
@@ -1323,17 +1365,20 @@ static int parse_file_extra_version(struct archive_read* a,
|
||||
struct archive_string version_string;
|
||||
struct archive_string name_utf8_string;
|
||||
const char* cur_filename;
|
||||
int r;
|
||||
|
||||
/* Flags are ignored. */
|
||||
if(!read_var_sized(a, &flags, &value_len))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &flags, &value_len);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
*extra_data_size -= value_len;
|
||||
if(ARCHIVE_OK != consume(a, value_len))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
if(!read_var_sized(a, &version, &value_len))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &version, &value_len);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
*extra_data_size -= value_len;
|
||||
if(ARCHIVE_OK != consume(a, value_len))
|
||||
@@ -1374,6 +1419,7 @@ static int parse_file_extra_htime(struct archive_read* a,
|
||||
char unix_time, has_unix_ns, has_mtime, has_ctime, has_atime;
|
||||
size_t flags = 0;
|
||||
size_t value_len;
|
||||
int ret;
|
||||
|
||||
enum HTIME_FLAGS {
|
||||
IS_UNIX = 0x01,
|
||||
@@ -1383,8 +1429,9 @@ static int parse_file_extra_htime(struct archive_read* a,
|
||||
HAS_UNIX_NS = 0x10,
|
||||
};
|
||||
|
||||
if(!read_var_sized(a, &flags, &value_len))
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &flags, &value_len);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
|
||||
*extra_data_size -= value_len;
|
||||
if(ARCHIVE_OK != consume(a, value_len)) {
|
||||
@@ -1399,18 +1446,24 @@ static int parse_file_extra_htime(struct archive_read* a,
|
||||
rar5->file.e_atime_ns = rar5->file.e_ctime_ns = rar5->file.e_mtime_ns = 0;
|
||||
|
||||
if(has_mtime) {
|
||||
parse_htime_item(a, unix_time, &rar5->file.e_mtime,
|
||||
ret = parse_htime_item(a, unix_time, &rar5->file.e_mtime,
|
||||
&rar5->file.e_mtime_ns, extra_data_size);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(has_ctime) {
|
||||
parse_htime_item(a, unix_time, &rar5->file.e_ctime,
|
||||
ret = parse_htime_item(a, unix_time, &rar5->file.e_ctime,
|
||||
&rar5->file.e_ctime_ns, extra_data_size);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(has_atime) {
|
||||
parse_htime_item(a, unix_time, &rar5->file.e_atime,
|
||||
ret = parse_htime_item(a, unix_time, &rar5->file.e_atime,
|
||||
&rar5->file.e_atime_ns, extra_data_size);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(has_mtime && has_unix_ns) {
|
||||
@@ -1455,25 +1508,31 @@ static int parse_file_extra_redir(struct archive_read* a,
|
||||
struct archive_entry* e, struct rar5 *rar5, int64_t* extra_data_size)
|
||||
{
|
||||
uint64_t value_size = 0;
|
||||
size_t varint_len = 0;
|
||||
size_t target_size = 0;
|
||||
char target_utf8_buf[MAX_NAME_IN_BYTES];
|
||||
const uint8_t* p;
|
||||
int r;
|
||||
|
||||
if(!read_var(a, &rar5->file.redir_type, &value_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &rar5->file.redir_type, &value_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)value_size))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= value_size;
|
||||
|
||||
if(!read_var(a, &rar5->file.redir_flags, &value_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &rar5->file.redir_flags, &value_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)value_size))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= value_size;
|
||||
|
||||
if(!read_var_sized(a, &target_size, NULL))
|
||||
r = read_var_sized(a, &target_size, &varint_len);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)varint_len))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= target_size + 1;
|
||||
|
||||
if(target_size > (MAX_NAME_IN_CHARS - 1)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@@ -1487,6 +1546,14 @@ static int parse_file_extra_redir(struct archive_read* a,
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
if((int64_t)(target_size + varint_len) > *extra_data_size) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Extra data size is too small for link target");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
*extra_data_size -= (int64_t)(target_size + varint_len);
|
||||
|
||||
if(!read_ahead(a, target_size, &p))
|
||||
return ARCHIVE_EOF;
|
||||
|
||||
@@ -1530,19 +1597,35 @@ static int parse_file_extra_owner(struct archive_read* a,
|
||||
uint64_t id = 0;
|
||||
size_t name_len = 0;
|
||||
size_t name_size = 0;
|
||||
size_t varint_len = 0;
|
||||
char namebuf[OWNER_MAXNAMELEN];
|
||||
const uint8_t* p;
|
||||
int r;
|
||||
|
||||
if(!read_var(a, &flags, &value_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &flags, &value_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)value_size))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= value_size;
|
||||
|
||||
if ((flags & OWNER_USER_NAME) != 0) {
|
||||
if(!read_var_sized(a, &name_size, NULL))
|
||||
r = read_var_sized(a, &name_size, &varint_len);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
/* The name cannot be larger than the remaining extra data of
|
||||
* this field. Rejecting an oversized length here also avoids
|
||||
* requesting a huge allocation from read_ahead() below. */
|
||||
if(*extra_data_size < 0 ||
|
||||
name_size > (uint64_t)*extra_data_size) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Owner name is too long");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)varint_len))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= name_size + 1;
|
||||
*extra_data_size -= (int64_t)(name_size + varint_len);
|
||||
|
||||
if(!read_ahead(a, name_size, &p))
|
||||
return ARCHIVE_EOF;
|
||||
@@ -1561,9 +1644,19 @@ static int parse_file_extra_owner(struct archive_read* a,
|
||||
archive_entry_set_uname(e, namebuf);
|
||||
}
|
||||
if ((flags & OWNER_GROUP_NAME) != 0) {
|
||||
if(!read_var_sized(a, &name_size, NULL))
|
||||
r = read_var_sized(a, &name_size, &varint_len);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(*extra_data_size < 0 ||
|
||||
name_size > (uint64_t)*extra_data_size) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT, "Group name is too long");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)varint_len))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= name_size + 1;
|
||||
*extra_data_size -= (int64_t)(name_size + varint_len);
|
||||
|
||||
if(!read_ahead(a, name_size, &p))
|
||||
return ARCHIVE_EOF;
|
||||
@@ -1582,8 +1675,9 @@ static int parse_file_extra_owner(struct archive_read* a,
|
||||
archive_entry_set_gname(e, namebuf);
|
||||
}
|
||||
if ((flags & OWNER_USER_UID) != 0) {
|
||||
if(!read_var(a, &id, &value_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &id, &value_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)value_size))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= value_size;
|
||||
@@ -1591,8 +1685,9 @@ static int parse_file_extra_owner(struct archive_read* a,
|
||||
archive_entry_set_uid(e, (la_int64_t)id);
|
||||
}
|
||||
if ((flags & OWNER_GROUP_GID) != 0) {
|
||||
if(!read_var(a, &id, &value_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &id, &value_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
if(ARCHIVE_OK != consume(a, (int64_t)value_size))
|
||||
return ARCHIVE_EOF;
|
||||
*extra_data_size -= value_size;
|
||||
@@ -1610,20 +1705,24 @@ static int process_head_file_extra(struct archive_read* a,
|
||||
uint64_t var_size;
|
||||
|
||||
while(extra_data_size > 0) {
|
||||
int r;
|
||||
|
||||
/* Make sure we won't fail if the file declares only unsupported
|
||||
attributes. */
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
if(!read_var(a, &extra_field_size, &var_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &extra_field_size, &var_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
extra_data_size -= var_size;
|
||||
if(ARCHIVE_OK != consume(a, var_size)) {
|
||||
return ARCHIVE_EOF;
|
||||
}
|
||||
|
||||
if(!read_var(a, &extra_field_id, &var_size))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &extra_field_id, &var_size);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
extra_field_size -= var_size;
|
||||
extra_data_size -= var_size;
|
||||
@@ -1662,6 +1761,12 @@ static int process_head_file_extra(struct archive_read* a,
|
||||
/* fallthrough */
|
||||
default:
|
||||
/* Skip unsupported entry. */
|
||||
if (extra_field_size > (uint64_t)extra_data_size) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"RAR5 extra-field size exceeds remaining extra-field data");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
extra_data_size -= extra_field_size;
|
||||
if (ARCHIVE_OK != consume(a, extra_field_size)) {
|
||||
return ARCHIVE_EOF;
|
||||
@@ -1734,6 +1839,7 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
char name_utf8_buf[MAX_NAME_IN_BYTES];
|
||||
const uint8_t* p;
|
||||
int sanity_ret;
|
||||
int r;
|
||||
|
||||
enum FILE_FLAGS {
|
||||
DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004,
|
||||
@@ -1763,16 +1869,32 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
|
||||
if(block_flags & HFL_EXTRA_DATA) {
|
||||
uint64_t edata_size = 0;
|
||||
if(!read_var(a, &edata_size, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &edata_size, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
/* The extra area is part of the file header, which
|
||||
* process_base_block() has already bounded to MAX_HEADER_SIZE.
|
||||
* A declared extra-area size larger than that cannot be valid,
|
||||
* and if left unchecked it is later used as the ceiling for
|
||||
* the owner/group name length in parse_file_extra_owner(),
|
||||
* letting a crafted archive drive read_ahead() into an
|
||||
* attacker-controlled allocation. Reject it here. */
|
||||
if(edata_size > MAX_HEADER_SIZE) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"File extra data size is too large");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
/* Intentional type cast from unsigned to signed. */
|
||||
extra_data_size = (int64_t) edata_size;
|
||||
}
|
||||
|
||||
if(block_flags & HFL_DATA) {
|
||||
if(!read_var_sized(a, &data_size, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &data_size, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(data_size > SSIZE_MAX) {
|
||||
archive_set_error(&a->archive,
|
||||
@@ -1786,11 +1908,13 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
rar5->file.bytes_remaining = 0;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &file_flags, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &file_flags, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(!read_var(a, &unpacked_size, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var(a, &unpacked_size, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(file_flags & UNKNOWN_UNPACKED_SIZE) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
@@ -1807,8 +1931,9 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
return sanity_ret;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &file_attr, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &file_attr, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(file_flags & UTIME) {
|
||||
if(!read_u32(a, &mtime))
|
||||
@@ -1820,8 +1945,9 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
return ARCHIVE_EOF;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &compression_info, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &compression_info, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
c_method = (int) (compression_info >> 7) & 0x7;
|
||||
c_version = (int) (compression_info & 0x3f);
|
||||
@@ -1912,8 +2038,9 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
|
||||
rar5->file.service = 0;
|
||||
|
||||
if(!read_var_sized(a, &host_os, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &host_os, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(host_os == HOST_WINDOWS) {
|
||||
/* Host OS is Windows */
|
||||
@@ -1964,8 +2091,9 @@ static int process_head_file(struct archive_read* a, struct rar5 *rar5,
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &name_size, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
r = read_var_sized(a, &name_size, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
|
||||
if(name_size > (MAX_NAME_IN_CHARS - 1)) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@@ -2093,14 +2221,17 @@ static int process_head_main(struct archive_read* a, struct rar5 *rar5,
|
||||
(void) entry;
|
||||
|
||||
if(block_flags & HFL_EXTRA_DATA) {
|
||||
if(!read_var(a, &extra_data_size, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
int r;
|
||||
r = read_var(a, &extra_data_size, NULL);
|
||||
if(r != ARCHIVE_OK)
|
||||
return r;
|
||||
} else {
|
||||
extra_data_size = 0;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &archive_flags, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &archive_flags, NULL);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
rar5->main.volume = (archive_flags & VOLUME) > 0;
|
||||
@@ -2108,8 +2239,9 @@ static int process_head_main(struct archive_read* a, struct rar5 *rar5,
|
||||
|
||||
if(archive_flags & VOLUME_NUMBER) {
|
||||
size_t v = 0;
|
||||
if(!read_var_sized(a, &v, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &v, NULL);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (v > UINT_MAX) {
|
||||
@@ -2140,12 +2272,14 @@ static int process_head_main(struct archive_read* a, struct rar5 *rar5,
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &extra_field_size, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &extra_field_size, NULL);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &extra_field_id, NULL)) {
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &extra_field_id, NULL);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(extra_field_size == 0) {
|
||||
@@ -2314,20 +2448,23 @@ static int process_base_block(struct archive_read* a,
|
||||
}
|
||||
|
||||
/* Read header size. */
|
||||
if(!read_var_sized(a, &raw_hdr_size, &hdr_size_len)) {
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &raw_hdr_size, &hdr_size_len);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
hdr_size = raw_hdr_size + hdr_size_len;
|
||||
|
||||
/* Sanity check, maximum header size for RAR5 is 2MB. */
|
||||
if(hdr_size > (2 * 1024 * 1024)) {
|
||||
/* Sanity check. Bounding raw_hdr_size (instead of the sum) also
|
||||
* ensures that adding hdr_size_len below cannot wrap hdr_size
|
||||
* around SIZE_MAX. */
|
||||
if(raw_hdr_size > MAX_HEADER_SIZE - hdr_size_len) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Base block header is too large");
|
||||
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
hdr_size = raw_hdr_size + hdr_size_len;
|
||||
|
||||
/* Additional sanity checks to weed out invalid files. */
|
||||
if(raw_hdr_size == 0 || hdr_size_len == 0 ||
|
||||
hdr_size < SMALLEST_RAR5_BLOCK_SIZE)
|
||||
@@ -2346,7 +2483,7 @@ static int process_base_block(struct archive_read* a,
|
||||
}
|
||||
|
||||
/* Verify the CRC32 of the header data. */
|
||||
computed_crc = (uint32_t) crc32(0, p, (int) hdr_size);
|
||||
computed_crc = (uint32_t) __archive_crc32(0, p, (int) hdr_size);
|
||||
if(computed_crc != hdr_crc) {
|
||||
#ifndef DONT_FAIL_ON_CRC_ERROR
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
@@ -2365,11 +2502,13 @@ static int process_base_block(struct archive_read* a,
|
||||
return ARCHIVE_EOF;
|
||||
}
|
||||
|
||||
if(!read_var_sized(a, &header_id, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &header_id, NULL);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
|
||||
if(!read_var_sized(a, &header_flags, NULL))
|
||||
return ARCHIVE_EOF;
|
||||
ret = read_var_sized(a, &header_flags, NULL);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
|
||||
rar5->generic.split_after = (header_flags & HFL_SPLIT_AFTER) > 0;
|
||||
rar5->generic.split_before = (header_flags & HFL_SPLIT_BEFORE) > 0;
|
||||
@@ -2507,7 +2646,7 @@ static int try_skip_sfx(struct archive_read *a)
|
||||
|
||||
rar5_signature(signature);
|
||||
|
||||
while (total + window <= (1024 * 512)) {
|
||||
while (total + window <= SFX_MAX_READAHEAD) {
|
||||
h = __archive_read_ahead(a, window, &bytes);
|
||||
if (h == NULL) {
|
||||
/* Remaining bytes are less than window. */
|
||||
@@ -2633,7 +2772,7 @@ static void update_crc(struct rar5 *rar5, const uint8_t* p, size_t to_read) {
|
||||
* `stored_crc32` info filled in. */
|
||||
if(rar5->file.stored_crc32 > 0) {
|
||||
rar5->file.calculated_crc32 =
|
||||
crc32(rar5->file.calculated_crc32, p,
|
||||
__archive_crc32(rar5->file.calculated_crc32, p,
|
||||
(unsigned int)to_read);
|
||||
}
|
||||
|
||||
@@ -3454,6 +3593,18 @@ static int scan_for_signature(struct archive_read* a) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
/* Report that the archive ended while the current file was still expected to
|
||||
* continue in a following volume (its header had the 'split after' flag set),
|
||||
* which typically happens when a multivolume set is opened without supplying
|
||||
* its later volumes. Returning a clean EOF here would silently hand back a
|
||||
* short, corrupted read, so this is a fatal error. */
|
||||
static int truncated_multivolume_error(struct archive_read* a) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Truncated RAR5 archive: file continues in a subsequent volume "
|
||||
"that is not available");
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
/* This function will switch the multivolume archive file to another file,
|
||||
* i.e. from part03 to part 04. */
|
||||
static int advance_multivolume(struct archive_read* a) {
|
||||
@@ -3550,8 +3701,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size,
|
||||
rar5->cstate.switch_multivolume = 1;
|
||||
|
||||
/* Reallocate the memory which will hold the whole block. */
|
||||
if(rar5->vol.push_buf)
|
||||
free((void*) rar5->vol.push_buf);
|
||||
free(rar5->vol.push_buf);
|
||||
|
||||
/* Increasing the allocation block by 8 is due to bit reading functions,
|
||||
* which are using additional 2 or 4 bytes. Allocating the block size
|
||||
@@ -3591,8 +3741,11 @@ static int merge_block(struct archive_read* a, ssize_t block_size,
|
||||
}
|
||||
|
||||
if(!read_ahead(a, cur_block_size, &lp)) {
|
||||
/* We are in the middle of merging a block that spans
|
||||
* volumes, so more data must follow; running out of
|
||||
* input here means the following volume is missing. */
|
||||
rar5->cstate.switch_multivolume = 0;
|
||||
return ARCHIVE_EOF;
|
||||
return truncated_multivolume_error(a);
|
||||
}
|
||||
|
||||
/* Sanity check; there should never be a situation where this
|
||||
@@ -3636,7 +3789,13 @@ static int merge_block(struct archive_read* a, ssize_t block_size,
|
||||
rar5->merge_mode++;
|
||||
ret = advance_multivolume(a);
|
||||
rar5->merge_mode--;
|
||||
if(ret != ARCHIVE_OK) {
|
||||
if(ret == ARCHIVE_EOF) {
|
||||
/* The block is only partially merged but the
|
||||
* input ended, so the volume that holds the rest
|
||||
* of it is missing. */
|
||||
rar5->cstate.switch_multivolume = 0;
|
||||
return truncated_multivolume_error(a);
|
||||
} else if(ret != ARCHIVE_OK) {
|
||||
rar5->cstate.switch_multivolume = 0;
|
||||
return ret;
|
||||
}
|
||||
@@ -3659,7 +3818,15 @@ static int process_block(struct archive_read* a) {
|
||||
/* If we don't have any data to be processed, this most probably means
|
||||
* we need to switch to the next volume. */
|
||||
if(rar5->main.volume && rar5->file.bytes_remaining == 0) {
|
||||
/* Capture 'split after' before advancing: advance_multivolume()
|
||||
* parses following headers and overwrites this flag. */
|
||||
int split_after = rar5->generic.split_after > 0;
|
||||
ret = advance_multivolume(a);
|
||||
if(ret == ARCHIVE_EOF && split_after) {
|
||||
/* The file is promised to continue in a following
|
||||
* volume, but the input ended first. */
|
||||
return truncated_multivolume_error(a);
|
||||
}
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
}
|
||||
@@ -4063,6 +4230,13 @@ static int do_unstore_file(struct archive_read* a,
|
||||
size_t to_read;
|
||||
const uint8_t* p;
|
||||
|
||||
/* This function returns without any data on more than one path,
|
||||
* and the end of the stored data is the position all of them
|
||||
* should report. */
|
||||
if(buf) *buf = NULL;
|
||||
if(size) *size = 0;
|
||||
if(offset) *offset = rar5->cstate.last_unstore_ptr;
|
||||
|
||||
if(rar5->file.bytes_remaining == 0 && rar5->main.volume > 0 &&
|
||||
rar5->generic.split_after > 0)
|
||||
{
|
||||
@@ -4072,7 +4246,16 @@ static int do_unstore_file(struct archive_read* a,
|
||||
ret = advance_multivolume(a);
|
||||
rar5->cstate.switch_multivolume = 0;
|
||||
|
||||
if(ret != ARCHIVE_OK) {
|
||||
if(ret == ARCHIVE_EOF) {
|
||||
/* We only reach this advance because 'split after' was
|
||||
* set, i.e. the file is promised to continue in a
|
||||
* following volume, but the input ended before we could
|
||||
* reach it (for example, only the first volume of the
|
||||
* set was supplied). The data decoded so far is
|
||||
* incomplete, so report truncation rather than silently
|
||||
* returning a short read as a clean end of file. */
|
||||
return truncated_multivolume_error(a);
|
||||
} else if(ret != ARCHIVE_OK) {
|
||||
/* Failed to advance to next multivolume archive
|
||||
* file. */
|
||||
return ret;
|
||||
@@ -4272,6 +4455,8 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
|
||||
struct rar5 *rar5 = a->format->data;
|
||||
int ret;
|
||||
|
||||
if (buff)
|
||||
*buff = NULL;
|
||||
if (size)
|
||||
*size = 0;
|
||||
|
||||
@@ -4307,6 +4492,11 @@ static int rar5_read_data(struct archive_read *a, const void **buff,
|
||||
}
|
||||
|
||||
if(rar5->file.eof == 1) {
|
||||
/* The entry is over; report the end of the unpacked data,
|
||||
* so that a sparse-file aware caller does not have to
|
||||
* guess where it is. */
|
||||
if (offset)
|
||||
*offset = rar5->cstate.last_write_ptr;
|
||||
return ARCHIVE_EOF;
|
||||
}
|
||||
|
||||
@@ -4458,12 +4648,12 @@ static void rar5_deinit(struct rar5 *rar5) {
|
||||
}
|
||||
|
||||
int archive_read_support_format_rar5(struct archive *_a) {
|
||||
struct archive_read* ar;
|
||||
int ret;
|
||||
struct archive_read* ar = (struct archive_read*)_a;
|
||||
struct rar5 *rar5;
|
||||
int r;
|
||||
|
||||
if(ARCHIVE_OK != (ret = get_archive_read(_a, &ar)))
|
||||
return ret;
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
|
||||
"archive_read_support_format_rar5");
|
||||
|
||||
rar5 = malloc(sizeof(*rar5));
|
||||
if(rar5 == NULL) {
|
||||
@@ -4479,7 +4669,7 @@ int archive_read_support_format_rar5(struct archive *_a) {
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
ret = __archive_read_register_format(ar,
|
||||
r = __archive_read_register_format(ar,
|
||||
rar5,
|
||||
"rar5",
|
||||
rar5_bid,
|
||||
@@ -4492,10 +4682,9 @@ int archive_read_support_format_rar5(struct archive *_a) {
|
||||
rar5_capabilities,
|
||||
rar5_has_encrypted_entries);
|
||||
|
||||
if(ret != ARCHIVE_OK) {
|
||||
if(r != ARCHIVE_OK) {
|
||||
rar5_deinit(rar5);
|
||||
free(rar5);
|
||||
}
|
||||
|
||||
return ARCHIVE_OK;
|
||||
return r;
|
||||
}
|
||||
@@ -64,8 +64,7 @@ archive_read_support_format_raw(struct archive *_a)
|
||||
|
||||
raw = calloc(1, sizeof(*raw));
|
||||
if (raw == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate raw data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate raw data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -81,6 +80,7 @@ archive_read_support_format_raw(struct archive *_a)
|
||||
archive_read_format_raw_cleanup,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(raw);
|
||||
return (r);
|
||||
@@ -137,8 +137,15 @@ archive_read_format_raw_read_data(struct archive_read *a,
|
||||
raw->unconsumed = 0;
|
||||
}
|
||||
|
||||
if (raw->end_of_file)
|
||||
if (raw->end_of_file) {
|
||||
/* Keep reporting the end of the entry, so that a caller
|
||||
* that asks once more after end-of-file still gets a
|
||||
* position it can use. */
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
*offset = raw->offset;
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
/* Get whatever bytes are immediately available. */
|
||||
*buff = __archive_read_ahead(a, 1, &avail);
|
||||
|
||||
@@ -187,6 +187,8 @@ static int header_old_tar(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *);
|
||||
static int header_pax_extension(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *, int64_t *);
|
||||
static int header_pax_records(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, int64_t *, int);
|
||||
static int header_pax_global(struct archive_read *, struct tar *,
|
||||
struct archive_entry *, const void *h, int64_t *);
|
||||
static int header_gnu_longlink(struct archive_read *, struct tar *,
|
||||
@@ -272,8 +274,7 @@ archive_read_support_format_tar(struct archive *_a)
|
||||
|
||||
tar = calloc(1, sizeof(*tar));
|
||||
if (tar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate tar data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate tar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#ifdef HAVE_COPYFILE_H
|
||||
@@ -281,7 +282,9 @@ archive_read_support_format_tar(struct archive *_a)
|
||||
tar->process_mac_extensions = 1;
|
||||
#endif
|
||||
|
||||
r = __archive_read_register_format(a, tar, "tar",
|
||||
r = __archive_read_register_format(a,
|
||||
tar,
|
||||
"tar",
|
||||
archive_read_format_tar_bid,
|
||||
archive_read_format_tar_options,
|
||||
archive_read_format_tar_read_header,
|
||||
@@ -294,7 +297,7 @@ archive_read_support_format_tar(struct archive *_a)
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(tar);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -568,11 +571,21 @@ archive_read_format_tar_read_header(struct archive_read *a,
|
||||
return (ARCHIVE_FATAL);
|
||||
} else {
|
||||
struct sparse_block *sb;
|
||||
size_t added = 0;
|
||||
int count;
|
||||
|
||||
for (sb = tar->sparse_list; sb != NULL; sb = sb->next) {
|
||||
if (!sb->hole)
|
||||
if (!sb->hole) {
|
||||
archive_entry_sparse_add_entry(entry,
|
||||
sb->offset, sb->remaining);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
count = archive_entry_sparse_count(entry);
|
||||
if (count < 0 || (size_t)count != added) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Malformed sparse map data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1737,34 +1750,102 @@ read_mac_metadata_blob(struct archive_read *a,
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a file header for a pax extended archive entry.
|
||||
* Attributes that we act on when we see them in an `x` header.
|
||||
*
|
||||
* A `g` header supplies defaults for every following member, which we
|
||||
* do not implement. Silently ignoring one of these would therefore
|
||||
* change how those members are interpreted, so we reject the archive
|
||||
* instead. Anything not listed here we already ignore wherever it
|
||||
* appears, so ignoring it in a `g` header is no less correct; that
|
||||
* keeps well-formed archives readable, in particular the `g` headers
|
||||
* that star always writes for its `exustar` format.
|
||||
*/
|
||||
#define PAX_GLOBAL_EXACT(k) { k, sizeof(k) - 1, 0 }
|
||||
#define PAX_GLOBAL_PREFIX(k) { k, sizeof(k) - 1, 1 }
|
||||
static const struct pax_global_unsupported_attr {
|
||||
const char *key;
|
||||
size_t length;
|
||||
int is_prefix;
|
||||
} pax_global_unsupported_attrs[] = {
|
||||
/* POSIX-standard attributes that describe the member. */
|
||||
PAX_GLOBAL_EXACT("atime"),
|
||||
PAX_GLOBAL_EXACT("ctime"),
|
||||
PAX_GLOBAL_EXACT("gid"),
|
||||
PAX_GLOBAL_EXACT("gname"),
|
||||
PAX_GLOBAL_EXACT("hdrcharset"),
|
||||
PAX_GLOBAL_EXACT("linkpath"),
|
||||
PAX_GLOBAL_EXACT("mtime"),
|
||||
PAX_GLOBAL_EXACT("path"),
|
||||
PAX_GLOBAL_EXACT("size"),
|
||||
PAX_GLOBAL_EXACT("uid"),
|
||||
PAX_GLOBAL_EXACT("uname"),
|
||||
/* Vendor attributes that we honor. */
|
||||
PAX_GLOBAL_EXACT("GNU.sparse"),
|
||||
PAX_GLOBAL_PREFIX("GNU.sparse."),
|
||||
PAX_GLOBAL_EXACT("LIBARCHIVE.creationtime"),
|
||||
PAX_GLOBAL_EXACT("LIBARCHIVE.symlinktype"),
|
||||
PAX_GLOBAL_PREFIX("LIBARCHIVE.xattr."),
|
||||
PAX_GLOBAL_EXACT("RHT.security.selinux"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.acl.access"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.acl.ace"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.acl.default"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.dev"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.devmajor"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.devminor"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.fflags"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.ino"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.nlink"),
|
||||
PAX_GLOBAL_EXACT("SCHILY.realsize"),
|
||||
PAX_GLOBAL_PREFIX("SCHILY.xattr."),
|
||||
PAX_GLOBAL_EXACT("SUN.holesdata"),
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO: This is a linear scan over the table above. It runs once per
|
||||
* attribute in a `g` header, and `g` headers are rare, so the cost is
|
||||
* not measurable today. If that ever changes -- or if the table grows
|
||||
* much larger -- a sorted table with a binary search, or a hash of the
|
||||
* exact keys with a separate short prefix list, would be worth doing.
|
||||
*/
|
||||
static int
|
||||
pax_global_attribute_unsupported(const char *key, size_t key_length)
|
||||
{
|
||||
const struct pax_global_unsupported_attr *attr;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(pax_global_unsupported_attrs)
|
||||
/ sizeof(pax_global_unsupported_attrs[0]); i++) {
|
||||
attr = &pax_global_unsupported_attrs[i];
|
||||
if (attr->is_prefix) {
|
||||
if (key_length > attr->length
|
||||
&& memcmp(key, attr->key, attr->length) == 0)
|
||||
return (1);
|
||||
} else if (key_length == attr->length
|
||||
&& memcmp(key, attr->key, attr->length) == 0) {
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a file header for a pax global archive entry.
|
||||
*/
|
||||
static int
|
||||
header_pax_global(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
const struct archive_entry_header_ustar *header;
|
||||
int64_t size, to_consume;
|
||||
return (header_pax_records(a, tar, entry, h, unconsumed, 1));
|
||||
}
|
||||
|
||||
(void)tar; /* UNUSED */
|
||||
(void)entry; /* UNUSED */
|
||||
|
||||
header = (const struct archive_entry_header_ustar *)h;
|
||||
size = tar_atol(header->size, sizeof(header->size));
|
||||
if (size < 0 || size > entry_limit) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Special header has invalid size: %lld",
|
||||
(long long)size);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (size == 0) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid empty pax global extended header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
to_consume = ((size + 511) & ~511);
|
||||
*unconsumed += to_consume;
|
||||
return (ARCHIVE_OK);
|
||||
/*
|
||||
* Parse a file header for a pax extended archive entry.
|
||||
*/
|
||||
static int
|
||||
header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
{
|
||||
return (header_pax_records(a, tar, entry, h, unconsumed, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1863,9 +1944,18 @@ header_ustar(struct archive_read *a, struct tar *tar,
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the attribute records in the body of an `x` or `g` header.
|
||||
*
|
||||
* With global == 0 each attribute is applied to the entry. With
|
||||
* global == 1 the attributes are only inspected: we do not implement
|
||||
* global defaults, so we reject any attribute that we would otherwise
|
||||
* have honored and ignore the rest.
|
||||
*/
|
||||
static int
|
||||
header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed)
|
||||
header_pax_records(struct archive_read *a, struct tar *tar,
|
||||
struct archive_entry *entry, const void *h, int64_t *unconsumed,
|
||||
int global)
|
||||
{
|
||||
/* Sanity checks: The largest `x` body I've ever heard of was
|
||||
* a little over 4MB. So I doubt there has ever been a
|
||||
@@ -1910,7 +2000,8 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
if (ext_size == 0) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid empty pax extended header");
|
||||
global ? "Invalid empty pax global extended header"
|
||||
: "Invalid empty pax extended header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -2034,8 +2125,25 @@ header_pax_extension(struct archive_read *a, struct tar *tar,
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/* pax_attribute will consume value_length - 1 */
|
||||
r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
|
||||
if (global) {
|
||||
if (pax_global_attribute_unsupported(attr_name.s,
|
||||
archive_strlen(&attr_name))) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unsupported pax global extended header attribute '%s'",
|
||||
attr_name.s);
|
||||
archive_string_free(&attr_name);
|
||||
*unconsumed += ext_size + ext_padding;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Not an attribute we would have acted on, so
|
||||
* ignoring it here changes nothing. */
|
||||
__archive_read_consume(a, value_length - 1);
|
||||
r = ARCHIVE_OK;
|
||||
} else {
|
||||
/* pax_attribute will consume value_length - 1 */
|
||||
r = pax_attribute(a, tar, entry, attr_name.s, archive_strlen(&attr_name), value_length - 1, unconsumed);
|
||||
}
|
||||
ext_size -= value_length - 1;
|
||||
|
||||
// Release the allocated attr_name (either here or before every return in this function)
|
||||
@@ -3136,6 +3244,8 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
|
||||
{
|
||||
struct sparse_block *p;
|
||||
|
||||
if (remaining == 0)
|
||||
return (ARCHIVE_OK);
|
||||
p = calloc(1, sizeof(*p));
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Out of memory");
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
typedef enum {
|
||||
WT_NONE,
|
||||
@@ -95,16 +96,6 @@ typedef enum {
|
||||
LAST_WT
|
||||
} warc_type_t;
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
const char *str;
|
||||
} warc_string_t;
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
char *str;
|
||||
} warc_strbuf_t;
|
||||
|
||||
struct warc {
|
||||
/* Content length of the current record */
|
||||
int64_t cntlen;
|
||||
@@ -113,8 +104,8 @@ struct warc {
|
||||
/* Bytes to consume before the next read */
|
||||
int64_t unconsumed;
|
||||
|
||||
/* String pool */
|
||||
warc_strbuf_t pool;
|
||||
/* Reusable buffer while parsing file names. */
|
||||
struct archive_string fname;
|
||||
/* Previous version */
|
||||
unsigned int pver;
|
||||
/* Stringified format name */
|
||||
@@ -132,7 +123,8 @@ static int archive_read_format_warc_read_header(struct archive_read *,
|
||||
/* Private routines */
|
||||
static unsigned int warc_read_version(const char *, size_t);
|
||||
static unsigned int warc_read_type(const char *, size_t);
|
||||
static warc_string_t warc_read_uri(const char *, size_t);
|
||||
static void warc_read_uri(const char *, size_t,
|
||||
struct archive_string *);
|
||||
static int64_t warc_read_length(const char *, size_t);
|
||||
static time_t warc_read_date(const char *, size_t);
|
||||
static time_t warc_read_last_modified(const char *, size_t);
|
||||
@@ -150,8 +142,7 @@ archive_read_support_format_warc(struct archive *_a)
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_warc");
|
||||
|
||||
if ((warc = calloc(1, sizeof(*warc))) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate warc data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate warc data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -168,11 +159,9 @@ archive_read_support_format_warc(struct archive *_a)
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
if (r != ARCHIVE_OK)
|
||||
free(warc);
|
||||
return (r);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -180,9 +169,7 @@ archive_read_format_warc_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct warc *warc = a->format->data;
|
||||
|
||||
if (warc->pool.len > 0U) {
|
||||
free(warc->pool.str);
|
||||
}
|
||||
archive_string_free(&warc->fname);
|
||||
archive_string_free(&warc->sver);
|
||||
free(warc);
|
||||
a->format->data = NULL;
|
||||
@@ -192,20 +179,20 @@ archive_read_format_warc_cleanup(struct archive_read *a)
|
||||
static int
|
||||
archive_read_format_warc_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *hdr;
|
||||
const void *h;
|
||||
ssize_t nrd;
|
||||
unsigned int ver;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
/* Check the first line, which should already be a record header. */
|
||||
if ((hdr = __archive_read_ahead(a, 12, &nrd)) == NULL) {
|
||||
if ((h = __archive_read_ahead(a, 12, &nrd)) == NULL) {
|
||||
/* Not enough data to identify this format. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse the record version number. */
|
||||
ver = warc_read_version(hdr, nrd);
|
||||
ver = warc_read_version(h, nrd);
|
||||
if (ver < 1200U || ver > 10000U) {
|
||||
/* Only WARC 0.12 through WARC 1.0 are supported. */
|
||||
return -1;
|
||||
@@ -225,9 +212,6 @@ archive_read_format_warc_read_header(struct archive_read *a,
|
||||
const char *buf;
|
||||
ssize_t nrd;
|
||||
const char *eoh;
|
||||
char *tmp;
|
||||
/* Reuse the header buffer while parsing the file name. */
|
||||
warc_string_t fnam;
|
||||
/* WARC record type */
|
||||
warc_type_t ftyp;
|
||||
/* Content length, or a negative error indicator */
|
||||
@@ -314,31 +298,14 @@ start_over:
|
||||
case WT_RSP:
|
||||
/* Read the filename only for record types that are expected to
|
||||
* have a target URI. */
|
||||
fnam = warc_read_uri(buf, eoh - buf);
|
||||
warc_read_uri(buf, eoh - buf, &warc->fname);
|
||||
/* Avoid creating directory endpoints as files. */
|
||||
if (fnam.len == 0 || fnam.str[fnam.len - 1] == '/') {
|
||||
if (archive_strlen(&warc->fname) == 0 ||
|
||||
warc->fname.s[warc->fname.length - 1] == '/') {
|
||||
/* Skip this record. */
|
||||
fnam.len = 0U;
|
||||
fnam.str = NULL;
|
||||
archive_string_empty(&warc->fname);
|
||||
break;
|
||||
}
|
||||
/* Copy the name into the reusable string pool to avoid a malloc/free
|
||||
* roundtrip for each entry. */
|
||||
if (fnam.len + 1U > warc->pool.len) {
|
||||
warc->pool.len = ((fnam.len + 64U) / 64U) * 64U;
|
||||
tmp = realloc(warc->pool.str, warc->pool.len);
|
||||
if (tmp == NULL) {
|
||||
archive_set_error(
|
||||
&a->archive, ENOMEM,
|
||||
"Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
warc->pool.str = tmp;
|
||||
}
|
||||
memcpy(warc->pool.str, fnam.str, fnam.len);
|
||||
warc->pool.str[fnam.len] = '\0';
|
||||
/* Hide the pool implementation behind the parsed string. */
|
||||
fnam.str = warc->pool.str;
|
||||
|
||||
/* Use a Last-Modified record header when present; otherwise fall back
|
||||
* to WARC-Date. */
|
||||
@@ -355,8 +322,7 @@ start_over:
|
||||
case WT_CONT:
|
||||
case LAST_WT:
|
||||
default:
|
||||
fnam.len = 0U;
|
||||
fnam.str = NULL;
|
||||
archive_string_empty(&warc->fname);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -366,10 +332,10 @@ start_over:
|
||||
switch (ftyp) {
|
||||
case WT_RSRC:
|
||||
case WT_RSP:
|
||||
if (fnam.len > 0U) {
|
||||
if (archive_strlen(&warc->fname) > 0) {
|
||||
/* Populate the entry object. */
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_copy_pathname(entry, fnam.str);
|
||||
archive_entry_copy_pathname(entry, warc->fname.s);
|
||||
archive_entry_set_size(entry, cntlen);
|
||||
archive_entry_set_perm(entry, 0644);
|
||||
/* WARC-Date becomes ctime; mtime comes from Last-Modified or WARC-Date. */
|
||||
@@ -457,15 +423,8 @@ archive_read_format_warc_skip(struct archive_read *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
/* Private routines */
|
||||
static void*
|
||||
deconst(const void *c)
|
||||
{
|
||||
return (void *)(uintptr_t)c;
|
||||
}
|
||||
|
||||
static char*
|
||||
static const char*
|
||||
xmemmem(const char *hay, const size_t haysize,
|
||||
const char *needle, const size_t needlesize)
|
||||
{
|
||||
@@ -482,7 +441,7 @@ xmemmem(const char *hay, const size_t haysize,
|
||||
* found anywhere in the haystack; otherwise find the first candidate
|
||||
* that begins with *NEEDLE. */
|
||||
if (needlesize == 0UL) {
|
||||
return deconst(hay);
|
||||
return hay;
|
||||
} else if ((hay = memchr(hay, *needle, haysize)) == NULL) {
|
||||
/* No candidate match remains. */
|
||||
return NULL;
|
||||
@@ -501,7 +460,7 @@ xmemmem(const char *hay, const size_t haysize,
|
||||
return NULL;
|
||||
} else if (eqp) {
|
||||
/* Found a match. */
|
||||
return deconst(hay);
|
||||
return hay;
|
||||
}
|
||||
|
||||
/* Loop through the rest of the haystack and update the rolling XOR
|
||||
@@ -514,7 +473,7 @@ xmemmem(const char *hay, const size_t haysize,
|
||||
* NEEDLESIZE - 1 characters for equality. CAND is always before
|
||||
* HP by design, so no range check is needed. */
|
||||
if (hsum == nsum && memcmp(cand, needle, needlesize - 1U) == 0) {
|
||||
return deconst(cand);
|
||||
return cand;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -552,24 +511,34 @@ time_from_tm(struct tm *t)
|
||||
/* Use platform timegm() if available. */
|
||||
return (timegm(t));
|
||||
#else
|
||||
int64_t days, result;
|
||||
|
||||
/* Otherwise, calculate directly using POSIX assumptions. */
|
||||
/* First, fix up tm_yday based on the year, month, and day. */
|
||||
if (mktime(t) == (time_t)-1)
|
||||
return ((time_t)-1);
|
||||
/* Then compute timegm() from first principles. */
|
||||
return (t->tm_sec
|
||||
+ t->tm_min * 60
|
||||
+ t->tm_hour * 3600
|
||||
+ t->tm_yday * 86400
|
||||
+ (t->tm_year - 70) * 31536000
|
||||
+ ((t->tm_year - 69) / 4) * 86400
|
||||
- ((t->tm_year - 1) / 100) * 86400
|
||||
+ ((t->tm_year + 299) / 400) * 86400);
|
||||
days = (int64_t)t->tm_yday
|
||||
+ ((int64_t)t->tm_year - 70) * 365
|
||||
+ ((int64_t)t->tm_year - 69) / 4
|
||||
- ((int64_t)t->tm_year - 1) / 100
|
||||
+ ((int64_t)t->tm_year + 299) / 400;
|
||||
if (archive_ckd_mul_i64(&result, days, 86400) ||
|
||||
archive_ckd_add_i64(&result, result,
|
||||
(int64_t)t->tm_hour * 3600 + t->tm_min * 60
|
||||
+ t->tm_sec))
|
||||
return ((time_t)-1);
|
||||
if (result < 0) {
|
||||
if (TIME_MIN == 0 || result < (int64_t)TIME_MIN)
|
||||
return ((time_t)-1);
|
||||
} else if ((uint64_t)result > (uint64_t)TIME_MAX)
|
||||
return ((time_t)-1);
|
||||
return ((time_t)result);
|
||||
#endif
|
||||
}
|
||||
|
||||
static time_t
|
||||
xstrpisotime(const char *s, char **endptr)
|
||||
xstrpisotime(const char *s, const char **endptr)
|
||||
{
|
||||
/* Like strptime(), but only for ISO 8601 Zulu strings. */
|
||||
struct tm tm;
|
||||
@@ -617,7 +586,7 @@ xstrpisotime(const char *s, char **endptr)
|
||||
|
||||
out:
|
||||
if (endptr != NULL) {
|
||||
*endptr = deconst(s);
|
||||
*endptr = s;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -701,22 +670,23 @@ warc_read_type(const char *buf, size_t bsz)
|
||||
return WT_NONE;
|
||||
}
|
||||
|
||||
static warc_string_t
|
||||
warc_read_uri(const char *buf, size_t bsz)
|
||||
static void
|
||||
warc_read_uri(const char *buf, size_t bsz, struct archive_string *str)
|
||||
{
|
||||
static const char _key[] = "\r\nWARC-Target-URI:";
|
||||
const char *val, *uri, *eol, *p;
|
||||
warc_string_t res = {0U, NULL};
|
||||
|
||||
archive_string_empty(str);
|
||||
|
||||
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
|
||||
/* Header field is absent. */
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
/* Skip leading whitespace. */
|
||||
val += sizeof(_key) - 1U;
|
||||
if ((eol = warc_find_eol(val, buf + bsz - val)) == NULL) {
|
||||
/* Header field has no end of line. */
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
||||
while (val < eol && (*val == ' ' || *val == '\t'))
|
||||
@@ -725,18 +695,18 @@ warc_read_uri(const char *buf, size_t bsz)
|
||||
/* Locate the :// separator. */
|
||||
if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) {
|
||||
/* Ignore values without a :// separator. */
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Spaces inside a URI are not allowed; CRLF should follow. */
|
||||
for (p = val; p < eol; p++) {
|
||||
if (isspace((unsigned char)*p))
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Require enough room for the shortest supported scheme. */
|
||||
if (uri < (val + 3U))
|
||||
return res;
|
||||
return;
|
||||
|
||||
/* Move uri past the :// separator. */
|
||||
uri += 3U;
|
||||
@@ -751,11 +721,14 @@ warc_read_uri(const char *buf, size_t bsz)
|
||||
while (uri < eol && *uri++ != '/');
|
||||
} else {
|
||||
/* Unsupported URI scheme. */
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
res.str = uri;
|
||||
res.len = eol - uri;
|
||||
return res;
|
||||
|
||||
/* Require valid C string representation. */
|
||||
if (memchr(uri, '\0', eol - uri) != NULL)
|
||||
return;
|
||||
|
||||
archive_strncpy(str, uri, eol - uri);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
@@ -803,8 +776,7 @@ static time_t
|
||||
warc_read_date(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nWARC-Date:";
|
||||
const char *val, *eol;
|
||||
char *on = NULL;
|
||||
const char *val, *eol, *on = NULL;
|
||||
time_t res;
|
||||
|
||||
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
|
||||
@@ -830,8 +802,7 @@ static time_t
|
||||
warc_read_last_modified(const char *buf, size_t bsz)
|
||||
{
|
||||
static const char _key[] = "\r\nLast-Modified:";
|
||||
const char *val, *eol;
|
||||
char *on = NULL;
|
||||
const char *val, *eol, *on = NULL;
|
||||
time_t res;
|
||||
|
||||
if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) {
|
||||
|
||||
@@ -30,16 +30,8 @@
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#if HAVE_LIBXML_XMLREADER_H
|
||||
#include <libxml/xmlreader.h>
|
||||
#elif HAVE_BSDXML_H
|
||||
#include <bsdxml.h>
|
||||
#elif HAVE_EXPAT_H
|
||||
#include <expat.h>
|
||||
#elif HAVE_XMLLITE_H
|
||||
#include <objidl.h>
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#include <bzlib.h>
|
||||
@@ -59,12 +51,11 @@
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_xml_private.h"
|
||||
|
||||
#if (!defined(HAVE_LIBXML_XMLREADER_H) && \
|
||||
!defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H) && \
|
||||
!defined(HAVE_XMLLITE_H)) ||\
|
||||
!defined(HAVE_ZLIB_H) || \
|
||||
!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
|
||||
#if !defined(ARCHIVE_XML_READ) ||\
|
||||
!defined(HAVE_ZLIB_H) || \
|
||||
!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
|
||||
/*
|
||||
* xar needs several external libraries.
|
||||
* o libxml2, expat or (Windows only) xmllite --- XML parser
|
||||
@@ -318,7 +309,6 @@ struct unknown_tag {
|
||||
|
||||
struct xar {
|
||||
uint64_t offset; /* Current position in the file. */
|
||||
int64_t total;
|
||||
uint64_t h_base;
|
||||
int end_of_file;
|
||||
#define OUTBUFF_SIZE (1024 * 64)
|
||||
@@ -434,7 +424,7 @@ static void xml_end(void *, const char *);
|
||||
static int xml_data(void *, const char *, size_t);
|
||||
static int xml_parse_file_flags(struct xar *, const char *);
|
||||
static int xml_parse_file_ext2(struct xar *, const char *);
|
||||
#if defined(HAVE_LIBXML_XMLREADER_H)
|
||||
#if defined(ARCHIVE_XML_READER_XML2)
|
||||
static int xml2_xmlattr_setup(struct archive_read *,
|
||||
struct xmlattr_list *, xmlTextReaderPtr);
|
||||
static int xml2_read_cb(void *, char *, int);
|
||||
@@ -442,7 +432,7 @@ static int xml2_close_cb(void *);
|
||||
static void xml2_error_hdr(void *, const char *, xmlParserSeverities,
|
||||
xmlTextReaderLocatorPtr);
|
||||
static int xml2_read_toc(struct archive_read *);
|
||||
#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
|
||||
#elif defined(ARCHIVE_XML_READER_BSDXML) || defined(ARCHIVE_XML_READER_EXPAT)
|
||||
struct expat_userData {
|
||||
int state;
|
||||
struct archive_read *archive;
|
||||
@@ -453,15 +443,15 @@ static void expat_start_cb(void *, const XML_Char *, const XML_Char **);
|
||||
static void expat_end_cb(void *, const XML_Char *);
|
||||
static void expat_data_cb(void *, const XML_Char *, int);
|
||||
static int expat_read_toc(struct archive_read *);
|
||||
#elif defined(HAVE_XMLLITE_H)
|
||||
#elif defined(ARCHIVE_XML_READER_XMLLITE)
|
||||
static int xmllite_read_toc(struct archive_read *);
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_format_xar(struct archive *_a)
|
||||
{
|
||||
struct xar *xar;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct xar *xar;
|
||||
int r;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
@@ -469,8 +459,7 @@ archive_read_support_format_xar(struct archive *_a)
|
||||
|
||||
xar = calloc(1, sizeof(*xar));
|
||||
if (xar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate xar data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate xar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -491,6 +480,7 @@ archive_read_support_format_xar(struct archive *_a)
|
||||
xar_cleanup,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(xar);
|
||||
return (r);
|
||||
@@ -499,38 +489,38 @@ archive_read_support_format_xar(struct archive *_a)
|
||||
static int
|
||||
xar_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const unsigned char *b;
|
||||
const char *h;
|
||||
int bid;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
b = __archive_read_ahead(a, HEADER_SIZE, NULL);
|
||||
if (b == NULL)
|
||||
h = __archive_read_ahead(a, HEADER_SIZE, NULL);
|
||||
if (h == NULL)
|
||||
return (-1);
|
||||
|
||||
bid = 0;
|
||||
/*
|
||||
* Verify magic code
|
||||
*/
|
||||
if (archive_be32dec(b) != HEADER_MAGIC)
|
||||
if (archive_be32dec(h) != HEADER_MAGIC)
|
||||
return (0);
|
||||
bid += 32;
|
||||
/*
|
||||
* Verify header size
|
||||
*/
|
||||
if (archive_be16dec(b+4) != HEADER_SIZE)
|
||||
if (archive_be16dec(h+4) != HEADER_SIZE)
|
||||
return (0);
|
||||
bid += 16;
|
||||
/*
|
||||
* Verify header version
|
||||
*/
|
||||
if (archive_be16dec(b+6) != HEADER_VERSION)
|
||||
if (archive_be16dec(h+6) != HEADER_VERSION)
|
||||
return (0);
|
||||
bid += 16;
|
||||
/*
|
||||
* Verify type of checksum
|
||||
*/
|
||||
switch (archive_be32dec(b+24)) {
|
||||
switch (archive_be32dec(h+24)) {
|
||||
case CKSUM_NONE:
|
||||
case CKSUM_SHA1:
|
||||
case CKSUM_MD5:
|
||||
@@ -602,11 +592,11 @@ read_toc(struct archive_read *a)
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
|
||||
#ifdef HAVE_LIBXML_XMLREADER_H
|
||||
#ifdef ARCHIVE_XML_READER_XML2
|
||||
r = xml2_read_toc(a);
|
||||
#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
|
||||
#elif defined(ARCHIVE_XML_READER_BSDXML) || defined(ARCHIVE_XML_READER_EXPAT)
|
||||
r = expat_read_toc(a);
|
||||
#elif defined(HAVE_XMLLITE_H)
|
||||
#elif defined(ARCHIVE_XML_READER_XMLLITE)
|
||||
r = xmllite_read_toc(a);
|
||||
#endif
|
||||
if (r != ARCHIVE_OK)
|
||||
@@ -918,7 +908,6 @@ xar_read_data(struct archive_read *a,
|
||||
|
||||
*offset = xar->entry_total;
|
||||
xar->entry_total += *size;
|
||||
xar->total += *size;
|
||||
xar->offset += used;
|
||||
xar->entry_remaining -= used;
|
||||
xar->entry_unconsumed = used;
|
||||
@@ -1063,6 +1052,11 @@ rd_contents(struct archive_read *a, const void **buff, size_t *size,
|
||||
*used = bytes;
|
||||
if (decompress(a, buff, size, b, used) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (remaining > 0 && *used == 0 && *size == 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"XAR decompressor made no progress");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update checksum of a compressed data and a extracted data.
|
||||
@@ -1643,6 +1637,11 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
|
||||
avail_out = *outbytes;
|
||||
switch (xar->rd_encoding) {
|
||||
case GZIP:
|
||||
/* avail_in and avail_out are 32 bits wide in zlib. */
|
||||
if (avail_in > UINT_MAX)
|
||||
avail_in = UINT_MAX;
|
||||
if (avail_out > UINT_MAX)
|
||||
avail_out = UINT_MAX;
|
||||
xar->stream.next_in = (Bytef *)(uintptr_t)b;
|
||||
xar->stream.avail_in = (uInt)avail_in;
|
||||
xar->stream.next_out = (unsigned char *)outbuff;
|
||||
@@ -1662,6 +1661,11 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes,
|
||||
break;
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
case BZIP2:
|
||||
/* avail_in and avail_out are 32 bits wide in bzlib. */
|
||||
if (avail_in > UINT_MAX)
|
||||
avail_in = UINT_MAX;
|
||||
if (avail_out > UINT_MAX)
|
||||
avail_out = UINT_MAX;
|
||||
xar->bzstream.next_in = (char *)(uintptr_t)b;
|
||||
xar->bzstream.avail_in = (unsigned int)avail_in;
|
||||
xar->bzstream.next_out = (char *)outbuff;
|
||||
@@ -3164,7 +3168,7 @@ xml_parse_file_ext2(struct xar *xar, const char *name)
|
||||
return (1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBXML_XMLREADER_H
|
||||
#ifdef ARCHIVE_XML_READER_XML2
|
||||
|
||||
static int
|
||||
xml2_xmlattr_setup(struct archive_read *a,
|
||||
@@ -3321,7 +3325,7 @@ xml2_read_toc(struct archive_read *a)
|
||||
return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H)
|
||||
#elif defined(ARCHIVE_XML_READER_BSDXML) || defined(ARCHIVE_XML_READER_EXPAT)
|
||||
|
||||
static int
|
||||
expat_xmlattr_setup(struct archive_read *a,
|
||||
@@ -3445,7 +3449,7 @@ expat_read_toc(struct archive_read *a)
|
||||
return (ud.state);
|
||||
}
|
||||
|
||||
#elif defined(HAVE_XMLLITE_H)
|
||||
#elif defined(ARCHIVE_XML_READER_XMLLITE)
|
||||
|
||||
struct ArchiveStreamAdapter {
|
||||
const ISequentialStreamVtbl *lpVtbl; /* see asaStaticVtable */
|
||||
@@ -3765,6 +3769,6 @@ out:
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif /* defined(XMLLITE) */
|
||||
#endif /* defined(ARCHIVE_XML_READER_XMLLITE) */
|
||||
|
||||
#endif /* Support xar format */
|
||||
@@ -45,6 +45,9 @@
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@@ -74,9 +77,7 @@
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_ppmd8_private.h"
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
#include "archive_crc32.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* length of local file header, not including filename and extra */
|
||||
#define ZIP_LOCHDR_LEN 30U
|
||||
@@ -96,6 +97,12 @@ struct zip_entry {
|
||||
time_t mtime;
|
||||
time_t atime;
|
||||
time_t ctime;
|
||||
/* File creation time, from an NTFS extra field only */
|
||||
time_t btime;
|
||||
/* Nanosecond precision, from an NTFS extra field only */
|
||||
uint32_t mtime_ns;
|
||||
uint32_t atime_ns;
|
||||
uint32_t btime_ns;
|
||||
uint32_t crc32;
|
||||
uint16_t mode;
|
||||
uint16_t zip_flags; /* From GP Flags Field */
|
||||
@@ -135,6 +142,12 @@ struct trad_enc_ctx {
|
||||
/* Bits used in flags. */
|
||||
#define LA_USED_ZIP64 (1 << 0)
|
||||
#define LA_FROM_CENTRAL_DIRECTORY (1 << 1)
|
||||
#define LA_MTIME_FROM_EXTRA (1 << 2)
|
||||
#define LA_ATIME_FROM_EXTRA (1 << 3)
|
||||
#define LA_CTIME_FROM_EXTRA (1 << 4)
|
||||
#define LA_NTFS_MTIME (1 << 5)
|
||||
#define LA_NTFS_ATIME (1 << 6)
|
||||
#define LA_NTFS_BTIME (1 << 7)
|
||||
|
||||
/*
|
||||
* See "WinZip - AES Encryption Information"
|
||||
@@ -230,7 +243,6 @@ struct zip {
|
||||
unsigned char *decrypted_ptr;
|
||||
size_t decrypted_buffer_size;
|
||||
size_t decrypted_bytes_remaining;
|
||||
size_t decrypted_unconsumed_bytes;
|
||||
|
||||
/* Traditional PKWARE decryption. */
|
||||
struct trad_enc_ctx tctx;
|
||||
@@ -337,7 +349,7 @@ static void
|
||||
trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
|
||||
{
|
||||
uint8_t t;
|
||||
#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL)
|
||||
#define CRC32(c, b) (__archive_crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL)
|
||||
|
||||
ctx->keys[0] = CRC32(ctx->keys[0], c);
|
||||
ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1;
|
||||
@@ -479,6 +491,7 @@ zipx_read_header_and_decrypt(struct archive_read *a, const void **buf, size_t in
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#if (HAVE_LZMA_H && HAVE_LIBLZMA) || defined(HAVE_BZLIB_H) || (HAVE_ZSTD_H && HAVE_LIBZSTD) || defined(HAVE_ZLIB_H)
|
||||
/* Decrypt bulk compressed data for zipx decompression.
|
||||
* Manages the decryption buffer, handles partial fills, and returns decrypted
|
||||
* data pointer + length. `sp` is set to the raw pointer for HMAC accounting. */
|
||||
@@ -575,6 +588,7 @@ zip_read_decrypt_update(struct zip *zip, ssize_t to_consume, const void *sp)
|
||||
if (zip->hctx_valid)
|
||||
archive_hmac_sha1_update(&zip->hctx, sp, to_consume);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Common code for streaming or seeking modes.
|
||||
@@ -586,7 +600,7 @@ zip_read_decrypt_update(struct zip *zip, ssize_t to_consume, const void *sp)
|
||||
static unsigned long
|
||||
real_crc32(unsigned long crc, const void *buff, size_t len)
|
||||
{
|
||||
return crc32(crc, buff, (unsigned int)len);
|
||||
return __archive_crc32(crc, buff, (unsigned int)len);
|
||||
}
|
||||
|
||||
/* Used by "ignorecrc32" option to speed up tests. */
|
||||
@@ -647,6 +661,23 @@ compression_name(const int compression)
|
||||
return "??";
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret a raw 32-bit Unix timestamp, preferring the signed
|
||||
* (pre-1970-capable) reading unless it would land before 1960, in
|
||||
* which case the unsigned (post-2038-capable) reading is used instead.
|
||||
* On a platform where time_t is no wider than 32 bits, that unsigned
|
||||
* reading could never be represented anyway, so it's always skipped.
|
||||
* See https://github.com/libarchive/libarchive/issues/3550.
|
||||
*/
|
||||
static time_t
|
||||
to_time_t(uint32_t raw)
|
||||
{
|
||||
const int32_t year_1960_offset = (10 * 365 + 3) * 24 * 60 * 60;
|
||||
const int32_t t = (int32_t)raw;
|
||||
return (sizeof(time_t) <= sizeof(raw) || t >= -year_1960_offset)
|
||||
? (time_t)t : (time_t)raw;
|
||||
}
|
||||
|
||||
/*
|
||||
* The extra data is stored as a list of
|
||||
* id1+size1+data1 + id2+size2+data2 ...
|
||||
@@ -756,12 +787,96 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
||||
* on which file starts, but we don't handle
|
||||
* multi-volume Zip files. */
|
||||
break;
|
||||
case 0x000a:
|
||||
{
|
||||
/* NTFS Extra Field: 4 reserved bytes, then one or
|
||||
* more Tag(2)/Size(2)/Data(Size) attribute blocks.
|
||||
* Only Tag 1 (size 24: Mtime, Atime, Ctime, each an
|
||||
* 8-byte Windows FILETIME) is defined; skip any
|
||||
* other tag, per spec. Unlike every other ZIP
|
||||
* timestamp source, FILETIME has no negative/pre-
|
||||
* epoch ambiguity (it's unsigned ticks since
|
||||
* 1601), and it's 100ns-precision rather than
|
||||
* 1-second, so it also supplies mtime_ns/atime_ns.
|
||||
* "Ctime" here is Windows creation time, not POSIX
|
||||
* ctime, so it maps to btime. */
|
||||
unsigned sub_offset = offset;
|
||||
unsigned sub_remaining = datasize;
|
||||
|
||||
if (sub_remaining < 4)
|
||||
break;
|
||||
sub_offset += 4;
|
||||
sub_remaining -= 4;
|
||||
|
||||
while (sub_remaining >= 4) {
|
||||
unsigned short tag =
|
||||
archive_le16dec(p + sub_offset);
|
||||
unsigned short size =
|
||||
archive_le16dec(p + sub_offset + 2);
|
||||
sub_offset += 4;
|
||||
sub_remaining -= 4;
|
||||
if (size > sub_remaining)
|
||||
break;
|
||||
if (tag == 1 && size == 24) {
|
||||
/* A raw FILETIME of 0 marks a slot
|
||||
* the writer didn't have a value
|
||||
* for (see the matching comment in
|
||||
* archive_write_set_format_zip.c);
|
||||
* treat it as absent rather than
|
||||
* decoding it as 1601-01-01. */
|
||||
uint64_t raw;
|
||||
int64_t secs;
|
||||
uint32_t nsecs;
|
||||
|
||||
raw = archive_le64dec(p + sub_offset);
|
||||
if (raw != 0) {
|
||||
__archive_ntfs_to_unix(raw,
|
||||
&secs, &nsecs);
|
||||
zip_entry->mtime = (time_t)secs;
|
||||
zip_entry->mtime_ns = nsecs;
|
||||
zip_entry->flags |= LA_NTFS_MTIME;
|
||||
zip_entry->flags |= LA_MTIME_FROM_EXTRA;
|
||||
}
|
||||
|
||||
raw = archive_le64dec(p + sub_offset + 8);
|
||||
if (raw != 0) {
|
||||
__archive_ntfs_to_unix(raw,
|
||||
&secs, &nsecs);
|
||||
zip_entry->atime = (time_t)secs;
|
||||
zip_entry->atime_ns = nsecs;
|
||||
zip_entry->flags |= LA_NTFS_ATIME;
|
||||
zip_entry->flags |= LA_ATIME_FROM_EXTRA;
|
||||
}
|
||||
|
||||
raw = archive_le64dec(p + sub_offset + 16);
|
||||
if (raw != 0) {
|
||||
__archive_ntfs_to_unix(raw,
|
||||
&secs, &nsecs);
|
||||
zip_entry->btime = (time_t)secs;
|
||||
zip_entry->btime_ns = nsecs;
|
||||
zip_entry->flags |= LA_NTFS_BTIME;
|
||||
}
|
||||
}
|
||||
sub_offset += size;
|
||||
sub_remaining -= size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x000d:
|
||||
/* PKWARE Unix Extra Field fixed metadata. */
|
||||
if (datasize >= 12) {
|
||||
zip_entry->atime = archive_le32dec(p + offset);
|
||||
zip_entry->mtime =
|
||||
archive_le32dec(p + offset + 4);
|
||||
if (!(zip_entry->flags & LA_NTFS_ATIME)) {
|
||||
zip_entry->atime =
|
||||
to_time_t(archive_le32dec(p + offset));
|
||||
zip_entry->atime_ns = 0;
|
||||
zip_entry->flags |= LA_ATIME_FROM_EXTRA;
|
||||
}
|
||||
if (!(zip_entry->flags & LA_NTFS_MTIME)) {
|
||||
zip_entry->mtime =
|
||||
to_time_t(archive_le32dec(p + offset + 4));
|
||||
zip_entry->mtime_ns = 0;
|
||||
zip_entry->flags |= LA_MTIME_FROM_EXTRA;
|
||||
}
|
||||
zip_entry->uid =
|
||||
archive_le16dec(p + offset + 8);
|
||||
zip_entry->gid =
|
||||
@@ -812,7 +927,12 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
||||
#endif
|
||||
if (datasize < 4)
|
||||
break;
|
||||
zip_entry->mtime = archive_le32dec(p + offset);
|
||||
if (!(zip_entry->flags & LA_NTFS_MTIME)) {
|
||||
zip_entry->mtime =
|
||||
to_time_t(archive_le32dec(p + offset));
|
||||
zip_entry->mtime_ns = 0;
|
||||
zip_entry->flags |= LA_MTIME_FROM_EXTRA;
|
||||
}
|
||||
offset += 4;
|
||||
datasize -= 4;
|
||||
}
|
||||
@@ -820,7 +940,12 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
||||
{
|
||||
if (datasize < 4)
|
||||
break;
|
||||
zip_entry->atime = archive_le32dec(p + offset);
|
||||
if (!(zip_entry->flags & LA_NTFS_ATIME)) {
|
||||
zip_entry->atime =
|
||||
to_time_t(archive_le32dec(p + offset));
|
||||
zip_entry->atime_ns = 0;
|
||||
zip_entry->flags |= LA_ATIME_FROM_EXTRA;
|
||||
}
|
||||
offset += 4;
|
||||
datasize -= 4;
|
||||
}
|
||||
@@ -828,7 +953,9 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
||||
{
|
||||
if (datasize < 4)
|
||||
break;
|
||||
zip_entry->ctime = archive_le32dec(p + offset);
|
||||
zip_entry->ctime =
|
||||
to_time_t(archive_le32dec(p + offset));
|
||||
zip_entry->flags |= LA_CTIME_FROM_EXTRA;
|
||||
offset += 4;
|
||||
datasize -= 4;
|
||||
}
|
||||
@@ -838,9 +965,18 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
||||
{
|
||||
/* Info-ZIP Unix Extra Field (old version) "UX". */
|
||||
if (datasize >= 8) {
|
||||
zip_entry->atime = archive_le32dec(p + offset);
|
||||
zip_entry->mtime =
|
||||
archive_le32dec(p + offset + 4);
|
||||
if (!(zip_entry->flags & LA_NTFS_ATIME)) {
|
||||
zip_entry->atime =
|
||||
to_time_t(archive_le32dec(p + offset));
|
||||
zip_entry->atime_ns = 0;
|
||||
zip_entry->flags |= LA_ATIME_FROM_EXTRA;
|
||||
}
|
||||
if (!(zip_entry->flags & LA_NTFS_MTIME)) {
|
||||
zip_entry->mtime =
|
||||
to_time_t(archive_le32dec(p + offset + 4));
|
||||
zip_entry->mtime_ns = 0;
|
||||
zip_entry->flags |= LA_MTIME_FROM_EXTRA;
|
||||
}
|
||||
}
|
||||
if (datasize >= 12) {
|
||||
zip_entry->uid =
|
||||
@@ -1155,7 +1291,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
}
|
||||
zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
|
||||
zip_entry->compression = (char)archive_le16dec(p + 8);
|
||||
zip_entry->mtime = dos_to_unix(archive_le32dec(p + 10));
|
||||
/* This DOS timestamp carries no information a Central Directory
|
||||
* prescan wouldn't already have, and no sub-second precision:
|
||||
* only use it (and reset mtime_ns to match, since it has none) as
|
||||
* a fallback default, not an unconditional override of a more
|
||||
* precise value the prescan may have already established from an
|
||||
* extra field the Local Header doesn't itself repeat. */
|
||||
if (!(zip_entry->flags & LA_MTIME_FROM_EXTRA)) {
|
||||
zip_entry->mtime = __archive_dos_to_unix(archive_le32dec(p + 10));
|
||||
zip_entry->mtime_ns = 0;
|
||||
}
|
||||
zip_entry->crc32 = archive_le32dec(p + 14);
|
||||
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
|
||||
zip_entry->decdat = p[11];
|
||||
@@ -1350,9 +1495,17 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
archive_entry_set_mode(entry, zip_entry->mode);
|
||||
archive_entry_set_uid(entry, zip_entry->uid);
|
||||
archive_entry_set_gid(entry, zip_entry->gid);
|
||||
archive_entry_set_mtime(entry, zip_entry->mtime, 0);
|
||||
archive_entry_set_ctime(entry, zip_entry->ctime, 0);
|
||||
archive_entry_set_atime(entry, zip_entry->atime, 0);
|
||||
archive_entry_set_mtime(entry, zip_entry->mtime, zip_entry->mtime_ns);
|
||||
/* Without an extra field to supply them, leave atime and ctime
|
||||
* unset, rather than reporting them as set to the Unix epoch. */
|
||||
if (zip_entry->flags & LA_CTIME_FROM_EXTRA)
|
||||
archive_entry_set_ctime(entry, zip_entry->ctime, 0);
|
||||
if (zip_entry->flags & LA_ATIME_FROM_EXTRA)
|
||||
archive_entry_set_atime(entry, zip_entry->atime,
|
||||
zip_entry->atime_ns);
|
||||
if (zip_entry->flags & LA_NTFS_BTIME)
|
||||
archive_entry_set_birthtime(entry, zip_entry->btime,
|
||||
zip_entry->btime_ns);
|
||||
|
||||
if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) {
|
||||
size_t linkname_length;
|
||||
@@ -2347,17 +2500,18 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
|
||||
}
|
||||
}
|
||||
|
||||
if(zip->end_of_entry && zip->entry_bytes_remaining > 0) {
|
||||
ssize_t remaining = (ssize_t)zip->entry_bytes_remaining;
|
||||
const void *p = __archive_read_ahead(a, remaining, NULL);
|
||||
if (p != NULL) {
|
||||
if (zip->hctx_valid)
|
||||
archive_hmac_sha1_update(&zip->hctx,
|
||||
p, remaining);
|
||||
__archive_read_consume(a, remaining);
|
||||
zip->entry_compressed_bytes_read += remaining;
|
||||
zip->entry_bytes_remaining = 0;
|
||||
}
|
||||
while(zip->end_of_entry && zip->entry_bytes_remaining > 0) {
|
||||
const void *p = __archive_read_ahead(a, 1, &bytes_avail);
|
||||
if (p == NULL)
|
||||
break;
|
||||
if (bytes_avail > zip->entry_bytes_remaining)
|
||||
bytes_avail = (ssize_t)zip->entry_bytes_remaining;
|
||||
if (zip->hctx_valid)
|
||||
archive_hmac_sha1_update(&zip->hctx,
|
||||
p, bytes_avail);
|
||||
__archive_read_consume(a, bytes_avail);
|
||||
zip->entry_compressed_bytes_read += bytes_avail;
|
||||
zip->entry_bytes_remaining -= bytes_avail;
|
||||
}
|
||||
|
||||
/* Free lzma decoder handle because we'll no longer need it. */
|
||||
@@ -2615,7 +2769,7 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
|
||||
size_t *size, int64_t *offset)
|
||||
{
|
||||
struct zip *zip = a->format->data;
|
||||
ssize_t bytes_avail = 0, to_consume;
|
||||
ssize_t bytes_avail = 0, max_in, to_consume;
|
||||
const void *compressed_buff;
|
||||
const void *sp;
|
||||
int r;
|
||||
@@ -2649,7 +2803,14 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
|
||||
zip_read_decrypt(zip, compressed_buff, bytes_avail,
|
||||
&compressed_buff, &bytes_avail, &sp);
|
||||
|
||||
/* Setup buffer boundaries. */
|
||||
/* Setup buffer boundaries. bzstream.avail_in is 32 bits wide,
|
||||
* so clamp the available byte count before the assignment. */
|
||||
if (UINT_MAX >= SSIZE_MAX)
|
||||
max_in = SSIZE_MAX;
|
||||
else
|
||||
max_in = UINT_MAX;
|
||||
if (bytes_avail > max_in)
|
||||
bytes_avail = max_in;
|
||||
zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff;
|
||||
zip->bzstream.avail_in = (uint32_t)bytes_avail;
|
||||
zip->bzstream.total_in_hi32 = 0;
|
||||
@@ -2888,7 +3049,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
size_t *size, int64_t *offset)
|
||||
{
|
||||
struct zip *zip = a->format->data;
|
||||
ssize_t bytes_avail, to_consume = 0;
|
||||
ssize_t bytes_avail, max_in, to_consume = 0;
|
||||
const void *compressed_buff;
|
||||
const void *sp;
|
||||
int r;
|
||||
@@ -2931,6 +3092,16 @@ zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||
zip_read_decrypt(zip, compressed_buff, bytes_avail,
|
||||
&compressed_buff, &bytes_avail, &sp);
|
||||
|
||||
/* stream.avail_in is a uInt, which is 32 bits wide even where
|
||||
* ssize_t is 64 bits. Clamp the available byte count so that a
|
||||
* read-ahead window larger than 4 GiB is not truncated. */
|
||||
if (UINT_MAX >= SSIZE_MAX)
|
||||
max_in = SSIZE_MAX;
|
||||
else
|
||||
max_in = UINT_MAX;
|
||||
if (bytes_avail > max_in)
|
||||
bytes_avail = max_in;
|
||||
|
||||
/*
|
||||
* A bug in zlib.h: stream.next_in should be marked 'const'
|
||||
* but isn't (the library never alters data through the
|
||||
@@ -3653,11 +3824,11 @@ archive_read_support_format_zip_capabilities_streamable(struct archive_read * a)
|
||||
static int
|
||||
archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const char *p;
|
||||
const char *h;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, 4, NULL)) == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
@@ -3668,13 +3839,13 @@ archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid)
|
||||
*
|
||||
* So we've effectively verified ~29 total bits of check data.
|
||||
*/
|
||||
if (p[0] == 'P' && p[1] == 'K') {
|
||||
if ((p[2] == '\001' && p[3] == '\002')
|
||||
|| (p[2] == '\003' && p[3] == '\004')
|
||||
|| (p[2] == '\005' && p[3] == '\006')
|
||||
|| (p[2] == '\006' && p[3] == '\006')
|
||||
|| (p[2] == '\007' && p[3] == '\010')
|
||||
|| (p[2] == '0' && p[3] == '0'))
|
||||
if (h[0] == 'P' && h[1] == 'K') {
|
||||
if ((h[2] == '\001' && h[3] == '\002')
|
||||
|| (h[2] == '\003' && h[3] == '\004')
|
||||
|| (h[2] == '\005' && h[3] == '\006')
|
||||
|| (h[2] == '\006' && h[3] == '\006')
|
||||
|| (h[2] == '\007' && h[3] == '\010')
|
||||
|| (h[2] == '0' && h[3] == '0'))
|
||||
return (29);
|
||||
}
|
||||
|
||||
@@ -3881,8 +4052,7 @@ archive_read_support_format_zip_streamable(struct archive *_a)
|
||||
|
||||
zip = calloc(1, sizeof(*zip));
|
||||
if (zip == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate zip data");
|
||||
archive_set_error(_a, ENOMEM, "Can't allocate zip data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -3911,7 +4081,7 @@ archive_read_support_format_zip_streamable(struct archive *_a)
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(zip);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -4027,7 +4197,7 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
struct zip *zip = a->format->data;
|
||||
int64_t file_size, current_offset;
|
||||
const char *p;
|
||||
const char *h;
|
||||
int i, tail;
|
||||
|
||||
/* If someone has already bid more than 32, then avoid
|
||||
@@ -4045,22 +4215,26 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
|
||||
current_offset = __archive_read_seek(a, -tail, SEEK_END);
|
||||
if (current_offset < 0)
|
||||
return 0;
|
||||
if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
|
||||
if ((h = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
|
||||
return 0;
|
||||
/* Boyer-Moore search backwards from the end, since we want
|
||||
* to match the last EOCD in the file (there can be more than
|
||||
* one if there is an uncompressed Zip archive as a member
|
||||
* within this Zip archive). */
|
||||
for (i = tail - 22; i > 0;) {
|
||||
switch (p[i]) {
|
||||
* within this Zip archive).
|
||||
*
|
||||
* The lower bound is inclusive (>= 0, not > 0): a minimal,
|
||||
* valid, zero-entry archive is exactly 22 bytes long, putting
|
||||
* the EOCD signature at index 0 of this search window. */
|
||||
for (i = tail - 22; i >= 0;) {
|
||||
switch (h[i]) {
|
||||
case 'P':
|
||||
if (memcmp(p + i, "PK\005\006", 4) == 0) {
|
||||
int ret = read_eocd(zip, p + i,
|
||||
if (memcmp(h + i, "PK\005\006", 4) == 0) {
|
||||
int ret = read_eocd(zip, h + i,
|
||||
current_offset + i);
|
||||
/* Zip64 EOCD locator precedes
|
||||
* regular EOCD if present. */
|
||||
if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
|
||||
int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
|
||||
if (i >= 20 && memcmp(h + i - 20, "PK\006\007", 4) == 0) {
|
||||
int ret_zip64 = read_zip64_eocd(a, zip, h + i - 20);
|
||||
if (ret_zip64 > ret)
|
||||
ret = ret_zip64;
|
||||
}
|
||||
@@ -4269,7 +4443,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
|
||||
zip->has_encrypted_entries = 1;
|
||||
}
|
||||
zip_entry->compression = (char)archive_le16dec(p + 10);
|
||||
zip_entry->mtime = dos_to_unix(archive_le32dec(p + 12));
|
||||
zip_entry->mtime = __archive_dos_to_unix(archive_le32dec(p + 12));
|
||||
zip_entry->crc32 = archive_le32dec(p + 16);
|
||||
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
|
||||
zip_entry->decdat = p[13];
|
||||
@@ -4704,7 +4878,7 @@ archive_read_support_format_zip_seekable(struct archive *_a)
|
||||
|
||||
if (r != ARCHIVE_OK)
|
||||
free(zip);
|
||||
return (ARCHIVE_OK);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*# vim:set noet:*/
|
||||
+44
-19
@@ -62,6 +62,7 @@
|
||||
#endif
|
||||
|
||||
#include "archive_endian.h"
|
||||
#include "archive_integer.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_string_composition.h"
|
||||
@@ -318,9 +319,8 @@ archive_string_ensure(struct archive_string *as, size_t s)
|
||||
new_length = as->buffer_length + as->buffer_length;
|
||||
else {
|
||||
/* Buffers 8k and over grow by at least 25% each time. */
|
||||
new_length = as->buffer_length + as->buffer_length / 4;
|
||||
/* Be safe: If size wraps, fail. */
|
||||
if (new_length < as->buffer_length) {
|
||||
if (archive_ckd_add_size(&new_length,
|
||||
as->buffer_length, as->buffer_length / 4)) {
|
||||
/* On failure, wipe the string and return NULL. */
|
||||
archive_string_free(as);
|
||||
errno = ENOMEM;/* Make sure errno has ENOMEM. */
|
||||
@@ -445,7 +445,7 @@ static const char *
|
||||
default_iconv_charset(const char *charset) {
|
||||
if (charset != NULL && charset[0] != '\0')
|
||||
return charset;
|
||||
#if HAVE_LOCALE_CHARSET && !defined(__APPLE__)
|
||||
#if HAVE_LOCALE_CHARSET && HAVE_LOCALCHARSET_H && !defined(__APPLE__)
|
||||
/* locale_charset() is broken on Mac OS */
|
||||
return locale_charset();
|
||||
#elif HAVE_NL_LANGINFO
|
||||
@@ -785,6 +785,10 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
r = WideCharToMultiByte(to_cp, 0, ws, (int)wslen,
|
||||
as->s + as->length,
|
||||
(int)(as->buffer_length - as->length - 1), NULL, dp);
|
||||
if (r == 0 && wslen == 0) {
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
if (r == 0 &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
/* Expand the MBS buffer and retry. */
|
||||
@@ -1316,17 +1320,7 @@ create_sconv_object(const char *fc, const char *tc,
|
||||
else if (strcmp(fc, "CP932") == 0)
|
||||
sc->cd = iconv_open(tc, "SJIS");
|
||||
}
|
||||
#if defined(__FreeBSD__) && !defined(HAVE_LIBICONV)
|
||||
/*
|
||||
* FreeBSD's native iconv() by default returns the number of
|
||||
* invalid characters in the input string, as specified by
|
||||
* POSIX, but iconv_strncat_in_locale() assumes GNU iconv
|
||||
* semantics.
|
||||
*/
|
||||
int v = 1;
|
||||
|
||||
(void)iconvctl(sc->cd, ICONV_SET_ILSEQ_INVALID, &v);
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/*
|
||||
* archive_mstring on Windows directly convert multi-bytes
|
||||
* into archive_wstring in order not to depend on locale
|
||||
@@ -1593,9 +1587,15 @@ static struct {
|
||||
unsigned ocp;
|
||||
const char *locale;
|
||||
} acp_ocp_map[] = {
|
||||
{ 950, 950, "Chinese_Taiwan" },
|
||||
{ 950, 950, "Chinese_Hong Kong S.A.R." },
|
||||
{ 950, 950, "Chinese_Macau S.A.R." },
|
||||
{ 936, 936, "Chinese_People's Republic of China" },
|
||||
{ 936, 936, "Chinese (Simplified)_China" },
|
||||
{ 936, 936, "Chinese (Simplified)_People's Republic of China" },
|
||||
{ 950, 950, "Chinese_Taiwan" },
|
||||
{ 950, 950, "Chinese (Traditional)_Hong Kong SAR" },
|
||||
{ 950, 950, "Chinese (Traditional)_Macau SAR" },
|
||||
{ 950, 950, "Chinese (Traditional)_Taiwan" },
|
||||
{ 1250, 852, "Czech_Czech Republic" },
|
||||
{ 1252, 850, "Danish_Denmark" },
|
||||
{ 1252, 850, "Dutch_Netherlands" },
|
||||
@@ -1621,14 +1621,20 @@ static struct {
|
||||
{ 1252, 850, "Italian_Switzerland" },
|
||||
{ 932, 932, "Japanese_Japan" },
|
||||
{ 949, 949, "Korean_Korea" },
|
||||
{ 949, 949, "Korean_South Korea" },
|
||||
{ 949, 949, "Korean (Unified)_Korea" },
|
||||
{ 1252, 850, "Norwegian (Bokmål)_Norway" },
|
||||
{ 1252, 850, "Norwegian (BokmOl)_Norway" },
|
||||
{ 1252, 850, "Norwegian (BokmOl)_Norway" },
|
||||
{ 1252, 850, "Norwegian (Nynorsk)_Norway" },
|
||||
{ 1252, 850, "Norwegian-Nynorsk_Norway" },
|
||||
{ 1250, 852, "Polish_Poland" },
|
||||
{ 1252, 850, "Portuguese_Portugal" },
|
||||
{ 1252, 850, "Portuguese_Brazil" },
|
||||
{ 1252, 850, "Portuguese_Portugal" },
|
||||
{ 1252, 850, "Portuguese (Brazil)_Brazil" },
|
||||
{ 1252, 850, "Portuguese (Portugal)_Portugal" },
|
||||
{ 1251, 866, "Russian_Russia" },
|
||||
{ 1250, 852, "Slovak_Slovakia" },
|
||||
{ 1250, 852, "Slovak_Slovak Republic" },
|
||||
{ 1252, 850, "Spanish_Spain" },
|
||||
{ 1252, 850, "Spanish_Mexico" },
|
||||
{ 1252, 850, "Spanish_Spain" },
|
||||
@@ -2126,8 +2132,16 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
while (remaining >= from_size) {
|
||||
size_t result = iconv(cd, &itp, &remaining, &outp, &avail);
|
||||
|
||||
if (result != (size_t)-1)
|
||||
if (result == 0)
|
||||
break; /* Conversion completed. */
|
||||
if (result != (size_t)-1) {
|
||||
/*
|
||||
* Conversion did not fail, but it performed
|
||||
* some non-identical character substitutions.
|
||||
*/
|
||||
return_value = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno == EILSEQ || errno == EINVAL) {
|
||||
/*
|
||||
@@ -2163,6 +2177,17 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p,
|
||||
avail -= rbytes;
|
||||
} else {
|
||||
/* Skip the illegal input bytes. */
|
||||
if (avail < 1) {
|
||||
as->length = outp - as->s;
|
||||
bs = as->buffer_length +
|
||||
(remaining * to_size) + 1;
|
||||
if (NULL ==
|
||||
archive_string_ensure(as, bs))
|
||||
return (-1);
|
||||
outp = as->s + as->length;
|
||||
avail = as->buffer_length
|
||||
- as->length - to_size;
|
||||
}
|
||||
*outp++ = '?';
|
||||
avail--;
|
||||
}
|
||||
|
||||
@@ -50,11 +50,15 @@
|
||||
* them to an archive_string.
|
||||
*/
|
||||
static void
|
||||
append_uint(struct archive_string *as, uintmax_t d, unsigned base)
|
||||
append_uint(struct archive_string *as, uintmax_t d, unsigned base,
|
||||
int upper)
|
||||
{
|
||||
static const char digits[] = "0123456789abcdef";
|
||||
static const char digits_lower[] = "0123456789abcdef";
|
||||
static const char digits_upper[] = "0123456789ABCDEF";
|
||||
const char *digits = upper ? digits_upper : digits_lower;
|
||||
|
||||
if (d >= base)
|
||||
append_uint(as, d/base, base);
|
||||
append_uint(as, d/base, base, upper);
|
||||
archive_strappend_char(as, digits[d % base]);
|
||||
}
|
||||
|
||||
@@ -68,7 +72,7 @@ append_int(struct archive_string *as, intmax_t d, unsigned base)
|
||||
ud = (d == INTMAX_MIN) ? (uintmax_t)(INTMAX_MAX) + 1 : (uintmax_t)(-d);
|
||||
} else
|
||||
ud = d;
|
||||
append_uint(as, ud, base);
|
||||
append_uint(as, ud, base, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -186,9 +190,10 @@ archive_string_vsprintf(struct archive_string *as, const char *fmt,
|
||||
}
|
||||
/* Format it in the correct base. */
|
||||
switch (*p) {
|
||||
case 'o': append_uint(as, u, 8); break;
|
||||
case 'u': append_uint(as, u, 10); break;
|
||||
default: append_uint(as, u, 16); break;
|
||||
case 'o': append_uint(as, u, 8, 0); break;
|
||||
case 'u': append_uint(as, u, 10, 0); break;
|
||||
case 'x': append_uint(as, u, 16, 0); break;
|
||||
case 'X': append_uint(as, u, 16, 1); break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#include <winnt.h>
|
||||
/* Windows FILETIME to NTFS time. */
|
||||
uint64_t
|
||||
FILETIME_to_ntfs(const FILETIME* filetime)
|
||||
__archive_FILETIME_to_ntfs(const FILETIME* filetime)
|
||||
{
|
||||
ULARGE_INTEGER utc;
|
||||
utc.HighPart = filetime->dwHighDateTime;
|
||||
@@ -60,7 +60,7 @@ FILETIME_to_ntfs(const FILETIME* filetime)
|
||||
|
||||
/* Convert an MSDOS-style date/time into Unix-style time. */
|
||||
int64_t
|
||||
dos_to_unix(uint32_t dos_time)
|
||||
__archive_dos_to_unix(uint32_t dos_time)
|
||||
{
|
||||
uint16_t msTime, msDate;
|
||||
struct tm ts;
|
||||
@@ -83,7 +83,7 @@ dos_to_unix(uint32_t dos_time)
|
||||
|
||||
/* Convert into MSDOS-style date/time. */
|
||||
uint32_t
|
||||
unix_to_dos(int64_t unix_time)
|
||||
__archive_unix_to_dos(int64_t unix_time)
|
||||
{
|
||||
struct tm *t;
|
||||
uint32_t dt;
|
||||
@@ -132,7 +132,7 @@ unix_to_dos(int64_t unix_time)
|
||||
|
||||
/* Convert NTFS time to Unix sec/nsec */
|
||||
void
|
||||
ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
|
||||
__archive_ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
|
||||
{
|
||||
if (ntfs > INT64_MAX) {
|
||||
ntfs -= NTFS_EPOC_TICKS;
|
||||
@@ -143,7 +143,17 @@ ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
|
||||
lldiv_t tdiv;
|
||||
int64_t value = (int64_t)ntfs - (int64_t)NTFS_EPOC_TICKS;
|
||||
|
||||
/* lldiv() truncates toward zero, not toward -infinity, so
|
||||
* for a negative |value| that isn't an exact multiple of
|
||||
* NTFS_TICKS, tdiv.rem would itself come out negative here.
|
||||
* Adjust to floor division so *nsecs always ends up
|
||||
* non-negative, with the sign folded entirely into *secs,
|
||||
* as callers (e.g. struct timespec) expect. */
|
||||
tdiv = lldiv(value, NTFS_TICKS);
|
||||
if (tdiv.rem < 0) {
|
||||
tdiv.quot -= 1;
|
||||
tdiv.rem += NTFS_TICKS;
|
||||
}
|
||||
*secs = tdiv.quot;
|
||||
*nsecs = (uint32_t)(tdiv.rem * 100);
|
||||
}
|
||||
@@ -151,7 +161,7 @@ ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
|
||||
|
||||
/* Convert Unix sec/nsec to NTFS time */
|
||||
uint64_t
|
||||
unix_to_ntfs(int64_t secs, uint32_t nsecs)
|
||||
__archive_unix_to_ntfs(int64_t secs, uint32_t nsecs)
|
||||
{
|
||||
uint64_t ntfs;
|
||||
|
||||
|
||||
Loaded 100 of 317 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user