summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2020-02-11 23:48:03 +0000
committerMartin Matuska <mm@FreeBSD.org>2020-02-11 23:48:03 +0000
commit8185c4ae244f9a52ad987b36e7d6300500054d00 (patch)
tree11e2d7cd0caf20998ed1e1146e1c1d7fc747165e
parent98c1f51f769841d99d879099f9075ff60d51ee4a (diff)
Notes
-rw-r--r--.github/workflows/ci.yml26
-rw-r--r--CMakeLists.txt13
-rw-r--r--Makefile.am5
-rw-r--r--NEWS8
-rwxr-xr-xbuild/ci/build.sh7
-rwxr-xr-xbuild/ci/github_actions/ci.cmd65
-rw-r--r--build/cmake/config.h.in3
-rw-r--r--build/release/Dockerfile11
-rwxr-xr-xbuild/release/release.sh8
-rw-r--r--build/version2
-rw-r--r--cat/bsdcat.h5
-rw-r--r--cat/test/test_0.c2
-rw-r--r--configure.ac4
-rw-r--r--contrib/archivetest.c16
-rw-r--r--cpio/cpio.c22
-rw-r--r--cpio/test/test_basic.c14
-rw-r--r--cpio/test/test_format_newc.c15
-rw-r--r--libarchive/CMakeLists.txt1
-rw-r--r--libarchive/archive.h4
-rw-r--r--libarchive/archive_acl_private.h6
-rw-r--r--libarchive/archive_blake2.h5
-rw-r--r--libarchive/archive_blake2_impl.h5
-rw-r--r--libarchive/archive_cmdline_private.h6
-rw-r--r--libarchive/archive_crc32.h5
-rw-r--r--libarchive/archive_cryptor_private.h7
-rw-r--r--libarchive/archive_digest_private.h7
-rw-r--r--libarchive/archive_endian.h11
-rw-r--r--libarchive/archive_entry.c10
-rw-r--r--libarchive/archive_entry_locale.h6
-rw-r--r--libarchive/archive_entry_private.h6
-rw-r--r--libarchive/archive_getdate.c149
-rw-r--r--libarchive/archive_getdate.h6
-rw-r--r--libarchive/archive_hmac_private.h7
-rw-r--r--libarchive/archive_openssl_evp_private.h5
-rw-r--r--libarchive/archive_openssl_hmac_private.h5
-rw-r--r--libarchive/archive_options_private.h4
-rw-r--r--libarchive/archive_pack_dev.c9
-rw-r--r--libarchive/archive_pack_dev.h6
-rw-r--r--libarchive/archive_pathmatch.h6
-rw-r--r--libarchive/archive_platform_acl.h6
-rw-r--r--libarchive/archive_platform_xattr.h6
-rw-r--r--libarchive/archive_ppmd7.c2
-rw-r--r--libarchive/archive_ppmd7_private.h6
-rw-r--r--libarchive/archive_ppmd8_private.h4
-rw-r--r--libarchive/archive_ppmd_private.h6
-rw-r--r--libarchive/archive_private.h11
-rw-r--r--libarchive/archive_random_private.h6
-rw-r--r--libarchive/archive_rb.h21
-rw-r--r--libarchive/archive_read.c2
-rw-r--r--libarchive/archive_read_disk_posix.c37
-rw-r--r--libarchive/archive_read_disk_private.h6
-rw-r--r--libarchive/archive_read_private.h6
-rw-r--r--libarchive/archive_read_set_options.334
-rw-r--r--libarchive/archive_read_support_filter_uu.c30
-rw-r--r--libarchive/archive_read_support_format_7zip.c9
-rw-r--r--libarchive/archive_read_support_format_lha.c35
-rw-r--r--libarchive/archive_read_support_format_mtree.c1
-rw-r--r--libarchive/archive_read_support_format_rar.c69
-rw-r--r--libarchive/archive_read_support_format_rar5.c238
-rw-r--r--libarchive/archive_read_support_format_warc.c3
-rw-r--r--libarchive/archive_read_support_format_xar.c17
-rw-r--r--libarchive/archive_string.c3
-rw-r--r--libarchive/archive_string.h6
-rw-r--r--libarchive/archive_string_composition.h6
-rw-r--r--libarchive/archive_util.c230
-rw-r--r--libarchive/archive_windows.h8
-rw-r--r--libarchive/archive_write_disk.37
-rw-r--r--libarchive/archive_write_disk_posix.c78
-rw-r--r--libarchive/archive_write_disk_private.h6
-rw-r--r--libarchive/archive_write_disk_windows.c110
-rw-r--r--libarchive/archive_write_private.h6
-rw-r--r--libarchive/archive_write_set_format.c45
-rw-r--r--libarchive/archive_write_set_format_7zip.c3
-rw-r--r--libarchive/archive_write_set_format_ar.c1
-rw-r--r--libarchive/archive_write_set_format_cpio.c1
-rw-r--r--libarchive/archive_write_set_format_cpio_newc.c1
-rw-r--r--libarchive/archive_write_set_format_gnutar.c15
-rw-r--r--libarchive/archive_write_set_format_iso9660.c22
-rw-r--r--libarchive/archive_write_set_format_pax.c100
-rw-r--r--libarchive/archive_write_set_format_private.h42
-rw-r--r--libarchive/archive_write_set_format_shar.c5
-rw-r--r--libarchive/archive_write_set_format_ustar.c30
-rw-r--r--libarchive/archive_write_set_format_v7tar.c29
-rw-r--r--libarchive/archive_write_set_format_warc.c18
-rw-r--r--libarchive/archive_write_set_format_xar.c65
-rw-r--r--libarchive/archive_write_set_format_zip.c23
-rw-r--r--libarchive/archive_write_set_options.3237
-rw-r--r--libarchive/archive_xxhash.h5
-rw-r--r--libarchive/filter_fork.h6
-rw-r--r--libarchive/test/test_archive_write_set_format_filter_by_ext.c2
-rw-r--r--libarchive/test/test_compat_zip.c10
-rw-r--r--libarchive/test/test_fuzz.c3
-rw-r--r--libarchive/test/test_read_extract.c2
-rw-r--r--libarchive/test/test_read_format_7zip.c19
-rw-r--r--libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu407
-rw-r--r--libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu407
-rw-r--r--libarchive/test/test_read_format_7zip_packinfo_digests.c76
-rw-r--r--libarchive/test/test_read_format_gtar_sparse.c5
-rw-r--r--libarchive/test/test_read_format_rar5.c15
-rw-r--r--libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu8
-rw-r--r--libarchive/test/test_read_format_zip.c8
-rw-r--r--libarchive/test/test_read_format_zip_7075_utf8_paths.c2
-rw-r--r--libarchive/test/test_read_format_zip_comment_stored.c2
-rw-r--r--libarchive/test/test_read_format_zip_extra_padding.c2
-rw-r--r--libarchive/test/test_read_format_zip_high_compression.c2
-rw-r--r--libarchive/test/test_read_format_zip_jar.c2
-rw-r--r--libarchive/test/test_read_format_zip_mac_metadata.c2
-rw-r--r--libarchive/test/test_read_format_zip_malformed.c2
-rw-r--r--libarchive/test/test_read_format_zip_msdos.c2
-rw-r--r--libarchive/test/test_read_format_zip_nested.c2
-rw-r--r--libarchive/test/test_read_format_zip_nofiletype.c2
-rw-r--r--libarchive/test/test_read_format_zip_padded.c2
-rw-r--r--libarchive/test/test_read_format_zip_sfx.c2
-rw-r--r--libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c2
-rw-r--r--libarchive/test/test_read_format_zip_zip64.c4
-rw-r--r--libarchive/test/test_read_pax_truncated.c6
-rw-r--r--libarchive/test/test_read_truncated_filter.c4
-rw-r--r--libarchive/test/test_sparse_basic.c6
-rw-r--r--libarchive/test/test_write_disk.c2
-rw-r--r--libarchive/test/test_write_format_cpio_empty.c2
-rw-r--r--libarchive/test/test_write_format_pax.c46
-rw-r--r--libarchive/test/test_write_format_shar_empty.c2
-rw-r--r--libarchive/test/test_write_format_tar.c2
-rw-r--r--libarchive/test/test_write_format_tar_sparse.c4
-rw-r--r--libarchive/test/test_write_format_xar.c3
-rw-r--r--libarchive/test/test_write_format_zip_file.c2
-rw-r--r--libarchive/test/test_write_format_zip_file_zip64.c2
-rw-r--r--libarchive_fe/err.h9
-rw-r--r--tar/bsdtar.149
-rw-r--r--tar/bsdtar.c6
-rw-r--r--tar/bsdtar.h7
-rw-r--r--tar/cmdline.c2
-rw-r--r--tar/test/CMakeLists.txt1
-rw-r--r--tar/test/test_basic.c2
-rw-r--r--tar/test/test_copy.c4
-rw-r--r--tar/test/test_option_C_upper.c2
-rw-r--r--tar/test/test_option_s.c6
-rw-r--r--tar/test/test_option_safe_writes.c77
-rw-r--r--tar/util.c22
-rw-r--r--test_utils/test_common.h28
-rw-r--r--test_utils/test_main.c42
141 files changed, 2767 insertions, 728 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 510cb9c29155a..2ffa282479b56 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -33,6 +33,14 @@ jobs:
run: ./build/ci/build.sh -a install
env:
BS: ${{ matrix.bs }}
+ - name: Artifact
+ run: ./build/ci/build.sh -a artifact
+ env:
+ BS: ${{ matrix.bs }}
+ - uses: actions/upload-artifact@v1
+ with:
+ name: libarchive-macos-${{ matrix.bs }}-${{ github.sha }}
+ path: libarchive.tar.xz
Ubuntu:
runs-on: ubuntu-latest
@@ -66,7 +74,14 @@ jobs:
run: ./build/ci/build.sh -a install
env:
BS: ${{ matrix.bs }}
-
+ - name: Artifact
+ run: ./build/ci/build.sh -a artifact
+ env:
+ BS: ${{ matrix.bs }}
+ - uses: actions/upload-artifact@v1
+ with:
+ name: libarchive-ubuntu-${{ matrix.bs }}-${{ matrix.crypto }}-${{ github.sha }}
+ path: libarchive.tar.xz
Ubuntu-distcheck:
runs-on: ubuntu-latest
steps:
@@ -114,3 +129,12 @@ jobs:
shell: cmd
env:
BE: ${{ matrix.be }}
+ - name: Artifact
+ run: ./build/ci/github_actions/ci.cmd artifact
+ shell: cmd
+ env:
+ BE: ${{ matrix.be }}
+ - uses: actions/upload-artifact@v1
+ with:
+ name: libarchive-windows-${{ matrix.be }}-${{ github.sha }}
+ path: libarchive.zip
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 51c4c00d3569b..5a9b325044390 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,7 @@ endif()
# RelWithDebInfo : Release build with Debug Info
# MinSizeRel : Release Min Size build
IF(NOT CMAKE_BUILD_TYPE)
- SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
+ SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
# value type is "UNINITIALIZED".
@@ -155,9 +155,9 @@ IF (MSVC)
#################################################################
# Set compile flags for debug build.
# This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug"
- # Enable level 4 C4061: The enumerate has no associated handler in a switch
- # statement.
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4061")
+ # Enable level 4 C4062: The enumerate has no associated handler in a switch
+ # statement and there is no default that can catch it.
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4062")
# Enable level 4 C4254: A larger bit field was assigned to a smaller bit
# field.
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /we4254")
@@ -287,6 +287,10 @@ IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$")
ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t
ENDIF()
+IF(MINGW)
+ ADD_DEFINITIONS(-D__USE_MINGW_ANSI_STDIO)
+ENDIF()
+
#
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckCSourceRuns)
@@ -1392,6 +1396,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB)
CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S)
CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64)
CHECK_FUNCTION_EXISTS_GLIBC(_get_timezone HAVE__GET_TIMEZONE)
+CHECK_FUNCTION_EXISTS_GLIBC(_gmtime64_s HAVE__GMTIME64_S)
CHECK_FUNCTION_EXISTS_GLIBC(_localtime64_s HAVE__LOCALTIME64_S)
CHECK_FUNCTION_EXISTS_GLIBC(_mkgmtime64 HAVE__MKGMTIME64)
diff --git a/Makefile.am b/Makefile.am
index 781bbf726c2de..41b2808e9f7d0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -228,6 +228,7 @@ libarchive_la_SOURCES= \
libarchive/archive_write_set_format_iso9660.c \
libarchive/archive_write_set_format_mtree.c \
libarchive/archive_write_set_format_pax.c \
+ libarchive/archive_write_set_format_private.h \
libarchive/archive_write_set_format_raw.c \
libarchive/archive_write_set_format_shar.c \
libarchive/archive_write_set_format_ustar.c \
@@ -751,7 +752,9 @@ 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_delta_lzma1.7z.uu \
+ libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu \
libarchive/test/test_read_format_7zip_delta_lzma2.7z.uu \
+ libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu \
libarchive/test/test_read_format_7zip_empty_archive.7z.uu \
libarchive/test/test_read_format_7zip_empty_file.7z.uu \
libarchive/test/test_read_format_7zip_encryption.7z.uu \
@@ -876,6 +879,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_rar5_win32.rar.uu \
libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \
libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \
+ libarchive/test/test_read_format_rar5_block_size_is_too_small.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 \
@@ -1081,6 +1085,7 @@ bsdtar_test_SOURCES= \
tar/test/test_option_q.c \
tar/test/test_option_r.c \
tar/test/test_option_s.c \
+ tar/test/test_option_safe_writes.c \
tar/test/test_option_uid_uname.c \
tar/test/test_option_uuencode.c \
tar/test/test_option_xattrs.c \
diff --git a/NEWS b/NEWS
index deffabca0f7d4..15360f5d9d00a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Feb 11, 2020: libarchive 3.4.2 released
+
+Jan 23, 2020: Important fixes for writing XAR archives
+
+Jan 20, 2020: New tar option: --safe-writes (atomical file extraction)
+
+Jan 03, 2020: Support mbed TLS (PolarSSL) as optional crypto provider
+
Dec 30, 2019: libarchive 3.4.1 released
Dec 11, 2019: New pax write option "xattrhdr"
diff --git a/build/ci/build.sh b/build/ci/build.sh
index 97d570b5e0160..0e0c2fbab0cf2 100755
--- a/build/ci/build.sh
+++ b/build/ci/build.sh
@@ -42,6 +42,7 @@ while getopts a:b:c:d:s: opt; do
test) ;;
install) ;;
distcheck) ;;
+ artifact) ;;
*) inputerror "Invalid action (-a)" ;;
esac
ACTIONS="${ACTIONS} ${OPTARG}"
@@ -147,12 +148,16 @@ for action in ${ACTIONS}; do
install)
${MAKE} ${MAKE_ARGS} install DESTDIR="${BUILDDIR}/destdir"
RET="$?"
- cd ${BUILDDIR}/destdir && ls -lR .
+ cd "${BUILDDIR}/destdir" && ls -lR .
;;
distcheck)
${MAKE} ${MAKE_ARGS} distcheck
RET="$?"
;;
+ artifact)
+ tar -c -J -C "${BUILDDIR}/destdir" -f "${CURDIR}/libarchive.tar.xz" usr
+ ls -l "${CURDIR}/libarchive.tar.xz"
+ ;;
esac
if [ "${RET}" != "0" ]; then
exit "${RET}"
diff --git a/build/ci/github_actions/ci.cmd b/build/ci/github_actions/ci.cmd
index 30626d5c2a407..954d515c3b42b 100755
--- a/build/ci/github_actions/ci.cmd
+++ b/build/ci/github_actions/ci.cmd
@@ -1,5 +1,6 @@
@ECHO OFF
SET ZLIB_VERSION=1.2.11
+SET BZIP2_VERSION=b7a672291188a6469f71dd13ad14f2f9a7344fc8
IF NOT "%BE%"=="mingw-gcc" (
IF NOT "%BE%"=="msvc" (
ECHO Environment variable BE must be mingw-gcc or msvc
@@ -7,20 +8,31 @@ IF NOT "%BE%"=="mingw-gcc" (
)
)
+SET ORIGPATH=%PATH%
+IF "%BE%"=="mingw-gcc" (
+ SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
+)
+
IF "%1"=="deplibs" (
IF NOT EXIST build_ci\libs (
MKDIR build_ci\libs
)
CD build_ci\libs
- IF NOT EXIST zlib-%ZLIB_VERSION%.tar.gz (
- curl -o zlib-%ZLIB_VERSION%.tar.gz https://www.zlib.net/zlib-%ZLIB_VERSION%.tar.gz
+ IF NOT EXIST zlib-%ZLIB_VERSION%.zip (
+ curl -L -o zlib-%ZLIB_VERSION%.zip https://github.com/libarchive/zlib/archive/v%ZLIB_VERSION%.zip
)
IF NOT EXIST zlib-%ZLIB_VERSION% (
- tar -x -z -f zlib-%ZLIB_VERSION%.tar.gz
+ tar -x -f zlib-%ZLIB_VERSION%.zip
+ )
+ IF NOT EXIST bzip2-%BZIP2_VERSION%.zip (
+ curl -L -o bzip2-%BZIP2_VERSION%.zip https://github.com/libarchive/bzip2/archive/%BZIP2_VERSION%.zip
+ )
+ IF NOT EXIST bzip2-%BZIP2_VERSION% (
+ tar -x -f bzip2-%BZIP2_VERSION%.zip
)
CD zlib-%ZLIB_VERSION%
IF "%BE%"=="mingw-gcc" (
- SET PATH=C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
+ SET PATH=%MINGWPATH%
cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
mingw32-make || EXIT /b 1
mingw32-make test || EXIT /b 1
@@ -31,49 +43,66 @@ IF "%1"=="deplibs" (
cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
cmake --build . --target INSTALL --config Release || EXIT /b 1
)
+ CD ..
+ CD bzip2-%BZIP2_VERSION%
+ IF "%BE%"=="mingw-gcc" (
+ SET PATH=%MINGWPATH%
+ cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1
+ mingw32-make || EXIT /b 1
+ REM mingw32-make test || EXIT /b 1
+ mingw32-make install || EXIT /b 1
+ ) ELSE IF "%BE%"=="msvc" (
+ cmake -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1
+ cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
+ REM cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
+ cmake --build . --target INSTALL --config Release || EXIT /b 1
+ )
+ CD ..
) ELSE IF "%1%"=="configure" (
IF "%BE%"=="mingw-gcc" (
- SET PATH=C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
+ SET PATH=%MINGWPATH%
MKDIR build_ci\cmake
CD build_ci\cmake
- cmake -G "MinGW Makefiles" ..\.. || EXIT /b 1
+ cmake -G "MinGW Makefiles" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/libzlibstatic.a" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/libbz2.a" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" ..\.. || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
MKDIR build_ci\cmake
CD build_ci\cmake
- cmake -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE="Release" ..\.. || EXIT /b 1
+ cmake -G "Visual Studio 16 2019" -D CMAKE_BUILD_TYPE="Release" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/zlibstatic.lib" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/bz2.lib" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" ..\.. || EXIT /b 1
)
) ELSE IF "%1%"=="build" (
IF "%BE%"=="mingw-gcc" (
- SET PATH=C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
+ SET PATH=%MINGWPATH%
CD build_ci\cmake
- mingw32-make || EXIT /b 1
+ mingw32-make VERBOSE=1 || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
CD build_ci\cmake
- cmake --build . --target ALL_BUILD --config Release
+ cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
)
) ELSE IF "%1%"=="test" (
IF "%BE%"=="mingw-gcc" (
- SET PATH=C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
- COPY "C:\Program Files (x86)\zlib\bin\libzlib.dll" build_ci\cmake\bin\
+ SET PATH=%MINGWPATH%
CD build_ci\cmake
SET SKIP_TEST_SPARSE=1
- mingw32-make test
+ mingw32-make test VERBOSE=1 || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
ECHO "Skipping tests on this platform"
EXIT /b 0
REM CD build_ci\cmake
- REM cmake --build . --target RUN_TESTS --config Release
+ REM cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
)
) ELSE IF "%1%"=="install" (
IF "%BE%"=="mingw-gcc" (
- SET PATH=C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
+ SET PATH=%MINGWPATH%
CD build_ci\cmake
- mingw32-make install DESTDIR=%cd%\destdir
+ mingw32-make install || EXIT /b 1
) ELSE IF "%BE%"=="msvc" (
- cmake --build . --target INSTALL --config Release
+ CD build_ci\cmake
+ cmake --build . --target INSTALL --config Release || EXIT /b 1
)
+) ELSE IF "%1"=="artifact" (
+ tar -c -C "C:\Program Files (x86)" --format=zip -f libarchive.zip libarchive
) ELSE (
- ECHO "Usage: %0% deplibs|configure|build|test|install"
+ ECHO "Usage: %0% deplibs|configure|build|test|install|artifact"
@EXIT /b 0
)
@EXIT /b 0
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index 3b1f0b95c8fb7..fcbd80c5a1715 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -1210,6 +1210,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the `_get_timezone' function. */
#cmakedefine HAVE__GET_TIMEZONE 1
+/* Define to 1 if you have the `_gmtime64_s' function. */
+#cmakedefine HAVE__GMTIME64_S 1
+
/* Define to 1 if you have the `_localtime64_s' function. */
#cmakedefine HAVE__LOCALTIME64_S 1
diff --git a/build/release/Dockerfile b/build/release/Dockerfile
new file mode 100644
index 0000000000000..76944f40c4843
--- /dev/null
+++ b/build/release/Dockerfile
@@ -0,0 +1,11 @@
+FROM ubuntu:18.04
+RUN apt-get update && apt-get install -y build-essential autoconf automake libtool pkg-config cmake libssl-dev libacl1-dev libbz2-dev liblzma-dev libzip-dev liblz4-dev libzstd-dev lzop groff ghostscript bsdmainutils zip
+ADD . $HOME/libarchive/
+ADD "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" $HOME/libarchive/build/autoconf/config.guess
+ADD "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" $HOME/libarchive/build/autoconf/config.sub
+WORKDIR $HOME/libarchive
+RUN /bin/sh build/clean.sh
+RUN /bin/sh build/autogen.sh
+ENV SKIP_OPEN_FD_ERR_TEST=1 SKIP_TEST_SPARSE=1
+RUN ./configure
+RUN make V=1 distcheck
diff --git a/build/release/release.sh b/build/release/release.sh
new file mode 100755
index 0000000000000..4d08038926877
--- /dev/null
+++ b/build/release/release.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+ID=$(docker build -q -f build/release/Dockerfile .)
+if [ -z "$ID" ]; then
+ echo "Failed to build docker image"
+ exit 1
+else
+ docker run $ID sh -c "tar -c -f - libarchive-*" | tar -x -f -
+fi
diff --git a/build/version b/build/version
index bd97679ec3cc4..78be3ab7e349c 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3004002dev
+3004002
diff --git a/cat/bsdcat.h b/cat/bsdcat.h
index 2e055e7c187c8..6467d6e3d310d 100644
--- a/cat/bsdcat.h
+++ b/cat/bsdcat.h
@@ -23,6 +23,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef BSDCAT_H_INCLUDED
+#define BSDCAT_H_INCLUDED
+
#if defined(PLATFORM_CONFIG_H)
/* Use hand-built config.h in environments that need it. */
#include PLATFORM_CONFIG_H
@@ -54,3 +57,5 @@ void usage(FILE *stream, int eval);
void bsdcat_next(void);
void bsdcat_print_error(void);
void bsdcat_read_to_stdout(const char* filename);
+
+#endif
diff --git a/cat/test/test_0.c b/cat/test/test_0.c
index f9fe5d8473f9d..c806c24356c0b 100644
--- a/cat/test/test_0.c
+++ b/cat/test/test_0.c
@@ -59,7 +59,7 @@ DEFINE_TEST(test_0)
* we know some option that will succeed.
*/
if (0 != systemf("%s --version >" DEV_NULL, testprog)) {
- failure("Unable to successfully run: %s --version\n", testprog, testprog);
+ failure("Unable to successfully run: %s --version\n", testprog);
assert(0);
}
diff --git a/configure.ac b/configure.ac
index ce90ee83957f8..2581087988bf7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ 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.4.2dev])
+m4_define([LIBARCHIVE_VERSION_S],[3.4.2])
m4_define([LIBARCHIVE_VERSION_N],[3004002])
dnl bsdtar and bsdcpio versioning tracks libarchive
@@ -641,7 +641,7 @@ AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm])
AC_CHECK_FUNCS([tzset unlinkat unsetenv utime utimensat utimes vfork])
AC_CHECK_FUNCS([wcrtomb wcscmp wcscpy wcslen wctomb wmemcmp wmemcpy wmemmove])
AC_CHECK_FUNCS([_ctime64_s _fseeki64])
-AC_CHECK_FUNCS([_get_timezone _localtime64_s _mkgmtime64])
+AC_CHECK_FUNCS([_get_timezone _gmtime64_s _localtime64_s _mkgmtime64])
# detects cygwin-1.7, as opposed to older versions
AC_CHECK_FUNCS([cygwin_conv_path])
diff --git a/contrib/archivetest.c b/contrib/archivetest.c
index 8002039ee4e28..e4a25e3c911dc 100644
--- a/contrib/archivetest.c
+++ b/contrib/archivetest.c
@@ -37,10 +37,14 @@
#include <archive.h>
#include <archive_entry.h>
-const char *errnostr(int errno)
+#if defined __MINGW32__
+#include <getopt.h>
+#endif
+
+static const char *errnostr(int e)
{
char *estr;
- switch(errno) {
+ switch(e) {
case ARCHIVE_EOF:
estr = "ARCHIVE_EOF";
break;
@@ -66,12 +70,12 @@ const char *errnostr(int errno)
return (estr);
}
-void usage(const char *prog)
+static void usage(const char *prog)
{
fprintf(stderr, "Usage: %s [-f filename] [-h] [-q] [-s]\n", prog);
}
-void printhelp()
+static void printhelp()
{
fprintf(stdout, "archivetest: verify reading archives with "
"libarchive\n\n"
@@ -84,7 +88,7 @@ void printhelp()
"\n%s\n", archive_version_details());
}
-int v_print(int verbose, const char *format, ...)
+static int v_print(int verbose, const char *format, ...)
{
int r = 0;
@@ -139,6 +143,8 @@ int main(int argc, char *argv[])
fprintf(stderr, "Unknown option "
"character '\\x%x'.\n", optopt);
usage(argv[0]);
+ exit(1);
+ break;
default:
exit(1);
}
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 4fd394dea5f16..da5c398600188 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -1139,6 +1139,14 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
const char *fmt;
time_t mtime;
static time_t now;
+ struct tm *ltime;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
if (!now)
time(&now);
@@ -1186,7 +1194,19 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
else
fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
#endif
- strftime(date, sizeof(date), fmt, localtime(&mtime));
+#if defined(HAVE_LOCALTIME_R)
+ ltime = localtime_r(&mtime, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = mtime;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ ltime = NULL;
+ else
+ ltime = &tmbuf;
+#else
+ ltime = localtime(&mtime);
+#endif
+ strftime(date, sizeof(date), fmt, ltime);
fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
archive_entry_strmode(entry),
diff --git a/cpio/test/test_basic.c b/cpio/test/test_basic.c
index a8fedf89e9688..b716253408fa5 100644
--- a/cpio/test/test_basic.c
+++ b/cpio/test/test_basic.c
@@ -33,15 +33,15 @@ verify_files(const char *msg)
*/
/* Regular file with 2 links. */
- failure(msg);
+ failure("%s", msg);
assertIsReg("file", 0644);
- failure(msg);
+ failure("%s", msg);
assertFileSize("file", 10);
- failure(msg);
+ failure("%s", msg);
assertFileNLinks("file", 2);
/* Another name for the same file. */
- failure(msg);
+ failure("%s", msg);
assertIsHardlink("linkfile", "file");
/* Symlink */
@@ -49,11 +49,11 @@ verify_files(const char *msg)
assertIsSymlink("symlink", "file", 0);
/* Another file with 1 link and different permissions. */
- failure(msg);
+ failure("%s", msg);
assertIsReg("file2", 0777);
- failure(msg);
+ failure("%s", msg);
assertFileSize("file2", 10);
- failure(msg);
+ failure("%s", msg);
assertFileNLinks("file2", 1);
/* dir */
diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c
index 6c981f6ac1393..49387a73580bf 100644
--- a/cpio/test/test_format_newc.c
+++ b/cpio/test/test_format_newc.c
@@ -205,9 +205,11 @@ DEFINE_TEST(test_format_newc)
gid = from_hex(e + 30, 8); /* gid */
assertEqualMem(e + 38, "00000003", 8); /* nlink */
t = from_hex(e + 46, 8); /* mtime */
- failure("t=0x%08x now=0x%08x=%d", t, now, now);
+ failure("t=%#08jx now=%#08jx=%jd", (intmax_t)t, (intmax_t)now,
+ (intmax_t)now);
assert(t <= now); /* File wasn't created in future. */
- failure("t=0x%08x now - 2=0x%08x = %d", t, now - 2, now - 2);
+ failure("t=%#08jx now - 2=%#08jx=%jd", (intmax_t)t, (intmax_t)now - 2,
+ (intmax_t)now - 2);
assert(t >= now - 2); /* File was created w/in last 2 secs. */
failure("newc format stores body only with last appearance of a link\n"
" first appearance should be empty, so this file size\n"
@@ -243,7 +245,8 @@ DEFINE_TEST(test_format_newc)
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
assertEqualMem(e + 38, "00000001", 8); /* nlink */
t2 = from_hex(e + 46, 8); /* mtime */
- failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
+ failure("First entry created at t=%#08jx this entry created"
+ " at t2=%#08jx", (intmax_t)t, (intmax_t)t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualMem(e + 54, "00000005", 8); /* File size */
fs = from_hex(e + 54, 8);
@@ -278,7 +281,8 @@ DEFINE_TEST(test_format_newc)
assertEqualInt(nlinks("dir"), from_hex(e + 38, 8)); /* nlinks */
#endif
t2 = from_hex(e + 46, 8); /* mtime */
- failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
+ failure("First entry created at t=%#08jx this entry created at"
+ "t2=%#08jx", (intmax_t)t, (intmax_t)t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualMem(e + 54, "00000000", 8); /* File size */
fs = from_hex(e + 54, 8);
@@ -311,7 +315,8 @@ DEFINE_TEST(test_format_newc)
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
assertEqualMem(e + 38, "00000003", 8); /* nlink */
t2 = from_hex(e + 46, 8); /* mtime */
- failure("First entry created at t=0x%08x this entry created at t2=0x%08x", t, t2);
+ failure("First entry created at t=%#08jx this entry created at"
+ "t2=%#08jx", (intmax_t)t, (intmax_t)t2);
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
assertEqualInt(10, from_hex(e + 54, 8)); /* File size */
fs = from_hex(e + 54, 8);
diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt
index ec775bb49939e..9389bbc9a95bf 100644
--- a/libarchive/CMakeLists.txt
+++ b/libarchive/CMakeLists.txt
@@ -150,6 +150,7 @@ SET(libarchive_SOURCES
archive_write_set_format_iso9660.c
archive_write_set_format_mtree.c
archive_write_set_format_pax.c
+ archive_write_set_format_private.h
archive_write_set_format_raw.c
archive_write_set_format_shar.c
archive_write_set_format_ustar.c
diff --git a/libarchive/archive.h b/libarchive/archive.h
index fe6dc63c8ea33..55818eac8e680 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.4.2dev"
+#define ARCHIVE_VERSION_ONLY_STRING "3.4.2"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -693,6 +693,8 @@ __LA_DECL int archive_read_set_passphrase_callback(struct archive *,
#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000)
/* Default: Do not clear no-change flags when unlinking object */
#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000)
+/* Default: Do not extract atomically (using rename) */
+#define ARCHIVE_EXTRACT_SAFE_WRITES (0x40000)
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
int flags);
diff --git a/libarchive/archive_acl_private.h b/libarchive/archive_acl_private.h
index ef0b0234cc1ab..af108162c6649 100644
--- a/libarchive/archive_acl_private.h
+++ b/libarchive/archive_acl_private.h
@@ -25,13 +25,13 @@
* $FreeBSD$
*/
+#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED
+#define ARCHIVE_ACL_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED
-#define ARCHIVE_ACL_PRIVATE_H_INCLUDED
-
#include "archive_string.h"
struct archive_acl_entry {
diff --git a/libarchive/archive_blake2.h b/libarchive/archive_blake2.h
index 337be194654e9..dd6fe6fe5a986 100644
--- a/libarchive/archive_blake2.h
+++ b/libarchive/archive_blake2.h
@@ -12,8 +12,9 @@
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
-#ifndef BLAKE2_H
-#define BLAKE2_H
+
+#ifndef ARCHIVE_BLAKE2_H
+#define ARCHIVE_BLAKE2_H
#include <stddef.h>
#include <stdint.h>
diff --git a/libarchive/archive_blake2_impl.h b/libarchive/archive_blake2_impl.h
index c1df82e0c95dc..0f05defea36ff 100644
--- a/libarchive/archive_blake2_impl.h
+++ b/libarchive/archive_blake2_impl.h
@@ -12,8 +12,9 @@
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
-#ifndef BLAKE2_IMPL_H
-#define BLAKE2_IMPL_H
+
+#ifndef ARCHIVE_BLAKE2_IMPL_H
+#define ARCHIVE_BLAKE2_IMPL_H
#include <stdint.h>
#include <string.h>
diff --git a/libarchive/archive_cmdline_private.h b/libarchive/archive_cmdline_private.h
index 4e409e814817a..57a19494fd7af 100644
--- a/libarchive/archive_cmdline_private.h
+++ b/libarchive/archive_cmdline_private.h
@@ -25,15 +25,15 @@
* $FreeBSD$
*/
+#ifndef ARCHIVE_CMDLINE_PRIVATE_H
+#define ARCHIVE_CMDLINE_PRIVATE_H
+
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
-#ifndef ARCHIVE_CMDLINE_PRIVATE_H
-#define ARCHIVE_CMDLINE_PRIVATE_H
-
struct archive_cmdline {
char *path;
char **argv;
diff --git a/libarchive/archive_crc32.h b/libarchive/archive_crc32.h
index cd633af89b4a5..4f1aed305930b 100644
--- a/libarchive/archive_crc32.h
+++ b/libarchive/archive_crc32.h
@@ -25,6 +25,9 @@
* $FreeBSD: head/lib/libarchive/archive_crc32.h 201102 2009-12-28 03:11:36Z kientzle $
*/
+#ifndef ARCHIVE_CRC32_H
+#define ARCHIVE_CRC32_H
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
@@ -76,3 +79,5 @@ crc32(unsigned long crc, const void *_p, size_t len)
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return (crc ^ 0xffffffffUL);
}
+
+#endif
diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h
index 0063f3e001495..64a20556a3996 100644
--- a/libarchive/archive_cryptor_private.h
+++ b/libarchive/archive_cryptor_private.h
@@ -23,13 +23,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
#ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
+#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.
diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h
index 2685b4a017db5..15312ee9a07a3 100644
--- a/libarchive/archive_digest_private.h
+++ b/libarchive/archive_digest_private.h
@@ -24,13 +24,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef ARCHIVE_DIGEST_PRIVATE_H_INCLUDED
+#define ARCHIVE_DIGEST_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-
-#ifndef ARCHIVE_CRYPTO_PRIVATE_H_INCLUDED
-#define ARCHIVE_CRYPTO_PRIVATE_H_INCLUDED
-
/*
* Crypto support in various Operating Systems:
*
diff --git a/libarchive/archive_endian.h b/libarchive/archive_endian.h
index 1c48563b137d2..e6d3f2ce5e700 100644
--- a/libarchive/archive_endian.h
+++ b/libarchive/archive_endian.h
@@ -28,16 +28,15 @@
* Borrowed from FreeBSD's <sys/endian.h>
*/
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
+#ifndef ARCHIVE_ENDIAN_H_INCLUDED
+#define ARCHIVE_ENDIAN_H_INCLUDED
/* Note: This is a purely internal header! */
/* Do not use this outside of libarchive internal code! */
-#ifndef ARCHIVE_ENDIAN_H_INCLUDED
-#define ARCHIVE_ENDIAN_H_INCLUDED
-
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
/*
* Disabling inline keyword for compilers known to choke on it:
diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c
index 72c644e6079b0..a15e98c284256 100644
--- a/libarchive/archive_entry.c
+++ b/libarchive/archive_entry.c
@@ -1699,7 +1699,7 @@ static const struct flag {
const wchar_t *wname;
unsigned long set;
unsigned long clear;
-} flags[] = {
+} fileflags[] = {
/* Preferred (shorter) names per flag first, all prefixed by "no" */
#ifdef SF_APPEND
{ "nosappnd", L"nosappnd", SF_APPEND, 0},
@@ -1876,7 +1876,7 @@ ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
bits = bitset | bitclear;
length = 0;
- for (flag = flags; flag->name != NULL; flag++)
+ for (flag = fileflags; flag->name != NULL; flag++)
if (bits & (flag->set | flag->clear)) {
length += strlen(flag->name) + 1;
bits &= ~(flag->set | flag->clear);
@@ -1889,7 +1889,7 @@ ae_fflagstostr(unsigned long bitset, unsigned long bitclear)
return (NULL);
dp = string;
- for (flag = flags; flag->name != NULL; flag++) {
+ for (flag = fileflags; flag->name != NULL; flag++) {
if (bitset & flag->set || bitclear & flag->clear) {
sp = flag->name + 2;
} else if (bitset & flag->clear || bitclear & flag->set) {
@@ -1941,7 +1941,7 @@ ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp)
*end != ' ' && *end != ',')
end++;
length = end - start;
- for (flag = flags; flag->name != NULL; flag++) {
+ for (flag = fileflags; flag->name != NULL; flag++) {
size_t flag_length = strlen(flag->name);
if (length == flag_length
&& memcmp(start, flag->name, length) == 0) {
@@ -2009,7 +2009,7 @@ ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp)
*end != L' ' && *end != L',')
end++;
length = end - start;
- for (flag = flags; flag->wname != NULL; flag++) {
+ for (flag = fileflags; flag->wname != NULL; flag++) {
size_t flag_length = wcslen(flag->wname);
if (length == flag_length
&& wmemcmp(start, flag->wname, length) == 0) {
diff --git a/libarchive/archive_entry_locale.h b/libarchive/archive_entry_locale.h
index 44550c51ec6a0..803c0368bb699 100644
--- a/libarchive/archive_entry_locale.h
+++ b/libarchive/archive_entry_locale.h
@@ -25,13 +25,13 @@
* $FreeBSD$
*/
+#ifndef ARCHIVE_ENTRY_LOCALE_H_INCLUDED
+#define ARCHIVE_ENTRY_LOCALE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_ENTRY_LOCALE_H_INCLUDED
-#define ARCHIVE_ENTRY_LOCALE_H_INCLUDED
-
struct archive_entry;
struct archive_string_conv;
diff --git a/libarchive/archive_entry_private.h b/libarchive/archive_entry_private.h
index 3d569bbfc6b54..2b9a084ca1549 100644
--- a/libarchive/archive_entry_private.h
+++ b/libarchive/archive_entry_private.h
@@ -25,13 +25,13 @@
* $FreeBSD: head/lib/libarchive/archive_entry_private.h 201096 2009-12-28 02:41:27Z kientzle $
*/
+#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
+#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
-#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
-
#include "archive_acl_private.h"
#include "archive_string.h"
diff --git a/libarchive/archive_getdate.c b/libarchive/archive_getdate.c
index 030c083ce716b..3ec5bba88896b 100644
--- a/libarchive/archive_getdate.c
+++ b/libarchive/archive_getdate.c
@@ -27,6 +27,7 @@
** This code is in the public domain and has no copyright.
*/
+#include "archive_platform.h"
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -694,8 +695,16 @@ Convert(time_t Month, time_t Day, time_t Year,
signed char DaysInMonth[12] = {
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
- time_t Julian;
- int i;
+ time_t Julian;
+ int i;
+ struct tm *ltime;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
if (Year < 69)
Year += 2000;
@@ -722,21 +731,64 @@ Convert(time_t Month, time_t Day, time_t Year,
Julian *= DAY;
Julian += Timezone;
Julian += Hours * HOUR + Minutes * MINUTE + Seconds;
+#if defined(HAVE_LOCALTIME_R)
+ ltime = localtime_r(&Julian, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = Julian;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ ltime = NULL;
+ else
+ ltime = &tmbuf;
+#else
+ ltime = localtime(&Julian);
+#endif
if (DSTmode == DSTon
- || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ || (DSTmode == DSTmaybe && ltime->tm_isdst))
Julian -= HOUR;
return Julian;
}
-
static time_t
DSTcorrect(time_t Start, time_t Future)
{
- time_t StartDay;
- time_t FutureDay;
+ time_t StartDay;
+ time_t FutureDay;
+ struct tm *ltime;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
- StartDay = (localtime(&Start)->tm_hour + 1) % 24;
- FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+#if defined(HAVE_LOCALTIME_R)
+ ltime = localtime_r(&Start, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = Start;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ ltime = NULL;
+ else
+ ltime = &tmbuf;
+#else
+ ltime = localtime(&Start);
+#endif
+ StartDay = (ltime->tm_hour + 1) % 24;
+#if defined(HAVE_LOCALTIME_R)
+ ltime = localtime_r(&Future, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = Future;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ ltime = NULL;
+ else
+ ltime = &tmbuf;
+#else
+ ltime = localtime(&Future);
+#endif
+ FutureDay = (ltime->tm_hour + 1) % 24;
return (Future - Start) + (StartDay - FutureDay) * HOUR;
}
@@ -747,9 +799,27 @@ RelativeDate(time_t Start, time_t zone, int dstmode,
{
struct tm *tm;
time_t t, now;
+#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__GMTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
t = Start - zone;
+#if defined(HAVE_GMTIME_R)
+ tm = gmtime_r(&t, &tmbuf);
+#elif defined(HAVE__GMTIME64_S)
+ tmptime = t;
+ terr = _gmtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ tm = NULL;
+ else
+ tm = &tmbuf;
+#else
tm = gmtime(&t);
+#endif
now = Start;
now += DAY * ((DayNumber - tm->tm_wday + 7) % 7);
now += 7 * DAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
@@ -765,10 +835,28 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
struct tm *tm;
time_t Month;
time_t Year;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
if (RelMonth == 0)
return 0;
+#if defined(HAVE_LOCALTIME_R)
+ tm = localtime_r(&Start, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = Start;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ tm = NULL;
+ else
+ tm = &tmbuf;
+#else
tm = localtime(&Start);
+#endif
Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
Year = Month / 12;
Month = Month % 12 + 1;
@@ -905,6 +993,10 @@ __archive_get_date(time_t now, const char *p)
time_t Start;
time_t tod;
long tzone;
+#if defined(HAVE__LOCALTIME64_S) || defined(HAVE__GMTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
/* Clear out the parsed token array. */
memset(tokens, 0, sizeof(tokens));
@@ -913,20 +1005,44 @@ __archive_get_date(time_t now, const char *p)
gds = &_gds;
/* Look up the current time. */
+#if defined(HAVE_LOCALTIME_R)
+ tm = localtime_r(&now, &local);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = now;
+ terr = _localtime64_s(&local, &tmptime);
+ if (terr)
+ tm = NULL;
+ else
+ tm = &local;
+#else
memset(&local, 0, sizeof(local));
- tm = localtime (&now);
+ tm = localtime(&now);
+#endif
if (tm == NULL)
return -1;
+#if !defined(HAVE_LOCALTIME_R) && !defined(HAVE__LOCALTIME64_S)
local = *tm;
+#endif
/* Look up UTC if we can and use that to determine the current
* timezone offset. */
+#if defined(HAVE_GMTIME_R)
+ gmt_ptr = gmtime_r(&now, &gmt);
+#elif defined(HAVE__GMTIME64_S)
+ tmptime = now;
+ terr = _gmtime64_s(&gmt, &tmptime);
+ if (terr)
+ gmt_ptr = NULL;
+ else
+ gmt_ptr = &gmt;
+#else
memset(&gmt, 0, sizeof(gmt));
- gmt_ptr = gmtime (&now);
+ gmt_ptr = gmtime(&now);
if (gmt_ptr != NULL) {
/* Copy, in case localtime and gmtime use the same buffer. */
gmt = *gmt_ptr;
}
+#endif
if (gmt_ptr != NULL)
tzone = difftm (&gmt, &local);
else
@@ -960,7 +1076,18 @@ __archive_get_date(time_t now, const char *p)
* time components instead of the local timezone. */
if (gds->HaveZone && gmt_ptr != NULL) {
now -= gds->Timezone;
- gmt_ptr = gmtime (&now);
+#if defined(HAVE_GMTIME_R)
+ gmt_ptr = gmtime_r(&now, &gmt);
+#elif defined(HAVE__GMTIME64_S)
+ tmptime = now;
+ terr = _gmtime64_s(&gmt, &tmptime);
+ if (terr)
+ gmt_ptr = NULL;
+ else
+ gmt_ptr = &gmt;
+#else
+ gmt_ptr = gmtime(&now);
+#endif
if (gmt_ptr != NULL)
local = *gmt_ptr;
now += gds->Timezone;
diff --git a/libarchive/archive_getdate.h b/libarchive/archive_getdate.h
index 666ff5ff78b9e..900a8f692e98e 100644
--- a/libarchive/archive_getdate.h
+++ b/libarchive/archive_getdate.h
@@ -25,13 +25,13 @@
* $FreeBSD$
*/
+#ifndef ARCHIVE_GETDATE_H_INCLUDED
+#define ARCHIVE_GETDATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_GETDATE_H_INCLUDED
-#define ARCHIVE_GETDATE_H_INCLUDED
-
#include <time.h>
time_t __archive_get_date(time_t now, const char *);
diff --git a/libarchive/archive_hmac_private.h b/libarchive/archive_hmac_private.h
index b7b365c7ad426..13a67d4955a5b 100644
--- a/libarchive/archive_hmac_private.h
+++ b/libarchive/archive_hmac_private.h
@@ -23,13 +23,12 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
#ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED
#define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
+#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.
diff --git a/libarchive/archive_openssl_evp_private.h b/libarchive/archive_openssl_evp_private.h
index 43a3ccc52a1d7..ebb06702d0c53 100644
--- a/libarchive/archive_openssl_evp_private.h
+++ b/libarchive/archive_openssl_evp_private.h
@@ -22,9 +22,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#ifndef ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED
#define ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
#include <openssl/evp.h>
#include <openssl/opensslv.h>
diff --git a/libarchive/archive_openssl_hmac_private.h b/libarchive/archive_openssl_hmac_private.h
index 921249bb9450f..25c8dda654fcb 100644
--- a/libarchive/archive_openssl_hmac_private.h
+++ b/libarchive/archive_openssl_hmac_private.h
@@ -22,9 +22,14 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#ifndef ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED
#define ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
diff --git a/libarchive/archive_options_private.h b/libarchive/archive_options_private.h
index 6ef0165aff687..9a7f8080d2f68 100644
--- a/libarchive/archive_options_private.h
+++ b/libarchive/archive_options_private.h
@@ -23,6 +23,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef ARCHIVE_OPTIONS_PRIVATE_H_INCLUDED
+#define ARCHIVE_OPTIONS_PRIVATE_H_INCLUDED
+
#include "archive_platform.h"
__FBSDID("$FreeBSD$");
@@ -45,3 +48,4 @@ _archive_set_either_option(struct archive *a,
const char *m, const char *o, const char *v,
option_handler use_format_option, option_handler use_filter_option);
+#endif
diff --git a/libarchive/archive_pack_dev.c b/libarchive/archive_pack_dev.c
index a5e57ac209d44..f8286d82183f6 100644
--- a/libarchive/archive_pack_dev.c
+++ b/libarchive/archive_pack_dev.c
@@ -57,11 +57,12 @@ __RCSID("$NetBSD$");
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#ifdef HAVE_SYS_SYSMACROS_H
-#include <sys/sysmacros.h>
-#endif
-#ifdef HAVE_SYS_MKDEV_H
+#if MAJOR_IN_MKDEV
#include <sys/mkdev.h>
+#define HAVE_MAJOR
+#elif MAJOR_IN_SYSMACROS
+#include <sys/sysmacros.h>
+#define HAVE_MAJOR
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
diff --git a/libarchive/archive_pack_dev.h b/libarchive/archive_pack_dev.h
index 749fd3d2cb657..eaf23e3883ef4 100644
--- a/libarchive/archive_pack_dev.h
+++ b/libarchive/archive_pack_dev.h
@@ -31,8 +31,8 @@
/* Originally from NetBSD's mknod(8) source. */
-#ifndef _PACK_DEV_H
-#define _PACK_DEV_H
+#ifndef ARCHIVE_PACK_DEV_H
+#define ARCHIVE_PACK_DEV_H
typedef dev_t pack_t(int, unsigned long [], const char **);
@@ -46,4 +46,4 @@ pack_t pack_native;
(((y) << 12) & 0xfff00000) | \
(((y) << 0) & 0x000000ff)))
-#endif /* _PACK_DEV_H */
+#endif /* ARCHIVE_PACK_DEV_H */
diff --git a/libarchive/archive_pathmatch.h b/libarchive/archive_pathmatch.h
index e6901774dddbb..9995142921e5b 100644
--- a/libarchive/archive_pathmatch.h
+++ b/libarchive/archive_pathmatch.h
@@ -26,15 +26,15 @@
* $FreeBSD$
*/
+#ifndef ARCHIVE_PATHMATCH_H
+#define ARCHIVE_PATHMATCH_H
+
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
-#ifndef ARCHIVE_PATHMATCH_H
-#define ARCHIVE_PATHMATCH_H
-
/* Don't anchor at beginning unless the pattern starts with "^" */
#define PATHMATCH_NO_ANCHOR_START 1
/* Don't anchor at end unless the pattern ends with "$" */
diff --git a/libarchive/archive_platform_acl.h b/libarchive/archive_platform_acl.h
index 3498f78b3c857..264e6de375a18 100644
--- a/libarchive/archive_platform_acl.h
+++ b/libarchive/archive_platform_acl.h
@@ -30,6 +30,12 @@
#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED
#define ARCHIVE_PLATFORM_ACL_H_INCLUDED
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST_COMMON
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
/*
* Determine what ACL types are supported
*/
diff --git a/libarchive/archive_platform_xattr.h b/libarchive/archive_platform_xattr.h
index 4edfecfdbdf18..ad4b90ab7b2af 100644
--- a/libarchive/archive_platform_xattr.h
+++ b/libarchive/archive_platform_xattr.h
@@ -30,6 +30,12 @@
#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED
#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST_COMMON
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
/*
* Determine if we support extended attributes
*/
diff --git a/libarchive/archive_ppmd7.c b/libarchive/archive_ppmd7.c
index d0bacc68cd7c6..4029395b4c7f4 100644
--- a/libarchive/archive_ppmd7.c
+++ b/libarchive/archive_ppmd7.c
@@ -1000,7 +1000,7 @@ static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p)
static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total)
{
- p->Low += start * (p->Range /= total);
+ p->Low += (UInt64)start * (UInt64)(p->Range /= total);
p->Range *= size;
while (p->Range < kTopValue)
{
diff --git a/libarchive/archive_ppmd7_private.h b/libarchive/archive_ppmd7_private.h
index 577d6fb43d0bf..71b954458c65a 100644
--- a/libarchive/archive_ppmd7_private.h
+++ b/libarchive/archive_ppmd7_private.h
@@ -6,13 +6,13 @@ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
+#ifndef ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
+#define ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
-#define ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
-
#include "archive_ppmd_private.h"
#define PPMD7_MIN_ORDER 2
diff --git a/libarchive/archive_ppmd8_private.h b/libarchive/archive_ppmd8_private.h
index 534927860ebc2..454b75f41f251 100644
--- a/libarchive/archive_ppmd8_private.h
+++ b/libarchive/archive_ppmd8_private.h
@@ -4,8 +4,8 @@ This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
-#ifndef __PPMD8_H
-#define __PPMD8_H
+#ifndef ARCHIVE_PPMD8_PRIVATE_H_INCLUDED
+#define ARCHIVE_PPMD8_PRIVATE_H_INCLUDED
#include "archive_ppmd_private.h"
diff --git a/libarchive/archive_ppmd_private.h b/libarchive/archive_ppmd_private.h
index a83b8514d8779..582803e5fd0f7 100644
--- a/libarchive/archive_ppmd_private.h
+++ b/libarchive/archive_ppmd_private.h
@@ -2,13 +2,13 @@
2010-03-12 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
+#ifndef ARCHIVE_PPMD_PRIVATE_H_INCLUDED
+#define ARCHIVE_PPMD_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_PPMD_PRIVATE_H_INCLUDED
-#define ARCHIVE_PPMD_PRIVATE_H_INCLUDED
-
#include <stddef.h>
#include "archive_read_private.h"
diff --git a/libarchive/archive_private.h b/libarchive/archive_private.h
index 4b4be9796dfc5..937a87bb1efca 100644
--- a/libarchive/archive_private.h
+++ b/libarchive/archive_private.h
@@ -25,13 +25,13 @@
* $FreeBSD: head/lib/libarchive/archive_private.h 201098 2009-12-28 02:58:14Z kientzle $
*/
+#ifndef ARCHIVE_PRIVATE_H_INCLUDED
+#define ARCHIVE_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_PRIVATE_H_INCLUDED
-#define ARCHIVE_PRIVATE_H_INCLUDED
-
#if HAVE_ICONV_H
#include <iconv.h>
#endif
@@ -153,6 +153,11 @@ void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
void __archive_ensure_cloexec_flag(int fd);
int __archive_mktemp(const char *tmpdir);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+int __archive_mkstemp(wchar_t *template);
+#else
+int __archive_mkstemp(char *template);
+#endif
int __archive_clean(struct archive *);
diff --git a/libarchive/archive_random_private.h b/libarchive/archive_random_private.h
index c414779f8d443..08b91b3b7a31f 100644
--- a/libarchive/archive_random_private.h
+++ b/libarchive/archive_random_private.h
@@ -23,13 +23,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
+#define ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
-#define ARCHIVE_RANDOM_PRIVATE_H_INCLUDED
-
/* Random number generator. */
int archive_random(void *buf, size_t nbytes);
diff --git a/libarchive/archive_rb.h b/libarchive/archive_rb.h
index 4562e9ebc41b1..8851f1081867d 100644
--- a/libarchive/archive_rb.h
+++ b/libarchive/archive_rb.h
@@ -28,8 +28,9 @@
*
* Based on NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp
*/
-#ifndef ARCHIVE_RB_H_
-#define ARCHIVE_RB_H_
+
+#ifndef ARCHIVE_RB_H_INCLUDED
+#define ARCHIVE_RB_H_INCLUDED
struct archive_rb_node {
struct archive_rb_node *rb_nodes[2];
@@ -48,12 +49,24 @@ struct archive_rb_node {
__archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_LEFT)
#define ARCHIVE_RB_TREE_MAX(T) \
__archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_RIGHT)
+#define ARCHIVE_RB_TREE_NEXT(T, N) \
+ __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_RIGHT)
+#define ARCHIVE_RB_TREE_PREV(T, N) \
+ __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_LEFT)
#define ARCHIVE_RB_TREE_FOREACH(N, T) \
for ((N) = ARCHIVE_RB_TREE_MIN(T); (N); \
- (N) = __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_RIGHT))
+ (N) = ARCHIVE_RB_TREE_NEXT((T), (N)))
#define ARCHIVE_RB_TREE_FOREACH_REVERSE(N, T) \
for ((N) = ARCHIVE_RB_TREE_MAX(T); (N); \
- (N) = __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_LEFT))
+ (N) = ARCHIVE_RB_TREE_PREV((T), (N)))
+#define ARCHIVE_RB_TREE_FOREACH_SAFE(N, T, S) \
+ for ((N) = ARCHIVE_RB_TREE_MIN(T); \
+ (N) && ((S) = ARCHIVE_RB_TREE_NEXT((T), (N)), 1); \
+ (N) = (S))
+#define ARCHIVE_RB_TREE_FOREACH_REVERSE_SAFE(N, T, S) \
+ for ((N) = ARCHIVE_RB_TREE_MAX(T); \
+ (N) && ((S) = ARCHIVE_RB_TREE_PREV((T), (N)), 1); \
+ (N) = (S))
/*
* archive_rbto_compare_nodes_fn:
diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
index 5872601101ba6..4a933b2fc084d 100644
--- a/libarchive/archive_read.c
+++ b/libarchive/archive_read.c
@@ -433,7 +433,7 @@ archive_read_add_callback_data(struct archive *_a, void *client_data,
return ARCHIVE_FATAL;
}
a->client.dataset = (struct archive_read_data_node *)p;
- for (i = a->client.nodes - 1; i > iindex && i > 0; i--) {
+ for (i = a->client.nodes - 1; i > iindex; i--) {
a->client.dataset[i].data = a->client.dataset[i-1].data;
a->client.dataset[i].begin_position = -1;
a->client.dataset[i].total_size = -1;
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index 183ca1e8790d7..52fec7bb42c8a 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -729,27 +729,23 @@ _archive_read_data_block(struct archive *_a, const void **buff,
if ((t->flags & needsRestoreTimes) != 0 &&
t->restore_time.noatime == 0)
flags |= O_NOATIME;
- do {
#endif
- t->entry_fd = open_on_current_dir(t,
- tree_current_access_path(t), flags);
- __archive_ensure_cloexec_flag(t->entry_fd);
+ t->entry_fd = open_on_current_dir(t,
+ tree_current_access_path(t), flags);
+ __archive_ensure_cloexec_flag(t->entry_fd);
#if defined(O_NOATIME)
- /*
- * When we did open the file with O_NOATIME flag,
- * if successful, set 1 to t->restore_time.noatime
- * not to restore an atime of the file later.
- * if failed by EPERM, retry it without O_NOATIME flag.
- */
- if (flags & O_NOATIME) {
- if (t->entry_fd >= 0)
- t->restore_time.noatime = 1;
- else if (errno == EPERM) {
- flags &= ~O_NOATIME;
- continue;
- }
- }
- } while (0);
+ /*
+ * When we did open the file with O_NOATIME flag,
+ * if successful, set 1 to t->restore_time.noatime
+ * not to restore an atime of the file later.
+ * if failed by EPERM, retry it without O_NOATIME flag.
+ */
+ if (flags & O_NOATIME) {
+ if (t->entry_fd >= 0)
+ t->restore_time.noatime = 1;
+ else if (errno == EPERM)
+ flags &= ~O_NOATIME;
+ }
#endif
if (t->entry_fd < 0) {
archive_set_error(&a->archive, errno,
@@ -1110,8 +1106,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
"%s", delayed_str.s);
}
}
- if (!archive_string_empty(&delayed_str))
- archive_string_free(&delayed_str);
+ archive_string_free(&delayed_str);
return (r);
}
diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h
index f03a0a9cc30fd..bc8abc15d15ca 100644
--- a/libarchive/archive_read_disk_private.h
+++ b/libarchive/archive_read_disk_private.h
@@ -26,13 +26,13 @@
* $FreeBSD: head/lib/libarchive/archive_read_disk_private.h 201105 2009-12-28 03:20:54Z kientzle $
*/
+#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
+#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
-#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
-
#include "archive_platform_acl.h"
struct tree;
diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h
index bf04f64104384..c842e6f09ad8c 100644
--- a/libarchive/archive_read_private.h
+++ b/libarchive/archive_read_private.h
@@ -25,15 +25,15 @@
* $FreeBSD: head/lib/libarchive/archive_read_private.h 201088 2009-12-28 02:18:55Z kientzle $
*/
+#ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
+#define ARCHIVE_READ_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
-#ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
-#define ARCHIVE_READ_PRIVATE_H_INCLUDED
-
#include "archive.h"
#include "archive_string.h"
#include "archive_private.h"
diff --git a/libarchive/archive_read_set_options.3 b/libarchive/archive_read_set_options.3
index d23f028b0ce29..78d99999cf831 100644
--- a/libarchive/archive_read_set_options.3
+++ b/libarchive/archive_read_set_options.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 2, 2012
+.Dd January 31, 2020
.Dt ARCHIVE_READ_OPTIONS 3
.Os
.Sh NAME
@@ -180,6 +180,18 @@ only to modules whose name matches
.\"
.Sh OPTIONS
.Bl -tag -compact -width indent
+.It Format cab
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.El
+.It Format cpio
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.El
.It Format iso9660
.Bl -tag -compact -width indent
.It Cm joliet
@@ -193,6 +205,24 @@ Defaults to enabled, use
.Cm !rockridge
to disable.
.El
+.It Format lha
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.El
+.It Format mtree
+.Bl -tag -compact -width indent
+.It Cm checkfs
+Allow reading information missing from the mtree from the file system.
+Disabled by default.
+.El
+.It Format rar
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.El
.It Format tar
.Bl -tag -compact -width indent
.It Cm compat-2x
@@ -202,7 +232,7 @@ This option mimics the libarchive 2.x filename handling
so that such archives can be read correctly.
.It Cm hdrcharset
The value is used as a character set name that will be
-used when translating filenames.
+used when translating file names.
.It Cm mac-ext
Support Mac OS metadata extension that records data in special
files beginning with a period and underscore.
diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c
index 641297990d261..67ddffb069436 100644
--- a/libarchive/archive_read_support_filter_uu.c
+++ b/libarchive/archive_read_support_filter_uu.c
@@ -574,14 +574,13 @@ read_more:
while (l > 0) {
int n = 0;
- if (l > 0) {
- if (!uuchar[b[0]] || !uuchar[b[1]])
- break;
- n = UUDECODE(*b++) << 18;
- n |= UUDECODE(*b++) << 12;
- *out++ = n >> 16; total++;
- --l;
- }
+ if (!uuchar[b[0]] || !uuchar[b[1]])
+ break;
+ n = UUDECODE(*b++) << 18;
+ n |= UUDECODE(*b++) << 12;
+ *out++ = n >> 16; total++;
+ --l;
+
if (l > 0) {
if (!uuchar[b[0]])
break;
@@ -626,14 +625,13 @@ read_more:
while (l > 0) {
int n = 0;
- if (l > 0) {
- if (!base64[b[0]] || !base64[b[1]])
- break;
- n = base64num[*b++] << 18;
- n |= base64num[*b++] << 12;
- *out++ = n >> 16; total++;
- l -= 2;
- }
+ if (!base64[b[0]] || !base64[b[1]])
+ break;
+ n = base64num[*b++] << 18;
+ n |= base64num[*b++] << 12;
+ *out++ = n >> 16; total++;
+ l -= 2;
+
if (l > 0) {
if (*b == '=')
break;
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index 87c6c52721975..6ce9d1a0e1bb2 100644
--- a/libarchive/archive_read_support_format_7zip.c
+++ b/libarchive/archive_read_support_format_7zip.c
@@ -1086,10 +1086,17 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
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 = 1;
+ delta_opt.dist =
+ (uint32_t)coder2->properties[0] + 1;
filters[fi].options = &delta_opt;
fi++;
break;
diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c
index 35405bcdd97fe..bff0f01f41cf6 100644
--- a/libarchive/archive_read_support_format_lha.c
+++ b/libarchive/archive_read_support_format_lha.c
@@ -1246,8 +1246,9 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
archive_array_append(&lha->filename,
(const char *)extdheader, datasize);
/* Setup a string conversion for a filename. */
- lha->sconv_fname = archive_string_conversion_from_charset(
- &a->archive, "UTF-16LE", 1);
+ lha->sconv_fname =
+ archive_string_conversion_from_charset(&a->archive,
+ "UTF-16LE", 1);
if (lha->sconv_fname == NULL)
return (ARCHIVE_FATAL);
break;
@@ -1273,32 +1274,46 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha,
break;
case EXT_UTF16_DIRECTORY:
/* UTF-16 characters take always 2 or 4 bytes */
- if (datasize == 0 || (datasize & 1) || extdheader[0] == '\0')
+ if (datasize == 0 || (datasize & 1) ||
+ extdheader[0] == '\0') {
/* no directory name data. exit this case. */
goto invalid;
+ }
archive_string_empty(&lha->dirname);
archive_array_append(&lha->dirname,
(const char *)extdheader, datasize);
- lha->sconv_dir = archive_string_conversion_from_charset(
- &a->archive, "UTF-16LE", 1);
+ lha->sconv_dir =
+ archive_string_conversion_from_charset(&a->archive,
+ "UTF-16LE", 1);
if (lha->sconv_dir == NULL)
return (ARCHIVE_FATAL);
else {
/*
- * Convert directory delimiter from 0xFF
+ * Convert directory delimiter from 0xFFFF
* to '/' for local system.
*/
+ uint16_t dirSep;
+ uint16_t d = 1;
+ if (archive_be16dec(&d) == 1)
+ dirSep = 0x2F00;
+ else
+ dirSep = 0x002F;
+
/* UTF-16LE character */
- uint16_t *utf16name = (uint16_t *)lha->dirname.s;
+ uint16_t *utf16name =
+ (uint16_t *)lha->dirname.s;
for (i = 0; i < lha->dirname.length / 2; i++) {
- if (utf16name[i] == 0xFFFF)
- utf16name[i] = L'/';
+ if (utf16name[i] == 0xFFFF) {
+ utf16name[i] = dirSep;
+ }
}
/* Is last character directory separator? */
- if (utf16name[lha->dirname.length / 2 - 1] != L'/')
+ if (utf16name[lha->dirname.length / 2 - 1] !=
+ dirSep) {
/* invalid directory data */
goto invalid;
+ }
}
break;
case EXT_DOS_ATTR:
diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
index a7331a2672c7a..332944ac51bff 100644
--- a/libarchive/archive_read_support_format_mtree.c
+++ b/libarchive/archive_read_support_format_mtree.c
@@ -258,6 +258,7 @@ archive_read_support_format_mtree(struct archive *_a)
"Can't allocate mtree data");
return (ARCHIVE_FATAL);
}
+ mtree->checkfs = 0;
mtree->fd = -1;
__archive_rb_tree_init(&mtree->rbtree, &rb_ops);
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index 41e5a3cadd90c..98efbb1a6c4a3 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -148,6 +148,9 @@
#define FILE_ATTRIBUTE_DIRECTORY 0x10
#endif
+#undef minimum
+#define minimum(a, b) ((a)<(b)?(a):(b))
+
/* Fields common to all headers */
struct rar_header
{
@@ -1722,6 +1725,13 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
struct tm *tm;
time_t t;
long nsec;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
if (p + 2 > endp)
return (-1);
@@ -1753,7 +1763,18 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
p++;
}
+#if defined(HAVE_LOCALTIME_R)
+ tm = localtime_r(&t, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = t;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ tm = NULL;
+ else
+ tm = &tmbuf;
+#else
tm = localtime(&t);
+#endif
nsec = tm->tm_sec + rem / NS_UNIT;
if (rmode & 4)
{
@@ -2452,8 +2473,11 @@ create_code(struct archive_read *a, struct huffman_code *code,
if (add_value(a, code, j, codebits, i) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
codebits++;
- if (--symbolsleft <= 0) { break; break; }
+ if (--symbolsleft <= 0)
+ break;
}
+ if (symbolsleft <= 0)
+ break;
codebits <<= 1;
}
return (ARCHIVE_OK);
@@ -2463,7 +2487,8 @@ static int
add_value(struct archive_read *a, struct huffman_code *code, int value,
int codebits, int length)
{
- int repeatpos, lastnode, bitpos, bit, repeatnode, nextnode;
+ int lastnode, bitpos, bit;
+ /* int repeatpos, repeatnode, nextnode; */
free(code->table);
code->table = NULL;
@@ -2473,6 +2498,9 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
if(length < code->minlength)
code->minlength = length;
+ /*
+ * Dead code, repeatpos was is -1
+ *
repeatpos = -1;
if (repeatpos == 0 || (repeatpos >= 0
&& (((codebits >> (repeatpos - 1)) & 3) == 0
@@ -2482,6 +2510,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
"Invalid repeat position");
return (ARCHIVE_FATAL);
}
+ */
lastnode = 0;
for (bitpos = length - 1; bitpos >= 0; bitpos--)
@@ -2497,9 +2526,12 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
return (ARCHIVE_FATAL);
}
+ /*
+ * Dead code, repeatpos was -1, bitpos >=0
+ *
if (bitpos == repeatpos)
{
- /* Open branch check */
+ * Open branch check *
if (!(code->tree[lastnode].branches[bit] < 0))
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
@@ -2518,16 +2550,17 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
return (ARCHIVE_FATAL);
}
- /* Set branches */
+ * Set branches *
code->tree[lastnode].branches[bit] = repeatnode;
code->tree[repeatnode].branches[bit] = repeatnode;
code->tree[repeatnode].branches[bit^1] = nextnode;
lastnode = nextnode;
- bitpos++; /* terminating bit already handled, skip it */
+ bitpos++; * terminating bit already handled, skip it *
}
else
{
+ */
/* Open branch check */
if (code->tree[lastnode].branches[bit] < 0)
{
@@ -2541,7 +2574,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value,
/* set to branch */
lastnode = code->tree[lastnode].branches[bit];
- }
+ /* } */
}
if (!(code->tree[lastnode].branches[0] == -1
@@ -2625,11 +2658,15 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
table[i].value = code->tree[node].branches[0];
}
}
+ /*
+ * Dead code, node >= 0
+ *
else if (node < 0)
{
for(i = 0; i < currtablesize; i++)
table[i].length = -1;
}
+ */
else
{
if(depth == maxdepth)
@@ -2661,6 +2698,10 @@ expand(struct archive_read *a, int64_t end)
0, 1, 1, 1, 1, 2, 2,
2, 2, 3, 3, 3, 3, 4,
4, 4, 4, 5, 5, 5, 5 };
+ static const int lengthb_min = minimum(
+ (int)(sizeof(lengthbases)/sizeof(lengthbases[0])),
+ (int)(sizeof(lengthbits)/sizeof(lengthbits[0]))
+ );
static const unsigned int offsetbases[] =
{ 0, 1, 2, 3, 4, 6,
8, 12, 16, 24, 32, 48,
@@ -2678,6 +2719,10 @@ expand(struct archive_read *a, int64_t end)
11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 };
+ static const int offsetb_min = minimum(
+ (int)(sizeof(offsetbases)/sizeof(offsetbases[0])),
+ (int)(sizeof(offsetbits)/sizeof(offsetbits[0]))
+ );
static const unsigned char shortbases[] =
{ 0, 4, 8, 16, 32, 64, 128, 192 };
static const unsigned char shortbits[] =
@@ -2757,9 +2802,7 @@ expand(struct archive_read *a, int64_t end)
if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0)
goto bad_data;
- if (lensymbol > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
- goto bad_data;
- if (lensymbol > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
+ if (lensymbol > lengthb_min)
goto bad_data;
len = lengthbases[lensymbol] + 2;
if (lengthbits[lensymbol] > 0) {
@@ -2791,9 +2834,7 @@ expand(struct archive_read *a, int64_t end)
}
else
{
- if (symbol-271 > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
- goto bad_data;
- if (symbol-271 > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
+ if (symbol-271 > lengthb_min)
goto bad_data;
len = lengthbases[symbol-271]+3;
if(lengthbits[symbol-271] > 0) {
@@ -2805,9 +2846,7 @@ expand(struct archive_read *a, int64_t end)
if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0)
goto bad_data;
- if (offssymbol > (int)(sizeof(offsetbases)/sizeof(offsetbases[0])))
- goto bad_data;
- if (offssymbol > (int)(sizeof(offsetbits)/sizeof(offsetbits[0])))
+ if (offssymbol > offsetb_min)
goto bad_data;
offs = offsetbases[offssymbol]+1;
if(offsetbits[offssymbol] > 0)
diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c
index ce38b1fc990f3..82729bdcdb3c7 100644
--- a/libarchive/archive_read_support_format_rar5.c
+++ b/libarchive/archive_read_support_format_rar5.c
@@ -73,15 +73,14 @@
* 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00
* "Rar!→•☺·\x00"
*
- * It's stored in `rar5_signature` after XOR'ing it with 0xA1, because I don't
+ * Retrieved with `rar5_signature()` by XOR'ing it with 0xA1, because I don't
* want to put this magic sequence in each binary that uses libarchive, so
* applications that scan through the file for this marker won't trigger on
* this "false" one.
*
* The array itself is decrypted in `rar5_init` function. */
-static unsigned char rar5_signature[] = { 243, 192, 211, 128, 187, 166, 160, 161 };
-static const ssize_t rar5_signature_size = sizeof(rar5_signature);
+static unsigned char rar5_signature_xor[] = { 243, 192, 211, 128, 187, 166, 160, 161 };
static const size_t g_unpack_window_size = 0x20000;
/* These could have been static const's, but they aren't, because of
@@ -211,7 +210,7 @@ struct comp_state {
or just a part of it. */
uint8_t block_parsing_finished : 1;
- int notused : 4;
+ signed int notused : 4;
int flags; /* Uncompression flags. */
int method; /* Uncompression algorithm method. */
@@ -357,6 +356,7 @@ struct rar5 {
/* Forward function declarations. */
+static void rar5_signature(char *buf);
static int verify_global_checksums(struct archive_read* a);
static int rar5_read_data_skip(struct archive_read *a);
static int push_data_ready(struct archive_read* a, struct rar5* rar,
@@ -384,7 +384,7 @@ static int cdeque_init(struct cdeque* d, int max_capacity_power_of_2) {
d->cap_mask = max_capacity_power_of_2 - 1;
d->arr = NULL;
- if((max_capacity_power_of_2 & d->cap_mask) > 0)
+ if((max_capacity_power_of_2 & d->cap_mask) != 0)
return CDE_PARAM;
cdeque_clear(d);
@@ -881,10 +881,10 @@ static inline int get_archive_read(struct archive* a,
static int read_ahead(struct archive_read* a, size_t how_many,
const uint8_t** ptr)
{
+ ssize_t avail = -1;
if(!ptr)
return 0;
- ssize_t avail = -1;
*ptr = __archive_read_ahead(a, how_many, &avail);
if(*ptr == NULL) {
return 0;
@@ -1086,11 +1086,14 @@ static int read_u64(struct archive_read* a, uint64_t* pvalue) {
static int bid_standard(struct archive_read* a) {
const uint8_t* p;
+ char signature[sizeof(rar5_signature_xor)];
+
+ rar5_signature(signature);
- if(!read_ahead(a, rar5_signature_size, &p))
+ if(!read_ahead(a, sizeof(rar5_signature_xor), &p))
return -1;
- if(!memcmp(rar5_signature, p, rar5_signature_size))
+ if(!memcmp(signature, p, sizeof(rar5_signature_xor)))
return 30;
return -1;
@@ -1150,14 +1153,14 @@ static int process_main_locator_extra_block(struct archive_read* a,
{
uint64_t locator_flags;
- if(!read_var(a, &locator_flags, NULL)) {
- return ARCHIVE_EOF;
- }
-
enum LOCATOR_FLAGS {
QLIST = 0x01, RECOVERY = 0x02,
};
+ if(!read_var(a, &locator_flags, NULL)) {
+ return ARCHIVE_EOF;
+ }
+
if(locator_flags & QLIST) {
if(!read_var(a, &rar->qlist_offset, NULL)) {
return ARCHIVE_EOF;
@@ -1183,6 +1186,10 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
size_t hash_type = 0;
size_t value_len;
+ enum HASH_TYPE {
+ BLAKE2sp = 0x00
+ };
+
if(!read_var_sized(a, &hash_type, &value_len))
return ARCHIVE_EOF;
@@ -1191,10 +1198,6 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
return ARCHIVE_EOF;
}
- enum HASH_TYPE {
- BLAKE2sp = 0x00
- };
-
/* The file uses BLAKE2sp checksum algorithm instead of plain old
* CRC32. */
if(hash_type == BLAKE2sp) {
@@ -1257,6 +1260,7 @@ static int parse_file_extra_version(struct archive_read* a,
size_t value_len = 0;
struct archive_string version_string;
struct archive_string name_utf8_string;
+ const char* cur_filename;
/* Flags are ignored. */
if(!read_var_sized(a, &flags, &value_len))
@@ -1275,7 +1279,7 @@ static int parse_file_extra_version(struct archive_read* a,
/* extra_data_size should be zero here. */
- const char* cur_filename = archive_entry_pathname_utf8(e);
+ cur_filename = archive_entry_pathname_utf8(e);
if(cur_filename == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"Version entry without file name");
@@ -1586,6 +1590,25 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
char name_utf8_buf[MAX_NAME_IN_BYTES];
const uint8_t* p;
+ enum FILE_FLAGS {
+ DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004,
+ UNKNOWN_UNPACKED_SIZE = 0x0008,
+ };
+
+ enum FILE_ATTRS {
+ ATTR_READONLY = 0x1, ATTR_HIDDEN = 0x2, ATTR_SYSTEM = 0x4,
+ ATTR_DIRECTORY = 0x10,
+ };
+
+ enum COMP_INFO_FLAGS {
+ SOLID = 0x0040,
+ };
+
+ enum HOST_OS {
+ HOST_WINDOWS = 0,
+ HOST_UNIX = 1,
+ };
+
archive_entry_clear(entry);
/* Do not reset file context if we're switching archives. */
@@ -1615,20 +1638,6 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
return ARCHIVE_FATAL;
}
- enum FILE_FLAGS {
- DIRECTORY = 0x0001, UTIME = 0x0002, CRC32 = 0x0004,
- UNKNOWN_UNPACKED_SIZE = 0x0008,
- };
-
- enum FILE_ATTRS {
- ATTR_READONLY = 0x1, ATTR_HIDDEN = 0x2, ATTR_SYSTEM = 0x4,
- ATTR_DIRECTORY = 0x10,
- };
-
- enum COMP_INFO_FLAGS {
- SOLID = 0x0040,
- };
-
if(!read_var_sized(a, &file_flags, NULL))
return ARCHIVE_EOF;
@@ -1725,11 +1734,6 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
if(!read_var_sized(a, &host_os, NULL))
return ARCHIVE_EOF;
- enum HOST_OS {
- HOST_WINDOWS = 0,
- HOST_UNIX = 1,
- };
-
if(host_os == HOST_WINDOWS) {
/* Host OS is Windows */
@@ -1821,12 +1825,16 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
int ret = process_head_file_extra(a, entry, rar,
extra_data_size);
- /* Sanity check. */
+ /*
+ * TODO: rewrite or remove useless sanity check
+ * as extra_data_size is not passed as a pointer
+ *
if(extra_data_size < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
"File extra data size is not zero");
return ARCHIVE_FATAL;
}
+ */
if(ret != ARCHIVE_OK)
return ret;
@@ -1891,14 +1899,28 @@ static int process_head_service(struct archive_read* a, struct rar5* rar,
static int process_head_main(struct archive_read* a, struct rar5* rar,
struct archive_entry* entry, size_t block_flags)
{
- (void) entry;
-
int ret;
size_t extra_data_size = 0;
size_t extra_field_size = 0;
size_t extra_field_id = 0;
size_t archive_flags = 0;
+ enum MAIN_FLAGS {
+ VOLUME = 0x0001, /* multi-volume archive */
+ VOLUME_NUMBER = 0x0002, /* volume number, first vol doesn't
+ * have it */
+ SOLID = 0x0004, /* solid archive */
+ PROTECT = 0x0008, /* contains Recovery info */
+ LOCK = 0x0010, /* readonly flag, not used */
+ };
+
+ enum MAIN_EXTRA {
+ // Just one attribute here.
+ LOCATOR = 0x01,
+ };
+
+ (void) entry;
+
if(block_flags & HFL_EXTRA_DATA) {
if(!read_var_sized(a, &extra_data_size, NULL))
return ARCHIVE_EOF;
@@ -1910,15 +1932,6 @@ static int process_head_main(struct archive_read* a, struct rar5* rar,
return ARCHIVE_EOF;
}
- enum MAIN_FLAGS {
- VOLUME = 0x0001, /* multi-volume archive */
- VOLUME_NUMBER = 0x0002, /* volume number, first vol doesn't
- * have it */
- SOLID = 0x0004, /* solid archive */
- PROTECT = 0x0008, /* contains Recovery info */
- LOCK = 0x0010, /* readonly flag, not used */
- };
-
rar->main.volume = (archive_flags & VOLUME) > 0;
rar->main.solid = (archive_flags & SOLID) > 0;
@@ -1970,11 +1983,6 @@ static int process_head_main(struct archive_read* a, struct rar5* rar,
return ARCHIVE_FATAL;
}
- enum MAIN_EXTRA {
- // Just one attribute here.
- LOCATOR = 0x01,
- };
-
switch(extra_field_id) {
case LOCATOR:
ret = process_main_locator_extra_block(a, rar);
@@ -2080,6 +2088,8 @@ static int scan_for_signature(struct archive_read* a);
static int process_base_block(struct archive_read* a,
struct archive_entry* entry)
{
+ const size_t SMALLEST_RAR5_BLOCK_SIZE = 3;
+
struct rar5* rar = get_context(a);
uint32_t hdr_crc, computed_crc;
size_t raw_hdr_size = 0, hdr_size_len, hdr_size;
@@ -2088,6 +2098,12 @@ static int process_base_block(struct archive_read* a,
const uint8_t* p;
int ret;
+ enum HEADER_TYPE {
+ HEAD_MARK = 0x00, HEAD_MAIN = 0x01, HEAD_FILE = 0x02,
+ HEAD_SERVICE = 0x03, HEAD_CRYPT = 0x04, HEAD_ENDARC = 0x05,
+ HEAD_UNKNOWN = 0xff,
+ };
+
/* Skip any unprocessed data for this file. */
ret = skip_unprocessed_bytes(a);
if(ret != ARCHIVE_OK)
@@ -2103,15 +2119,26 @@ static int process_base_block(struct archive_read* a,
return ARCHIVE_EOF;
}
+ hdr_size = raw_hdr_size + hdr_size_len;
+
/* Sanity check, maximum header size for RAR5 is 2MB. */
- if(raw_hdr_size > (2 * 1024 * 1024)) {
+ if(hdr_size > (2 * 1024 * 1024)) {
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)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Too small block encountered (%zu bytes)",
+ raw_hdr_size);
+
+ return ARCHIVE_FATAL;
+ }
/* Read the whole header data into memory, maximum memory use here is
* 2MB. */
@@ -2146,12 +2173,6 @@ static int process_base_block(struct archive_read* a,
rar->main.endarc = 0;
/* Those are possible header ids in RARv5. */
- enum HEADER_TYPE {
- HEAD_MARK = 0x00, HEAD_MAIN = 0x01, HEAD_FILE = 0x02,
- HEAD_SERVICE = 0x03, HEAD_CRYPT = 0x04, HEAD_ENDARC = 0x05,
- HEAD_UNKNOWN = 0xff,
- };
-
switch(header_id) {
case HEAD_MAIN:
ret = process_head_main(a, rar, entry, header_flags);
@@ -2264,7 +2285,7 @@ static int rar5_read_header(struct archive_read *a,
}
if(rar->skipped_magic == 0) {
- if(ARCHIVE_OK != consume(a, rar5_signature_size)) {
+ if(ARCHIVE_OK != consume(a, sizeof(rar5_signature_xor))) {
return ARCHIVE_EOF;
}
@@ -2536,12 +2557,10 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
/* 0..15: store directly */
table[i] = (uint8_t) num;
i++;
- continue;
- }
-
- if(num < 18) {
+ } else if(num < 18) {
/* 16..17: repeat previous code */
uint16_t n;
+
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
return ARCHIVE_EOF;
@@ -2567,27 +2586,26 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
"huffman tables");
return ARCHIVE_FATAL;
}
+ } else {
+ /* other codes: fill with zeroes `n` times */
+ uint16_t n;
- continue;
- }
+ if(ARCHIVE_OK != read_bits_16(rar, p, &n))
+ return ARCHIVE_EOF;
- /* other codes: fill with zeroes `n` times */
- uint16_t n;
- if(ARCHIVE_OK != read_bits_16(rar, p, &n))
- return ARCHIVE_EOF;
+ if(num == 18) {
+ n >>= 13;
+ n += 3;
+ skip_bits(rar, 3);
+ } else {
+ n >>= 9;
+ n += 11;
+ skip_bits(rar, 7);
+ }
- if(num == 18) {
- n >>= 13;
- n += 3;
- skip_bits(rar, 3);
- } else {
- n >>= 9;
- n += 11;
- skip_bits(rar, 7);
+ while(n-- > 0 && i < HUFF_TABLE_SIZE)
+ table[i++] = 0;
}
-
- while(n-- > 0 && i < HUFF_TABLE_SIZE)
- table[i++] = 0;
}
ret = create_decode_tables(&table[idx], &rar->cstate.ld, HUFF_NC);
@@ -2632,6 +2650,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
static int parse_block_header(struct archive_read* a, const uint8_t* p,
ssize_t* block_size, struct compressed_block_header* hdr)
{
+ uint8_t calculated_cksum;
memcpy(hdr, p, sizeof(struct compressed_block_header));
if(bf_byte_count(hdr) > 2) {
@@ -2670,7 +2689,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
/* Verify the block header checksum. 0x5A is a magic value and is
* always * constant. */
- uint8_t calculated_cksum = 0x5A
+ calculated_cksum = 0x5A
^ (uint8_t) hdr->block_flags_u8
^ (uint8_t) *block_size
^ (uint8_t) (*block_size >> 8)
@@ -2744,6 +2763,7 @@ static int is_valid_filter_block_start(struct rar5* rar,
static int parse_filter(struct archive_read* ar, const uint8_t* p) {
uint32_t block_start, block_length;
uint16_t filter_type;
+ struct filter_info* filt = NULL;
struct rar5* rar = get_context(ar);
/* Read the parameters from the input stream. */
@@ -2774,7 +2794,7 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
}
/* Allocate a new filter. */
- struct filter_info* filt = add_new_filter(rar);
+ filt = add_new_filter(rar);
if(filt == NULL) {
archive_set_error(&ar->archive, ENOMEM,
"Can't allocate memory for a filter descriptor.");
@@ -3043,7 +3063,8 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
}
continue;
- } else if(num < 262) {
+ } else {
+ /* num < 262 */
const int idx = num - 258;
const int dist = dist_cache_touch(rar, idx);
@@ -3079,6 +3100,7 @@ static int scan_for_signature(struct archive_read* a) {
const uint8_t* p;
const int chunk_size = 512;
ssize_t i;
+ char signature[sizeof(rar5_signature_xor)];
/* If we're here, it means we're on an 'unknown territory' data.
* There's no indication what kind of data we're reading here.
@@ -3092,19 +3114,23 @@ static int scan_for_signature(struct archive_read* a) {
* end of the file? If so, it would be a better approach than the
* current implementation of this function. */
+ rar5_signature(signature);
+
while(1) {
if(!read_ahead(a, chunk_size, &p))
return ARCHIVE_EOF;
- for(i = 0; i < chunk_size - rar5_signature_size; i++) {
- if(memcmp(&p[i], rar5_signature,
- rar5_signature_size) == 0) {
+ for(i = 0; i < chunk_size - (int)sizeof(rar5_signature_xor);
+ i++) {
+ if(memcmp(&p[i], signature,
+ sizeof(rar5_signature_xor)) == 0) {
/* Consume the number of bytes we've used to
* search for the signature, as well as the
* number of bytes used by the signature
* itself. After this we should be standing
* on a valid base block header. */
- (void) consume(a, i + rar5_signature_size);
+ (void) consume(a,
+ i + sizeof(rar5_signature_xor));
return ARCHIVE_OK;
}
}
@@ -3314,6 +3340,8 @@ static int process_block(struct archive_read* a) {
if(rar->cstate.block_parsing_finished) {
ssize_t block_size;
+ ssize_t to_skip;
+ ssize_t cur_block_size;
/* The header size won't be bigger than 6 bytes. */
if(!read_ahead(a, 6, &p)) {
@@ -3337,7 +3365,7 @@ static int process_block(struct archive_read* a) {
/* Skip block header. Next data is huffman tables,
* if present. */
- ssize_t to_skip = sizeof(struct compressed_block_header) +
+ to_skip = sizeof(struct compressed_block_header) +
bf_byte_count(&rar->last_block_hdr) + 1;
if(ARCHIVE_OK != consume(a, to_skip))
@@ -3351,7 +3379,7 @@ static int process_block(struct archive_read* a) {
* bigger than the actual data stored in this file. Remaining
* part of the data will be in another file. */
- ssize_t cur_block_size =
+ cur_block_size =
rar5_min(rar->file.bytes_remaining, block_size);
if(block_size > rar->file.bytes_remaining) {
@@ -3679,6 +3707,7 @@ static int uncompress_file(struct archive_read* a) {
static int do_unstore_file(struct archive_read* a,
struct rar5* rar, const void** buf, size_t* size, int64_t* offset)
{
+ size_t to_read;
const uint8_t* p;
if(rar->file.bytes_remaining == 0 && rar->main.volume > 0 &&
@@ -3697,7 +3726,7 @@ static int do_unstore_file(struct archive_read* a,
}
}
- size_t to_read = rar5_min(rar->file.bytes_remaining, 64 * 1024);
+ to_read = rar5_min(rar->file.bytes_remaining, 64 * 1024);
if(to_read == 0) {
return ARCHIVE_EOF;
}
@@ -3866,6 +3895,18 @@ static int verify_global_checksums(struct archive_read* a) {
return verify_checksums(a);
}
+/*
+ * Decryption function for the magic signature pattern. Check the comment near
+ * the `rar5_signature_xor` symbol to read the rationale behind this.
+ */
+static void rar5_signature(char *buf) {
+ size_t i;
+
+ for(i = 0; i < sizeof(rar5_signature_xor); i++) {
+ buf[i] = rar5_signature_xor[i] ^ 0xA1;
+ }
+}
+
static int rar5_read_data(struct archive_read *a, const void **buff,
size_t *size, int64_t *offset) {
int ret;
@@ -4012,19 +4053,8 @@ static int rar5_has_encrypted_entries(struct archive_read *_a) {
}
static int rar5_init(struct rar5* rar) {
- ssize_t i;
-
memset(rar, 0, sizeof(struct rar5));
- /* Decrypt the magic signature pattern. Check the comment near the
- * `rar5_signature` symbol to read the rationale behind this. */
-
- if(rar5_signature[0] == 243) {
- for(i = 0; i < rar5_signature_size; i++) {
- rar5_signature[i] ^= 0xA1;
- }
- }
-
if(CDE_OK != cdeque_init(&rar->cstate.filters, 8192))
return ARCHIVE_FATAL;
diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
index c1c54450c3964..72977b8e0739d 100644
--- a/libarchive/archive_read_support_format_warc.c
+++ b/libarchive/archive_read_support_format_warc.c
@@ -626,7 +626,8 @@ _warc_rdver(const char *buf, size_t bsz)
if (ver >= 1200U) {
if (memcmp(c, "\r\n", 2U) != 0)
ver = 0U;
- } else if (ver < 1200U) {
+ } else {
+ /* ver < 1200U */
if (*c != ' ' && *c != '\t')
ver = 0U;
}
diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c
index 34253a52fb753..7f8be398c7a26 100644
--- a/libarchive/archive_read_support_format_xar.c
+++ b/libarchive/archive_read_support_format_xar.c
@@ -2613,15 +2613,14 @@ strappend_base64(struct xar *xar,
while (l > 0) {
int n = 0;
- if (l > 0) {
- if (base64[b[0]] < 0 || base64[b[1]] < 0)
- break;
- n = base64[*b++] << 18;
- n |= base64[*b++] << 12;
- *out++ = n >> 16;
- len++;
- l -= 2;
- }
+ if (base64[b[0]] < 0 || base64[b[1]] < 0)
+ break;
+ n = base64[*b++] << 18;
+ n |= base64[*b++] << 12;
+ *out++ = n >> 16;
+ len++;
+ l -= 2;
+
if (l > 0) {
if (base64[*b] < 0)
break;
diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c
index 399299ea631fb..c77dcf52c25f0 100644
--- a/libarchive/archive_string.c
+++ b/libarchive/archive_string.c
@@ -744,7 +744,8 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
else
dp = &defchar_used;
count = WideCharToMultiByte(to_cp, 0, ws, wslen,
- as->s + as->length, (int)as->buffer_length-1, NULL, dp);
+ as->s + as->length,
+ (int)as->buffer_length - as->length - 1, NULL, dp);
if (count == 0 &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/* Expand the MBS buffer and retry. */
diff --git a/libarchive/archive_string.h b/libarchive/archive_string.h
index 56dfbb28f2872..27e1ad69c56ef 100644
--- a/libarchive/archive_string.h
+++ b/libarchive/archive_string.h
@@ -26,15 +26,15 @@
*
*/
+#ifndef ARCHIVE_STRING_H_INCLUDED
+#define ARCHIVE_STRING_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
-#ifndef ARCHIVE_STRING_H_INCLUDED
-#define ARCHIVE_STRING_H_INCLUDED
-
#include <stdarg.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* required for wchar_t on some systems */
diff --git a/libarchive/archive_string_composition.h b/libarchive/archive_string_composition.h
index 8902ac1f7f30f..d0ac340961a0a 100644
--- a/libarchive/archive_string_composition.h
+++ b/libarchive/archive_string_composition.h
@@ -34,13 +34,13 @@
* See also http://unicode.org/report/tr15/
*/
+#ifndef ARCHIVE_STRING_COMPOSITION_H_INCLUDED
+#define ARCHIVE_STRING_COMPOSITION_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_STRING_COMPOSITION_H_INCLUDED
-#define ARCHIVE_STRING_COMPOSITION_H_INCLUDED
-
struct unicode_composition_table {
uint32_t cp1;
uint32_t cp2;
diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c
index 3399c0b5f492e..288a44280dc21 100644
--- a/libarchive/archive_util.c
+++ b/libarchive/archive_util.c
@@ -218,8 +218,8 @@ __archive_errx(int retvalue, const char *msg)
* Also Windows version of mktemp family including _mktemp_s
* are not secure.
*/
-int
-__archive_mktemp(const char *tmpdir)
+static int
+__archive_mktempx(const char *tmpdir, wchar_t *template)
{
static const wchar_t prefix[] = L"libarchive_";
static const wchar_t suffix[] = L"XXXXXXXXXX";
@@ -243,64 +243,76 @@ __archive_mktemp(const char *tmpdir)
hProv = (HCRYPTPROV)NULL;
fd = -1;
ws = NULL;
- archive_string_init(&temp_name);
- /* Get a temporary directory. */
- if (tmpdir == NULL) {
- size_t l;
- wchar_t *tmp;
+ if (template == NULL) {
+ archive_string_init(&temp_name);
- l = GetTempPathW(0, NULL);
- if (l == 0) {
- la_dosmaperr(GetLastError());
- goto exit_tmpfile;
- }
- tmp = malloc(l*sizeof(wchar_t));
- if (tmp == NULL) {
- errno = ENOMEM;
- goto exit_tmpfile;
- }
- GetTempPathW((DWORD)l, tmp);
- archive_wstrcpy(&temp_name, tmp);
- free(tmp);
- } else {
- if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
- strlen(tmpdir)) < 0)
- goto exit_tmpfile;
- if (temp_name.s[temp_name.length-1] != L'/')
- archive_wstrappend_wchar(&temp_name, L'/');
- }
+ /* Get a temporary directory. */
+ if (tmpdir == NULL) {
+ size_t l;
+ wchar_t *tmp;
- /* Check if temp_name is a directory. */
- attr = GetFileAttributesW(temp_name.s);
- if (attr == (DWORD)-1) {
- if (GetLastError() != ERROR_FILE_NOT_FOUND) {
- la_dosmaperr(GetLastError());
- goto exit_tmpfile;
- }
- ws = __la_win_permissive_name_w(temp_name.s);
- if (ws == NULL) {
- errno = EINVAL;
- goto exit_tmpfile;
+ l = GetTempPathW(0, NULL);
+ if (l == 0) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+ tmp = malloc(l*sizeof(wchar_t));
+ if (tmp == NULL) {
+ errno = ENOMEM;
+ goto exit_tmpfile;
+ }
+ GetTempPathW((DWORD)l, tmp);
+ archive_wstrcpy(&temp_name, tmp);
+ free(tmp);
+ } else {
+ if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
+ strlen(tmpdir)) < 0)
+ goto exit_tmpfile;
+ if (temp_name.s[temp_name.length-1] != L'/')
+ archive_wstrappend_wchar(&temp_name, L'/');
}
- attr = GetFileAttributesW(ws);
+
+ /* Check if temp_name is a directory. */
+ attr = GetFileAttributesW(temp_name.s);
if (attr == (DWORD)-1) {
- la_dosmaperr(GetLastError());
+ if (GetLastError() != ERROR_FILE_NOT_FOUND) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+ ws = __la_win_permissive_name_w(temp_name.s);
+ if (ws == NULL) {
+ errno = EINVAL;
+ goto exit_tmpfile;
+ }
+ attr = GetFileAttributesW(ws);
+ if (attr == (DWORD)-1) {
+ la_dosmaperr(GetLastError());
+ goto exit_tmpfile;
+ }
+ }
+ if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
+ errno = ENOTDIR;
goto exit_tmpfile;
}
- }
- if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
- errno = ENOTDIR;
- goto exit_tmpfile;
- }
- /*
- * Create a temporary file.
- */
- archive_wstrcat(&temp_name, prefix);
- archive_wstrcat(&temp_name, suffix);
- ep = temp_name.s + archive_strlen(&temp_name);
- xp = ep - wcslen(suffix);
+ /*
+ * Create a temporary file.
+ */
+ archive_wstrcat(&temp_name, prefix);
+ archive_wstrcat(&temp_name, suffix);
+ ep = temp_name.s + archive_strlen(&temp_name);
+ xp = ep - wcslen(suffix);
+ template = temp_name.s;
+ } else {
+ xp = wcschr(template, L'X');
+ if (xp == NULL) /* No X, programming error */
+ abort();
+ for (ep = xp; *ep == L'X'; ep++)
+ continue;
+ if (*ep) /* X followed by non X, programming error */
+ abort();
+ }
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
@@ -323,20 +335,24 @@ __archive_mktemp(const char *tmpdir)
*p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
free(ws);
- ws = __la_win_permissive_name_w(temp_name.s);
+ ws = __la_win_permissive_name_w(template);
if (ws == NULL) {
errno = EINVAL;
goto exit_tmpfile;
}
- /* Specifies FILE_FLAG_DELETE_ON_CLOSE flag is to
- * delete this temporary file immediately when this
- * file closed. */
+ if (template == temp_name.s) {
+ attr = FILE_ATTRIBUTE_TEMPORARY |
+ FILE_FLAG_DELETE_ON_CLOSE;
+ } else {
+ /* mkstemp */
+ attr = FILE_ATTRIBUTE_NORMAL;
+ }
h = CreateFileW(ws,
GENERIC_READ | GENERIC_WRITE | DELETE,
0,/* Not share */
NULL,
CREATE_NEW,/* Create a new file only */
- FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
+ attr,
NULL);
if (h == INVALID_HANDLE_VALUE) {
/* The same file already exists. retry with
@@ -358,10 +374,23 @@ exit_tmpfile:
if (hProv != (HCRYPTPROV)NULL)
CryptReleaseContext(hProv, 0);
free(ws);
- archive_wstring_free(&temp_name);
+ if (template == temp_name.s)
+ archive_wstring_free(&temp_name);
return (fd);
}
+int
+__archive_mktemp(const char *tmpdir)
+{
+ return __archive_mktempx(tmpdir, NULL);
+}
+
+int
+__archive_mkstemp(wchar_t *template)
+{
+ return __archive_mktempx(NULL, template);
+}
+
#else
static int
@@ -414,14 +443,24 @@ exit_tmpfile:
return (fd);
}
-#else
+int
+__archive_mkstemp(char *template)
+{
+ int fd = -1;
+ fd = mkstemp(template);
+ if (fd >= 0)
+ __archive_ensure_cloexec_flag(fd);
+ return (fd);
+}
+
+#else /* !HAVE_MKSTEMP */
/*
* We use a private routine.
*/
-int
-__archive_mktemp(const char *tmpdir)
+static int
+__archive_mktempx(const char *tmpdir, char *template)
{
static const char num[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
@@ -439,26 +478,37 @@ __archive_mktemp(const char *tmpdir)
char *tp, *ep;
fd = -1;
- archive_string_init(&temp_name);
- if (tmpdir == NULL) {
- if (get_tempdir(&temp_name) != ARCHIVE_OK)
+ if (template == NULL) {
+ archive_string_init(&temp_name);
+ if (tmpdir == NULL) {
+ if (get_tempdir(&temp_name) != ARCHIVE_OK)
+ goto exit_tmpfile;
+ } else
+ archive_strcpy(&temp_name, tmpdir);
+ if (temp_name.s[temp_name.length-1] == '/') {
+ temp_name.s[temp_name.length-1] = '\0';
+ temp_name.length --;
+ }
+ if (la_stat(temp_name.s, &st) < 0)
goto exit_tmpfile;
- } else
- archive_strcpy(&temp_name, tmpdir);
- if (temp_name.s[temp_name.length-1] == '/') {
- temp_name.s[temp_name.length-1] = '\0';
- temp_name.length --;
- }
- if (la_stat(temp_name.s, &st) < 0)
- goto exit_tmpfile;
- if (!S_ISDIR(st.st_mode)) {
- errno = ENOTDIR;
- goto exit_tmpfile;
+ if (!S_ISDIR(st.st_mode)) {
+ errno = ENOTDIR;
+ goto exit_tmpfile;
+ }
+ archive_strcat(&temp_name, "/libarchive_");
+ tp = temp_name.s + archive_strlen(&temp_name);
+ archive_strcat(&temp_name, "XXXXXXXXXX");
+ ep = temp_name.s + archive_strlen(&temp_name);
+ template = temp_name.s;
+ } else {
+ tp = strchr(template, 'X');
+ if (tp == NULL) /* No X, programming error */
+ abort();
+ for (ep = tp; *ep == 'X'; ep++)
+ continue;
+ if (*ep) /* X followed by non X, programming error */
+ abort();
}
- archive_strcat(&temp_name, "/libarchive_");
- tp = temp_name.s + archive_strlen(&temp_name);
- archive_strcat(&temp_name, "XXXXXXXXXX");
- ep = temp_name.s + archive_strlen(&temp_name);
do {
char *p;
@@ -469,19 +519,33 @@ __archive_mktemp(const char *tmpdir)
int d = *((unsigned char *)p) % sizeof(num);
*p++ = num[d];
}
- fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
+ fd = open(template, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
0600);
} while (fd < 0 && errno == EEXIST);
if (fd < 0)
goto exit_tmpfile;
__archive_ensure_cloexec_flag(fd);
- unlink(temp_name.s);
+ if (template == temp_name.s)
+ unlink(temp_name.s);
exit_tmpfile:
- archive_string_free(&temp_name);
+ if (template == temp_name.s)
+ archive_string_free(&temp_name);
return (fd);
}
-#endif /* HAVE_MKSTEMP */
+int
+__archive_mktemp(const char *tmpdir)
+{
+ return __archive_mktempx(tmpdir, NULL);
+}
+
+int
+__archive_mkstemp(char *template)
+{
+ return __archive_mktempx(NULL, template);
+}
+
+#endif /* !HAVE_MKSTEMP */
#endif /* !_WIN32 || __CYGWIN__ */
/*
diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h
index 87d8c891bb0b2..47b7cb8e379f9 100644
--- a/libarchive/archive_windows.h
+++ b/libarchive/archive_windows.h
@@ -27,10 +27,6 @@
* $FreeBSD$
*/
-#ifndef __LIBARCHIVE_BUILD
-#error This header is only to be used internally to libarchive.
-#endif
-
/*
* TODO: A lot of stuff in here isn't actually used by libarchive and
* can be trimmed out. Note that this file is used by libarchive and
@@ -48,6 +44,10 @@
#ifndef LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
#define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+
/* Start of configuration for native Win32 */
#ifndef MINGW_HAS_SECURE_API
#define MINGW_HAS_SECURE_API 1
diff --git a/libarchive/archive_write_disk.3 b/libarchive/archive_write_disk.3
index ff8e1a36a75ce..2fa016e4547be 100644
--- a/libarchive/archive_write_disk.3
+++ b/libarchive/archive_write_disk.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 3, 2017
+.Dd January 19, 2020
.Dt ARCHIVE_WRITE_DISK 3
.Os
.Sh NAME
@@ -139,6 +139,11 @@ is not specified, then SUID and SGID bits will only be restored
if the default user and group IDs of newly-created objects on disk
happen to match those specified in the archive entry.
By default, only basic permissions are restored, and umask is obeyed.
+.It Cm ARCHIVE_EXTRACT_SAFE_WRITES
+Extract files atomically, by first creating a unique temporary file and then
+renaming it to its required destination name.
+This avoids a race where an application might see a partial file (or no
+file) during extraction.
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index df4b02f5efa13..cc53a3d318e01 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -253,6 +253,8 @@ struct archive_write_disk {
struct archive_entry *entry; /* Entry being extracted. */
char *name; /* Name of entry, possibly edited. */
struct archive_string _name_data; /* backing store for 'name' */
+ char *tmpname; /* Temporary name * */
+ struct archive_string _tmpname_data; /* backing store for 'tmpname' */
/* Tasks remaining for this object. */
int todo;
/* Tasks deferred until end-of-archive. */
@@ -354,6 +356,7 @@ struct archive_write_disk {
static int la_opendirat(int, const char *);
+static int la_mktemp(struct archive_write_disk *);
static void fsobj_error(int *, struct archive_string *, int, const char *,
const char *);
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
@@ -407,6 +410,30 @@ static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
size_t, int64_t);
static int
+la_mktemp(struct archive_write_disk *a)
+{
+ int oerrno, fd;
+ mode_t mode;
+
+ archive_string_empty(&a->_tmpname_data);
+ archive_string_sprintf(&a->_tmpname_data, "%s.XXXXXX", a->name);
+ a->tmpname = a->_tmpname_data.s;
+
+ fd = __archive_mkstemp(a->tmpname);
+ if (fd == -1)
+ return -1;
+
+ mode = a->mode & 0777 & ~a->user_umask;
+ if (fchmod(fd, mode) == -1) {
+ oerrno = errno;
+ close(fd);
+ errno = oerrno;
+ return -1;
+ }
+ return fd;
+}
+
+static int
la_opendirat(int fd, const char *path) {
const int flags = O_CLOEXEC
#if defined(O_BINARY)
@@ -1826,6 +1853,14 @@ finish_metadata:
if (a->fd >= 0) {
close(a->fd);
a->fd = -1;
+ if (a->tmpname) {
+ if (rename(a->tmpname, a->name) == -1) {
+ archive_set_error(&a->archive, errno,
+ "rename failed");
+ ret = ARCHIVE_FATAL;
+ }
+ a->tmpname = NULL;
+ }
}
/* If there's an entry, we can release it now. */
archive_entry_free(a->entry);
@@ -2103,17 +2138,28 @@ restore_entry(struct archive_write_disk *a)
}
if (!S_ISDIR(a->st.st_mode)) {
- /* A non-dir is in the way, unlink it. */
if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
(void)clear_nochange_fflags(a);
- if (unlink(a->name) != 0) {
- archive_set_error(&a->archive, errno,
- "Can't unlink already-existing object");
- return (ARCHIVE_FAILED);
+
+ if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
+ S_ISREG(a->st.st_mode)) {
+ /* Use a temporary file to extract */
+ if ((a->fd = la_mktemp(a)) == -1)
+ return ARCHIVE_FAILED;
+ a->pst = NULL;
+ en = 0;
+ } else {
+ /* A non-dir is in the way, unlink it. */
+ if (unlink(a->name) != 0) {
+ archive_set_error(&a->archive, errno,
+ "Can't unlink already-existing "
+ "object");
+ return (ARCHIVE_FAILED);
+ }
+ a->pst = NULL;
+ /* Try again. */
+ en = create_filesystem_object(a);
}
- a->pst = NULL;
- /* Try again. */
- en = create_filesystem_object(a);
} else if (!S_ISDIR(a->mode)) {
/* A dir is in the way of a non-dir, rmdir it. */
if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
@@ -2215,6 +2261,13 @@ create_filesystem_object(struct archive_write_disk *a)
}
free(linkname_copy);
archive_string_free(&error_string);
+ /*
+ * Unlinking and linking here is really not atomic,
+ * but doing it right, would require us to construct
+ * an mktemplink() function, and then use rename(2).
+ */
+ if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
+ unlink(a->name);
r = link(linkname, a->name) ? errno : 0;
/*
* New cpio and pax formats allow hardlink entries
@@ -2253,6 +2306,13 @@ create_filesystem_object(struct archive_write_disk *a)
linkname = archive_entry_symlink(a->entry);
if (linkname != NULL) {
#if HAVE_SYMLINK
+ /*
+ * Unlinking and linking here is really not atomic,
+ * but doing it right, would require us to construct
+ * an mktempsymlink() function, and then use rename(2).
+ */
+ if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
+ unlink(a->name);
return symlink(linkname, a->name) ? errno : 0;
#else
return (EPERM);
@@ -2288,6 +2348,7 @@ create_filesystem_object(struct archive_write_disk *a)
/* POSIX requires that we fall through here. */
/* FALLTHROUGH */
case AE_IFREG:
+ a->tmpname = NULL;
a->fd = open(a->name,
O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode);
__archive_ensure_cloexec_flag(a->fd);
@@ -2449,6 +2510,7 @@ _archive_write_disk_free(struct archive *_a)
archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
archive_entry_free(a->entry);
archive_string_free(&a->_name_data);
+ archive_string_free(&a->_tmpname_data);
archive_string_free(&a->archive.error_string);
archive_string_free(&a->path_safe);
a->archive.magic = 0;
diff --git a/libarchive/archive_write_disk_private.h b/libarchive/archive_write_disk_private.h
index b655dea2b659b..557d7e2bf34fc 100644
--- a/libarchive/archive_write_disk_private.h
+++ b/libarchive/archive_write_disk_private.h
@@ -26,13 +26,13 @@
* $FreeBSD: head/lib/libarchive/archive_write_disk_private.h 201086 2009-12-28 02:17:53Z kientzle $
*/
+#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
+#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
-#define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED
-
#include "archive_platform_acl.h"
#include "archive_acl_private.h"
#include "archive_entry.h"
diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c
index 8b947304bd61a..77e36c4a621dd 100644
--- a/libarchive/archive_write_disk_windows.c
+++ b/libarchive/archive_write_disk_windows.c
@@ -165,6 +165,8 @@ struct archive_write_disk {
struct archive_entry *entry; /* Entry being extracted. */
wchar_t *name; /* Name of entry, possibly edited. */
struct archive_wstring _name_data; /* backing store for 'name' */
+ wchar_t *tmpname; /* Temporary name */
+ struct archive_wstring _tmpname_data; /* backing store for 'tmpname' */
/* Tasks remaining for this object. */
int todo;
/* Tasks deferred until end-of-archive. */
@@ -215,6 +217,7 @@ static int cleanup_pathname(struct archive_write_disk *);
static int create_dir(struct archive_write_disk *, wchar_t *);
static int create_parent_dir(struct archive_write_disk *, wchar_t *);
static int la_chmod(const wchar_t *, mode_t);
+static int la_mktemp(struct archive_write_disk *);
static int older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *);
static int permissive_name_w(struct archive_write_disk *);
static int restore_entry(struct archive_write_disk *);
@@ -534,6 +537,28 @@ exit_chmode:
return (ret);
}
+static int
+la_mktemp(struct archive_write_disk *a)
+{
+ int fd;
+ mode_t mode;
+
+ archive_wstring_empty(&(a->_tmpname_data));
+ archive_wstrcpy(&(a->_tmpname_data), a->name);
+ archive_wstrcat(&(a->_tmpname_data), L".XXXXXX");
+ a->tmpname = a->_tmpname_data.s;
+
+ fd = __archive_mkstemp(a->tmpname);
+
+ mode = a->mode & 0777 & ~a->user_umask;
+ if (la_chmod(a->tmpname, mode) == -1) {
+ la_dosmaperr(GetLastError());
+ _close(fd);
+ return -1;
+ }
+ return (fd);
+}
+
static void *
la_GetFunctionKernel32(const char *name)
{
@@ -1252,6 +1277,16 @@ _archive_write_disk_finish_entry(struct archive *_a)
if (a->fh != INVALID_HANDLE_VALUE) {
CloseHandle(a->fh);
a->fh = INVALID_HANDLE_VALUE;
+ if (a->tmpname) {
+ /* Windows does not support atomic rename */
+ disk_unlink(a->name);
+ if (_wrename(a->tmpname, a->name) != 0) {
+ archive_set_error(&a->archive, errno,
+ "rename failed");
+ ret = ARCHIVE_FATAL;
+ }
+ a->tmpname = NULL;
+ }
}
/* If there's an entry, we can release it now. */
archive_entry_free(a->entry);
@@ -1530,26 +1565,46 @@ restore_entry(struct archive_write_disk *a)
}
if (!S_ISDIR(st_mode)) {
- /* Edge case: a directory symlink pointing to a file */
if (a->flags &
ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) {
(void)clear_nochange_fflags(a);
}
- if (dirlnk) {
- if (disk_rmdir(a->name) != 0) {
- archive_set_error(&a->archive, errno,
- "Can't unlink directory symlink");
+ if ((a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) &&
+ S_ISREG(st_mode)) {
+ int fd = la_mktemp(a);
+
+ if (fd == -1)
+ return (ARCHIVE_FAILED);
+ a->fh = (HANDLE)_get_osfhandle(fd);
+ if (a->fh == INVALID_HANDLE_VALUE)
return (ARCHIVE_FAILED);
+
+ a->pst = NULL;
+ en = 0;
+ } else {
+ if (dirlnk) {
+ /* Edge case: dir symlink pointing
+ * to a file */
+ if (disk_rmdir(a->name) != 0) {
+ archive_set_error(&a->archive,
+ errno, "Can't unlink "
+ "directory symlink");
+ return (ARCHIVE_FAILED);
+ }
+ } else {
+ if (disk_unlink(a->name) != 0) {
+ /* A non-dir is in the way,
+ * unlink it. */
+ archive_set_error(&a->archive,
+ errno, "Can't unlink "
+ "already-existing object");
+ return (ARCHIVE_FAILED);
+ }
}
- } else if (disk_unlink(a->name) != 0) {
- /* A non-dir is in the way, unlink it. */
- archive_set_error(&a->archive, errno,
- "Can't unlink already-existing object");
- return (ARCHIVE_FAILED);
+ a->pst = NULL;
+ /* Try again. */
+ en = create_filesystem_object(a);
}
- a->pst = NULL;
- /* Try again. */
- en = create_filesystem_object(a);
} else if (!S_ISDIR(a->mode)) {
/* A dir is in the way of a non-dir, rmdir it. */
if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS)
@@ -1601,6 +1656,7 @@ create_filesystem_object(struct archive_write_disk *a)
wchar_t *fullname;
mode_t final_mode, mode;
int r;
+ DWORD attrs = 0;
/* We identify hard/symlinks according to the link names. */
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
@@ -1614,6 +1670,20 @@ create_filesystem_object(struct archive_write_disk *a)
errno = EINVAL;
r = -1;
} else {
+ /*
+ * Unlinking and linking here is really not atomic,
+ * but doing it right, would require us to construct
+ * an mktemplink() function, and then use _wrename().
+ */
+ if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES) {
+ attrs = GetFileAttributesW(namefull);
+ if (attrs != INVALID_FILE_ATTRIBUTES) {
+ if (attrs & FILE_ATTRIBUTE_DIRECTORY)
+ disk_rmdir(namefull);
+ else
+ disk_unlink(namefull);
+ }
+ }
r = la_CreateHardLinkW(namefull, linkfull);
if (r == 0) {
la_dosmaperr(GetLastError());
@@ -1650,6 +1720,18 @@ create_filesystem_object(struct archive_write_disk *a)
}
linkname = archive_entry_symlink_w(a->entry);
if (linkname != NULL) {
+ /*
+ * Unlinking and linking here is really not atomic,
+ * but doing it right, would require us to construct
+ * an mktemplink() function, and then use _wrename().
+ */
+ attrs = GetFileAttributesW(a->name);
+ if (attrs != INVALID_FILE_ATTRIBUTES) {
+ if (attrs & FILE_ATTRIBUTE_DIRECTORY)
+ disk_rmdir(a->name);
+ else
+ disk_unlink(a->name);
+ }
#if HAVE_SYMLINK
return symlink(linkname, a->name) ? errno : 0;
#else
@@ -1686,6 +1768,7 @@ create_filesystem_object(struct archive_write_disk *a)
/* POSIX requires that we fall through here. */
/* FALLTHROUGH */
case AE_IFREG:
+ a->tmpname = NULL;
fullname = a->name;
/* O_WRONLY | O_CREAT | O_EXCL */
a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
@@ -1842,6 +1925,7 @@ _archive_write_disk_free(struct archive *_a)
archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
archive_entry_free(a->entry);
archive_wstring_free(&a->_name_data);
+ archive_wstring_free(&a->_tmpname_data);
archive_string_free(&a->archive.error_string);
archive_wstring_free(&a->path_safe);
a->archive.magic = 0;
diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h
index 1c182f1368017..27cba0392ce1f 100644
--- a/libarchive/archive_write_private.h
+++ b/libarchive/archive_write_private.h
@@ -25,15 +25,15 @@
* $FreeBSD: head/lib/libarchive/archive_write_private.h 201155 2009-12-29 05:20:12Z kientzle $
*/
+#ifndef ARCHIVE_WRITE_PRIVATE_H_INCLUDED
+#define ARCHIVE_WRITE_PRIVATE_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
#endif
-#ifndef ARCHIVE_WRITE_PRIVATE_H_INCLUDED
-#define ARCHIVE_WRITE_PRIVATE_H_INCLUDED
-
#include "archive.h"
#include "archive_string.h"
#include "archive_private.h"
diff --git a/libarchive/archive_write_set_format.c b/libarchive/archive_write_set_format.c
index 0f706231add1e..12de080775345 100644
--- a/libarchive/archive_write_set_format.c
+++ b/libarchive/archive_write_set_format.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format.c 201168 2009-1
#include "archive.h"
#include "archive_private.h"
+#include "archive_write_set_format_private.h"
/* A table that maps format codes to functions. */
static const
@@ -76,3 +77,47 @@ archive_write_set_format(struct archive *a, int code)
archive_set_error(a, EINVAL, "No such format");
return (ARCHIVE_FATAL);
}
+
+void
+__archive_write_entry_filetype_unsupported(struct archive *a,
+ struct archive_entry *entry, const char *format)
+{
+ char *name = NULL;
+
+ switch (archive_entry_filetype(entry)) {
+ /*
+ * All formats should be able to archive regular files (AE_IFREG)
+ */
+ case AE_IFDIR:
+ name = "directories";
+ break;
+ case AE_IFLNK:
+ name = "symbolic links";
+ break;
+ case AE_IFCHR:
+ name = "character devices";
+ break;
+ case AE_IFBLK:
+ name = "block devices";
+ break;
+ case AE_IFIFO:
+ name = "named pipes";
+ break;
+ case AE_IFSOCK:
+ name = "sockets";
+ break;
+ default:
+ break;
+ }
+
+ if (name != NULL) {
+ archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
+ "%s: %s format cannot archive %s",
+ archive_entry_pathname(entry), format, name);
+ } else {
+ archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
+ "%s: %s format cannot archive files with mode 0%lo",
+ archive_entry_pathname(entry), format,
+ (unsigned long)archive_entry_mode(entry));
+ }
+}
diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c
index 92a87f74e6250..fb7697f659ca7 100644
--- a/libarchive/archive_write_set_format_7zip.c
+++ b/libarchive/archive_write_set_format_7zip.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include "archive_rb.h"
#include "archive_string.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
/*
* Codec ID
@@ -164,7 +165,7 @@ struct file {
mode_t mode;
uint32_t crc32;
- int dir:1;
+ signed int dir:1;
};
struct _7zip {
diff --git a/libarchive/archive_write_set_format_ar.c b/libarchive/archive_write_set_format_ar.c
index 253cac82efe6a..fc0de1e9f6f0b 100644
--- a/libarchive/archive_write_set_format_ar.c
+++ b/libarchive/archive_write_set_format_ar.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ar.c 201108 200
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct ar_w {
uint64_t entry_bytes_remaining;
diff --git a/libarchive/archive_write_set_format_cpio.c b/libarchive/archive_write_set_format_cpio.c
index 16cefad7b5b32..729f9c7755915 100644
--- a/libarchive/archive_write_set_format_cpio.c
+++ b/libarchive/archive_write_set_format_cpio.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
static ssize_t archive_write_cpio_data(struct archive_write *,
const void *buff, size_t s);
diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c
index 2d923cc33061f..172fda62f0bb7 100644
--- a/libarchive/archive_write_set_format_cpio_newc.c
+++ b/libarchive/archive_write_set_format_cpio_newc.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_cpio_newc.c 201
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
static ssize_t archive_write_newc_data(struct archive_write *,
const void *buff, size_t s);
diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c
index e7757c22badd5..ec29c5c418e4e 100644
--- a/libarchive/archive_write_set_format_gnutar.c
+++ b/libarchive/archive_write_set_format_gnutar.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_gnu_tar.c 19157
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct gnutar {
uint64_t entry_bytes_remaining;
@@ -534,17 +535,9 @@ archive_write_gnutar_header(struct archive_write *a,
case AE_IFBLK: tartype = '4' ; break;
case AE_IFDIR: tartype = '5' ; break;
case AE_IFIFO: tartype = '6' ; break;
- case AE_IFSOCK:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive socket");
- ret = ARCHIVE_FAILED;
- goto exit_write_header;
- default:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive this (mode=0%lo)",
- (unsigned long)archive_entry_mode(entry));
+ default: /* AE_IFSOCK and unknown */
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry, "gnutar");
ret = ARCHIVE_FAILED;
goto exit_write_header;
}
diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c
index cacbdde7dcb0f..7cde44c34f752 100644
--- a/libarchive/archive_write_set_format_iso9660.c
+++ b/libarchive/archive_write_set_format_iso9660.c
@@ -289,12 +289,12 @@ struct isoent {
struct extr_rec *current;
} extr_rec_list;
- int virtual:1;
+ signed int virtual:1;
/* If set to one, this file type is a directory.
* A convenience flag to be used as
* "archive_entry_filetype(isoent->file->entry) == AE_IFDIR".
*/
- int dir:1;
+ signed int dir:1;
};
struct hardlink {
@@ -755,9 +755,9 @@ struct iso9660 {
/* Used for making zisofs. */
struct {
- int detect_magic:1;
- int making:1;
- int allzero:1;
+ signed int detect_magic:1;
+ signed int making:1;
+ signed int allzero:1;
unsigned char magic_buffer[64];
int magic_cnt;
@@ -5094,13 +5094,11 @@ isofile_init_hardlinks(struct iso9660 *iso9660)
static void
isofile_free_hardlinks(struct iso9660 *iso9660)
{
- struct archive_rb_node *n, *next;
+ struct archive_rb_node *n, *tmp;
- for (n = ARCHIVE_RB_TREE_MIN(&(iso9660->hardlink_rbtree)); n;) {
- next = __archive_rb_tree_iterate(&(iso9660->hardlink_rbtree),
- n, ARCHIVE_RB_DIR_RIGHT);
+ ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(iso9660->hardlink_rbtree), tmp) {
+ __archive_rb_tree_remove_node(&(iso9660->hardlink_rbtree), n);
free(n);
- n = next;
}
}
@@ -7801,8 +7799,8 @@ struct zisofs_extract {
uint64_t pz_uncompressed_size;
size_t uncompressed_buffer_size;
- int initialized:1;
- int header_passed:1;
+ signed int initialized:1;
+ signed int header_passed:1;
uint32_t pz_offset;
unsigned char *block_pointers;
diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c
index 7c5e63bb3a233..a2b27107195de 100644
--- a/libarchive/archive_write_set_format_pax.c
+++ b/libarchive/archive_write_set_format_pax.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_pax.c 201162 20
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct sparse_block {
struct sparse_block *next;
@@ -713,17 +714,9 @@ archive_write_pax_header(struct archive_write *a,
}
break;
}
- case AE_IFSOCK:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive socket");
- return (ARCHIVE_FAILED);
- default:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive this (type=0%lo)",
- (unsigned long)
- archive_entry_filetype(entry_original));
+ default: /* AE_IFSOCK and unknown */
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry_original, "pax");
return (ARCHIVE_FAILED);
}
}
@@ -859,13 +852,16 @@ archive_write_pax_header(struct archive_write *a,
* them do.
*/
r = get_entry_pathname(a, entry_main, &path, &path_length, sconv);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
- else if (r != ARCHIVE_OK) {
+ } else if (r != ARCHIVE_OK) {
r = get_entry_pathname(a, entry_main, &path,
&path_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate pathname '%s' to %s", path,
archive_string_conversion_charset_name(sconv));
@@ -873,12 +869,15 @@ archive_write_pax_header(struct archive_write *a,
sconv = NULL;/* The header charset switches to binary mode. */
}
r = get_entry_uname(a, entry_main, &uname, &uname_length, sconv);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
- else if (r != ARCHIVE_OK) {
+ } else if (r != ARCHIVE_OK) {
r = get_entry_uname(a, entry_main, &uname, &uname_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate uname '%s' to %s", uname,
archive_string_conversion_charset_name(sconv));
@@ -886,12 +885,15 @@ archive_write_pax_header(struct archive_write *a,
sconv = NULL;/* The header charset switches to binary mode. */
}
r = get_entry_gname(a, entry_main, &gname, &gname_length, sconv);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
- else if (r != ARCHIVE_OK) {
+ } else if (r != ARCHIVE_OK) {
r = get_entry_gname(a, entry_main, &gname, &gname_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate gname '%s' to %s", gname,
archive_string_conversion_charset_name(sconv));
@@ -903,13 +905,16 @@ archive_write_pax_header(struct archive_write *a,
if (linkpath == NULL) {
r = get_entry_symlink(a, entry_main, &linkpath,
&linkpath_length, sconv);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
- else if (r != ARCHIVE_OK) {
+ } else if (r != ARCHIVE_OK) {
r = get_entry_symlink(a, entry_main, &linkpath,
&linkpath_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Can't translate linkname '%s' to %s", linkpath,
@@ -925,21 +930,29 @@ archive_write_pax_header(struct archive_write *a,
if (hardlink != NULL) {
r = get_entry_hardlink(a, entry_main, &hardlink,
&hardlink_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
linkpath = hardlink;
linkpath_length = hardlink_length;
}
r = get_entry_pathname(a, entry_main, &path,
&path_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
r = get_entry_uname(a, entry_main, &uname, &uname_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
r = get_entry_gname(a, entry_main, &gname, &gname_length, NULL);
- if (r == ARCHIVE_FATAL)
+ if (r == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
return (r);
+ }
}
/* Store the header encoding first, to be nice to readers. */
@@ -1196,24 +1209,33 @@ archive_write_pax_header(struct archive_write *a,
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA |
ARCHIVE_ENTRY_ACL_STYLE_COMPACT);
- if (ret == ARCHIVE_FATAL)
+ if (ret == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
+ }
}
if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
ret = add_pax_acl(a, entry_original, pax,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
- if (ret == ARCHIVE_FATAL)
+ if (ret == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
+ }
}
if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) {
ret = add_pax_acl(a, entry_original, pax,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA);
- if (ret == ARCHIVE_FATAL)
+ if (ret == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
+ }
}
/* We use GNU-tar-compatible sparse attributes. */
@@ -1352,8 +1374,11 @@ archive_write_pax_header(struct archive_write *a,
* numeric fields, though they're less critical.
*/
if (__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0,
- NULL) == ARCHIVE_FATAL)
+ NULL) == ARCHIVE_FATAL) {
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
+ }
/* If we built any extended attributes, write that entry first. */
if (archive_strlen(&(pax->pax_header)) > 0) {
@@ -1418,6 +1443,8 @@ archive_write_pax_header(struct archive_write *a,
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"archive_write_pax_header: "
"'x' header failed?! This can't happen.\n");
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
} else if (r < ret)
ret = r;
@@ -1426,6 +1453,8 @@ archive_write_pax_header(struct archive_write *a,
sparse_list_clear(pax);
pax->entry_bytes_remaining = 0;
pax->entry_padding = 0;
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
}
@@ -1437,12 +1466,16 @@ archive_write_pax_header(struct archive_write *a,
archive_strlen(&(pax->pax_header)));
if (r != ARCHIVE_OK) {
/* If a write fails, we're pretty much toast. */
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
}
/* Pad out the end of the entry. */
r = __archive_write_nulls(a, (size_t)pax->entry_padding);
if (r != ARCHIVE_OK) {
/* If a write fails, we're pretty much toast. */
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (ARCHIVE_FATAL);
}
pax->entry_bytes_remaining = pax->entry_padding = 0;
@@ -1450,8 +1483,11 @@ archive_write_pax_header(struct archive_write *a,
/* Write the header for main entry. */
r = __archive_write_output(a, ustarbuff, 512);
- if (r != ARCHIVE_OK)
+ if (r != ARCHIVE_OK) {
+ archive_entry_free(entry_main);
+ archive_string_free(&entry_name);
return (r);
+ }
/*
* Inform the client of the on-disk size we're using, so
diff --git a/libarchive/archive_write_set_format_private.h b/libarchive/archive_write_set_format_private.h
new file mode 100644
index 0000000000000..e20022755f8bb
--- /dev/null
+++ b/libarchive/archive_write_set_format_private.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2020 Martin Matuska
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef ARCHIVE_WRITE_SET_FORMAT_PRIVATE_H_INCLUDED
+#define ARCHIVE_WRITE_SET_FORMAT_PRIVATE_H_INCLUDED
+
+#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
+#error This header is only to be used internally to libarchive.
+#endif
+#endif
+
+#include "archive.h"
+#include "archive_entry.h"
+
+void __archive_write_entry_filetype_unsupported(struct archive *a,
+ struct archive_entry *entry, const char *format);
+#endif
diff --git a/libarchive/archive_write_set_format_shar.c b/libarchive/archive_write_set_format_shar.c
index 600c88257a0ce..9e4931c95c1fa 100644
--- a/libarchive/archive_write_set_format_shar.c
+++ b/libarchive/archive_write_set_format_shar.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_shar.c 189438 2
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct shar {
int dump;
@@ -194,8 +195,8 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
archive_entry_set_size(entry, 0);
if (archive_entry_hardlink(entry) == NULL &&
archive_entry_symlink(entry) == NULL) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "shar format cannot archive this");
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry, "shar");
return (ARCHIVE_WARN);
}
}
diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c
index ad4ccb77ea53a..d1a06bc4f7ec1 100644
--- a/libarchive/archive_write_set_format_ustar.c
+++ b/libarchive/archive_write_set_format_ustar.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_ustar.c 191579
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct ustar {
uint64_t entry_bytes_remaining;
@@ -512,9 +513,11 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
}
if (copy_length > 0) {
if (copy_length > USTAR_uname_size) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Username too long");
- ret = ARCHIVE_FAILED;
+ if (tartype != 'x') {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC, "Username too long");
+ ret = ARCHIVE_FAILED;
+ }
copy_length = USTAR_uname_size;
}
memcpy(h + USTAR_uname_offset, p, copy_length);
@@ -535,9 +538,11 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
}
if (copy_length > 0) {
if (strlen(p) > USTAR_gname_size) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Group name too long");
- ret = ARCHIVE_FAILED;
+ if (tartype != 'x') {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_MISC, "Group name too long");
+ ret = ARCHIVE_FAILED;
+ }
copy_length = USTAR_gname_size;
}
memcpy(h + USTAR_gname_offset, p, copy_length);
@@ -609,16 +614,9 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
case AE_IFBLK: h[USTAR_typeflag_offset] = '4' ; break;
case AE_IFDIR: h[USTAR_typeflag_offset] = '5' ; break;
case AE_IFIFO: h[USTAR_typeflag_offset] = '6' ; break;
- case AE_IFSOCK:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive socket");
- return (ARCHIVE_FAILED);
- default:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive this (mode=0%lo)",
- (unsigned long)archive_entry_mode(entry));
+ default: /* AE_IFSOCK and unknown */
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry, "ustar");
ret = ARCHIVE_FAILED;
}
}
diff --git a/libarchive/archive_write_set_format_v7tar.c b/libarchive/archive_write_set_format_v7tar.c
index 1fdaafd2a9391..5994071441211 100644
--- a/libarchive/archive_write_set_format_v7tar.c
+++ b/libarchive/archive_write_set_format_v7tar.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct v7tar {
uint64_t entry_bytes_remaining;
@@ -491,31 +492,11 @@ format_header_v7tar(struct archive_write *a, char h[512],
case AE_IFLNK:
h[V7TAR_typeflag_offset] = '2';
break;
- case AE_IFCHR:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive character device");
- return (ARCHIVE_FAILED);
- case AE_IFBLK:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive block device");
- return (ARCHIVE_FAILED);
- case AE_IFIFO:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive fifo");
- return (ARCHIVE_FAILED);
- case AE_IFSOCK:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive socket");
- return (ARCHIVE_FAILED);
default:
- archive_set_error(&a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "tar format cannot archive this (mode=0%lo)",
- (unsigned long)archive_entry_mode(entry));
+ /* AE_IFBLK, AE_IFCHR, AE_IFIFO, AE_IFSOCK
+ * and unknown */
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry, "v7tar");
ret = ARCHIVE_FAILED;
}
}
diff --git a/libarchive/archive_write_set_format_warc.c b/libarchive/archive_write_set_format_warc.c
index edad072cf77d2..46b05734121c3 100644
--- a/libarchive/archive_write_set_format_warc.c
+++ b/libarchive/archive_write_set_format_warc.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include "archive_private.h"
#include "archive_random_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
struct warc_s {
unsigned int omit_warcinfo:1;
@@ -259,10 +260,8 @@ _warc_header(struct archive_write *a, struct archive_entry *entry)
return (ARCHIVE_OK);
}
/* just resort to erroring as per Tim's advice */
- archive_set_error(
- &a->archive,
- ARCHIVE_ERRNO_FILE_FORMAT,
- "WARC can only process regular files");
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry, "WARC");
return (ARCHIVE_FAILED);
}
@@ -333,6 +332,10 @@ xstrftime(struct archive_string *as, const char *fmt, time_t t)
#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
struct tm timeHere;
#endif
+#if defined(HAVE__GMTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
char strtime[100];
size_t len;
@@ -340,7 +343,12 @@ xstrftime(struct archive_string *as, const char *fmt, time_t t)
if ((rt = gmtime_r(&t, &timeHere)) == NULL)
return;
#elif defined(HAVE__GMTIME64_S)
- _gmtime64_s(&timeHere, &t);
+ tmptime = t;
+ terr = _gmtime64_s(&timeHere, &tmptime);
+ if (terr)
+ rt = NULL;
+ else
+ rt = &timeHere;
#else
if ((rt = gmtime(&t)) == NULL)
return;
diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c
index 5e4b90e06b3f3..d456cf8f8aa97 100644
--- a/libarchive/archive_write_set_format_xar.c
+++ b/libarchive/archive_write_set_format_xar.c
@@ -212,8 +212,8 @@ struct file {
struct heap_data data;
struct archive_string script;
- int virtual:1;
- int dir:1;
+ signed int virtual:1;
+ signed int dir:1;
};
struct hardlink {
@@ -411,6 +411,8 @@ xar_options(struct archive_write *a, const char *key, const char *value)
if (strcmp(key, "checksum") == 0) {
if (value == NULL)
xar->opt_sumalg = CKSUM_NONE;
+ else if (strcmp(value, "none") == 0)
+ xar->opt_sumalg = CKSUM_NONE;
else if (strcmp(value, "sha1") == 0)
xar->opt_sumalg = CKSUM_SHA1;
else if (strcmp(value, "md5") == 0)
@@ -429,6 +431,8 @@ xar_options(struct archive_write *a, const char *key, const char *value)
if (value == NULL)
xar->opt_compression = NONE;
+ else if (strcmp(value, "none") == 0)
+ xar->opt_compression = NONE;
else if (strcmp(value, "gzip") == 0)
xar->opt_compression = GZIP;
else if (strcmp(value, "bzip2") == 0)
@@ -482,6 +486,8 @@ xar_options(struct archive_write *a, const char *key, const char *value)
if (strcmp(key, "toc-checksum") == 0) {
if (value == NULL)
xar->opt_toc_sumalg = CKSUM_NONE;
+ else if (strcmp(value, "none") == 0)
+ xar->opt_toc_sumalg = CKSUM_NONE;
else if (strcmp(value, "sha1") == 0)
xar->opt_toc_sumalg = CKSUM_SHA1;
else if (strcmp(value, "md5") == 0)
@@ -696,13 +702,37 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s)
else
run = ARCHIVE_Z_FINISH;
/* Compress file data. */
- r = compression_code(&(a->archive), &(xar->stream), run);
- if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
- return (ARCHIVE_FATAL);
+ for (;;) {
+ r = compression_code(&(a->archive), &(xar->stream),
+ run);
+ if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
+ return (ARCHIVE_FATAL);
+ if (xar->stream.avail_out == 0 ||
+ run == ARCHIVE_Z_FINISH) {
+ size = sizeof(xar->wbuff) -
+ xar->stream.avail_out;
+ checksum_update(&(xar->a_sumwrk), xar->wbuff,
+ size);
+ xar->cur_file->data.length += size;
+ if (write_to_temp(a, xar->wbuff,
+ size) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+ if (r == ARCHIVE_OK) {
+ /* Output buffer was full */
+ xar->stream.next_out = xar->wbuff;
+ xar->stream.avail_out =
+ sizeof(xar->wbuff);
+ } else {
+ /* ARCHIVE_EOF - We are done */
+ break;
+ }
+ } else {
+ /* Compressor wants more input */
+ break;
+ }
+ }
rsize = s - xar->stream.avail_in;
checksum_update(&(xar->e_sumwrk), buff, rsize);
- size = sizeof(xar->wbuff) - xar->stream.avail_out;
- checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
}
#if !defined(_WIN32) || defined(__CYGWIN__)
if (xar->bytes_remaining ==
@@ -739,12 +769,9 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s)
if (xar->cur_file->data.compression == NONE) {
if (write_to_temp(a, buff, size) != ARCHIVE_OK)
return (ARCHIVE_FATAL);
- } else {
- if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
+ xar->cur_file->data.length += size;
}
xar->bytes_remaining -= rsize;
- xar->cur_file->data.length += size;
return (rsize);
}
@@ -878,11 +905,15 @@ xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer,
{
char timestr[100];
struct tm tm;
+#if defined(HAVE__GMTIME64_S)
+ __time64_t tmptime;
+#endif
#if defined(HAVE_GMTIME_R)
gmtime_r(&t, &tm);
#elif defined(HAVE__GMTIME64_S)
- _gmtime64_s(&tm, &t);
+ tmptime = t;
+ _gmtime64_s(&tm, &tmptime);
#else
memcpy(&tm, gmtime(&t), sizeof(tm));
#endif
@@ -2103,7 +2134,7 @@ file_gen_utility_names(struct archive_write *a, struct file *file)
while (len > 0) {
size_t ll = len;
- if (len > 0 && p[len-1] == '/') {
+ if (p[len-1] == '/') {
p[len-1] = '\0';
len--;
}
@@ -2532,13 +2563,11 @@ file_init_hardlinks(struct xar *xar)
static void
file_free_hardlinks(struct xar *xar)
{
- struct archive_rb_node *n, *next;
+ struct archive_rb_node *n, *tmp;
- for (n = ARCHIVE_RB_TREE_MIN(&(xar->hardlink_rbtree)); n;) {
- next = __archive_rb_tree_iterate(&(xar->hardlink_rbtree),
- n, ARCHIVE_RB_DIR_RIGHT);
+ ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(xar->hardlink_rbtree), tmp) {
+ __archive_rb_tree_remove_node(&(xar->hardlink_rbtree), n);
free(n);
- n = next;
}
}
diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c
index f28a8c3a341f3..6d485295d50ff 100644
--- a/libarchive/archive_write_set_format_zip.c
+++ b/libarchive/archive_write_set_format_zip.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 20
#include "archive_private.h"
#include "archive_random_private.h"
#include "archive_write_private.h"
+#include "archive_write_set_format_private.h"
#ifndef HAVE_ZLIB_H
#include "archive_crc32.h"
@@ -526,8 +527,8 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
/* Ignore types of entries that we don't support. */
type = archive_entry_filetype(entry);
if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Filetype not supported");
+ __archive_write_entry_filetype_unsupported(
+ &a->archive, entry, "zip");
return ARCHIVE_FAILED;
};
@@ -1372,10 +1373,28 @@ dos_time(const time_t unix_time)
{
struct tm *t;
unsigned int dt;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
/* This will not preserve time when creating/extracting the archive
* on two systems with different time zones. */
+#if defined(HAVE_LOCALTIME_R)
+ t = localtime_r(&unix_time, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = unix_time;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ t = NULL;
+ else
+ t = &tmbuf;
+#else
t = localtime(&unix_time);
+#endif
/* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */
if (t->tm_year < 1980 - 1900)
diff --git a/libarchive/archive_write_set_options.3 b/libarchive/archive_write_set_options.3
index 09eb95ea5aa9a..cffe571e90a61 100644
--- a/libarchive/archive_write_set_options.3
+++ b/libarchive/archive_write_set_options.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 3, 2019
+.Dd January 31, 2020
.Dt ARCHIVE_WRITE_OPTIONS 3
.Os
.Sh NAME
@@ -170,33 +170,125 @@ only to modules whose name matches
.\"
.Sh OPTIONS
.Bl -tag -compact -width indent
+.It Filter b64encode
+.Bl -tag -compact -width indent
+.It Cm mode
+The value is interpreted as octal digits specifying the file mode.
+.It Cm name
+The value specifies the file name.
+.El
+.It Filter bzip2
+.Bl -tag -compact -width indent
+.It Cm compression-level
+The value is interpreted as a decimal integer specifying the
+bzip2 compression level. Supported values are from 1 to 9.
+.El
.It Filter gzip
.Bl -tag -compact -width indent
.It Cm compression-level
The value is interpreted as a decimal integer specifying the
-gzip compression level.
+gzip compression level. Supported values are from 0 to 9.
+.It Cm timestamp
+Store timestamp. This is enabled by default.
+.El
+.It Filter lrzip
+.Bl -tag -compact -width indent
+.It Cm compression Ns = Ns Ar type
+Use
+.Ar type
+as compression method.
+Supported values are
+.Dq bzip2 ,
+.Dq gzipi ,
+.Dq lzo
+.Pq ultra fast ,
+and
+.Dq zpaq
+.Pq best, extremely slow .
+.It Cm compression-level
+The value is interpreted as a decimal integer specifying the
+lrzip compression level. Supported values are from 1 to 9.
+.El
+.It Filter lz4
+.Bl -tag -compact -width indent
+.It Cm compression-level
+The value is interpreted as a decimal integer specifying the
+lz4 compression level. Supported values are from 0 to 9.
+.It Cm stream-checksum
+Enable stream checksum. This is enabled by default.
+.It Cm block-checksum
+Enable block checksum. This is disabled by default.
+.It Cm block-size
+The value is interpreted as a decimal integer specifying the
+lz4 compression block size. Supported values are from 4 to 7
+.Pq default .
+.It Cm block-dependence
+Use the previous block of the block being compressed for
+a compression dictionary to improve compression ratio.
+This is disabled by default.
+.El
+.It Filter lzop
+.Bl -tag -compact -width indent
+.It Cm compression-level
+The value is interpreted as a decimal integer specifying the
+lzop compression level. Supported values are from 1 to 9.
+.El
+.It Filter uuencode
+.Bl -tag -compact -width indent
+.It Cm mode
+The value is interpreted as octal digits specifying the file mode.
+.It Cm name
+The value specifies the file name.
.El
.It Filter xz
.Bl -tag -compact -width indent
.It Cm compression-level
The value is interpreted as a decimal integer specifying the
+compression level. Supported values are from 0 to 9.
+.It Cm threads
+The value is interpreted as a decimal integer specifying the
+number of threads for multi-threaded lzma compression.
+If supported, the default value is read from
+.Fn lzma_cputhreads .
+.El
+.It Filter zstd
+.Bl -tag -compact -width indent
+.It Cm compression-level
+The value is interpreted as a decimal integer specifying the
+compression level. Supported values are from 1 to 22.
+.El
+.It Format 7zip
+.Bl -tag -compact -width indent
+.It Cm compression
+The value is one of
+.Dq store ,
+.Dq deflate ,
+.Dq bzip2 ,
+.Dq lzma1 ,
+.Dq lzma2
+or
+.Dq ppmd
+to indicate how the following entries should be compressed.
+Note that this setting is ignored for directories, symbolic links,
+and other special entries.
+.It Cm compression-level
+The value is interpreted as a decimal integer specifying the
compression level.
+Values between 0 and 9 are supported.
+The interpretation of the compression level depends on the chosen
+compression method.
.El
-.It Format mtree
+.It Format cpio
.Bl -tag -compact -width indent
-.It Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent , Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 , Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname
-Enable a particular keyword in the mtree output.
-Prefix with an exclamation mark to disable the corresponding keyword.
-The default is equivalent to
-.Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname .
-.It Cm all
-Enables all of the above keywords.
-.It Cm use-set
-Enables generation of
-.Cm /set
-lines that specify default values for the following files and/or directories.
-.It Cm indent
-XXX needs explanation XXX
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.El
+.It Format gnutar
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file, group and user names.
.El
.It Format iso9660 - volume metadata
These options are used to set standard ISO9660 metadata.
@@ -404,10 +496,33 @@ Specifies a filename that should not be compressed when using
This option can be provided multiple times to suppress compression
on many files.
.El
+.It Format mtree
+.Bl -tag -compact -width indent
+.It Cm cksum , Cm device , Cm flags , Cm gid , Cm gname , Cm indent , Cm link , Cm md5 , Cm mode , Cm nlink , Cm rmd160 , Cm sha1 , Cm sha256 , Cm sha384 , Cm sha512 , Cm size , Cm time , Cm uid , Cm uname
+Enable a particular keyword in the mtree output.
+Prefix with an exclamation mark to disable the corresponding keyword.
+The default is equivalent to
+.Dq device, flags, gid, gname, link, mode, nlink, size, time, type, uid, uname .
+.It Cm all
+Enables all of the above keywords.
+.It Cm use-set
+Enables generation of
+.Cm /set
+lines that specify default values for the following files and/or directories.
+.It Cm indent
+XXX needs explanation XXX
+.El
+.It Format newc
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file names.
+.El
.It Format pax
.Bl -tag -compact -width indent
.It Cm hdrcharset
-This sets the character set used for filenames, uname and gname.
+The value is used as a character set name that will be
+used when translating file, group and user names.
The value is one of
.Dq BINARY
or
@@ -430,26 +545,61 @@ and
.Dq SCHILY.xattr
headers are written.
.El
-.It Format 7zip
+.It Format ustar
.Bl -tag -compact -width indent
-.It Cm compression
-The value is one of
-.Dq store ,
-.Dq deflate ,
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file, group and user names.
+.El
+.It Format v7tar
+.Bl -tag -compact -width indent
+.It Cm hdrcharset
+The value is used as a character set name that will be
+used when translating file, group and user names.
+.El
+.It Format warc
+.Bl -tag -compact -width indent
+.It Cm omit-warcinfo
+Set to
+.Dq true
+to disable output of the warcinfo record.
+.El
+.It Format xar
+.Bl -tag -compact -width indent
+.It Cm checksum Ns = Ns Ar type
+Use
+.Ar type
+as file checksum method.
+Supported values are
+.Dq none ,
+.Dq md5 ,
+and
+.Dq sha1
+.Pq default .
+.It Cm compression Ns = Ns Ar type
+Use
+.Ar type
+as compression method.
+Supported values are
+.Dq none ,
.Dq bzip2 ,
-.Dq lzma1 ,
-.Dq lzma2
-or
-.Dq ppmd
-to indicate how the following entries should be compressed.
-Note that this setting is ignored for directories, symbolic links,
-and other special entries.
-.It Cm compression-level
-The value is interpreted as a decimal integer specifying the
-compression level.
-Values between 0 and 9 are supported.
-The interpretation of the compression level depends on the chosen
-compression method.
+.Dq gzip
+.Pq default ,
+.Dq lzma
+and
+.Dq xz .
+.It Cm compression_level
+The value is a decimal integer from 1 to 9 specifying the compression level.
+.It Cm toc-checksum Ns = Ns Ar type
+Use
+.Ar type
+as table of contents checksum method.
+Supported values are
+.Dq none ,
+.Dq md5
+and
+.Dq sha1
+.Pq default .
.El
.It Format zip
.Bl -tag -compact -width indent
@@ -470,6 +620,20 @@ A compression level of 0 switches the compression method to
other values will enable
.Dq deflate
compression with the given level.
+.It Cm encryption
+Enable encryption using traditional zip encryption.
+.It Cm encryption Ns = Ns Ar type
+Use
+.Ar type
+as encryption type.
+Supported values are
+.Dq zipcrypt
+.Pq traditional zip encryption ,
+.Dq aes128
+.Pq WinZip AES-128 encryption
+and
+.Dq aes256
+.Pq WinZip AES-256 encryption .
.It Cm experimental
This boolean option enables or disables experimental Zip features
that may not be compatible with other Zip implementations.
@@ -478,7 +642,8 @@ This boolean option disables CRC calculations.
All CRC fields are set to zero.
It should not be used except for testing purposes.
.It Cm hdrcharset
-This sets the character set used for filenames.
+The value is used as a character set name that will be
+used when translating file names.
.It Cm zip64
Zip64 extensions provide additional file size information
for entries larger than 4 GiB.
diff --git a/libarchive/archive_xxhash.h b/libarchive/archive_xxhash.h
index 427241641a02b..1c7131ca1e7d7 100644
--- a/libarchive/archive_xxhash.h
+++ b/libarchive/archive_xxhash.h
@@ -24,12 +24,13 @@
*
*/
+#ifndef ARCHIVE_XXHASH_H_INCLUDED
+#define ARCHIVE_XXHASH_H_INCLUDED
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef ARCHIVE_XXHASH_H
-#define ARCHIVE_XXHASH_H
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
diff --git a/libarchive/filter_fork.h b/libarchive/filter_fork.h
index a28272bee33b6..908e7cdd4ddda 100644
--- a/libarchive/filter_fork.h
+++ b/libarchive/filter_fork.h
@@ -25,13 +25,13 @@
* $FreeBSD: head/lib/libarchive/filter_fork.h 201087 2009-12-28 02:18:26Z kientzle $
*/
+#ifndef FILTER_FORK_H
+#define FILTER_FORK_H
+
#ifndef __LIBARCHIVE_BUILD
#error This header is only to be used internally to libarchive.
#endif
-#ifndef FILTER_FORK_H
-#define FILTER_FORK_H
-
pid_t
__archive_create_child(const char *cmd, int *child_stdin, int *child_stdout);
diff --git a/libarchive/test/test_archive_write_set_format_filter_by_ext.c b/libarchive/test/test_archive_write_set_format_filter_by_ext.c
index 4fe18e18c2d15..22345038609a1 100644
--- a/libarchive/test/test_archive_write_set_format_filter_by_ext.c
+++ b/libarchive/test/test_archive_write_set_format_filter_by_ext.c
@@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$");
static void
test_format_filter_by_ext(const char *output_file,
- int format_id, int filter_id, int dot_stored, char * def_ext)
+ int format_id, int filter_id, int dot_stored, const char * def_ext)
{
struct archive_entry *ae;
struct archive *a;
diff --git a/libarchive/test/test_compat_zip.c b/libarchive/test/test_compat_zip.c
index 39152206c1bc6..813ea5dc6701c 100644
--- a/libarchive/test/test_compat_zip.c
+++ b/libarchive/test/test_compat_zip.c
@@ -156,7 +156,7 @@ DEFINE_TEST(test_compat_zip_4)
size_t s;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* SFX files require seek support. */
assert((a = archive_read_new()) != NULL);
@@ -214,7 +214,7 @@ DEFINE_TEST(test_compat_zip_5)
size_t s;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* Verify with seek support.
* Everything works correctly here. */
@@ -370,7 +370,7 @@ DEFINE_TEST(test_compat_zip_6)
size_t s;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
@@ -402,7 +402,7 @@ DEFINE_TEST(test_compat_zip_7)
int i;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
for (i = 1; i < 1000; ++i) {
assert((a = archive_read_new()) != NULL);
@@ -436,7 +436,7 @@ DEFINE_TEST(test_compat_zip_8)
size_t s;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
diff --git a/libarchive/test/test_fuzz.c b/libarchive/test/test_fuzz.c
index d02fd993f9728..b2654c4a3396d 100644
--- a/libarchive/test/test_fuzz.c
+++ b/libarchive/test/test_fuzz.c
@@ -119,7 +119,8 @@ test_fuzz(const struct files *filesets)
for (i = 0; filesets[n].names[i] != NULL; ++i)
{
char *newraw;
- tmp = slurpfile(&size, filesets[n].names[i]);
+ tmp = slurpfile(&size, "%s",
+ filesets[n].names[i]);
newraw = realloc(rawimage, oldsize + size);
if (!assert(newraw != NULL))
{
diff --git a/libarchive/test/test_read_extract.c b/libarchive/test/test_read_extract.c
index cd06096eff693..2b1a21e4715b0 100644
--- a/libarchive/test/test_read_extract.c
+++ b/libarchive/test/test_read_extract.c
@@ -120,7 +120,7 @@ DEFINE_TEST(test_read_extract)
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_open_memory(a, buff, BUFF_SIZE));
/* Restore first entry with _EXTRACT_PERM. */
- failure("Error reading first entry", i);
+ failure("Error reading first entry");
assertA(0 == archive_read_next_header(a, &ae));
assertA(0 == archive_read_extract(a, ae, ARCHIVE_EXTRACT_PERM));
/* Rest of entries get restored with no flags. */
diff --git a/libarchive/test/test_read_format_7zip.c b/libarchive/test/test_read_format_7zip.c
index 1d1e4c75d2d6d..3c72595aeef7c 100644
--- a/libarchive/test/test_read_format_7zip.c
+++ b/libarchive/test/test_read_format_7zip.c
@@ -87,7 +87,7 @@ test_copy(int use_open_fd)
* An archive file has no entry.
*/
static void
-test_empty_archive()
+test_empty_archive(void)
{
const char *refname = "test_read_format_7zip_empty_archive.7z";
struct archive_entry *ae;
@@ -119,7 +119,7 @@ test_empty_archive()
* in the archive file except for a header.
*/
static void
-test_empty_file()
+test_empty_file(void)
{
const char *refname = "test_read_format_7zip_empty_file.7z";
struct archive_entry *ae;
@@ -609,7 +609,7 @@ test_bcj(const char *refname)
* Extract a file compressed with PPMd.
*/
static void
-test_ppmd()
+test_ppmd(void)
{
const char *refname = "test_read_format_7zip_ppmd.7z";
struct archive_entry *ae;
@@ -663,7 +663,7 @@ test_ppmd()
}
static void
-test_symname()
+test_symname(void)
{
const char *refname = "test_read_format_7zip_symbolic_name.7z";
struct archive_entry *ae;
@@ -720,7 +720,8 @@ DEFINE_TEST(test_read_format_7zip)
/* Extracting with liblzma */
if (ARCHIVE_OK != archive_read_support_filter_xz(a)) {
- skipping("7zip:lzma decoding is not supported on this platform");
+ skipping("7zip:lzma decoding is not supported on this "
+ "platform");
} else {
test_symname();
test_extract_all_files("test_read_format_7zip_copy_2.7z");
@@ -795,7 +796,8 @@ DEFINE_TEST(test_read_format_7zip_lzma1)
/* Extracting with liblzma */
if (ARCHIVE_OK != archive_read_support_filter_xz(a)) {
- skipping("7zip:lzma decoding is not supported on this platform");
+ skipping("7zip:lzma decoding is not supported on this "
+ "platform");
} else {
test_plain_header("test_read_format_7zip_lzma1.7z");
test_extract_all_files("test_read_format_7zip_lzma1_2.7z");
@@ -804,6 +806,7 @@ DEFINE_TEST(test_read_format_7zip_lzma1)
test_bcj("test_read_format_7zip_bcj2_lzma1_1.7z");
test_bcj("test_read_format_7zip_bcj2_lzma1_2.7z");
test_delta_lzma("test_read_format_7zip_delta_lzma1.7z");
+ test_delta_lzma("test_read_format_7zip_delta4_lzma1.7z");
}
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
@@ -816,13 +819,15 @@ DEFINE_TEST(test_read_format_7zip_lzma2)
/* Extracting with liblzma */
if (ARCHIVE_OK != archive_read_support_filter_xz(a)) {
- skipping("7zip:lzma decoding is not supported on this platform");
+ skipping("7zip:lzma decoding is not supported on this "
+ "platform");
} else {
test_plain_header("test_read_format_7zip_lzma2.7z");
test_bcj("test_read_format_7zip_bcj_lzma2.7z");
test_bcj("test_read_format_7zip_bcj2_lzma2_1.7z");
test_bcj("test_read_format_7zip_bcj2_lzma2_2.7z");
test_delta_lzma("test_read_format_7zip_delta_lzma2.7z");
+ test_delta_lzma("test_read_format_7zip_delta4_lzma2.7z");
}
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
diff --git a/libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu b/libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu
new file mode 100644
index 0000000000000..750769c3e4f47
--- /dev/null
+++ b/libarchive/test/test_read_format_7zip_delta4_lzma1.7z.uu
@@ -0,0 +1,407 @@
+begin 664 test_read_format_7zip_delta4_lzma1.7z
+M-WJ\KR<<``2BP`@-648```````!B`````````'T^3LD`)QO*P@;2+(;6`.G?
+M97%G65J_4ERCV:^K1%6D4`M822)8PY<D^7G/"B('W#;A;/.<=2:F/\-O87SZ
+MD&`;L&),.K'5%'\0+@/P0N8HLMJO&R0YO^&>*%1<PY8IPQ5"L/NPIF49[<&@
+M"%+UW+)Y@7Q(U>4J=_<,7#6T/3RFH$9!9G6HOBE'<!.D2&1'&GJT+"P_(<MZ
+M`E8JLGT2IS"#`;@H/"BUVB1G3$?]A%,'`E0\0[C^JNSB$5;G;,N*`A>E<0M'
+M0-5!6&]I9Q(LNP>FO1,4C"0-HJF]E+UO?$`OP,0L]9]-?IRQ"#_84'^\-:$G
+MT3JIHJE5;*\M)]-TIEK1=3?[2#(5!+N!_HL=H!H_R)BU+F9HX\D5.\?T=(M`
+M=9=W4SJW579?/KS>1Y+'M^%0#4C+X<'3U$3C&%='!5[\EF[@4#2B9^U]FY)?
+M`J8B_0+7B.I$N.X)PP3;'V&J*6VY.!&;Q7R,;M8N$$GCE7A'DD("6>XDN+^7
+M'[7.>5XJAT[)1$"IP%"H\ENNG?(IVD$"4B#R#;E,KWX0"(+I)G\I;FDXUW0:
+MG\77W)*"$2C1DY7G2A@X<7?HF<0(324$@RQ94+EXCPV;A\!J_=-IO`P<X"C3
+M`+$L8ZZ:\JV3LS0*:G6F+AR0L6IX'^[L:]N:Z=&=(51-/.G$CEYV0@H!!KIF
+MW3Z0MFD7TPSI]&Q#KG@:<^Q]ZTV_R*Y,>B]JI0O;215>3NFC>&L@A8ZVO8G:
+M(Z+'4*>R53SX'U!L=#-R5/?1CX"K49RW+6#"?:O9#&F-VU+]XA>-H/+P67D.
+MZN0JL<P5M0F:<+A7$U=BY`C.[<MC1".["0V(23:JG:K@&F!2UWA[3G$1/!0S
+MU]HW$&2P6AZ[,U/^@"OI,L=T+YD1'G#E-N7LGRP%W`('P.S<3;]<Q'O"=):1
+M?9CGJ0>3&7/ST/0,:N;-K'@%MH5*U@'\5C)M\[!]I6*3,C]3NA^OCP?_.^L?
+M=17`;X\L"SHC@$#^"05.3&=DUY$\848Q-SC.@/%KQ:P`5J3YZ^,Q\-/Y(6LQ
+MP?6TCO<V>52!37-BUF`NWYVMM2?O%GP33Q3P%?#">B/A<F`UW*<2BE`1<1&@
+M09D(J$H;9TU5T2U3KU_+[JZ<K.89%>68F2MV1P'<E&E<GB>FKVPF);5);K1B
+M>8HI`'2@,V/:[^SK\W]3Z;KMD.*+:9B<=!"$;J;;UE<C;8=?7>5*DM)][UB?
+M]6V.JGB<\EVIL3WF^NX79\"D2_^:2*;[&U%K7_@JZDKEF1,3>-*</L@/V:<X
+M2!F4;L)[]D>2=:I*Z6Q%6C)N$U>TY<X8KHV!/+V\1O5)$(:6W,3Z243&%"&G
+MH`^,TV"5IEW!P,+V!E,XP`T[66G;>[(C`P/L=7ANK-S3-TT\L:SL.T*&Y0>E
+M.GQ/D;-/0XPRM5SL()'1_^7U(H`O&?G,YY4X%=>F@:@Z-KF"#'$:)WGH[<$,
+M.1GS0RT6+#EYTEZ8W(/*D52"P-B('Z;VJ('L\]<W(DA>V;[3YB+264VOM'M9
+M/U7+D0$Z>XTT<XH\N5"P5U'64)_&HM@Y-CZJ]/19H*%A!N>R0PP685OJ%/<&
+MJ2F(<2MA[/"%RY6$59Q4^<^.2E4`K*^\*=EF4`D<\@V"R2>@9+%ND3R*?DVC
+MY?U5RIHO)]4_)8R<3XLHQ<G@]%#MSDNL[TO%4-:H;[\*$Z@@'J><U*%_PKX_
+MM,LTP$2ITA\+->:ARO&7:7!:VK==FV^WJ;$;UM<&(,B#=E*6P*"V"T5QBA@I
+M!4R$!8.UO\`TE@9K9&W_'H:$?K3:4(%MF):*_OVK^A>=63C@11U@T1I"1Q?#
+M6CJRJNUTIW9D'7P=!P341-$$(0GVW+S/D5NL-H62CQW"4(";.>F1#VI1`S<B
+M,>N^2//BUZ2!*N-S5?\L%+&&+]KQ%-VW#[C)/0LX@$90T;HK*16"?-10DTO0
+M>).+H4UE!^5"8EZY\AI;S5W!&-W_GR_7YP*YD*]*(84G3+C"6?R[@K<$M+8"
+M'9V'M]T:$P]LZQ6A3#<)_X2D.=BY9BP7WN:17-HZ=K8E9V9>'#%.R$L/'`U2
+M%RBA6\@>;DV"%M-2Z_VL]=$Z/^)=`$-)$CDP#?3I3M&Q"21C?*R@#L:;1=**
+M>6J6M\$JO&[IM%E1\K(KV#CK]1!0:?M>([H%FUMVGTU,`#D*,+%)&$FT""V`
+M3=1]S*'&PDK^6@#Z,&X][V6I0Z^[B8*7P?4_5N'E9`)5*.4!K2G`=(U@/RV>
+M"C?],9@_Q]#\G67)I_,)+$U?R>51LS+,1<0/C$RW$8A_)U)K0:!3GQA004^(
+M:U*X8T!*T_1#W1V4@<A`6'AI=",RL"`GZ,YA>6DMD&89Q$$,KQ\3F%!52496
+M3-!]GJ5^KWZP[LWX!PPEUI'YM$#^I_KLT9X0#)6@K!PWB_<QZLHG"[`1>NF@
+MWT8/RU2Z8]AY4K"=0@6$,M"\?8/]ZFR2&1&`_!3U=IC.6Y0BN!TA.6C(>Y)E
+MI%0?'CJGYHT2-)@CS.KV"@Y<=3%Z4N%FE7E--^Y651G3+2.IEL@BMU6O&1?8
+MX45]0!(O%9X!M:1>K`YGV^_O%/GM_5>+640WA4F9R0420YS<L32-@S18$%NF
+MA>.DVJ\99T+VE?TO``CRDOS!&U(=)T6!7O'S!QZ!/&Z+KD=FN8U)\$M19IA^
+ME8N&#-K%0\KB=RE(0WMKCWNFP/9(//7_,0.J@:`(8F,M63OAJPG&`F/$\U>\
+ME?3``?\,Q!FODDU".=+F\0>6-QN([3HC%L$7E(5*FNR9B/R`O\&8;<:8U"H-
+ML?X;3TE6(>O0>/9T)7AX+(SZ6/D?FA(.D-JE)"38_Z9*0\%&R+`7Y%"/I@__
+MWF;"!AYKPC`NQ$A]4AFT!ZXW6G-CK3HE&(*Y:LP^FG8;+QYXJBN"!P9@CWYC
+MNX@XHZ>]I0YW[,6RH'.JY%\J&"UI8,UC!6+9BR$8ISK9U>KC)*JZYH[[*<QC
+MTT<A4?T6`$8!BX]_4']+F5?V,'CH>XDY9`UXU/1_KC'"'5G'Y"&QDW`4H^?0
+M0ZOI`F$V4_#7+OH<),CK;&JU[^F#;AL<5FW0%]&2.AG#K,3E8:ZI<KLW\_WV
+M=)NY%7GWEI3O<KB4.E5WH>WK+P[/`-['JND8[[^DAI`"ZV>]]YO#83_2-Z63
+M%G!2V?XI;66V?((CDM$I#793L`;V]-/[,8_!%6_S2H=<W4B1[TE&?Z1R!4ZK
+M_C$?\(:1`K:,%VEPLT0J8!IK-A<KD[1P_OPXFC#C#'NO$B.-Q`-Y.>/G`\M6
+MQU;]^=M/BMU/?,EQBMJY>6@=21H3LPE5LF9XL/AB4+8E.WGE6X2T!O\'-(WM
+M<B>EO'%E0`NU;*PKPV$PR-M9Y%1`&/MC941*O9L=CM/9_A8#*38Y6[=4E-`I
+M(M2?3[;8&3''0#RMMF'CW$_6L@E1\V%9^U]/F&G=&[-!=R-XO]=I0<E&<T_3
+MQ:BT^DG<5:!YP,XAV[&\W?6]]DUG^S5*TY+'-^I%U"5F-:XH9$;N18EL##]R
+M&*Z,M$RQY0!P(SM,7>O55K3CBY:66KWS>^MJQ\9$VL_2VB<H&:/P4-PM5#_E
+M-C`_U3*W3=2IBPFI,OOP1,LA),&:2=E3C<<,*D#3U8E)?]Q1LEK\&D)S%$'3
+M9_$CW;D5^3-,S&`,N^G:8-B^WLX`!MB(RP@&%A!*_P\B4-+M7!NG4O9PO#Q#
+MWIRFGEJ^/&ND]MB(?"XQ>B\1W1^A>=][1UMIL$].A,T,W?A5IA:W@/'.WAF:
+M2*K;Y']X8D/,;&X,YW-(C:O>"*@5_EZP#J]'/X,'`OZU=@2/&;O@ZX(!^<W6
+M,[L5G.J6WH5B^T[6FA/N8A:&[R(Q$6VLXH-0/6;6$$IZ]N-Y@5-7.6T+7V3,
+MB$"^W3#.)N=[LT;K+D5%Y"P:3\\,MM;I*?U<,WJ&I?:)X$.2'VJ-JV7D$#@I
+M[+N(X*_K3H6VVM/:HYJ55!JMR_-:8"\$*Q>?H\7>I'OPXHV(.@N6[6&;7[<H
+MR>*G'YH*M+W>S84F&^UQP/>!^$/*J6#8P);S!S3ALHDN3_BL+3>:8#XL,V3.
+M:69'F<4LN!:2(9RP#:V#A)'<`%`CMNJ[^WMKOCK^K.%J_T`@RA.`LPH:_W`3
+M-#"&2!B6PZ&30#4F:E.)@1&KRIB,&JIR13OQ<O9[5)3H#B#6)W6;:MW`J;DR
+M%_87)Z/4?M<):/,71H9ZX&9R*N"=NUF,PR_XZX)[YA\83\#N(HY9JGCBIHJK
+MZBZ@F/;"-+]?48E)+EW<JPHTM%MZ&@*I9DZMF+S_F3?&2<)U<9^N#8#V.=`4
+M&V2/.J\8N05'<6P*\L[F$UMU,B5_X?H@'M]8O)48@N[Y;<]L-F6T[?XQ@8L8
+M4+,5<WNH^*!8&<:02,I*U*\(LEYPI^1+"KD80K7E;K.BT](QC3_6WE;7RUTA
+M_>Y'R]Y(%?<G\8UK<AO2!T.D1D]PM.13C^!Z0W'Y:6TC_=>K\"/VL'(M&JII
+M'VO>J3U#_:[LB-JQZ9>*2.D]2_@U1`>CDQ"L3M0W(D09XTJ$>+T)\6[8[0.P
+MPWSWY$R7A.VC[]3SC&-%I$,#)0V$A_%KF."AMKSX/IG2T%BRNZHN$2<VE#E(
+M[3G!!S04BNTJW@6S\:A)KUF](D.9W_C\X$/(C,,`VVE_ZPD@K"?G2:]:6',2
+M?SB?S3^L>`W]O[,:4=$*F=AM(#HRD(`[!&`Y3>]="+V`@C<5[5D6J?GMYQ<"
+MDEL"N&A@L)PW_T=K7L6HBC3@-5W`S9W2DU9A5/'LQGM4*9TW[;#=LDKA[Q`H
+M(XK*DP6REW[4U@-<@"%&K4^-I5Q]W>)[+33W#8X5-LY0(6)P"*H]IT$=PL2;
+MV7]>=7S>WGG?H%DV>=ROMC->C]6<Q\A:ZM:$6ZH)H)>8@]YF;!!6F53BEQ_L
+M`0$I*5WKS*W7G>]2<LGF0NAD39YP4B!U#9(D)7_T?!(>YHHA1A)DI11RZNU3
+M(HXMRO2C5)*;!Z4_Z_S;E66MJ<G>%"%X@KZ)>2,IA:E+O:9F4EHL#'D0U](#
+MZ$1=A(5"RQPB"W:DCM$M957$TTX]?;_"W]'#,<K-C56D31@!3CIMP<@4P.@C
+M&)^$879%@&@$NT3=,IL-W0I6LG.+@3EX`]MOKA_*:OFL^)?3U195&.<Y&<=;
+M];J5$8N#KT/SY3^V0-1=O(@CE]CM)V>6[#T%:=BU%45@G>`(0W8HH;2WP.:>
+M7X.^L`0,QC6'QB.4'<:H_;?[HH55KK+ZZ(K(<SO](B?%V$!U@[12>;#4BU/6
+MM]A-C0R[-7?A!\A$XV)ZV<;3>(#PWJ'G`A1H^M73&2TBW80SG"6\;_OXLLVX
+MYX"RW]>A3W+`BH'-7?H)$L"JS&0PLA@6NZ_KV+$G$NV'N&&+PN)M'G5`7X^S
+MMS8K5ANE%#L&\;1RA3@"QV;B\,S=(VM7*6P.8;7>YK]SQZ5)/T5IW\X7J/F)
+MNH5RK0RF!YFU;``:"/K48?)96)H:VL/W<?PU]J@P.^#:(\"ZM-*>CSBK@FI:
+MEG7O*9+W1\`<L4U>4#U^CUUD)[A!W)[`::QDFW6+FWM<ERCD02,)&UZ7;TM5
+M*>>5AA<VCW?X!"OZ#"60(=861Q^2*\?SFCX%$)RW4`T/.[ZR"=J5F<!Z^/NO
+M"Z9F$W>5A[NZ/@G]K[-;E=Q/+VX04AU1D3SFJ35+AHSQ.:LL*B@;,;S@)LR>
+M(C]7B^7VTH$RLX+1JGD;-V!+R,*5G%7QY<!?_`>Y`>AG>9RA"1YQOM]^O*Z#
+M^.F?[5K(S6HC:U-CI\J@^=LXH<]U0=.?[:QWLN2_*H:.S/\_)XG%V<6-"3:+
+M\(K_EQVPN-IU^YY=#6Q+')ZE(BAR.DE[]QV?,&/$]UVN:H$VV&H!3S]=(Y88
+M^?CP.6IHOHQ&NT/)MOK%$E90.VO&>3\%W`0*6I@[$&"OKU1<XXJ!%;&+F'N?
+M42)P4(5Y[E/)MSSU"3,$LC(B_ZG*F`]NJ2^*1*\>/Q,"7YI)EYL2Y461?+1&
+MM2<\%E#K*'87RWDOF@X<;E4-LEBB$0?(CH5(ULI^S.D9:)O9D\52XM*N7>?_
+M&UEV@C3$3(!N;`>4-CU_ZCX?WFHBV"K[,!:08Q[@@`Z%).)!O>(H__Y12NQO
+MV+%>&TZS;9\1Q@D3WF_'37E%S"6@N;K@^&PS;2PQY\,DRW>;X^MK/*[QW(:@
+M-`IW$&7U>3@IG%W\HDOMTO*UU>-<KLSO1="-/)L+6;]RWXB538B74Q%:O@9=
+M^JQ<7M#I&^QJ+*+DYMF[5#)).:.`WF>>\P).[R-8?@JD?K.5T:8`V,N8_^@0
+MC=YQ'VNPS%3#"4\BVSY5-VJ&*D6Q(C1_0B#@<7A?>/-_Y:F^S;O4J8-0->_C
+ME`/I>\%4@M:.9?:,@/`*M6]4[_H#":*BPKM&-*.XBF\WHW,P,D71^62[3?"9
+M<L,?=<]IOM0:3@4<@LFF?6R!K&7`\X'.!5Y@!0A+4ZK%VT>0>H01XC.;&/,&
+MY1^?\5W9A*]LMIDHV:MDE@%?@SG"L<H?.*45[&[6FUTNP-]-4TI7=[<S`C7Z
+MM/E"VL=P?'1J1N>)XLS]6;!X8B-#.%83SI.T-!WH_OZ*]6.6"(DJZB8:+4[#
+MBI35;.F)C)J#^-Y1G_\/1-2Z%/^WML]Y`U`(!\%AO+R*+ROH'68P#W$]LNW4
+MN$23ZM0$*FWW>5==F.;B1#(4J&&7G;4?$7KD[4_0Y-S;G`<%O5PS_M[2\-]A
+M4-EF1<XX\#Y.D=7D:R'MG"W5/4D.RD(8E:?Y;WL30A;A`9/%LS9D)W25`[DZ
+M`T;[H9F\O"RXFOI;6G5TM;7&YQ;"M8Y)GD0/OI=_$1>&L$-Q)`*YG38`;^"`
+MQ$&?&V04*(>I(MSZJU>0BGD$KM,FR7P<TQA*BE*6-\71#M&=H8=-H9YT+:#&
+M^<+`)!Z>5Q[#<VZRRLC0>/HCE9-_]AY)VF?;R%-I!%14OB]F^RU,^&Q-2<E*
+MF(9E./YP`7O;O"&*E6B3%Y6LU=*]\!K'5.7W7#M>>*XPN!&O""WQHB?EB7MV
+M"*:BJ"UO6@U5(I]FX^]WAR+(*+TWZY(07;Z4;JMJ/35+;LRL*`0;'E87GUX1
+MXXBG5K!JQN^86V)%,-@BZR([\L(;]<B:I;AFK-ICT:'7K%T@(<8_(+`8#%C%
+MW?](G8]V]DA1W(\%9B5`H4,.PO8FVNI>/"@FT*\#TS]UJ9&<IM:PSMDR1XK"
+MS9MI2'6?<*-?A<-S;?=T)L@;U1(!>="`[]&@CSZ!CU9]Y8>(V&PIMKA*-%[A
+M.67]I'72](-.H6+$I]S=NVIW&?Y9CMBGC'^U.[=+F9W5IW?X:BY$Q&7VE5VM
+M."JPM-ZU!X?$YEQ#SCP3=H.3WDSV'JL[*^ZBU)2:QC=4$)*LG\18N&6#B&.)
+MSF`5A9(^F60I>/Y7)YC:\(HQWGPH1@I?8*&>QP5[T*!'9^EMJ`[I9^%_[>G8
+M.$Y1V9$HT_(QKYGJ(Q=,;J0:<]2/0.4D[5M#XB\("W)S?WHS&%5W\Q0*)24B
+MW47>9%4PG-92JL+CJHF("1+\P\??,G2>F"LZR<Z:>360WKT.5XQDK@/Q@U0-
+MMH2GF"N[F,E`U%<H['A&#\*1)RN+!#1[I3="Y2`P0F;0;(6/2,4^U`1[ZYOT
+M[-IXOO]%HY#?W^Q_5B#`&Z^<-M>L/3>U.^+SOM)/[Y!#H8(WNN56"1M)7)+9
+MZX^`QY$)VY<W<N,E/>V&C4A@5$MV6)N5QO5N[,XFLTN5(_Z/W.V2(MCY_4U9
+MIU'0<=YJOE&61^+4(+]"K%=,748Y;3;C(SRFD*LA,`Y\6%4DL!^'FUY8A-L1
+M'A)`Z#TQ@VO28XW:]>[$--59(S74PX(BG7CH3N:@MK<*!Y5*.77(A@:><URV
+MPV=&._:R\RR"F<P;IIVEPID67H5RQWZ4AT^'"/1)E**TC74<E%H;U^-AHB`O
+M*X>[^FTV$+8V(Z[4+?PC-,N^K%$@->=:5KJ:(4\,*H6:W#Q87-,*CL\45D1I
+MZ-<BK<HP\Q6)>BH)<:H'4<L.5M9DM"OR(1L@E,X(D'J*_9*<%]'S,[&0*;==
+MZ9X%/B"P\E^Y=4PE":33%BO9>=BMW(;TV+LNXVB`&U-JGZ)9"1_1ZC#<?9)%
+M--<TR,M+)A"Q!SMIJ;1OZR2U\#N>T-+E@,QT][:&5UOYS^Q__\X[:=U5C&&:
+MYL?V6CRK"/?%X=\K&]FRL\WD*$I@M8W=LTVS@EHN"BH,`&/65-=R2M6F,'&H
+M&C=6_(_'8,6H5_55K>K#]2Q$82F7NP1[ULZOQH/Y$K[I-5A!=P?E1?;("/:_
+M=K^,`P316_*N15(@$('MM6YT^>[-&<\01RX!A_]AW?NVY%T;Q:,O8&"A&$\0
+M)C`VM8:WDF"6>H8JHDE&JL1!D]Y:50%*>`?_Y759$N'X8%38HE4P:<'N_DL.
+M:E<2\AHV_WNS-O?Z=IZ].=Q$&Y4H.UK^.08H_V6/@LPF2'G2XMK#U]$I7NE[
+M2-ALYI2\T$TRJKUG1(BOH/"JEWN\O4AF3O)O0&J#796>G&/`5Z$/%]8Z(0.'
+MS6T2$U5H=9/6>/9UR>'3NX\7\T:9F>I`2[!9>1:[PU"U(]\9DL8I[,YI]IMA
+MN,8K3-\IIPCNL;*93)O"Z+*>_K%9]KYKY1O*,IF0@#V6E_:]3<!F`<$\)"$.
+M%0_[5)7NMA,_(S_PL,.EZ?,,[P("K9ND/0Y#(*#6KS`.8)(!KXB7LQI8GG8X
+M4CN_I_D5J$_+/RQ*R41OF\TO@W,&&Q*L9C2H:3BE4:M5-ZDND+G>+1`>0<W*
+MWID$F/+-Z'2$)3)I<I"<[I:[)$/M_V!3&+9B/)U`^U"SC"JV)/2@L[/Y13)0
+MX5243>IHIAVI!\T@MGNU7BK43RFW^X>!9-'$VON:PR,#VU]^!"O6V)V%*\OX
+M80:!WXNCD!!SGY!E[,C)SK::L-;*TB7S'WNS62B1&)[PC>U.Z;EA"H16D<#Z
+M1"C/>M8$_ZR*#;#\>*DO))@"]4Q;K?[W>?2\#B)9&YH&&1#*4)FXIV_7-.FV
+M-EF]2(:P=SUY3G]8)6KO"J'#(.7L'W"^#SYQN!I`DCF4>4-!'`C/*/`%23(Y
+M3O=L^=4*9VE-#4"46RX(!\_7L8'%,;'G".''P\#FK=7C#D>*[,3I?%LS=8H6
+MD>]BOWEC@)*B=YI)M;#!]<(!6"SM(<J=V^+JZ(L<-@[87]4Z%H[LI[`(V0W_
+MB$;G(([?UW0C5&+W4T8S*T7`T^2')U#6.5XF%ETU3C78VL9_H`_!Y!JQW:+,
+M#.'I(D'<D7,C;NAUK]S-*X@U;`8%Y;-MDVS;D=05<%'P0N>`HS*7>1R(,]:S
+MIXBX8:"N7'.PR2<.)P=%[</5)4\14^$UU!%5PI5>(/N6R(C:!=!&D.O4LCN[
+M$0U4^%:/8&>*MF/8G>+`]+D0%1W=LR&O#\BPED>!L%)0@)9C][;4@>XSM\9.
+M:)@-;`P;C2R[(9V``#!;2B#!((RQ_=Z6A8FC13AC)KPFS,2C#KC@0,,!=4?R
+MNT"$]8]=HQTZL(EN1[58BJV!V[57>%W%7X>JOLBE`M$2#H$]D*^XG5$W&.Z"
+M,UMY\(ZZ?PZ2Q8I97T1HY31%^T?DEJD<Z7><3B#IQ[R'N(RF;7Y5?FA:X>SN
+M(7R,Y(H;,A)1F"=-US`;XC%_I3B;D?T7FD;8![YAU#I-;%CXW7JK^PX\LV7F
+MA2=25.UV<CG/W"3W'#15S+7BC#`?A[.D85>$OSP6%60;NVVTJ4.A4_NXC%ZG
+M@OV7P!"@KL+@[/0<S#`>U@YU0RLHH(\`D2/S8NE73/1759@?VG-[#^5K)-V(
+MKC6BB"B-J9LJ?F(BIO&UP^-/FN6/E+:U3+;`=]/`ZK5#%!T+@O#UKQQ$3>V`
+M#?N3<3,8.])L;@N:L<PP:!_I3)0*#PS*Z$5)+V'2:-IQJ7/]*Z%B^[BW>%8V
+M%G.KOPN7][!"[<'*KR+>`%0ZO_69&<X]_7-J7<Q]!FHUBB8MH)@U!L-?Y6?F
+M;KTS*:`0%'GP$]UKT5(^/H&%X#)>2QU.UUBS4>G2\R`)1#0[B9[]O"E4N)/X
+M/RH)DT><1X-KU`4F93].H>N,X2VLZ]+;::6/Q72]V6FY42.I'7X@@09-A],I
+M3!,:C#/^]1Z>LS"7-]A3=Z.>]>)V>F1T\KH9=\5.07;*4JCJA"%Z`\C>PA3V
+MS>5?9UUE[S7/+R7B>K_&UGZ!Y7%0@A(T?$I=:6GZDM:)'2;2-S9/LO8OQ31K
+M(M^>-'.XA.G'!TF$BW7LCL,IF@6.0JR#Y.\(P;V!X74=#QH1T0%T%C&SCI$*
+M^'_2-=-9JNC"#ZJ",4\]LE*,%0[5'O<QUX8F@G5?`X=M]9X<!/&V]M1A/@YE
+M1%J`V1:5]4W_(5,"GK)AJ186[YJ,VPCJ!PXM7TH[M+(-1_->KA9P\,%&QZ%F
+MX`35=#VBJ>BXGVQA2XH#.SYX`),GM0SI9](2TZX1LH!+S*$BXB()*)C5L;LD
+MEB6YHX1"HN4=2%H*$Y:LNC^=5-M>#$I5YA)@WM].QN[0];"PJ&F#?,.BVJRM
+M27FN=O8,P?\`P=*M!EM!DGG[H_UZ8<,B>%`A%P!,O[/%@[8_5"DYRX51)=.`
+M\PHFMJ90"*@XI.^8F,9'T%FYMW\E%H5.4L`XRO\.=X.+42F7Z?%=UH.#\WWG
+MJ#_"]0F<4,V6G#T<7-ZA*MP+`CZ:N`KRI$N5NP1N%\2=SNAY40I2%KO\6QHG
+MQF4KH'C;5@VCGO(394<E)\^B>SKUP$USQF?(B`3ZU:FP9BR)&K,KC1`$X./>
+MF-TOJ2C,?Y!9K!B:J`Z''=?RG,I%\TB)I;KUTT-A66=SHB=B`D57L*\B9X:Y
+M]7CA-Z&[`7"=9Y`<"1V08NK?,;CS*5A#>0SOT29]?W+:$2WP(IR`6#;7(U"U
+M5?H&ZQM#?;Q$RJ0!JKC2I#K3/(!P6;2EU!<A".-P0K-/%"(7!SA[6EK5`N64
+M9'N`_$]G<@N1Q5_F?LY!<#D5Y?<>O,1:,2B%@4-;YL>TXPH0)@I7`P+BM<:Z
+MD'A$\_+O7XXGNHD20)0N--U#>LA+8IBW&@FWGG%SU[A%"$$L2560DF&G&SS-
+M9'V/_$0KPRN_X[QMJ^@2SK,YT4RYG,Y[19OVYO,1[RM8HV4X+<>8GD%0#9>.
+M\[9%/ZMK<@#&:I79^69,&>(IMYR7E>\;$&:&@S;'?%=7X3)7J$BT>)0U_TYQ
+M9<N(J7S!'3,IB>ZE9!;>)S@$)V(2M7+YD#U6:R9XKNH58<R'8@F7-BTPEP_/
+MF`KC"<%S`7Y-]7&?4P<#+0S$!JP/O[&5FD%[,9@*(NNT)10$ET-2T7_^4OF^
+MEW%<%7&+2_YN]%DT;^2/!(DKVQHU7T`DBCI5DMP!N1UP-/.%DS.IX6=F7(21
+MC!!Z46S4T0C=]3?)_&$4-L^BOAY@NH="?;*&T@MQ#X%X3=8JW1PL`_+KN!'7
+MX1OD=%E$1KNY9>$`Y0[?!,!E_%;P$@9M[J4!2V;?7J9KR@DK_5&0Z4D%.>R%
+MZ):(=I#:@8@P47-WUYI]GC3)=ZHM-RGW3DV4RF-N:;/ZC;F,`%XF:J3$DR^-
+MUO.%<GS)1\1P;8UU'OBOC?\<^=2>(6\"F@9D]+N>"<P#3!;2=!/R'(N%D*;8
+M4]\CEGA@NE<;-,:/$'33T&;T/G;G6%-[9M:`]Z$)2_30/>M+.`UPM7OEQ]FL
+M=+*8#`?/-V6:^@Y%SEG(<..;Y;(H^$H,G%&\,DFEB?*"!6]@VYG!GOOC!NCP
+M3GP'Y[:+1P$N#*F?6(UV)A?.XYS62=)&BQR:)TO^'6L6:O?TNGOHF>AE>VW3
+MQ+^7)L[9\V>8!"AT@0<?+C$:.0]9=72(O!%>/(5?/]9""`>7U]FAMD(3>IHQ
+MFM)CGJ,V"3X.3!Y`BWH9:/`L%%IV03`3"CB*>Q[@>,M.GO%(M,16IR[4N-H7
+M0_F1S`[>>ZR>0L8I<U,:Q3_4^.7&63KUH)6\K"_#_F@PB\/8Y?,^,=3(C!HN
+MX9QR(4UY\44.A2.<K9(VF/INB`(6+BI,.Q(<,(0_/]1ZM!+4)>041N/:1`ON
+M)P)JZ15?2%&?).C&0JD<30`?_:NO=WD!HX_O;?[SFKQE1X-)C<B`>%\Z\("^
+M.SP??@UG)[9(>E$''Z.VX4CG=W5`"XDM.(ZO43K*UNWT/9:2?8AT(),]T]8S
+M(D-VQM8A9O)O0Z%6U-FQA`CSH)+QSN1O#H]&B%7JS5]TDHP%/><[;6<SM.?$
+M"YJ+UXL3M\PPST(Q0!M!.RY''%!I*NXCX<!#]&CH!2[$H7T'MEYCY+3Y%0N_
+MLN2%:@61_+]T0KVU,0Q;NHPRZC.DPV8D&X4_K3.I,@^0,,F;5N.`.G0S8">B
+MV#FV<S8@?^Q!%QCP9/8/A!U3IJA?9#/(',N-S,F5K-^@SO`%E$G3U!=D)M'R
+M!S8S2TJA8TO1TN$UR\VRQMP,BA[PW,WF\S:KZ8%ZC^(YZDTZ19*`)CG,S]YO
+MN1Z,RQI>W&`*ZQGAFSV!#"#H/B=8Q&%J\"SR8@&8<U&T34*Q^CW\/YTJI4X'
+M6T7N,":9,R6EF+,"8^ZEU2+P+G5>R;`P1+6\A(\8QC/%$/.?1ITG^19+V--7
+M7A8J0;PBPT,)1REB/^984W3T;E'-EF6/QO\N<>WJ-M6\MK//H)=__J-E`'17
+M:M=Y]>J5K`:?=";=62H6^%BEO%*IF.JF`/4N_R7<1IW&[@#EJYZ"_S\W<^%B
+MDRHSI!"+1=?<+J0,I-+A,Q?:K.?FGHOT-M#2;F\(-L_L:"48C+`"W#!ZU&0J
+M^B)6X;P)5=7&#^E5`-:Y>[.UFGM#3X+KP1-W>^F,Q:;@T:YOV?Y]J4CIVM2L
+MO(/=LOCHY@R&HP3IP9LR))TK:`OW/A=H4-HSPI."(I`[)R&CI6[4)!1J3"3F
+ML;%]WD8X8O^[L1T$1#(2V;+(X&L$\F\8:>>KQ8:IB#.F).O(1L3JB^MW&%<X
+M\V`EKLQ%5>F`99/E<I;2\]<O;NTK-PJ4V)5C1C<C1^O*3E%A!.[;GGAJV:,5
+MC$3OJO(,/5JI'"V@^E$2]D,&E-(@170/](9NKTG1PP#D^20MV!3!(88O[G2`
+M,#<TZ#DAE1F8?@@]*!A-\^V?O'T3ZH6HT/.TL3L24HC[I;2[K@SOS-GIAIT&
+MGN>XP1-^>*@"NT3'^,,:C>*E=#?-$'-P+W*?DFGG+RV(V7Y1DD%^13&2K\[(
+MW6&D;*IGQGN@/@75IQI3B\.R$[WG%`][8JZONR"G!MD>;DO`M#S7.#F+2*EP
+M\)D<(Z)5E6_\NX<U$Q.L^`3OA1E76'9436-]U"U)WJQA<>RI#.8FPSMY[SR1
+M_Q!M@A"1["=3C!MC$\I=D&4_,LZ6.VB#9(R-0:RC7N#H)8`X;.R(OOI>%0(-
+MA^G"&8WSYE=:$LH&KI0R8\A\(245F%S>,>*@!\DIFN2D8>UUFRG,DY/3B"QY
+M%R^8%]#BE*SP\LA-J#*BHOP^KL!#4'S@7K:BXOM6>]K(\:Q-Y#9M&:0''!W1
+M2).:.8;W=B;:*A7[8UE/I^#OS#!+K-%75./$>*Z/-R$5FY_2"9%Q%+IGF-,8
+M.*!/U+B49C6!7B9CFH3^#$0IUM\_EL[I;^:[K^$7E\.0B/0U::D"<)>I!H=4
+MT#D:R$E]*;2(U2?8>I2IO<-9=&##O32K$-T=0#`6I@L3"W*;&YZ21.V`TE."
+M&42I%D-,[&UY!L>A:]Z)MW,9(#X)6@3*40H\EU5C!:"1]KT_2Q+9W9)HD):2
+M==I=*F'KQUX_VQB00Z2)COJ$;..3>7=7="`"^CY+(%/>)=4@"<1L;*;0`D_2
+M[PS93J2SI=MS)=:<N'HW86LNB2+(WZP%R@K&0HB_^<ZAO>M=P`7"*CE@##"6
+MJZ&B:%LTQI65O^3"$0@KN6.+'+98S#SRV?B;N/Z3833[SOG(O]W?(!3SSB'C
+MU7R"-#6+C'Z^/>6D/4Z"<\%G;E:.+1#F/4R.=BU3_1&FE**#EX6'J4E?-)\-
+M"O*X52TK19<%1A'L$4O:<"H"D;RD[`>S3ARV(4)/F%<J2V)Z=G9/GG?X^KL(
+M!Q.A%IY27DF$HXAKM1MX<B;A+',$)G(A.?]!]"=R&?+G3&H_^2]PHJ8EG;_,
+MIN%90GE.J\7VZ5(+3"JVZ)";]]-#N%X3"GZ:;$'38&IC_X"X#YH523L.>J;!
+M\I$,R!+>M8+'/K3SSZD/"3Y(01+;E1L,G1YU-?,T^"4:!!^$PKA7T[ENIM$P
+M]888.#/ZFXZ9Q8&&BNJ]O68EJ^6D12?)S1HDFSH:C$\'LW"DB%7QB;=I$X'F
+M,#-2AV!Y:FS]=QDPR51@_7=7,H,P_X6AR#'*VQC$3@?/;KZ@$RT%+>)?!"1K
+M5XH^VQ&9SQ<WU9":+D)-(O5C)$%4A'JSNHWK5UIIXS?Z=V/9MR?>E^1NL[GQ
+MWX4^.,=&6A()!6RP1%Q+U"K)'U8C:BC`Q1"_NKW_Y#R@='88JUY7_"F##Z&5
+M94Q?2'(A"$PQ%%\;_\2:3:ZFA6%?8PY97Y9N;2`+BG@0;>B[[`;7MH$T7XB_
+M>M]K821YHVV6#)5`2CQW.EK4:LPGE.!4J:W#X13RQOA7"NY$)-%M]\R'VH1<
+M3GYYF"S2`%941%][8L@\,,VZT\+0#:?FNF'-ZV*->]#M3PN2>M'7ZA!2V*`&
+M`J@;^%INM4.S]N+M@TXT9[]P6]Y!3-4\VC^MM)E]GMP)'D+1&R\FAS'C2S,P
+M3/SNG2`;)J9(`HJ&#XJ^(T81,J2[H4Y"!($_@$X4!+E0`(:7F_'=A4Z5YLF(
+M3L%Q.UKWM%E$$YD<=JZVX2:3`6F2@M(O"&T_"/!5&'-E3=++;:#0D1=?U*_Q
+M?]5%7@%IJ3R=)`0TDKU"D=SG"[K1'M5R/710FDWP[',9W$JLL)-,?L<F[;,9
+M9N;BSJ?%:[:ETY]7IL0V)S_OW2F[((-+6F]Y:,8D/W&SYSGW%*@U2`P)_J;P
+MI6M%0?[SMRLND+X;W1DEO9ALCPODL76W<]8D/8;9S+<Y2;H_%VB_[QK&CC`T
+M7"H-D5+8@4#A&N^V7:2SH9`KSL$GP>K4;\Y2B/&2"XF?9<?AK=NTO0<*^]&_
+M8<&H8RNP,ML<1+_1"^?+;H2GQP4'G$5R2$CA47GA1_:A:2`-CPZOAJ-;<QM!
+M?HE_];^6K)8?Z_F^5C,WA@P5Q!?O=-&6'?_BIC0'^=:/MTW5BK#__<FRTK`[
+M;7*P?U>MK[48':8.M^0Y/H-Q(H>00X.;">\'%$"@;DL.)[:*R5]V!W*N4")7
+M**KA;-."B]"3`R4)5TMDL$Z=BUGN^'/UJ.,&N-T:(E$'X"HFS'.(F7U%N@]2
+MRP4&YHX`8\^M)$$[#?U,&WK68/#!.[]+Y`+;Q@DXORL?,"^]*I;[I]YDMX&Z
+M2%/6I]O,]R>\&JA^Y%Z@WFL]TMS/VX]*VJQ)FQ>(N&'@$WW7VHC5/ZK,QL3A
+M`D[`7@WAN34HL2U:U?I[&O$1^,(-]$6(!E56K&>](Y%IYD:-'L!:.^A][3AY
+MBX+Y;0A`W-)")Z^PM!W4(3&M\1K!42/KVXK?&`_#>$(+)N";"DQ;S9A\0%+N
+M4LP93U4+7)B];I)0,SR"9^BU"H9H!%F='-GP(=5>U:7@D>ITZG&0SPI9"@:$
+M(;D.M$PIWS]._CP#+!L<&!@K/&QW\>'&\DAZ14_EV"FT0RL9U!;G`.&G$5'Q
+M*H<;>XEOE+M?```ZPK@`B<OS[4U0&1Q.8TQ-9QQD1!HBZ^#\+BF=?'ICJW_Z
+MOU>.JJ]H]EB+!K>0-;.2-,>[(V1T0-'NIXE'OD%]TZ+>2:"TE?K1#Y:&=@0@
+M0<8"CL@H)5G*2_8GG&B6UN[&]?B)]O_D>2%)UIU_';T.!GV+=4(NH1YJ"5.R
+MK6VT]E)]M%&H*,9-H1^S&J)ZD?P@P_=:/BF7`2V0BZ^GV?O#8^F58L:)OPXS
+MT#X'.''TMY!JTO<?:?M=3?(7/P?@;Z7P+>-(C6YUWA68@2VX6@+UQB[3#QIZ
+MGZO?T9/<_!I,F[MV(=L+3R-@,63-I,1XX>?[N9!BR0=O-Z@&0TW&B7[VM'Q<
+MDS,^-V\NCX:D!F;?7Z\6?`J@3-S'Q)>HU"10U;L^^;0'X!N*BLI[`%X^/X;D
+M![C/25?/J8J1$PW6D[UJ[C0LV6<(QV*(L-LPG/!,_^\C1J7YYOE_O'>9,LI!
+M!@YK6$%OD\O,>HRNU=KFN(7#2U8WTF_PS^*%C+O>-*NN0P0$'%>QQHA]Q;)B
+MF*J!C4?H,CAB><5PO"E>@FT0@+VEJY?F.^GD8P28:?QJ`8*GZQ.I9P"V"APO
+M/_7RBZ\VNE=ZW.@J4;21,]B$=33[D21X`-]08D;V+'[I4K<.0QLX,D@"9<(-
+M^Z#1#-&\.)4[6DX]^@=-;'NT`1.^N@N*LGW&9E>DYBAX4N4\6\T_T'ITL6^=
+M83<]PJP560@+SXZ\S++[:V@R[C9G;K"E.R5BUC@BX#X$1,R5]L'*HLO2+(:+
+M8:=@06<]YQA"U&>&7%ML#I?*Y3(SO$1!B`3_+P!X\9GO4B$M"(S=;F<OC)D_
+MW?$4<+BSW-;>;_UU9T*`FOU>O)\/_$4"M@C1K7K^)_4CBMCK0M3B].-[>G0)
+MZZVJ/=4.8Z>?(248O?);T8WJAMTCN0[%PTWU[.-CUO'5>4$T75'Q)O5".',A
+MGT!WALW&R8DV>TY,J6^NQ?*=BLL^?G,#U3'U;#1NN,RZ7'HC@#5?(D:X!;Y`
+M\&6!WI[+ODO46HR("Z.4'3LK^KO&$ZFS,WE?,DYJ>#DK4';BH'!]D&?X]\YC
+ML>[%;DF;E$"#%"@M8LQ#H2]K.E2K^Z"ZG8YC$\IN88<0E>>;``"ZH1*XN8)D
+MX*'L[KI)>'W6L__0P*T(I_4693<;@A%\-#A6\H*XGJ#/2T46JOAK+^YGH`;F
+M<P@2W0]L#]#E:;/C?-,6FEB`E^7QTN"([H(C*`/Y?IKS2#/I6M`AL#NRR4.\
+M0@L#<?T$(A66+XHPGK=:2P4?2J*Q9?J)@,]V:G&A]6='Q([?R5*A<U?RF(N!
+MQWV^#[*9N?9BH%+7T/<T.$;.)F!2,#%56E3`H^'NTOFE-$.1]`SMP>I=\"5S
+M0"FO5T"UX#J-Y#.SW'\YOS/@H6I('!`YJXDZT&`K$"A7USET[I3/+RU#9]ZL
+M6,(TT&9!TY,]1FG=_^:X987GD_2DY[[GWK19QP.39)F7:#P9`&=(.K5Y`CC"
+MDWW/9"P%48&0'VD8$%HTHNVG.Q%O]/.<^_)P0J\C(.IAY/;-!]6(=#/O'C2\
+MIBR:31K8@[[QY<;Q\1=A5[QSR"8B2-A/F1)3G$?91>KY_[94@'N33WWK%.M$
+MPR-G$YCMD;W7S[?]<2V4^=NS!V0SG8%&!T-^5&QL]BLV49Q+21RT7-<@&M;&
+M;B^Y$&YDVO301F&2C2_?`7=#ZFGY'TDZO;AF9_\9)65?9]V#>`NK:&'^?!"I
+M\/W08`7$K?_^S=FA3-2_H.^K1.%[X%VBHIMRS924QBI5M29].U@D[CR>\LY9
+MFCH"/RB?/8KRL7>1<V2-_].AVAL#(1@%TM[?^3GA"(P?O4%32";.&Q4/\QD6
+M#/-O6$_G(-K#`QN*J%FCCD(=U!)P[0G]7=L0)?'E[5]$%L=0AUE'>K?D;!CK
+M2JFRV+?#2"/_X5W]-J('=:Y=YXT>)V*&&^\]E$Z*?W"N+H1_S+2)"H3&@;4/
+M*](.UZR,;LITE-#=%EIO@6%T%VR9)*LCQV=&T_7S%_;%%L_JSSM4YW'=$C^'
+M(]#AS$97_A3&IZ"$+':9E%^'7]1?^:'!@U7[Z5$IXAPZFLR^ZC+=0H+(Z&M[
+M4WH0O\;*[V%&.:C-W.1Q;].Z>PWGQM/Y!=`?/+!#[B]:3839+81=@G<M4XGX
+MZH7,X)"<FV0_;%U->M//`3BP$']S^^2NH^K"Q[AZT"AK36LR\;WPW."@%Y_F
+MT3>FH?8UMQCKAO]LV%%IK2:_C@.;@6"LT_IV2K!2EYX(!K]6027B#J#P4C+;
+M[;>%TLKN3']+5?HCUK'Z5Q4DO!61L0H>D4'1^9&M'Q?E"MSHE/-4,=8MJ/$2
+M(C&0OV6H`*50KKOLVM-XB_5>-]==):(Z'$ZF3%COR%=S,7Z7/&9K=3/7>R`(
+M#I$$ZF_YC]W%\%J#$%R"/`5#0-V_6S-^C5EV9*;%L)G::QU\GY]D(H@5AC3Y
+M4R*.IX/!N"R99ZFT?@3$7D@>P]]=,\#"WTH$EB,Y[H0_0\Z_H<7[Q/<%($H8
+M\RZ3@,Q[!SKSV4]QXCB*3GIZR;M>OZT,YGZ$@?QT<;CSYT4*!!)F9F3-^\!Z
+M(EFOXEYT&%J8U<%T"HNK'$9AQ=D)Q90RC4!OJ]-1.Q0EGQ1QY<,QX\A;J2XL
+M@(@5#\!`)/)88#'LT$IT?\F8*%_&@1W^N&(PSJ$+<)M[`F@NVC91DB7)+;3'
+MZ'K4Q=ZQWU8YRVC_VR;'EA@%8U]=#2G)W(2XE0`AU(\%/OC9H5"/;&7KXE\W
+M?.8XVL<-,[,I\)HD=MS=Y2THV(3)!9-(E+.NU.DWMSN]L_/#NVH+?XJSH_0A
+M@8%X-`4)9ZL`J_A78C'DF;G"VB"?P$O&ZQ=Q.0%'6P`N\GOZC0*)=4L'JVO;
+M[-8=?M`X>;>X'ZO42T*L'SVG26!RP%RFHTXITO7+J8%U_U;6]2K#?8BB;JS;
+MT:%^:II9#9NP`&"(M*-G;17!KI]F28/&7+TLGK"6<E`?6H(=-WZ?D[TZT',8
+MF<6J84S6V!0$DF2YQ[7$/<_JW^6(S)NA5RG/7`>?\4=@<O[*Y,=6M:PS;AO@
+M?UG*63L`,AI=Q&%=P>T/>TPH$5F(FPD"]OW<XN%>-9JX@E$!`V0L1:-'V3Y%
+M/-P1(CGA/<#AS@)>J+:>E?K,$S=\WS+#<W0C;R;7W2(^Y^6F`YM/X4CN.`R^
+M315+13O97L!_/0D4C`O[>W^KIDQ>>YXE80`\NTRO%0%F?DL@O9.'[8HK&NW.
+MJ-U"#/7M=^=+H1@.R48J4L&BPI,+7UJ/X%"W]K[%K2*`&5_9387H7!P'SL(O
+M@+]D4VV'`$]+\!"'M.FT!@5XVZ(]!$$]4,/;Z90?;94YG%5D(0"PSRIDG(]_
+M!404$.3*!<^K"A^IN?(-?<Z[,["4H=5I5:#@)*[APC"H-:1J[)3=HN^&_U$^
+M/48/\U1]D>#M2F-U,5_W`(B9E+MTAY%-5CRLQ^(.H*0PW/1R=]4)?8MVX(N1
+MT0'<,8)MN9_Y3_&G!V,YHH$!<_:>=;HA^AYX`KLQ^097HXMTQC-ZPC>!P*W$
+M"G$]P0K%2R!NI6;K??%9@$A?&<FO]H`5E*INUJ`HM;<(/D.1"K'0\DVBC9*K
+MPJFN8K\Z6(;*ZKP:%KQ(#2F)SL2(1,O,],'FCFP8"$1#9M.^)Q?]IFJ]QQ;=
+M=@%XZRO:+6.*5_("7SD,.Z"X*M%>>7-:<-W1TB;V0]U=$6HT@5@V]EAI(<!`
+M`'\`O4VDC(I``]"G'[7]%0'!HD6#K:55%CBOBX]$XP6#NDJL)H$^(](E[W##
+MZ"<9#A@76BRWF]7@<`']B*]U?RQ.JVC<3#>F#:W=T:HH#2G44M_AZS.IHW4E
+MQ]?O%PPW9S&1?%5F@JHU@AX5T8$A(L:RP]A41DR`@<;V++D!O'G21X],J*MM
+M?8JF).WJU!H'X5:L\?JAF(=`^2:$DW6V=+84UTU>%5_\@:3KH\02U!LM^M3%
+M:)_4/GM"^_=M?]=>!K^L\R_<^VU!FDS]Y*,PF>NB"IR@!NVP'3@A*7VA%VA0
+M/XX(;+U[82(4]!.:]?2\SA,3BYL]I5DO<YG?"TP.3B-F!#T*F%#[FD0&<NA8
+M:RBO_(M*27Q`<&/D$Z+]V.KGIO?PKL4V^Z70^K5*7=DU/B^[[3\[7?X6?<`Y
+M4;3Z&U":>5*NB3(N$E=C;.A$O+9(-8HD\<)ZTJP!O#0\LV*%!3*)Z>\KUXQR
+M5/VO#I"EAZ6[2^=M@3B4<Z]W^`VX%">W[`"-+^69K#M*/UN)=P;*$PRK;8);
+M*&-+!7WXR4ZW;\2<CVK`C?8^I&]D>?2X?0M?@77]Y9IGT#LIQ0SCI>G=3($J
+M%#M3&-6[J"N'BA1/T*=AW1N\8IXP)ZZ>"CJ;<K,J^/%'$(H=Q8E96\7'P4'=
+MU#71R$X?>$KZU3-FDZ\:ZZ4^7`\$#-38V!_53T>Y<#VN7T<?YVHFHX[&D0F8
+M%8D5OPHK3VE\5\-YUJRK"6SZ:WNSJ-*G!N*`0ZVBA[%``ZC@>L4!-#1#OSMC
+M9Z#15ND>K9:PI@(KN=/GBSH4%S`&]2+3_8^#E\$3OBQWH'MWU6T;\Q=EP@_#
+MH>O6BB#6M^"MN3!^=RE]MRZ"VEWQ'$D>@++.[("^\LQ,T*SX`6?\!+7*`*7?
+M)]B=1!^YI&86T*6-0.GM[.*7M(>QE[HO'8,%S)947!AAL$+3%*]9Q.<J-F-P
+ML)ZLU3ZO*B(T(3]K$N"T`92-7\J2W3DEY+*DD?2U%Y<57>><O?A3%%%/0[';
+M)</*OE@5:*75\`#&-\;3T^@Z$9(E1=^_7@$WSKUZI6N\I*X+03=?/:K;7J[&
+MSC91K,7RR6E^'1!58JPFL?V4-"I/6^@M.LW,[1=<T8V4C^7D[7'KSE7ZJ3C,
+M6KK,L#]^QO_OA.;C3;P,`*%;-#2^/$J.#"(58,Y<R5DDQ77HH:[,>TZLE#68
+M2XK1;PK=54+\A4J[L'=#`@2$XV'.6)DCM7*!+-I=LEGZO'+O3"B5@&=#-MP?
+MIXE5:9*Q%S$#0+3OYZ#:GU,#ZA'*H6H"9S#%8='*\L%2)=QG?AB+[Q\CFIQ^
+M&^GX_?+E=EIL_=UM"@F58*?A*`YO`X?O4<#+Z!R`Z#,HD_<@3.W:]T"4_$>3
+M@[.U&%JEV-%KZ(L<-X?*5AEO2#F&@"YXX!=T)Q+HO2*T*,[<[O9VLTVTKD9R
+ML:4S"ER16"LL+0(MC&_*DSQ?MZ1.G)2LAFM";J;(RE1>!<$-=GR&6]JN;T/D
+M:'#_JP004=/^\0WT`J8T?(V05T_<["1R9KGA1WP@YBF85J;6R"9R^0=;3T6/
+M0L/M7[8S7Y4/B%[:L_-`$'G(#9E<^DS_,HE14SH&;%`F!<8(%[%W$9],MG>'
+M-%6S!I<*40F<$$*85-P6Q!9B]&"VU^R&K$LLQF_&\Q^H-?=05=-H&25;A<5@
+MFKGV5>BK_JOD]'8DYH1C&>8?S(X4,.AK7*(0B86_\`T'&'=D62W;(.=92\<^
+MQPNGQ<$QDL>PVLPJ0"Q!71D)]MM!JV?"!,GOMMI+]ZK=85$Z"4V<<8'RT<2,
+MX%W@\GJRS/B4_W4XS-8N%.J#$,6LT2)V>X?I3H?*K*83&3J=-<@A7%N'6#QG
+M[*XC&=@%O=^!AJZTE$>VCH5%B$,%,,YS!UB3K\:[__U_/?W_L^9=+$0[]%34
+M$%2A`I$X_W$51X*$Y]?)/CQX'%U'2W`E#Z&.'5)\N^35,U"1;LY%E*C6[(NX
+MNI%F&E9B(R19Y]:6\_A/!(>;^%9]LF./CM)1G`TT"Y=]=(8/X5N.70L*B$*;
+M.8/6<F^?EA!840;"VFDVS1:-RSS:M^%N-BM?KOBL^BYI<>-;0\5)V^)[P(ON
+MAA0'%ZWQG,!H&+GT"UYVTWI#G'6J:H`LK]COP.Q-+1Q)9N8]8YYYD^I+K;^R
+MU`7(;"V/W//3P5I:!AX'0>XL:H`*B*>:.^LA0W'"I5YI;T+Q6+1(%+[VJ+)9
+MN<B7U;$3KYWV-TIP17!]]G<KXYL\.>^7\BFZ^U"$2)%5*7BK9-VI2N06O@'1
+M\')`*S#DBK>)L],YQ!G$#2#?*#E+K]?(?@;JW1@]6N1XNW&USE=O`<?JHVJR
+MJ&7%T5^TE(FN&]JZ)L"3LIP:S'Y@\,87<^*Q=DXLP`TAPE7'8>IRR$#%_S(^
+MLQ.?0ZVF@+88#8L>CE[7&[I;2\I2=%DR+MR$-:4QV#A94_)A&,+FQ=UN6_>P
+M989E%2:S:SVHZ2#*#`+*,X*NAX>"NF4YS9;V$<#)'L\R_8;51*F1>3X`,L8S
+MM]]V4(%%6D1WU\7>+)7*/+EOW@S!/D57QR9#R3M:&N6SJB!B.5%AY20`P\UP
+M12;DPNX'ER`G4E,87<\@D(.0#:7.%-H+V'&"M[!JAM<S_?3RFXL,&S^#OW2$
+MQ/1SQ&9(&N&`(+J0_$WMN+RC(R2H43>&<MI[#5/_=W@+IA)`;&DZ;*;B.MS_
+M=Z\TOLU5$('I6T"Y=Z+%:M;PGC@-26;5]V!&QO];/&2$D(&*+NR:0-:`O8)F
+MJLQ9PZ&HO,U2SAI.4#!><:4P,F[,3*)CK>5KUU^MZCY>>NH`H'[3A'K]=&Z6
+M!?G>SAB]^W8W0HK)%-\4LG?10`A,G0;XZ]1S'[-7(T^>16]B0LC!;<PTDM0)
+MB^S?*)HB'%2&"E$9BW<'"TY5HX2C_\&!;E62Q#J<G&R[^JL!28<X`XLS3/'[
+MA"J,CA_IQ_$:II!$(*WLG1J3JY0;-<0AI^![.26&7BT4`U5;JZG]G>`3D<YO
+M0S$S[)$LA<2T0OS6'*@A)RE%U$8]2HPX'20D,O*FH+6B2;RJ^>.DE<H@)F(7
+M1:ZO='*P+F>;'FEC90`JK::$Y[8`U(2T6H@BUF`)8-PPZ`/`4+NB,Q5;.$^Q
+MD+O=>N+^"6'X[=A2O5D5;IU-M,KP^N783S%ZE\C,*\X;@P5X:QV^;T1Y#)%*
+MLC@7GEE.\,]*4<[3!;`7GH#8/E]72:C]TCTEL:;387`2P+CB-^H*J!1^[C@4
+M%!55-B[<$[F!I*EX]=<5W0W=NP9ICH*JN4V6O1ZA4Z=4H_&GR`PS1]7GE:AO
+M]?39:FOK'Q%GNE)%^FH>-98O$#/U?2`B@GD.G&L4_7`B`41A..V_D!!G3_8^
+M>G^$CBM*_#@W@>@0\#W#5\X1\&C*R#&=EZ(HU`90ZB6^9I*4Z'FH_\,L_5*=
+M!$IL#Q7A3S!IYO!P]T5%9EMB7DM:A_78]9YN_[]+RZFJ4V>J@0SA#[NP-D#1
+M:C"-(%KC&'R>WHUS>%I2?_`H,_NJQ.C'4QLJS'XVE\)HT#0_.?[$2%/[!=K2
+MHK47V@L3JAGSL0&6M_HO>!KX61&'6#G;RZ<P'^UGB'^.H%\C5P1X7+-'XK>?
+M!%%NBHU2-_V7X.*[9ZK;\N0N=9M\=$>EL7#]NHAD\7*FJKU.^E:()]6(2ZR!
+M3PPIS`"1YC$SY8Z/])K`#883#9&Z8:`W63_'WC1\^#.6!H\='78>HD(7]:M%
+M]K(`0J,F>L/0N2LE$+;>/(89ZDD\U6W+CA<+.S'I_G+-S,*@N,HYR3:4#@,@
+M`MG2V"[EA$K`^P:O`^(.:(.B'FK@-M[`S"I$9W/**,=?C>5;I/!L0OST&X.D
+M(&ZI*&\4M8D5B3-S,33)*R>/*X4I<8!V0>6YW'<TJ='#^5D)K\QGY`>57OY?
+M@S$?1(MILODT@KL2K2^^_L(;43,(W==PA>",I\?COZUI5C^UB6&B,[(<^_$+
+MYKU8,9";R/_2@+9D#WQ=@^0G*EM'TC-58)&V8JBD=]VJUMURJQH2=RE]&2WB
+MN<V%+DPI@B2[H45_?I0K>^;BIA!)ROUGE4Q"T3`@"TK6XT8E,^W0'N<*(4;R
+ME=TAXS8SQMYES6>SPIVB!EOVR0I36T/D1_]WL5W#5N<`=^C(QRWIE?N@3?TG
+M_Y8__>U%Z?BL^N9Z;F\<<F4NF,P?P:N-C"O#`<"C*)HTR^Z:^WEX\NMTCSM;
+MSHS/LITHL/^[G-6>Y53SON2&L61A<]!T_4?%:EC9&GU84U/1A-[?4#[-9J%Y
+MPD30#+9`6#_G+]%`";]Y\D6(OWXAZ)]]K%`D[B*+H]V2=^]M&[:Y_^L?94I=
+M=M2U@)%LT]N%GV]=<R&2>\A3GBB-K>A2PTBJE%<,<4XPGA)C(/1+S1*(E3&P
+MA@6$5)V",Q[0E6;-*E0=*A6T5U.KY^_C66Y'44^BP3<AK\LQD2S'`VS?:$':
+MR4U`;#YH=@7NV&I@Q$%Q&B].NS@\SH$F'NBG'1]7H3(-W@@/F_9_4D9&*394
+MUH7-0PS.R0>5>=31^5S>,T3;IH^"$4%^3OM/P796=[G_HXE!"5@1+V#?H6"#
+M[49)5#Z-6K_XMB;K;,MGSN_&I4"VT%%A9#$J&FMN>8)_\(G6@-]ERD58.OQ"
+M_PZ@>Y'+TPY0Y2T3%TMN/,V\.16J8&X"5;AMM)85SNS$6Q[_8+2A9^V[>0T4
+MZNHACJ&`])R!9R7BFS=:[OL:HPQ@V'KC?/.[0-)\/2GV<5=TTD@X$``!!`8`
+M`0G`648`!PL!``(C`P$!!5T`@```(0,!`P$`#,#K:\#K:P`("@$6V^8W```%
+M`1D)````````````$0T`9@!I`&P`90`Q````%`H!```M0RMQLYT!%08!`""`
+$I($`````
+`
+end
diff --git a/libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu b/libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu
new file mode 100644
index 0000000000000..951da15ec6f87
--- /dev/null
+++ b/libarchive/test/test_read_format_7zip_delta4_lzma2.7z.uu
@@ -0,0 +1,407 @@
+begin 664 test_read_format_7zip_delta4_lzma2.7z
+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
++`14&`0`@@*2!````
+`
+end
diff --git a/libarchive/test/test_read_format_7zip_packinfo_digests.c b/libarchive/test/test_read_format_7zip_packinfo_digests.c
index 94cd1ad32e421..7f105d1f2806e 100644
--- a/libarchive/test/test_read_format_7zip_packinfo_digests.c
+++ b/libarchive/test/test_read_format_7zip_packinfo_digests.c
@@ -35,43 +35,55 @@ DEFINE_TEST(test_read_format_7zip_packinfo_digests)
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
- assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
- assertEqualIntA(a, ARCHIVE_OK,
- archive_read_open_filename(a, refname, 10240));
+ if (ARCHIVE_OK != archive_read_support_filter_xz(a)) {
+ skipping("7zip:lzma decoding is not supported on this "
+ "platform");
+ } else {
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
- /* Verify regular file1. */
- assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
- assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
- assertEqualString("a.txt", archive_entry_pathname(ae));
- assertEqualInt(1576808819, archive_entry_mtime(ae));
- assertEqualInt(4, archive_entry_size(ae));
- assertEqualInt(archive_entry_is_encrypted(ae), 0);
- assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
- assertEqualInt(4, archive_read_data(a, buff, sizeof(buff)));
- assertEqualMem(buff, "aaa\n", 4);
+ /* Verify regular file1. */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
+ assertEqualString("a.txt", archive_entry_pathname(ae));
+ assertEqualInt(1576808819, archive_entry_mtime(ae));
+ assertEqualInt(4, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+ assertEqualInt(4, archive_read_data(a, buff, sizeof(buff)));
+ assertEqualMem(buff, "aaa\n", 4);
- /* Verify regular file2. */
- assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
- assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
- assertEqualString("b.txt", archive_entry_pathname(ae));
- assertEqualInt(1576808819, archive_entry_mtime(ae));
- assertEqualInt(4, archive_entry_size(ae));
- assertEqualInt(archive_entry_is_encrypted(ae), 0);
- assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
- assertEqualInt(4, archive_read_data(a, buff, sizeof(buff)));
- assertEqualMem(buff, "bbb\n", 4);
+ /* Verify regular file2. */
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_next_header(a, &ae));
+ assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
+ assertEqualString("b.txt", archive_entry_pathname(ae));
+ assertEqualInt(1576808819, archive_entry_mtime(ae));
+ assertEqualInt(4, archive_entry_size(ae));
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
+ assertEqualInt(4, archive_read_data(a, buff, sizeof(buff)));
+ assertEqualMem(buff, "bbb\n", 4);
- assertEqualInt(2, archive_file_count(a));
+ assertEqualInt(2, archive_file_count(a));
- /* End of archive. */
- assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF,
+ archive_read_next_header(a, &ae));
- /* Verify archive format. */
- assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
- assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a));
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_FILTER_NONE,
+ archive_filter_code(a, 0));
+ assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP,
+ archive_format(a));
- /* Close the archive. */
- assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ /* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ }
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
diff --git a/libarchive/test/test_read_format_gtar_sparse.c b/libarchive/test/test_read_format_gtar_sparse.c
index 7ab13c1109a02..6d15a4745f9ce 100644
--- a/libarchive/test/test_read_format_gtar_sparse.c
+++ b/libarchive/test/test_read_format_gtar_sparse.c
@@ -214,8 +214,9 @@ verify_archive_file(const char *name, struct archive_contents *ac)
* Any byte before the expected
* data must be NULL.
*/
- failure("%s: pad at offset %d "
- "should be zero", name, actual.o);
+ failure("%s: pad at offset %jd "
+ "should be zero", name,
+ (intmax_t)actual.o);
assertEqualInt(c, 0);
} else if (actual.o == expect.o) {
/*
diff --git a/libarchive/test/test_read_format_rar5.c b/libarchive/test/test_read_format_rar5.c
index bb94d4e34e25a..f91521e72f820 100644
--- a/libarchive/test/test_read_format_rar5.c
+++ b/libarchive/test/test_read_format_rar5.c
@@ -1256,3 +1256,18 @@ DEFINE_TEST(test_read_format_rar5_different_winsize_on_merge)
EPILOGUE();
}
+
+DEFINE_TEST(test_read_format_rar5_block_size_is_too_small)
+{
+ char buf[4096];
+ PROLOGUE("test_read_format_rar5_block_size_is_too_small.rar");
+
+ /* This file is damaged, so those functions should return failure.
+ * Additionally, SIGSEGV shouldn't be raised during execution
+ * of those functions. */
+
+ assertA(archive_read_next_header(a, &ae) != ARCHIVE_OK);
+ assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
+
+ EPILOGUE();
+}
diff --git a/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu b/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu
new file mode 100644
index 0000000000000..5cad2194ee1e9
--- /dev/null
+++ b/libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu
@@ -0,0 +1,8 @@
+begin 644 test_read_format_rar5_block_size_is_too_small.rar
+M4F%R(1H'`0"-[P+2``+'(!P,("`@N`,!`B`@("`@("`@("`@("`@("#_("`@
+M("`@("`@("`@((:Q;2!4-'-^4B`!((WO`M(``O\@$/\@-R`@("`@("`@("`@
+M``X@("`@("`@____("`@("`@(/\@("`@("`@("`@("#_(+6U,2"UM;6UM[CU
+M)B`@*(0G(`!.`#D\3R``(/__(,+_````-0#_($&%*/HE=C+N`"```"```"`D
+J`)$#("#_("#__P`@__\@_R#_("`@("`@("#_("#__R`@(/__("#__R`"
+`
+end
diff --git a/libarchive/test/test_read_format_zip.c b/libarchive/test/test_read_format_zip.c
index 9afbfb6c58666..04f7e98ccfcd2 100644
--- a/libarchive/test/test_read_format_zip.c
+++ b/libarchive/test/test_read_format_zip.c
@@ -194,7 +194,7 @@ test_basic(void)
verify_basic(a, 1);
/* Verify with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
@@ -264,7 +264,7 @@ test_info_zip_ux(void)
verify_info_zip_ux(a, 1);
/* Verify with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
@@ -328,7 +328,7 @@ test_extract_length_at_end(void)
verify_extract_length_at_end(a, 1);
/* Verify extraction with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
@@ -347,7 +347,7 @@ test_symlink(void)
struct archive_entry *ae;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* Symlinks can only be extracted with the seeking reader. */
assert((a = archive_read_new()) != NULL);
diff --git a/libarchive/test/test_read_format_zip_7075_utf8_paths.c b/libarchive/test/test_read_format_zip_7075_utf8_paths.c
index 7b78770aae437..a0a510c8f29ba 100644
--- a/libarchive/test/test_read_format_zip_7075_utf8_paths.c
+++ b/libarchive/test/test_read_format_zip_7075_utf8_paths.c
@@ -90,7 +90,7 @@ DEFINE_TEST(test_read_format_zip_utf8_paths)
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
diff --git a/libarchive/test/test_read_format_zip_comment_stored.c b/libarchive/test/test_read_format_zip_comment_stored.c
index b92b2886cddaf..95df0107fecb9 100644
--- a/libarchive/test/test_read_format_zip_comment_stored.c
+++ b/libarchive/test/test_read_format_zip_comment_stored.c
@@ -38,7 +38,7 @@ verify(const char *refname)
struct archive_entry *ae;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* Symlinks can only be extracted with the seeking reader. */
assert((a = archive_read_new()) != NULL);
diff --git a/libarchive/test/test_read_format_zip_extra_padding.c b/libarchive/test/test_read_format_zip_extra_padding.c
index 54f7fa04ee89a..6e2f836f16e4e 100644
--- a/libarchive/test/test_read_format_zip_extra_padding.c
+++ b/libarchive/test/test_read_format_zip_extra_padding.c
@@ -80,7 +80,7 @@ DEFINE_TEST(test_read_format_zip_extra_padding)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
diff --git a/libarchive/test/test_read_format_zip_high_compression.c b/libarchive/test/test_read_format_zip_high_compression.c
index 42faed378f6d9..16cfbb182893c 100644
--- a/libarchive/test/test_read_format_zip_high_compression.c
+++ b/libarchive/test/test_read_format_zip_high_compression.c
@@ -56,7 +56,7 @@ DEFINE_TEST(test_read_format_zip_high_compression)
}
extract_reference_file(refname);
- p = slurpfile(&archive_size, refname);
+ p = slurpfile(&archive_size, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
diff --git a/libarchive/test/test_read_format_zip_jar.c b/libarchive/test/test_read_format_zip_jar.c
index ffb520eb83c12..912e671377042 100644
--- a/libarchive/test/test_read_format_zip_jar.c
+++ b/libarchive/test/test_read_format_zip_jar.c
@@ -40,7 +40,7 @@ DEFINE_TEST(test_read_format_zip_jar)
char data[16];
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a));
diff --git a/libarchive/test/test_read_format_zip_mac_metadata.c b/libarchive/test/test_read_format_zip_mac_metadata.c
index 99b7012328cbf..3f2813cc98947 100644
--- a/libarchive/test/test_read_format_zip_mac_metadata.c
+++ b/libarchive/test/test_read_format_zip_mac_metadata.c
@@ -76,7 +76,7 @@ DEFINE_TEST(test_read_format_zip_mac_metadata)
};
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* Mac metadata can only be extracted with the seeking reader. */
assert((a = archive_read_new()) != NULL);
diff --git a/libarchive/test/test_read_format_zip_malformed.c b/libarchive/test/test_read_format_zip_malformed.c
index e14a3f5660daf..f1160648e759c 100644
--- a/libarchive/test/test_read_format_zip_malformed.c
+++ b/libarchive/test/test_read_format_zip_malformed.c
@@ -46,7 +46,7 @@ test_malformed1(void)
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
diff --git a/libarchive/test/test_read_format_zip_msdos.c b/libarchive/test/test_read_format_zip_msdos.c
index 5f147d5577845..1867204bb6ec2 100644
--- a/libarchive/test/test_read_format_zip_msdos.c
+++ b/libarchive/test/test_read_format_zip_msdos.c
@@ -103,7 +103,7 @@ DEFINE_TEST(test_read_format_zip_msdos)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
diff --git a/libarchive/test/test_read_format_zip_nested.c b/libarchive/test/test_read_format_zip_nested.c
index 5f6edf2674430..4418fc4f25022 100644
--- a/libarchive/test/test_read_format_zip_nested.c
+++ b/libarchive/test/test_read_format_zip_nested.c
@@ -34,7 +34,7 @@ DEFINE_TEST(test_read_format_zip_nested)
struct archive_entry *ae;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* Inspect outer Zip */
assert((a = archive_read_new()) != NULL);
diff --git a/libarchive/test/test_read_format_zip_nofiletype.c b/libarchive/test/test_read_format_zip_nofiletype.c
index b01afabe953bf..b3260fa7563be 100644
--- a/libarchive/test/test_read_format_zip_nofiletype.c
+++ b/libarchive/test/test_read_format_zip_nofiletype.c
@@ -40,7 +40,7 @@ DEFINE_TEST(test_read_format_zip_nofiletype)
char data[16];
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a));
diff --git a/libarchive/test/test_read_format_zip_padded.c b/libarchive/test/test_read_format_zip_padded.c
index 2094eca3557ae..d8c694bae5e25 100644
--- a/libarchive/test/test_read_format_zip_padded.c
+++ b/libarchive/test/test_read_format_zip_padded.c
@@ -34,7 +34,7 @@ verify_padded_archive(const char *refname)
struct archive_entry *ae;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a));
diff --git a/libarchive/test/test_read_format_zip_sfx.c b/libarchive/test/test_read_format_zip_sfx.c
index dc76ef9b38266..a33c1b808c567 100644
--- a/libarchive/test/test_read_format_zip_sfx.c
+++ b/libarchive/test/test_read_format_zip_sfx.c
@@ -37,7 +37,7 @@ DEFINE_TEST(test_read_format_zip_sfx)
struct archive_entry *ae;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* Symlinks can only be extracted with the seeking reader. */
assert((a = archive_read_new()) != NULL);
diff --git a/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c b/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c
index dc94f94f1571e..aca8bed609483 100644
--- a/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c
+++ b/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c
@@ -39,7 +39,7 @@ DEFINE_TEST(test_read_format_zip_with_invalid_traditional_eocd)
struct archive_entry *ae;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a));
diff --git a/libarchive/test/test_read_format_zip_zip64.c b/libarchive/test/test_read_format_zip_zip64.c
index ac3789f46b83c..bd2324e549b3c 100644
--- a/libarchive/test/test_read_format_zip_zip64.c
+++ b/libarchive/test/test_read_format_zip_zip64.c
@@ -88,7 +88,7 @@ DEFINE_TEST(test_read_format_zip_zip64a)
size_t s;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* First read with seeking. */
assert((a = archive_read_new()) != NULL);
@@ -112,7 +112,7 @@ DEFINE_TEST(test_read_format_zip_zip64b)
size_t s;
extract_reference_file(refname);
- p = slurpfile(&s, refname);
+ p = slurpfile(&s, "%s", refname);
/* First read with seeking. */
assert((a = archive_read_new()) != NULL);
diff --git a/libarchive/test/test_read_pax_truncated.c b/libarchive/test/test_read_pax_truncated.c
index bc5d74d5bdb85..1f6e78ace2027 100644
--- a/libarchive/test/test_read_pax_truncated.c
+++ b/libarchive/test/test_read_pax_truncated.c
@@ -82,7 +82,7 @@ DEFINE_TEST(test_read_pax_truncated)
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
goto wrap_up;
} else {
- failure("Archive truncated to %d bytes", i);
+ failure("Archive truncated to %zu bytes", i);
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
}
@@ -91,7 +91,7 @@ DEFINE_TEST(test_read_pax_truncated)
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, filedata, filedata_size));
goto wrap_up;
} else {
- failure("Archive truncated to %d bytes", i);
+ failure("Archive truncated to %zu bytes", i);
assertEqualIntA(a, filedata_size,
archive_read_data(a, filedata, filedata_size));
}
@@ -103,7 +103,7 @@ DEFINE_TEST(test_read_pax_truncated)
* does not return an error if it can't consume
* it.) */
if (i < 1536 + 512*((filedata_size + 511)/512) + 512) {
- failure("i=%d minsize=%d", i,
+ failure("i=%zu minsize=%zu", i,
1536 + 512*((filedata_size + 511)/512) + 512);
assertEqualIntA(a, ARCHIVE_FATAL,
archive_read_next_header(a, &ae));
diff --git a/libarchive/test/test_read_truncated_filter.c b/libarchive/test/test_read_truncated_filter.c
index 6cc91e347a234..632638d6fe928 100644
--- a/libarchive/test/test_read_truncated_filter.c
+++ b/libarchive/test/test_read_truncated_filter.c
@@ -83,7 +83,7 @@ test_truncation(const char *compression,
for (i = 0; i < 100; i++) {
sprintf(path, "%s%d", compression, i);
archive_entry_copy_pathname(ae, path);
- failure(path);
+ failure("%s", path);
if (!assertEqualIntA(a, ARCHIVE_OK,
archive_write_header(a, ae))) {
archive_write_free(a);
@@ -94,7 +94,7 @@ test_truncation(const char *compression,
for (j = 0; j < (int)datasize; ++j) {
data[j] = (char)(rand() % 256);
}
- failure(path);
+ failure("%s", path);
if (!assertEqualIntA(a, datasize,
archive_write_data(a, data, datasize))) {
archive_write_free(a);
diff --git a/libarchive/test/test_sparse_basic.c b/libarchive/test/test_sparse_basic.c
index 5ad591be830d7..0fbb7f7bf4678 100644
--- a/libarchive/test/test_sparse_basic.c
+++ b/libarchive/test/test_sparse_basic.c
@@ -430,7 +430,7 @@ verify_sparse_file(struct archive *a, const char *path,
assert(sparse->type == END);
assertEqualInt(expected_offset, archive_entry_size(ae));
- failure(path);
+ failure("%s", path);
assertEqualInt(holes_seen, expected_holes);
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
@@ -466,13 +466,13 @@ verify_sparse_file2(struct archive *a, const char *path,
/* Verify the number of holes only, not its offset nor its
* length because those alignments are deeply dependence on
* its filesystem. */
- failure(path);
+ failure("%s", path);
assertEqualInt(blocks, archive_entry_sparse_count(ae));
archive_entry_free(ae);
}
static void
-test_sparse_whole_file_data()
+test_sparse_whole_file_data(void)
{
struct archive_entry *ae;
int64_t offset;
diff --git a/libarchive/test/test_write_disk.c b/libarchive/test/test_write_disk.c
index 60bcdc24edf5e..e38dbc78ff4ea 100644
--- a/libarchive/test/test_write_disk.c
+++ b/libarchive/test/test_write_disk.c
@@ -186,7 +186,7 @@ static void create_reg_file4(struct archive_entry *ae, const char *msg)
#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
- failure(msg);
+ failure("%s", msg);
assertEqualInt(st.st_size, sizeof(data));
}
diff --git a/libarchive/test/test_write_format_cpio_empty.c b/libarchive/test/test_write_format_cpio_empty.c
index 60fb283401337..2ba415c7b9877 100644
--- a/libarchive/test/test_write_format_cpio_empty.c
+++ b/libarchive/test/test_write_format_cpio_empty.c
@@ -64,7 +64,7 @@ DEFINE_TEST(test_write_format_cpio_empty)
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
- failure("Empty cpio archive should be exactly 87 bytes, was %d.", used);
+ failure("Empty cpio archive should be exactly 87 bytes, was %zu.", used);
assert(used == 87);
failure("Empty cpio archive is incorrectly formatted.");
assertEqualMem(buff, ref, 87);
diff --git a/libarchive/test/test_write_format_pax.c b/libarchive/test/test_write_format_pax.c
index 41a423a96a0e7..4538aac8241d9 100644
--- a/libarchive/test/test_write_format_pax.c
+++ b/libarchive/test/test_write_format_pax.c
@@ -105,6 +105,28 @@ DEFINE_TEST(test_write_format_pax)
assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
/*
+ * "file4" is similar to "file1" but has a large uid, large gid,
+ * uname and gname are longer than 32 characters
+ */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_set_atime(ae, 2, 20);
+ archive_entry_set_birthtime(ae, 3, 30);
+ archive_entry_set_ctime(ae, 4, 40);
+ archive_entry_set_mtime(ae, 5, 50);
+ archive_entry_copy_pathname(ae, "file4");
+ archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_size(ae, 8);
+ archive_entry_copy_uname(ae,
+ "long-uname123456789012345678901234567890");
+ archive_entry_copy_gname(ae,
+ "long-gname123456789012345678901234567890");
+ archive_entry_set_uid(ae, 536870912);
+ archive_entry_set_gid(ae, 536870913);
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
+
+ /*
* XXX TODO XXX Archive directory, other file types.
* Archive extended attributes, ACLs, other metadata.
* Verify they get read back correctly.
@@ -199,6 +221,30 @@ DEFINE_TEST(test_write_format_pax)
assertEqualMem(buff2, "12345678", 8);
/*
+ * Read "file4
+ */
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
+ assertEqualInt(2, archive_entry_atime(ae));
+ assertEqualInt(20, archive_entry_atime_nsec(ae));
+ assertEqualInt(3, archive_entry_birthtime(ae));
+ assertEqualInt(30, archive_entry_birthtime_nsec(ae));
+ assertEqualInt(4, archive_entry_ctime(ae));
+ assertEqualInt(40, archive_entry_ctime_nsec(ae));
+ assertEqualInt(5, archive_entry_mtime(ae));
+ assertEqualInt(50, archive_entry_mtime_nsec(ae));
+ assertEqualString("file4", archive_entry_pathname(ae));
+ assertEqualString("long-uname123456789012345678901234567890",
+ archive_entry_uname(ae));
+ assertEqualString("long-gname123456789012345678901234567890",
+ archive_entry_gname(ae));
+ assertEqualInt(536870912, archive_entry_uid(ae));
+ assertEqualInt(536870913, archive_entry_gid(ae));
+ assert((S_IFREG | 0755) == archive_entry_mode(ae));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345678", 8);
+
+ /*
* Verify the end of the archive.
*/
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
diff --git a/libarchive/test/test_write_format_shar_empty.c b/libarchive/test/test_write_format_shar_empty.c
index 03d70a3b5fa6a..13794b02bb06a 100644
--- a/libarchive/test/test_write_format_shar_empty.c
+++ b/libarchive/test/test_write_format_shar_empty.c
@@ -49,6 +49,6 @@ DEFINE_TEST(test_write_format_shar_empty)
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
- failure("Empty shar archive should be exactly 0 bytes, was %d.", used);
+ failure("Empty shar archive should be exactly 0 bytes, was %zu.", used);
assert(used == 0);
}
diff --git a/libarchive/test/test_write_format_tar.c b/libarchive/test/test_write_format_tar.c
index 3588e8fe2d948..a5ccdc0115bfa 100644
--- a/libarchive/test/test_write_format_tar.c
+++ b/libarchive/test/test_write_format_tar.c
@@ -81,7 +81,7 @@ DEFINE_TEST(test_write_format_tar)
/* This calculation gives "the smallest multiple of
* the block size that is at least 2048 bytes". */
- failure("blocksize=%d", blocksize);
+ failure("blocksize=%zu", blocksize);
assertEqualInt(((2048 - 1)/blocksize+1)*blocksize, used);
/*
diff --git a/libarchive/test/test_write_format_tar_sparse.c b/libarchive/test/test_write_format_tar_sparse.c
index cc725a9a72ea5..54ac00988e3d5 100644
--- a/libarchive/test/test_write_format_tar_sparse.c
+++ b/libarchive/test/test_write_format_tar_sparse.c
@@ -94,7 +94,7 @@ test_1(void)
/* This calculation gives "the smallest multiple of
* the block size that is at least 11264 bytes". */
- failure("blocksize=%d", blocksize);
+ failure("blocksize=%zu", blocksize);
assertEqualInt(((11264 - 1)/blocksize+1)*blocksize, used);
/*
@@ -229,7 +229,7 @@ test_2(void)
/* This calculation gives "the smallest multiple of
* the block size that is at least 11264 bytes". */
- failure("blocksize=%d", blocksize);
+ failure("blocksize=%zu", blocksize);
assertEqualInt(((11264 - 1)/blocksize+1)*blocksize, used);
/*
diff --git a/libarchive/test/test_write_format_xar.c b/libarchive/test/test_write_format_xar.c
index 7cfdbcf4d17df..02fd2c0e35a7d 100644
--- a/libarchive/test/test_write_format_xar.c
+++ b/libarchive/test/test_write_format_xar.c
@@ -279,6 +279,7 @@ DEFINE_TEST(test_write_format_xar)
/* Disable TOC checksum. */
test_xar("!toc-checksum");
+ test_xar("toc-checksum=none");
/* Specify TOC checksum type to sha1. */
test_xar("toc-checksum=sha1");
/* Specify TOC checksum type to md5. */
@@ -286,6 +287,7 @@ DEFINE_TEST(test_write_format_xar)
/* Disable file checksum. */
test_xar("!checksum");
+ test_xar("checksum=none");
/* Specify file checksum type to sha1. */
test_xar("checksum=sha1");
/* Specify file checksum type to md5. */
@@ -293,6 +295,7 @@ DEFINE_TEST(test_write_format_xar)
/* Disable compression. */
test_xar("!compression");
+ test_xar("compression=none");
/* Specify compression type to gzip. */
test_xar("compression=gzip");
test_xar("compression=gzip,compression-level=1");
diff --git a/libarchive/test/test_write_format_zip_file.c b/libarchive/test/test_write_format_zip_file.c
index e27b23b4b6d18..9ac0126e5ace9 100644
--- a/libarchive/test/test_write_format_zip_file.c
+++ b/libarchive/test/test_write_format_zip_file.c
@@ -84,7 +84,7 @@ DEFINE_TEST(test_write_format_zip_file)
unsigned char *central_header, *local_header, *eocd, *eocd_record;
unsigned char *extension_start, *extension_end;
char file_data[] = {'1', '2', '3', '4', '5', '6', '7', '8'};
- char *file_name = "file";
+ const char *file_name = "file";
#ifndef HAVE_ZLIB_H
zip_version = 10;
diff --git a/libarchive/test/test_write_format_zip_file_zip64.c b/libarchive/test/test_write_format_zip_file_zip64.c
index 7bba50d292239..4e6344fb53335 100644
--- a/libarchive/test/test_write_format_zip_file_zip64.c
+++ b/libarchive/test/test_write_format_zip_file_zip64.c
@@ -86,7 +86,7 @@ DEFINE_TEST(test_write_format_zip_file_zip64)
unsigned char *central_header, *local_header, *eocd, *eocd_record;
unsigned char *extension_start, *extension_end;
char file_data[] = {'1', '2', '3', '4', '5', '6', '7', '8'};
- char *file_name = "file";
+ const char *file_name = "file";
#ifndef HAVE_ZLIB_H
zip_compression = 0;
diff --git a/libarchive_fe/err.h b/libarchive_fe/err.h
index ebf5de814f5e5..c663103b0b44e 100644
--- a/libarchive_fe/err.h
+++ b/libarchive_fe/err.h
@@ -35,9 +35,14 @@
#if defined(__GNUC__) && (__GNUC__ > 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
-#define __LA_PRINTFLIKE(f,a) __attribute__((__format__(__printf__, f, a)))
+# ifdef __MINGW_PRINTF_FORMAT
+# define __LA_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
+# else
+# define __LA_PRINTF_FORMAT __printf__
+# endif
+# define __LA_PRINTFLIKE(f,a) __attribute__((__format__(__LA_PRINTF_FORMAT, f, a)))
#else
-#define __LA_PRINTFLIKE(f,a)
+# define __LA_PRINTFLIKE(f,a)
#endif
void lafe_warnc(int code, const char *fmt, ...) __LA_PRINTFLIKE(2, 3);
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index 04b56553ce022..f1574234905c7 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 3, 2019
+.Dd January 31, 2020
.Dt TAR 1
.Os
.Sh NAME
@@ -209,15 +209,16 @@ specified on the command line.
.It Fl Fl exclude-vcs
Do not process files or directories internally used by the
version control systems
+.Sq Arch ,
+.Sq Bazaar ,
.Sq CVS ,
+.Sq Darcs ,
+.Sq Mercurial ,
.Sq RCS ,
.Sq SCCS ,
-.Sq SVN ,
-.Sq Arch ,
-.Sq Bazaar ,
-.Sq Mercurial
+.Sq SVN
and
-.Sq Darcs .
+.Sq git .
.It Fl Fl fflags
(c, r, u, x modes only)
Archive or extract platform-specific file attributes or file flags.
@@ -469,6 +470,13 @@ This is the reverse of
and the default behavior if
.Nm
is run as non-root in x mode.
+.It Fl Fl no-safe-writes
+(x mode only)
+Do not create temporary files and use
+.Xr rename 2
+to replace the original ones.
+This is the reverse of
+.Fl Fl safe-writes .
.It Fl Fl no-same-owner
(x mode only)
Do not extract owner and group IDs.
@@ -567,7 +575,14 @@ As above, but the corresponding key and value will be provided
only to modules whose name matches
.Ar module .
.El
-The currently supported modules and keys are:
+.Pp
+The complete list of supported modules and keys
+for create and append modes is in
+.Xr archive_write_set_options 3
+and for extract and list modes in
+.Xr archive_read_set_options 3 .
+.Pp
+Examples of supported options:
.Bl -tag -compact -width indent
.It Cm iso9660:joliet
Support Joliet extensions.
@@ -756,6 +771,26 @@ The default is
.Ar hrs
which applies substitutions to all names.
In particular, it is never necessary to specify h, r, or s.
+.It Fl Fl safe-writes
+(x mode only)
+Extract files atomically.
+By default
+.Nm
+unlinks the original file with the same name as the extracted file (if it
+exists), and then creates it immediately under the same name and writes to
+it.
+For a short period of time, applications trying to access the file might
+not find it, or see incomplete results.
+If
+.Fl Fl safe-writes
+is enabled,
+.Nm
+first creates a unique temporary file, then writes the new contents to
+the temporary file, and finally renames the temporary file to its final
+name atomically using
+.Xr rename 2 .
+This guarantees that an application accessing the file, will either see
+the old contents or the new contents at all times.
.It Fl Fl same-owner
(x mode only)
Extract owner and group IDs.
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index b59963d0f822b..af41be5e4e26f 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -542,6 +542,9 @@ main(int argc, char **argv)
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_MAC_METADATA;
bsdtar->flags |= OPTFLAG_NO_MAC_METADATA;
break;
+ case OPTION_NO_SAFE_WRITES:
+ bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_SAFE_WRITES;
+ break;
case OPTION_NO_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags &= ~ARCHIVE_EXTRACT_OWNER;
break;
@@ -658,6 +661,9 @@ main(int argc, char **argv)
usage();
#endif
break;
+ case OPTION_SAFE_WRITES:
+ bsdtar->extract_flags |= ARCHIVE_EXTRACT_SAFE_WRITES;
+ break;
case OPTION_SAME_OWNER: /* GNU tar */
bsdtar->extract_flags |= ARCHIVE_EXTRACT_OWNER;
break;
diff --git a/tar/bsdtar.h b/tar/bsdtar.h
index c61d568fd7483..89aa3aa9198d6 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -25,6 +25,9 @@
* $FreeBSD: src/usr.bin/tar/bsdtar.h,v 1.37 2008/12/06 07:37:14 kientzle Exp $
*/
+#ifndef BSDTAR_H_INCLUDED
+#define BSDTAR_H_INCLUDED
+
#include "bsdtar_platform.h"
#include <stdio.h>
@@ -161,6 +164,7 @@ enum {
OPTION_NO_ACLS,
OPTION_NO_FFLAGS,
OPTION_NO_MAC_METADATA,
+ OPTION_NO_SAFE_WRITES,
OPTION_NO_SAME_OWNER,
OPTION_NO_SAME_PERMISSIONS,
OPTION_NO_XATTRS,
@@ -174,6 +178,7 @@ enum {
OPTION_OPTIONS,
OPTION_PASSPHRASE,
OPTION_POSIX,
+ OPTION_SAFE_WRITES,
OPTION_SAME_OWNER,
OPTION_STRIP_COMPONENTS,
OPTION_TOTALS,
@@ -224,3 +229,5 @@ const char * passphrase_callback(struct archive *, void *);
void passphrase_free(char *);
void list_item_verbose(struct bsdtar *, FILE *,
struct archive_entry *);
+
+#endif
diff --git a/tar/cmdline.c b/tar/cmdline.c
index 21558e12df42d..b80937ffcb6e3 100644
--- a/tar/cmdline.c
+++ b/tar/cmdline.c
@@ -123,6 +123,7 @@ static const struct bsdtar_option {
{ "no-fflags", 0, OPTION_NO_FFLAGS },
{ "no-mac-metadata", 0, OPTION_NO_MAC_METADATA },
{ "no-recursion", 0, 'n' },
+ { "no-safe-writes", 0, OPTION_NO_SAFE_WRITES },
{ "no-same-owner", 0, OPTION_NO_SAME_OWNER },
{ "no-same-permissions", 0, OPTION_NO_SAME_PERMISSIONS },
{ "no-xattr", 0, OPTION_NO_XATTRS },
@@ -144,6 +145,7 @@ static const struct bsdtar_option {
{ "posix", 0, OPTION_POSIX },
{ "preserve-permissions", 0, 'p' },
{ "read-full-blocks", 0, 'B' },
+ { "safe-writes", 0, OPTION_SAFE_WRITES },
{ "same-owner", 0, OPTION_SAME_OWNER },
{ "same-permissions", 0, 'p' },
{ "strip-components", 1, OPTION_STRIP_COMPONENTS },
diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt
index 459d9dcb1eff2..2cd573acfaa51 100644
--- a/tar/test/CMakeLists.txt
+++ b/tar/test/CMakeLists.txt
@@ -59,6 +59,7 @@ IF(ENABLE_TAR AND ENABLE_TEST)
test_option_q.c
test_option_r.c
test_option_s.c
+ test_option_safe_writes.c
test_option_uid_uname.c
test_option_uuencode.c
test_option_xattrs.c
diff --git a/tar/test/test_basic.c b/tar/test/test_basic.c
index 9bb966a0cf866..b1c49834a45f2 100644
--- a/tar/test/test_basic.c
+++ b/tar/test/test_basic.c
@@ -96,7 +96,7 @@ run_tar(const char *target, const char *pack_options,
/* Use the tar program to create an archive. */
r = systemf("%s cf - %s %s >%s/archive 2>%s/pack.err", testprog, pack_options, flist, target, target);
- failure("Error invoking %s cf -", testprog, pack_options);
+ failure("Error invoking %s cf -%s", testprog, pack_options);
assertEqualInt(r, 0);
assertChdir(target);
diff --git a/tar/test/test_copy.c b/tar/test/test_copy.c
index b828666b93fd6..d618e45ca36b1 100644
--- a/tar/test/test_copy.c
+++ b/tar/test/test_copy.c
@@ -256,13 +256,13 @@ verify_tree(size_t limit)
continue;
switch(dp[0]) {
case 'l': case 'm': case 'd':
- failure("strlen(p)=%d", strlen(p));
+ failure("strlen(p)=%zu", strlen(p));
assert(strlen(p) < limit);
assertEqualString(p,
filenames[strlen(p)]);
break;
case 'f': case 's':
- failure("strlen(p)=%d", strlen(p));
+ failure("strlen(p)=%zu", strlen(p));
assert(strlen(p) < limit + 1);
assertEqualString(p,
filenames[strlen(p)]);
diff --git a/tar/test/test_option_C_upper.c b/tar/test/test_option_C_upper.c
index dae985446892d..538890f581786 100644
--- a/tar/test/test_option_C_upper.c
+++ b/tar/test/test_option_C_upper.c
@@ -117,7 +117,7 @@ DEFINE_TEST(test_option_C_upper)
assertMakeDir("test6", 0755);
assertChdir("test6");
r = systemf("%s -cf archive.tar -C XXX -C ../d1 file1 2>write.err",
- testprog, testworkdir);
+ testprog);
assert(r != 0);
assertNonEmptyFile("write.err");
assertEqualInt(0,
diff --git a/tar/test/test_option_s.c b/tar/test/test_option_s.c
index 09c72ee7d63d2..fa799a295d01c 100644
--- a/tar/test/test_option_s.c
+++ b/tar/test/test_option_s.c
@@ -92,10 +92,8 @@ DEFINE_TEST(test_option_s)
* Test 5: Name-switching substitutions when extracting archive.
*/
assertMakeDir("test5", 0755);
- systemf("%s -cf test5.tar in/d1/foo in/d1/bar",
- testprog, testprog);
- systemf("%s -xf test5.tar -s /foo/bar/ -s }bar}foo} -C test5",
- testprog, testprog);
+ systemf("%s -cf test5.tar in/d1/foo in/d1/bar", testprog);
+ systemf("%s -xf test5.tar -s /foo/bar/ -s }bar}foo} -C test5", testprog);
assertFileContents("foo", 3, "test5/in/d1/bar");
assertFileContents("bar", 3, "test5/in/d1/foo");
diff --git a/tar/test/test_option_safe_writes.c b/tar/test/test_option_safe_writes.c
new file mode 100644
index 0000000000000..8edf5c69f7ece
--- /dev/null
+++ b/tar/test/test_option_safe_writes.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2020 Martin Matuska
+ * 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 "test.h"
+__FBSDID("$FreeBSD$");
+
+DEFINE_TEST(test_option_safe_writes)
+{
+ /* Create files */
+ assertMakeDir("in", 0755);
+ assertEqualInt(0, chdir("in"));
+ assertMakeFile("f", 0644, "a");
+ assertMakeFile("fh", 0644, "b");
+ assertMakeFile("d", 0644, "c");
+ assertMakeFile("fs", 0644, "d");
+ assertMakeFile("ds", 0644, "e");
+ assertEqualInt(0, chdir(".."));
+
+ /* Tar files up */
+ assertEqualInt(0,
+ systemf("%s -c -C in -f t.tar f fh d fs ds "
+ ">pack.out 2>pack.err", testprog));
+
+ /* Verify that nothing went to stdout or stderr. */
+ assertEmptyFile("pack.err");
+ assertEmptyFile("pack.out");
+
+ /* Create various objects */
+ assertMakeDir("out", 0755);
+ assertEqualInt(0, chdir("out"));
+ assertMakeFile("f", 0644, "a");
+ assertMakeHardlink("fh", "f");
+ assertMakeDir("d", 0755);
+ if (canSymlink()) {
+ assertMakeSymlink("fs", "f", 0);
+ assertMakeSymlink("ds", "d", 1);
+ }
+ assertEqualInt(0, chdir(".."));
+
+ /* Extract created archive withe safe writes */
+ assertEqualInt(0,
+ systemf("%s -x -C out --safe-writes -f t.tar "
+ ">unpack.out 2>unpack.err", testprog));
+
+ /* Verify that nothing went to stdout or stderr. */
+ assertEmptyFile("unpack.err");
+ assertEmptyFile("unpack.out");
+
+ /* Verify that files were overwritten properly */
+ assertEqualInt(0, chdir("out"));
+ assertTextFileContents("a","f");
+ assertTextFileContents("b","fh");
+ assertTextFileContents("c","d");
+ assertTextFileContents("d","fs");
+ assertTextFileContents("e","ds");
+}
diff --git a/tar/util.c b/tar/util.c
index 662db5baa7966..8ebec64c48d92 100644
--- a/tar/util.c
+++ b/tar/util.c
@@ -666,6 +666,14 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
const char *fmt;
time_t tim;
static time_t now;
+ struct tm *ltime;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE__LOCALTIME64_S)
+ struct tm tmbuf;
+#endif
+#if defined(HAVE__LOCALTIME64_S)
+ errno_t terr;
+ __time64_t tmptime;
+#endif
/*
* We avoid collecting the entire list in memory at once by
@@ -737,7 +745,19 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
fmt = bsdtar->day_first ? DAY_FMT " %b %Y" : "%b " DAY_FMT " %Y";
else
fmt = bsdtar->day_first ? DAY_FMT " %b %H:%M" : "%b " DAY_FMT " %H:%M";
- strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
+#if defined(HAVE_LOCALTIME_R)
+ ltime = localtime_r(&tim, &tmbuf);
+#elif defined(HAVE__LOCALTIME64_S)
+ tmptime = tim;
+ terr = _localtime64_s(&tmbuf, &tmptime);
+ if (terr)
+ ltime = NULL;
+ else
+ ltime = &tmbuf;
+#else
+ ltime = localtime(&tim);
+#endif
+ strftime(tmp, sizeof(tmp), fmt, ltime);
fprintf(out, " %s ", tmp);
safe_fprintf(out, "%s", archive_entry_pathname(entry));
diff --git a/test_utils/test_common.h b/test_utils/test_common.h
index 7538d8cb7b5a2..80d54f0a450c8 100644
--- a/test_utils/test_common.h
+++ b/test_utils/test_common.h
@@ -38,6 +38,9 @@
#elif defined(__FreeBSD__)
/* Building as part of FreeBSD system requires a pre-built config.h. */
#include "config_freebsd.h"
+#elif defined(__NetBSD__)
+/* Building as part of NetBSD system requires a pre-built config.h. */
+#include "config_netbsd.h"
#elif defined(_WIN32) && !defined(__CYGWIN__)
/* Win32 can't run the 'configure' script. */
#include "config_windows.h"
@@ -112,6 +115,19 @@
#pragma warn -8068 /* Constant out of range in comparison. */
#endif
+
+#if defined(__GNUC__) && (__GNUC__ > 2 || \
+ (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
+# ifdef __MINGW_PRINTF_FORMAT
+# define __LA_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
+# else
+# define __LA_PRINTF_FORMAT __printf__
+# endif
+# define __LA_PRINTFLIKE(f,a) __attribute__((__format__(__LA_PRINTF_FORMAT, f, a)))
+#else
+# define __LA_PRINTFLIKE(f,a)
+#endif
+
/* Haiku OS and QNX */
#if defined(__HAIKU__) || defined(__QNXNTO__)
/* Haiku and QNX have typedefs in stdint.h (needed for int64_t) */
@@ -132,6 +148,10 @@
#define O_BINARY 0
#endif
+#ifndef __LIBARCHIVE_TEST_COMMON
+#define __LIBARCHIVE_TEST_COMMON
+#endif
+
#include "archive_platform_acl.h"
#define ARCHIVE_TEST_ACL_TYPE_POSIX1E 1
#define ARCHIVE_TEST_ACL_TYPE_NFS4 2
@@ -259,7 +279,7 @@
skipping_setup(__FILE__, __LINE__);test_skipping
/* Function declarations. These are defined in test_utility.c. */
-void failure(const char *fmt, ...);
+void failure(const char *fmt, ...) __LA_PRINTFLIKE(1, 2);
int assertion_assert(const char *, int, int, const char *, void *);
int assertion_chdir(const char *, int, const char *);
int assertion_compare_fflags(const char *, int, const char *, const char *,
@@ -302,10 +322,10 @@ int assertion_utimes(const char *, int, const char *, long, long, long, long );
int assertion_version(const char*, int, const char *, const char *);
void skipping_setup(const char *, int);
-void test_skipping(const char *fmt, ...);
+void test_skipping(const char *fmt, ...) __LA_PRINTFLIKE(1, 2);
/* Like sprintf, then system() */
-int systemf(const char * fmt, ...);
+int systemf(const char *fmt, ...) __LA_PRINTFLIKE(1, 2);
/* Delay until time() returns a value after this. */
void sleepUntilAfter(time_t);
@@ -368,7 +388,7 @@ void *sunacl_get(int cmd, int *aclcnt, int fd, const char *path);
/* Suck file into string allocated via malloc(). Call free() when done. */
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
-char *slurpfile(size_t *, const char *fmt, ...);
+char *slurpfile(size_t *, const char *fmt, ...) __LA_PRINTFLIKE(2, 3);
/* Dump block of bytes to a file. */
void dumpfile(const char *filename, void *, size_t);
diff --git a/test_utils/test_main.c b/test_utils/test_main.c
index 1b44edf171d96..7b8aa70fac2a3 100644
--- a/test_utils/test_main.c
+++ b/test_utils/test_main.c
@@ -388,7 +388,7 @@ static const char *refdir;
*/
static int log_console = 0;
static FILE *logfile;
-static void
+static void __LA_PRINTFLIKE(1, 0)
vlogprintf(const char *fmt, va_list ap)
{
#ifdef va_copy
@@ -406,7 +406,7 @@ vlogprintf(const char *fmt, va_list ap)
#endif
}
-static void
+static void __LA_PRINTFLIKE(1, 2)
logprintf(const char *fmt, ...)
{
va_list ap;
@@ -478,7 +478,7 @@ static struct line {
const char *failed_filename;
/* Count this failure, setup up log destination and handle initial report. */
-static void
+static void __LA_PRINTFLIKE(3, 4)
failure_start(const char *filename, int line, const char *fmt, ...)
{
va_list ap;
@@ -751,7 +751,7 @@ static void strdump(const char *e, const char *p, int ewidth, int utf8)
logprintf("]");
logprintf(" (count %d", cnt);
if (n < 0) {
- logprintf(",unknown %d bytes", len);
+ logprintf(",unknown %zu bytes", len);
}
logprintf(")");
@@ -1167,7 +1167,7 @@ assertion_text_file_contents(const char *filename, int line, const char *buff, c
logprintf(" file=\"%s\"\n", fn);
if (n > 0) {
hexdump(contents, buff, n, 0);
- logprintf(" expected\n", fn);
+ logprintf(" expected\n");
hexdump(buff, contents, s, 0);
} else {
logprintf(" File empty, contents should be:\n");
@@ -1497,7 +1497,7 @@ assertion_file_time(const char *file, int line,
}
} else if (filet != t || filet_nsec != nsec) {
failure_start(file, line,
- "File %s has %ctime %lld.%09lld, expected %lld.%09lld",
+ "File %s has %ctime %lld.%09lld, expected %ld.%09ld",
pathname, type, filet, filet_nsec, t, nsec);
failure_finish(NULL);
return (0);
@@ -1593,8 +1593,8 @@ assertion_file_nlinks(const char *file, int line,
r = my_GetFileInformationByName(pathname, &bhfi);
if (r != 0 && bhfi.nNumberOfLinks == (DWORD)nlinks)
return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, bhfi.nNumberOfLinks, nlinks);
+ failure_start(file, line, "File %s has %jd links, expected %d",
+ pathname, (intmax_t)bhfi.nNumberOfLinks, nlinks);
failure_finish(NULL);
return (0);
#else
@@ -1605,8 +1605,8 @@ assertion_file_nlinks(const char *file, int line,
r = lstat(pathname, &st);
if (r == 0 && (int)st.st_nlink == nlinks)
return (1);
- failure_start(file, line, "File %s has %d links, expected %d",
- pathname, st.st_nlink, nlinks);
+ failure_start(file, line, "File %s has %jd links, expected %d",
+ pathname, (intmax_t)st.st_nlink, nlinks);
failure_finish(NULL);
return (0);
#endif
@@ -2480,7 +2480,7 @@ canBzip2(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("bzip2 -d -V %s", redirectArgs) == 0)
+ if (systemf("bzip2 --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2510,7 +2510,7 @@ canGzip(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("gzip -V %s", redirectArgs) == 0)
+ if (systemf("gzip --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2552,7 +2552,7 @@ canLz4(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("lz4 -V %s", redirectArgs) == 0)
+ if (systemf("lz4 --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2567,7 +2567,7 @@ canZstd(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("zstd -V %s", redirectArgs) == 0)
+ if (systemf("zstd --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2582,7 +2582,7 @@ canLzip(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("lzip -V %s", redirectArgs) == 0)
+ if (systemf("lzip --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2597,7 +2597,7 @@ canLzma(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("lzma -V %s", redirectArgs) == 0)
+ if (systemf("lzma %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2612,7 +2612,7 @@ canLzop(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("lzop -V %s", redirectArgs) == 0)
+ if (systemf("lzop --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -2627,7 +2627,7 @@ canXz(void)
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
- if (systemf("xz -V %s", redirectArgs) == 0)
+ if (systemf("xz --help %s", redirectArgs) == 0)
value = 1;
}
return (value);
@@ -3271,7 +3271,7 @@ assertion_entry_set_acls(const char *file, int line, struct archive_entry *ae,
acls[i].qual, acls[i].name);
if (r != 0) {
ret = 1;
- failure_start(file, line, "type=%#010x, ",
+ failure_start(file, line, "type=%#010x, "
"permset=%#010x, tag=%d, qual=%d name=%s",
acls[i].type, acls[i].permset, acls[i].tag,
acls[i].qual, acls[i].name);
@@ -3499,9 +3499,9 @@ static int
test_run(int i, const char *tmpdir)
{
#ifdef PATH_MAX
- char workdir[PATH_MAX];
+ char workdir[PATH_MAX * 2];
#else
- char workdir[1024];
+ char workdir[1024 * 2];
#endif
char logfilename[64];
int failures_before = failures;