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:
Martin Matuska committed 2026-10-26 14:25:48 +01:00
1 parent 6d46c752af
commit a8dfdb79eb
317 files changed
+14996 -3465

No files matched your search

+82 -22
View File
@@ -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' }}
+1 -1
View File
@@ -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
+3 -3
View File
@@ -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 }}"
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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 \
+2
View File
@@ -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
+84
View File
@@ -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
View File
@@ -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}"
+10 -9
View File
@@ -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
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
3008009
3008010
+320 -280
View File
@@ -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])
+1
View File
@@ -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 \
+3
View File
@@ -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 */
+35 -36
View File
@@ -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"
+16 -10
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}
-1
View File
@@ -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
View File
@@ -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");
+9 -1
View File
@@ -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");
}
+2 -38
View File
@@ -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 */
+7
View File
@@ -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");
}
+4 -1
View File
@@ -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
+6 -4
View File
@@ -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);
+13
View File
@@ -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__)
+1
View File
@@ -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");
+192
View File
@@ -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
+2 -15
View File
@@ -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)
+1 -11
View File
@@ -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
View File
@@ -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);
}
+14 -2
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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
+10 -10
View File
@@ -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
+3 -3
View File
@@ -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);
+4 -4
View File
@@ -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.
+29 -29
View File
@@ -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 */
+1 -1
View File
@@ -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.
+7 -7
View File
@@ -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.
+1 -15
View File
@@ -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
+1 -11
View File
@@ -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 {
+3 -2
View File
@@ -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);
}
+2 -3
View File
@@ -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;
+1 -2
View File
@@ -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) | \
+11 -7
View File
@@ -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
+6 -2
View File
@@ -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__))
+5 -5
View File
@@ -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
*/
+1 -1
View File
@@ -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
View File
@@ -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;
}
+2 -2
View File
@@ -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.
+22 -51
View File
@@ -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;
+15
View File
@@ -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
+1 -1
View File
@@ -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;
+16 -12
View File
@@ -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);
+12 -3
View File
@@ -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__) */
+3 -3
View File
@@ -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));
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
+4 -1
View File
@@ -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));
}
+4 -1
View File
@@ -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));
}
+11 -11
View File
@@ -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);
}
-7
View File
@@ -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 *);
+1 -1
View File
@@ -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
+4 -8
View File
@@ -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
+1 -1
View File
@@ -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);
}
+186 -324
View File
@@ -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);
+3 -3
View File
@@ -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);
+6 -10
View File
@@ -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);
}
+556 -132
View File
@@ -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.
*
+50 -38
View File
@@ -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. */
+68 -31
View File
@@ -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);
}
+10 -13
View File
@@ -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);
+77 -54
View File
@@ -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;
+27 -23
View File
@@ -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);
}
+59 -50
View File
@@ -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];
+339 -150
View File
@@ -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;
}
+10 -3
View File
@@ -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);
+142 -32
View File
@@ -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");
+61 -90
View File
@@ -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) {
+41 -37
View File
@@ -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 */
+230 -56
View File
@@ -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
View File
@@ -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--;
}
+12 -7
View File
@@ -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:
+15 -5
View File
@@ -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