summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt20
-rw-r--r--Makefile.am8
-rw-r--r--NEWS24
-rw-r--r--README15
-rw-r--r--build/autoconf/ax_append_compile_flags.m467
-rw-r--r--build/autoconf/ax_append_flag.m471
-rw-r--r--build/autoconf/ax_check_compile_flag.m474
-rw-r--r--build/autoconf/ax_require_defined.m437
-rwxr-xr-xbuild/autogen.sh2
-rw-r--r--build/cmake/config.h.in20
-rw-r--r--build/version2
-rw-r--r--cat/test/main.c66
-rw-r--r--cat/test/test.h13
-rw-r--r--cat/test/test_expand.Z.uu2
-rw-r--r--cat/test/test_expand.gz.uu4
-rw-r--r--configure.ac26
-rw-r--r--contrib/android/Android.mk23
-rw-r--r--contrib/android/config/android.h23
-rw-r--r--contrib/android/include/android_lf.h47
-rw-r--r--cpio/cpio_windows.h6
-rw-r--r--cpio/test/main.c67
-rw-r--r--cpio/test/test.h15
-rw-r--r--cpio/test/test_basic.c2
-rw-r--r--cpio/test/test_option_c.c10
-rw-r--r--cpio/test/test_option_lz4.c20
-rw-r--r--libarchive/CMakeLists.txt1
-rw-r--r--libarchive/archive.h19
-rw-r--r--libarchive/archive_cryptor.c9
-rw-r--r--libarchive/archive_cryptor_private.h9
-rw-r--r--libarchive/archive_entry.h7
-rw-r--r--libarchive/archive_entry_copy_stat.c4
-rw-r--r--libarchive/archive_getdate.c10
-rw-r--r--libarchive/archive_getdate.h39
-rw-r--r--libarchive/archive_hmac.c4
-rw-r--r--libarchive/archive_hmac_private.h11
-rw-r--r--libarchive/archive_match.c2
-rw-r--r--libarchive/archive_options.c6
-rw-r--r--libarchive/archive_platform.h9
-rw-r--r--libarchive/archive_random.c21
-rw-r--r--libarchive/archive_read.c10
-rw-r--r--libarchive/archive_read_disk_entry_from_file.c30
-rw-r--r--libarchive/archive_read_disk_posix.c18
-rw-r--r--libarchive/archive_read_open_file.c10
-rw-r--r--libarchive/archive_read_open_filename.c2
-rw-r--r--libarchive/archive_read_support_filter_lz4.c9
-rw-r--r--libarchive/archive_read_support_format_7zip.c2
-rw-r--r--libarchive/archive_read_support_format_rar.c45
-rw-r--r--libarchive/archive_read_support_format_warc.c19
-rw-r--r--libarchive/archive_read_support_format_xar.c23
-rw-r--r--libarchive/archive_util.c76
-rw-r--r--libarchive/archive_write.c2
-rw-r--r--libarchive/archive_write_add_filter_bzip2.c2
-rw-r--r--libarchive/archive_write_add_filter_grzip.c2
-rw-r--r--libarchive/archive_write_add_filter_gzip.c2
-rw-r--r--libarchive/archive_write_add_filter_lrzip.c2
-rw-r--r--libarchive/archive_write_add_filter_lz4.c109
-rw-r--r--libarchive/archive_write_add_filter_lzop.c2
-rw-r--r--libarchive/archive_write_add_filter_program.c16
-rw-r--r--libarchive/archive_write_disk_posix.c6
-rw-r--r--libarchive/archive_write_private.h2
-rw-r--r--libarchive/archive_write_set_format_7zip.c4
-rw-r--r--libarchive/archive_write_set_format_iso9660.c10
-rw-r--r--libarchive/archive_write_set_format_pax.c37
-rw-r--r--libarchive/archive_write_set_format_warc.c28
-rw-r--r--libarchive/archive_write_set_format_xar.c5
-rw-r--r--libarchive/archive_write_set_format_zip.c41
-rw-r--r--libarchive/libarchive-formats.526
-rw-r--r--libarchive/test/CMakeLists.txt3
-rw-r--r--libarchive/test/main.c18
-rw-r--r--libarchive/test/test.h7
-rw-r--r--libarchive/test/test_archive_getdate.c4
-rw-r--r--libarchive/test/test_archive_match_time.c3
-rw-r--r--libarchive/test/test_compat_zip.c10
-rw-r--r--libarchive/test/test_read_format_cab.c10
-rw-r--r--libarchive/test/test_read_format_zip.c14
-rw-r--r--libarchive/test/test_read_format_zip_mac_metadata.c10
-rw-r--r--libarchive/test/test_read_format_zip_msdos.c28
-rw-r--r--libarchive/test/test_read_format_zip_msdos.zip.uu4
-rw-r--r--libarchive/test/test_read_format_zip_traditional_encryption_data.c10
-rw-r--r--libarchive/test/test_read_format_zip_utf8_paths.c93
-rw-r--r--libarchive/test/test_read_format_zip_utf8_paths.zip.uu62
-rw-r--r--libarchive/test/test_read_format_zip_winzip_aes.c8
-rw-r--r--libarchive/test/test_read_format_zip_winzip_aes_large.c14
-rw-r--r--libarchive/test/test_read_too_many_filters.c6
-rw-r--r--libarchive/test/test_sparse_basic.c62
-rw-r--r--libarchive/test/test_write_disk_secure.c43
-rw-r--r--libarchive/test/test_write_filter_lz4.c24
-rw-r--r--libarchive_fe/passphrase.c6
-rw-r--r--tar/bsdtar.14
-rw-r--r--tar/bsdtar.h2
-rw-r--r--tar/read.c103
-rw-r--r--tar/subst.c106
-rw-r--r--tar/test/main.c66
-rw-r--r--tar/test/test.h13
-rw-r--r--tar/test/test_leading_slash.c4
-rw-r--r--tar/test/test_option_lz4.c18
-rw-r--r--tar/test/test_option_s.c23
-rw-r--r--tar/util.c100
-rw-r--r--tar/write.c23
99 files changed, 1567 insertions, 689 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d9e6ee6..e96d1080 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,7 +15,7 @@ endif()
# RelWithDebInfo : Release build with Debug Info
# MinSizeRel : Release Min Size build
IF(NOT CMAKE_BUILD_TYPE)
- SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
+ SET(CMAKE_BUILD_TYPE "Debug" 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".
@@ -613,12 +613,17 @@ IF(ENABLE_NETTLE)
FIND_PACKAGE(Nettle)
IF(NETTLE_FOUND)
SET(HAVE_LIBNETTLE 1)
- SET(HAVE_NETTLE_MD5_H 1)
- SET(HAVE_NETTLE_RIPEMD160_H 1)
- SET(HAVE_NETTLE_SHA_H 1)
- INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES})
+ INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
+
+ LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR})
+ LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H)
+ LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H)
+ LA_CHECK_INCLUDE_FILE("nettle/md5.h" HAVE_NETTLE_MD5_H)
LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H)
+ LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H)
+ LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H)
+
ENDIF(NETTLE_FOUND)
MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
@@ -632,6 +637,8 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
FIND_PACKAGE(OpenSSL)
IF(OPENSSL_FOUND)
SET(HAVE_LIBCRYPTO 1)
+ INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+ LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY})
ENDIF(OPENSSL_FOUND)
ELSE()
SET(OPENSSL_FOUND FALSE) # Override cached value
@@ -1281,8 +1288,11 @@ CHECK_SYMBOL_EXISTS(EILSEQ "errno.h" HAVE_EILSEQ)
CHECK_SYMBOL_EXISTS(D_MD_ORDER "langinfo.h" HAVE_D_MD_ORDER)
CHECK_SYMBOL_EXISTS(INT64_MAX "${headers}" HAVE_DECL_INT64_MAX)
CHECK_SYMBOL_EXISTS(INT64_MIN "${headers}" HAVE_DECL_INT64_MIN)
+CHECK_SYMBOL_EXISTS(INTMAX_MAX "${headers}" HAVE_DECL_INTMAX_MAX)
+CHECK_SYMBOL_EXISTS(INTMAX_MIN "${headers}" HAVE_DECL_INTMAX_MIN)
CHECK_SYMBOL_EXISTS(UINT32_MAX "${headers}" HAVE_DECL_UINT32_MAX)
CHECK_SYMBOL_EXISTS(UINT64_MAX "${headers}" HAVE_DECL_UINT64_MAX)
+CHECK_SYMBOL_EXISTS(UINTMAX_MAX "${headers}" HAVE_DECL_UINTMAX_MAX)
CHECK_SYMBOL_EXISTS(SIZE_MAX "${headers}" HAVE_DECL_SIZE_MAX)
CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX)
diff --git a/Makefile.am b/Makefile.am
index 0c04b54b..ca4afcc0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,11 +21,10 @@ TESTS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat
TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $(bsdcpio_TESTS_ENVIRONMENT) $(bsdcat_TESTS_ENVIRONMENT)
# Always build and test both bsdtar and bsdcpio as part of 'distcheck'
DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio
-COMMON_CFLAGS=-Wall -Wformat -Wformat-security
# The next line is commented out by default in shipping libarchive releases.
# It is uncommented by default in trunk.
DEV_CFLAGS=-Werror -Wextra -Wunused -Wshadow -Wmissing-prototypes -Wcast-qual -g
-AM_CFLAGS=$(COMMON_CFLAGS) $(DEV_CFLAGS)
+AM_CFLAGS=$(DEV_CFLAGS)
PLATFORMCPPFLAGS = @PLATFORMCPPFLAGS@
AM_CPPFLAGS=$(PLATFORMCPPFLAGS)
@@ -114,6 +113,7 @@ libarchive_la_SOURCES= \
libarchive/archive_entry_strmode.c \
libarchive/archive_entry_xattr.c \
libarchive/archive_getdate.c \
+ libarchive/archive_getdate.h \
libarchive/archive_hmac.c \
libarchive/archive_hmac_private.h \
libarchive/archive_match.c \
@@ -482,7 +482,6 @@ libarchive_test_SOURCES= \
libarchive/test/test_read_format_zip_padded.c \
libarchive/test/test_read_format_zip_sfx.c \
libarchive/test/test_read_format_zip_traditional_encryption_data.c \
- libarchive/test/test_read_format_zip_utf8_paths.c \
libarchive/test/test_read_format_zip_winzip_aes.c \
libarchive/test/test_read_format_zip_winzip_aes_large.c \
libarchive/test/test_read_format_zip_zip64.c \
@@ -767,6 +766,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \
libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \
libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
+ libarchive/test/test_read_format_warc.warc.uu \
libarchive/test/test_read_format_zip.zip.uu \
libarchive/test/test_read_format_zip_comment_stored_1.zip.uu \
libarchive/test/test_read_format_zip_comment_stored_2.zip.uu \
@@ -782,6 +782,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_zip_length_at_end.zip.uu \
libarchive/test/test_read_format_zip_mac_metadata.zip.uu \
libarchive/test/test_read_format_zip_malformed1.zip.uu \
+ libarchive/test/test_read_format_zip_msdos.zip.uu \
libarchive/test/test_read_format_zip_nested.zip.uu \
libarchive/test/test_read_format_zip_nofiletype.zip.uu \
libarchive/test/test_read_format_zip_padded1.zip.uu \
@@ -790,7 +791,6 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_zip_sfx.uu \
libarchive/test/test_read_format_zip_symlink.zip.uu \
libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu \
- libarchive/test/test_read_format_zip_utf8_paths.zip.uu \
libarchive/test/test_read_format_zip_ux.zip.uu \
libarchive/test/test_read_format_zip_winzip_aes128.zip.uu \
libarchive/test/test_read_format_zip_winzip_aes256.zip.uu \
diff --git a/NEWS b/NEWS
index 9dee879b..efe68daa 100644
--- a/NEWS
+++ b/NEWS
@@ -1,8 +1,32 @@
+Feb 13, 2016: libarchive 3.1.900a released
+ This is a test release in preparation for 3.2.0
+
+Oct 21, 2015: Preliminary port to OSF
+
Apr 11, 2015: libarchive's issue tracker is now hosted at GitHub.
https://github.com/libarchive/libarchive/issues
+Early 2015: Many fixes to crash and overflow bugs thanks to Hanno Boeck
+
+Oct 13, 2014: Zip encryption and decryption support
+
Aug 13, 2014: Add support for lz4 compression.
+Jun 10, 2014: Add warc format support
+
+May 3, 2014: Add experimental Zip streaming extension
+
+Apr 6, 2014: Add bsdcat command-line tool
+
+Jan 12, 2014: Add Zip64 support
+
+Dec 1, 2013: Rewrite Zip write logic
+
+Jul 1, 2013: Add ability to detect encrypted entries for many formats
+ (This does not add the ability to *decrypt* those entries, however)
+
+Feb 23, 2013: "raw" write support added
+
Feb 09, 2013: libarchive 3.1.2 released
Jan 28, 2013: libarchive's new website moved to http://www.libarchive.org.
diff --git a/README b/README
index 54a91e7e..180d2845 100644
--- a/README
+++ b/README
@@ -13,7 +13,7 @@ Questions? Issues?
This distribution bundle includes the following components:
* libarchive: a library for reading and writing streaming archives
* tar: the 'bsdtar' program is a full-featured 'tar'
- replacement built on libarchive
+ implementation built on libarchive
* cpio: the 'bsdcpio' program is a different interface to
essentially the same functionality
* cat: the 'bsdcat' program is a simple replacement tool for
@@ -96,6 +96,7 @@ The library can create archives in any of the following formats:
* "restricted" pax format, which will create ustar archives except for
entries that require pax extensions (for long filenames, ACLs, etc).
* Old GNU tar format
+ * Old V7 tar format
* POSIX octet-oriented cpio
* SVR4 "newc" cpio
* shar archives
@@ -130,12 +131,12 @@ Notes about the library architecture:
* I've attempted to minimize static link pollution. If you don't
explicitly invoke a particular feature (such as support for a
- particular compression or format), it won't get pulled in.
- In particular, if you don't explicitly enable a particular
- compression or decompression support, you won't need to link
- against the corresponding compression or decompression libraries.
- This also reduces the size of statically-linked binaries in
- environments where that matters.
+ particular compression or format), it won't get pulled in to
+ statically-linked programs. In particular, if you don't explicitly
+ enable a particular compression or decompression support, you won't
+ need to link against the corresponding compression or decompression
+ libraries. This also reduces the size of statically-linked
+ binaries in environments where that matters.
* On read, the library accepts whatever blocks you hand it.
Your read callback is free to pass the library a byte at a time
diff --git a/build/autoconf/ax_append_compile_flags.m4 b/build/autoconf/ax_append_compile_flags.m4
new file mode 100644
index 00000000..2bb27ef2
--- /dev/null
+++ b/build/autoconf/ax_append_compile_flags.m4
@@ -0,0 +1,67 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# For every FLAG1, FLAG2 it is checked whether the compiler works with the
+# flag. If it does, the flag is added FLAGS-VARIABLE
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. During the check the flag is always added to the
+# current language's flags.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: This macro depends on the AX_APPEND_FLAG and
+# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
+# AX_APPEND_LINK_FLAGS.
+#
+# LICENSE
+#
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
+[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
+AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
+for flag in $1; do
+ AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
+done
+])dnl AX_APPEND_COMPILE_FLAGS
diff --git a/build/autoconf/ax_append_flag.m4 b/build/autoconf/ax_append_flag.m4
new file mode 100644
index 00000000..08f2e07e
--- /dev/null
+++ b/build/autoconf/ax_append_flag.m4
@@ -0,0 +1,71 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
+#
+# DESCRIPTION
+#
+# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
+# added in between.
+#
+# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
+# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
+# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
+# FLAG.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 6
+
+AC_DEFUN([AX_APPEND_FLAG],
+[dnl
+AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
+AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
+AS_VAR_SET_IF(FLAGS,[
+ AS_CASE([" AS_VAR_GET(FLAGS) "],
+ [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
+ [
+ AS_VAR_APPEND(FLAGS,[" $1"])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+ ],
+ [
+ AS_VAR_SET(FLAGS,[$1])
+ AC_RUN_LOG([: FLAGS="$FLAGS"])
+ ])
+AS_VAR_POPDEF([FLAGS])dnl
+])dnl AX_APPEND_FLAG
diff --git a/build/autoconf/ax_check_compile_flag.m4 b/build/autoconf/ax_check_compile_flag.m4
new file mode 100644
index 00000000..ca363971
--- /dev/null
+++ b/build/autoconf/ax_check_compile_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 4
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/build/autoconf/ax_require_defined.m4 b/build/autoconf/ax_require_defined.m4
new file mode 100644
index 00000000..cae11112
--- /dev/null
+++ b/build/autoconf/ax_require_defined.m4
@@ -0,0 +1,37 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_REQUIRE_DEFINED(MACRO)
+#
+# DESCRIPTION
+#
+# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
+# been defined and thus are available for use. This avoids random issues
+# where a macro isn't expanded. Instead the configure script emits a
+# non-fatal:
+#
+# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
+#
+# It's like AC_REQUIRE except it doesn't expand the required macro.
+#
+# Here's an example:
+#
+# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
+#
+# LICENSE
+#
+# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 1
+
+AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
+ m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
+])dnl AX_REQUIRE_DEFINED
diff --git a/build/autogen.sh b/build/autogen.sh
index e7316246..64767b6e 100755
--- a/build/autogen.sh
+++ b/build/autogen.sh
@@ -43,7 +43,7 @@ cd ..
# Substitute the versions into Libarchive's archive.h and archive_entry.h
perl -p -i -e "s/^(#define\tARCHIVE_VERSION_NUMBER).*/\$1 $VN/" libarchive/archive.h
perl -p -i -e "s/^(#define\tARCHIVE_VERSION_NUMBER).*/\$1 $VN/" libarchive/archive_entry.h
-perl -p -i -e "s/^(#define\tARCHIVE_VERSION_STRING).*/\$1 \"libarchive $VS\"/" libarchive/archive.h
+perl -p -i -e "s/^(#define\tARCHIVE_VERSION_ONLY_STRING).*/\$1 \"$VS\"/" libarchive/archive.h
# Substitute versions into configure.ac as well
perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_S\]),.*\)/$1,['"$VS"'])/' configure.ac
perl -p -i -e 's/(m4_define\(\[LIBARCHIVE_VERSION_N\]),.*\)/$1,['"$VN"'])/' configure.ac
diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in
index a42a7c59..46f9d556 100644
--- a/build/cmake/config.h.in
+++ b/build/cmake/config.h.in
@@ -170,8 +170,6 @@ typedef unsigned char uint8_t;
/* Define intmax_t and uintmax_t if they are not already defined. */
#if !defined(HAVE_INTMAX_T)
typedef int64_t intmax_t;
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
#endif
#if !defined(HAVE_UINTMAX_T)
@@ -372,6 +370,14 @@ typedef uint64_t uintmax_t;
don't. */
#cmakedefine HAVE_DECL_INT64_MIN 1
+/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INTMAX_MAX 1
+
+/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_INTMAX_MIN 1
+
/* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_SIZE_MAX 1
@@ -392,6 +398,10 @@ typedef uint64_t uintmax_t;
don't. */
#cmakedefine HAVE_DECL_UINT64_MAX 1
+/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you
+ don't. */
+#cmakedefine HAVE_DECL_UINTMAX_MAX 1
+
/* Define to 1 if you have the <direct.h> header file. */
#cmakedefine HAVE_DIRECT_H 1
@@ -733,6 +743,12 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#cmakedefine HAVE_NDIR_H 1
+/* Define to 1 if you have the <nettle/aes.h> header file. */
+#cmakedefine HAVE_NETTLE_AES_H 1
+
+/* Define to 1 if you have the <nettle/hmac.h> header file. */
+#cmakedefine HAVE_NETTLE_HMAC_H 1
+
/* Define to 1 if you have the <nettle/md5.h> header file. */
#cmakedefine HAVE_NETTLE_MD5_H 1
diff --git a/build/version b/build/version
index 937b126a..bc085d24 100644
--- a/build/version
+++ b/build/version
@@ -1 +1 @@
-3001002
+3001900a
diff --git a/cat/test/main.c b/cat/test/main.c
index 22d211f9..8c414da1 100644
--- a/cat/test/main.c
+++ b/cat/test/main.c
@@ -131,11 +131,13 @@
/* Path to working directory for current test */
const char *testworkdir;
+#ifdef PROGRAM
/* Pathname of exe to be tested. */
const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
+#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
static void *GetFunctionKernel32(const char *);
@@ -572,10 +574,10 @@ static void strdump(const char *e, const char *p, int ewidth, int utf8)
while (*p != '\0') {
unsigned int c = 0xff & *p++;
switch (c) {
- case '\a': printf("\a"); break;
- case '\b': printf("\b"); break;
- case '\n': printf("\n"); break;
- case '\r': printf("\r"); break;
+ case '\a': logprintf("\\a"); break;
+ case '\b': logprintf("\\b"); break;
+ case '\n': logprintf("\\n"); break;
+ case '\r': logprintf("\\r"); break;
default:
if (c >= 32 && c < 127)
logprintf("%c", c);
@@ -1068,7 +1070,8 @@ assertion_file_contains_lines_any_order(const char *file, int line,
free(expected);
return (0);
}
- for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
+ for (j = 0, p = buff; p < buff + buff_size;
+ p += 1 + strlen(p)) {
if (*p != '\0') {
actual[j] = p;
++j;
@@ -1920,6 +1923,18 @@ canGzip(void)
* Can this platform run the lrzip program?
*/
int
+canRunCommand(const char *cmd)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("%s %s", cmd, redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+int
canLrzip(void)
{
static int tested = 0, value = 0;
@@ -2158,8 +2173,31 @@ slurpfile(size_t * sizep, const char *fmt, ...)
return (p);
}
+/*
+ * Slurp a file into memory for ease of comparison and testing.
+ * Returns size of file in 'sizep' if non-NULL, null-terminates
+ * data in memory for ease of use.
+ */
+void
+dumpfile(const char *filename, void *data, size_t len)
+{
+ ssize_t bytes_written;
+ FILE *f;
+
+ f = fopen(filename, "wb");
+ if (f == NULL) {
+ logprintf("Can't open file %s for writing\n", filename);
+ return;
+ }
+ bytes_written = fwrite(data, 1, len, f);
+ if (bytes_written < (ssize_t)len)
+ logprintf("Can't write file %s\n", filename);
+ fclose(f);
+}
+
/* Read a uuencoded file from the reference directory, decode, and
* write the result into the current directory. */
+#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
void
extract_reference_file(const char *name)
@@ -2183,7 +2221,6 @@ extract_reference_file(const char *name)
break;
}
/* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while (fgets(buff, sizeof(buff), in) != NULL) {
char *p = buff;
@@ -2197,17 +2234,21 @@ extract_reference_file(const char *name)
int n = 0;
/* Write out 1-3 bytes from that. */
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
+ assert(VALID_UUDECODE(p[1]));
n = UUDECODE(*p++) << 18;
n |= UUDECODE(*p++) << 12;
fputc(n >> 16, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++) << 6;
fputc((n >> 8) & 0xFF, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++);
fputc(n & 0xFF, out);
--bytes;
@@ -2262,6 +2303,14 @@ is_LargeInode(const char *file)
return (ino > 0xffffffff);
#endif
}
+
+void
+extract_reference_files(const char **names)
+{
+ while (names && *names)
+ extract_reference_file(*names++);
+}
+
/*
*
* TEST management
@@ -2333,7 +2382,7 @@ test_run(int i, const char *tmpdir)
case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
break;
case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-50s", i, tests[i].name);
+ printf("%3d: %-64s", i, tests[i].name);
fflush(stdout);
break;
default: /* Title of test, details will follow */
@@ -2526,6 +2575,7 @@ get_refdir(const char *d)
failure:
printf("Unable to locate known reference file %s\n", KNOWNREF);
printf(" Checked following directories:\n%s\n", tried);
+ printf("Use -r option to specify full path to reference directory\n");
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
DebugBreak();
#endif
@@ -2609,7 +2659,7 @@ main(int argc, char **argv)
exit(1);
}
memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir));
+ strlen(testprogdir) + 1);
memcpy(testprogdir, pwd, strlen(pwd));
testprogdir[strlen(pwd)] = '/';
}
diff --git a/cat/test/test.h b/cat/test/test.h
index 68473851..78f96792 100644
--- a/cat/test/test.h
+++ b/cat/test/test.h
@@ -92,7 +92,7 @@
#endif
/* Visual Studio */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
@@ -278,6 +278,9 @@ int canGrzip(void);
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
+/* Return true if this platform can run the specified command. */
+int canRunCommand(const char *);
+
/* Return true if this platform can run the "lrzip" program. */
int canLrzip(void);
@@ -306,11 +309,19 @@ int is_LargeInode(const char *);
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
+/* Dump block of bytes to a file. */
+void dumpfile(const char *filename, void *, size_t);
+
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
/* Copies named reference file to the current directory. */
void copy_reference_file(const char *);
+/* Extracts a list of files to the current directory.
+ * List must be NULL terminated.
+ */
+void extract_reference_files(const char **);
+
/* Path to working directory for current test */
extern const char *testworkdir;
diff --git a/cat/test/test_expand.Z.uu b/cat/test/test_expand.Z.uu
index c32f6557..b65efc1a 100644
--- a/cat/test/test_expand.Z.uu
+++ b/cat/test/test_expand.Z.uu
@@ -1,3 +1,3 @@
begin 664 test_expand.Z
-@'YV08]ZXH5-FX!P0;\R (#B'SI<R>."$<4/&A187"@
+@'YV08]ZXH5-FX!P0;\R`(#B'SI<R>."$<4/&A187"@`
end
diff --git a/cat/test/test_expand.gz.uu b/cat/test/test_expand.gz.uu
index 1c416117..528167c6 100644
--- a/cat/test/test_expand.gz.uu
+++ b/cat/test/test_expand.gz.uu
@@ -1,4 +1,4 @@
begin 664 test_expand.gz
-M'XL("-UD1%, V%S9 !+SL\K2<TK*5;(3U,H22TNB4^M*$C,2]%+K]+C @ Z
-'PQU''
+M'XL("-UD1%,``V%S9`!+SL\K2<TK*5;(3U,H22TNB4^M*$C,2]%+K]+C`@`Z
+'PQU''```````
end
diff --git a/configure.ac b/configure.ac
index ea2c5d77..487b60bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
dnl In particular, this allows the version macro to be used in AC_INIT
dnl These first two version numbers are updated automatically on each release.
-m4_define([LIBARCHIVE_VERSION_S],[3.1.2])
-m4_define([LIBARCHIVE_VERSION_N],[3001002])
+m4_define([LIBARCHIVE_VERSION_S],[3.1.900a])
+m4_define([LIBARCHIVE_VERSION_N],[3001900])
dnl bsdtar and bsdcpio versioning tracks libarchive
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
@@ -472,6 +472,9 @@ fi
# -larchive in that case.
#AC_CHECK_LIB(archive,archive_version)
+# Checks for supported compiler flags
+AX_APPEND_COMPILE_FLAGS([-Wall -Wformat -Wformat-security])
+
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
# la_TYPE_UID_T defaults to "int", which is incorrect for MinGW
@@ -537,6 +540,7 @@ AC_TYPE_UINT16_T
AC_TYPE_UINT8_T
AC_CHECK_DECLS([SIZE_MAX, INT64_MAX, INT64_MIN, UINT64_MAX, UINT32_MAX])
+AC_CHECK_DECLS([INTMAX_MAX, INTMAX_MIN, UINTMAX_MAX])
AC_CHECK_DECL([SSIZE_MAX],
[AC_DEFINE(HAVE_DECL_SSIZE_MAX, 1, [Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you don't.])],
@@ -779,8 +783,9 @@ esac
if test "x$with_nettle" != "xno"; then
AC_CHECK_HEADERS([nettle/md5.h nettle/ripemd160.h nettle/sha.h])
+ AC_CHECK_HEADERS([nettle/pbkdf2.h nettle/aes.h nettle/hmac.h])
saved_LIBS=$LIBS
- AC_CHECK_LIB(nettle,main)
+ AC_CHECK_LIB(nettle,nettle_sha1_init)
CRYPTO_CHECK(MD5, NETTLE, md5)
CRYPTO_CHECK(RMD160, NETTLE, rmd160)
CRYPTO_CHECK(SHA1, NETTLE, sha1)
@@ -789,10 +794,9 @@ if test "x$with_nettle" != "xno"; then
CRYPTO_CHECK(SHA512, NETTLE, sha512)
if test "x$found_NETTLE" != "xyes"; then
LIBS=$saved_LIBS
- else
- AC_CHECK_HEADERS([nettle/pbkdf2.h])
fi
fi
+
if test "x$with_openssl" != "xno"; then
AC_CHECK_HEADERS([openssl/evp.h])
saved_LIBS=$LIBS
@@ -800,18 +804,18 @@ if test "x$with_openssl" != "xno"; then
*mingw* | *cygwin*)
case "$host_cpu" in
x86_64)
- AC_CHECK_LIB(eay64,main)
+ AC_CHECK_LIB(eay64,OPENSSL_config)
if test "x$ac_cv_lib_eay64_main" != "xyes"; then
- AC_CHECK_LIB(eay32,main)
+ AC_CHECK_LIB(eay32,OPENSSL_config)
fi
;;
*)
- AC_CHECK_LIB(eay32,main)
+ AC_CHECK_LIB(eay32,OPENSSL_config)
;;
esac
;;
*)
- AC_CHECK_LIB(crypto,main)
+ AC_CHECK_LIB(crypto,OPENSSL_config)
;;
esac
CRYPTO_CHECK(MD5, OPENSSL, md5)
@@ -831,7 +835,7 @@ fi
# The two are incompatible and OpenSSL is more complete.
AC_CHECK_HEADERS([md5.h ripemd.h sha.h sha256.h sha512.h])
saved_LIBS=$LIBS
-AC_CHECK_LIB(md,main)
+AC_CHECK_LIB(md,MD5Init)
CRYPTO_CHECK(MD5, LIBMD, md5)
CRYPTO_CHECK(RMD160, LIBMD, rmd160)
CRYPTO_CHECK(SHA1, LIBMD, sha1)
@@ -853,6 +857,6 @@ esac
# Ensure test directories are present if building out-of-tree
AC_CONFIG_COMMANDS([mkdirs],
- [mkdir -p {libarchive,tar,cat,cpio}/test])
+ [mkdir -p libarchive/test tar/test cat/test cpio/test])
AC_OUTPUT
diff --git a/contrib/android/Android.mk b/contrib/android/Android.mk
index 43620279..b82beab4 100644
--- a/contrib/android/Android.mk
+++ b/contrib/android/Android.mk
@@ -179,9 +179,7 @@ LOCAL_MODULE := libarchive
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(libarchive_src_files) $(libarchive_host_src_files)
LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\"
-ifneq ($(strip $(USE_MINGW)),)
- LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
-endif
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -191,9 +189,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\"
LOCAL_SHARED_LIBRARIES := libz-host
LOCAL_WHOLE_STATIC_LIBRARIES := libarchive
-ifneq ($(strip $(USE_MINGW)),)
- LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
-endif
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive
include $(BUILD_HOST_SHARED_LIBRARY)
@@ -202,9 +198,7 @@ LOCAL_MODULE := libarchive_fe
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_host_config)\"
LOCAL_SRC_FILES := $(libarchive_fe_src_files)
-ifneq ($(strip $(USE_MINGW)),)
- LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
-endif
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive_fe
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -222,6 +216,7 @@ LOCAL_CFLAGS := -DBSDTAR_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_
LOCAL_SHARED_LIBRARIES := libz-host
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe
LOCAL_SRC_FILES := $(bsdtar_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
@@ -231,6 +226,7 @@ LOCAL_CFLAGS := -DBSDCPIO_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM
LOCAL_SHARED_LIBRARIES := libz-host
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe
LOCAL_SRC_FILES := $(bsdcpio_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
@@ -240,6 +236,7 @@ LOCAL_CFLAGS := -DBSDCAT_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_C
LOCAL_SHARED_LIBRARIES := libz-host
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe
LOCAL_SRC_FILES := $(bsdcat_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
include $(BUILD_HOST_EXECUTABLE)
@@ -248,8 +245,9 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libarchive
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(libarchive_src_files)
-LOCAL_STATIC_LIBRARIES := libz
+LOCAL_STATIC_LIBRARIES := libz liblz4
LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\"
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive
include $(BUILD_STATIC_LIBRARY)
@@ -261,6 +259,7 @@ LOCAL_C_INCLUDES :=
LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\"
LOCAL_SHARED_LIBRARIES := libz
LOCAL_WHOLE_STATIC_LIBRARIES := libarchive
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive
include $(BUILD_SHARED_LIBRARY)
@@ -269,6 +268,7 @@ LOCAL_MODULE := libarchive_fe
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\"
LOCAL_SRC_FILES := $(libarchive_fe_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/contrib/android/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libarchive_fe
include $(BUILD_STATIC_LIBRARY)
@@ -280,6 +280,7 @@ LOCAL_CFLAGS := -DBSDTAR_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_
LOCAL_SHARED_LIBRARIES := libz
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe
LOCAL_SRC_FILES := $(bsdtar_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
@@ -289,6 +290,7 @@ LOCAL_CFLAGS := -DBSDCPIO_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM
LOCAL_SHARED_LIBRARIES := libz
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe
LOCAL_SRC_FILES := $(bsdcpio_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
@@ -298,6 +300,7 @@ LOCAL_CFLAGS := -DBSDCAT_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_C
LOCAL_SHARED_LIBRARIES := libz
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe
LOCAL_SRC_FILES := $(bsdcat_src_files)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include
include $(BUILD_EXECUTABLE)
endif
diff --git a/contrib/android/config/android.h b/contrib/android/config/android.h
index 42fe22ca..8e183124 100644
--- a/contrib/android/config/android.h
+++ b/contrib/android/config/android.h
@@ -26,16 +26,31 @@
#ifndef ARCHIVE_PLATFORM_H_ANDROID_INCLUDED
#define ARCHIVE_PLATFORM_H_ANDROID_INCLUDED
+#include <android/api-level.h>
+#ifdef __ANDROID_API__
+#if __ANDROID_API__ > 20
+#define HAVE_FSTATVFS 1
+#define HAVE_STATVFS 1
+#define HAVE_TIMEGM 1
+#define HAVE_SYS_XATTR_H 1
+#define HAVE_LINUX_FIEMAP_H 1
+#define HAVE_SYS_STATVFS_H 1
+#endif
+#endif
+
#define HAVE_CHOWN 1
#define HAVE_CHROOT 1
#define HAVE_CTIME_R 1
#define HAVE_CTYPE_H 1
#define HAVE_DECL_EXTATTR_NAMESPACE_USER 0
+#define HAVE_DECL_INTMAX_MIN 1
+#define HAVE_DECL_INTMAX_MAX 1
#define HAVE_DECL_INT64_MAX 1
#define HAVE_DECL_INT64_MIN 1
#define HAVE_DECL_SIZE_MAX 1
#define HAVE_DECL_SSIZE_MAX 1
#define HAVE_DECL_STRERROR_R 1
+#define HAVE_DECL_UINTMAX_MAX 1
#define HAVE_DECL_UINT32_MAX 1
#define HAVE_DECL_UINT64_MAX 1
#define HAVE_DIRENT_H 1
@@ -57,7 +72,6 @@
#define HAVE_FSTAT 1
#define HAVE_FSTATAT 1
#define HAVE_FSTATFS 1
-#define HAVE_FSTATVFS 1
#define HAVE_FTRUNCATE 1
#define HAVE_GETEUID 1
#define HAVE_GETPID 1
@@ -74,7 +88,6 @@
#define HAVE_LIBZ 1
#define HAVE_LIMITS_H 1
#define HAVE_LINK 1
-#define HAVE_LINUX_FIEMAP_H 1
#define HAVE_LINUX_FS_H 1
#define HAVE_LINUX_MAGIC_H 1
#define HAVE_LINUX_TYPES_H 1
@@ -110,7 +123,6 @@
#define HAVE_SIGACTION 1
#define HAVE_SIGNAL_H 1
#define HAVE_STATFS 1
-#define HAVE_STATVFS 1
#define HAVE_STDARG_H 1
#define HAVE_STDINT_H 1
#define HAVE_STDLIB_H 1
@@ -123,7 +135,7 @@
#define HAVE_STRING_H 1
#define HAVE_STRRCHR 1
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
+#define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
#define HAVE_STRUCT_TM_TM_GMTOFF 1
#define HAVE_SYMLINK 1
#define HAVE_SYS_CDEFS_H 1
@@ -133,15 +145,12 @@
#define HAVE_SYS_POLL_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_STATFS_H 1
-#define HAVE_SYS_STATVFS_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_SYS_VFS_H 1
#define HAVE_SYS_WAIT_H 1
-#define HAVE_SYS_XATTR_H 1
-#define HAVE_TIMEGM 1
#define HAVE_TIME_H 1
#define HAVE_TZSET 1
#define HAVE_UINTMAX_T 1
diff --git a/contrib/android/include/android_lf.h b/contrib/android/include/android_lf.h
new file mode 100644
index 00000000..3c5475e3
--- /dev/null
+++ b/contrib/android/include/android_lf.h
@@ -0,0 +1,47 @@
+/*
+ * Macros for file64 functions
+ *
+ * Android does not support the macro _FILE_OFFSET_BITS=64
+ * As of android-21 it does however support many file64 functions
+*/
+
+#ifndef ARCHIVE_ANDROID_LF_H_INCLUDED
+#define ARCHIVE_ANDROID_LF_H_INCLUDED
+
+#if __ANDROID_API__ > 20
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+
+//dirent.h
+#define readdir_r readdir64_r
+#define readdir readdir64
+#define dirent dirent64
+//fcntl.h
+#define openat openat64
+#define open open64
+#define mkstemp mkstemp64
+//unistd.h
+#define lseek lseek64
+#define ftruncate ftruncate64
+//sys/stat.h
+#define fstatat fstatat64
+#define fstat fstat64
+#define lstat lstat64
+#define stat stat64
+//sys/statvfs.h
+#define fstatvfs fstatvfs64
+#define statvfs statvfs64
+//sys/types.h
+#define off_t off64_t
+//sys/vfs.h
+#define fstatfs fstatfs64
+#define statfs statfs64
+#endif
+
+#endif /* ARCHIVE_ANDROID_LF_H_INCLUDED */
diff --git a/cpio/cpio_windows.h b/cpio/cpio_windows.h
index d8576b31..970a63df 100644
--- a/cpio/cpio_windows.h
+++ b/cpio/cpio_windows.h
@@ -36,8 +36,10 @@
#define getpwnam(name) NULL
#define getpwuid(id) NULL
-#ifdef _MSC_VER
-#define snprintf sprintf_s
+#if defined(_MSC_VER)
+ #if _MSC_VER < 1900
+ #define snprintf sprintf_s
+ #endif // _MSC_VER < 1900
#define strdup _strdup
#define open _open
#define read _read
diff --git a/cpio/test/main.c b/cpio/test/main.c
index d4ed509a..58011274 100644
--- a/cpio/test/main.c
+++ b/cpio/test/main.c
@@ -132,11 +132,13 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/test/main.c,v 1.3 2008/08/24 04:58:22 kient
/* Path to working directory for current test */
const char *testworkdir;
+#ifdef PROGRAM
/* Pathname of exe to be tested. */
const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
+#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
static void *GetFunctionKernel32(const char *);
@@ -573,10 +575,10 @@ static void strdump(const char *e, const char *p, int ewidth, int utf8)
while (*p != '\0') {
unsigned int c = 0xff & *p++;
switch (c) {
- case '\a': printf("\a"); break;
- case '\b': printf("\b"); break;
- case '\n': printf("\n"); break;
- case '\r': printf("\r"); break;
+ case '\a': logprintf("\\a"); break;
+ case '\b': logprintf("\\b"); break;
+ case '\n': logprintf("\\n"); break;
+ case '\r': logprintf("\\r"); break;
default:
if (c >= 32 && c < 127)
logprintf("%c", c);
@@ -1044,6 +1046,7 @@ assertion_file_contains_lines_any_order(const char *file, int line,
if (expected == NULL) {
failure_start(pathname, line, "Can't allocate memory");
failure_finish(NULL);
+ free(expected);
return (0);
}
for (i = 0; lines[i] != NULL; ++i) {
@@ -1068,7 +1071,8 @@ assertion_file_contains_lines_any_order(const char *file, int line,
free(expected);
return (0);
}
- for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
+ for (j = 0, p = buff; p < buff + buff_size;
+ p += 1 + strlen(p)) {
if (*p != '\0') {
actual[j] = p;
++j;
@@ -1920,6 +1924,18 @@ canGzip(void)
* Can this platform run the lrzip program?
*/
int
+canRunCommand(const char *cmd)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("%s %s", cmd, redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+int
canLrzip(void)
{
static int tested = 0, value = 0;
@@ -2158,8 +2174,31 @@ slurpfile(size_t * sizep, const char *fmt, ...)
return (p);
}
+/*
+ * Slurp a file into memory for ease of comparison and testing.
+ * Returns size of file in 'sizep' if non-NULL, null-terminates
+ * data in memory for ease of use.
+ */
+void
+dumpfile(const char *filename, void *data, size_t len)
+{
+ ssize_t bytes_written;
+ FILE *f;
+
+ f = fopen(filename, "wb");
+ if (f == NULL) {
+ logprintf("Can't open file %s for writing\n", filename);
+ return;
+ }
+ bytes_written = fwrite(data, 1, len, f);
+ if (bytes_written < (ssize_t)len)
+ logprintf("Can't write file %s\n", filename);
+ fclose(f);
+}
+
/* Read a uuencoded file from the reference directory, decode, and
* write the result into the current directory. */
+#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
void
extract_reference_file(const char *name)
@@ -2183,7 +2222,6 @@ extract_reference_file(const char *name)
break;
}
/* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while (fgets(buff, sizeof(buff), in) != NULL) {
char *p = buff;
@@ -2197,17 +2235,21 @@ extract_reference_file(const char *name)
int n = 0;
/* Write out 1-3 bytes from that. */
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
+ assert(VALID_UUDECODE(p[1]));
n = UUDECODE(*p++) << 18;
n |= UUDECODE(*p++) << 12;
fputc(n >> 16, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++) << 6;
fputc((n >> 8) & 0xFF, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++);
fputc(n & 0xFF, out);
--bytes;
@@ -2262,6 +2304,14 @@ is_LargeInode(const char *file)
return (ino > 0xffffffff);
#endif
}
+
+void
+extract_reference_files(const char **names)
+{
+ while (names && *names)
+ extract_reference_file(*names++);
+}
+
/*
*
* TEST management
@@ -2333,7 +2383,7 @@ test_run(int i, const char *tmpdir)
case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
break;
case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-50s", i, tests[i].name);
+ printf("%3d: %-64s", i, tests[i].name);
fflush(stdout);
break;
default: /* Title of test, details will follow */
@@ -2526,6 +2576,7 @@ get_refdir(const char *d)
failure:
printf("Unable to locate known reference file %s\n", KNOWNREF);
printf(" Checked following directories:\n%s\n", tried);
+ printf("Use -r option to specify full path to reference directory\n");
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
DebugBreak();
#endif
@@ -2609,7 +2660,7 @@ main(int argc, char **argv)
exit(1);
}
memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir));
+ strlen(testprogdir) + 1);
memcpy(testprogdir, pwd, strlen(pwd));
testprogdir[strlen(pwd)] = '/';
}
diff --git a/cpio/test/test.h b/cpio/test/test.h
index 9898be65..0cd3e904 100644
--- a/cpio/test/test.h
+++ b/cpio/test/test.h
@@ -85,12 +85,14 @@
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(__BORLANDC__)
+#undef chdir
+#define chdir _chdir
#define strdup _strdup
#endif
#endif
/* Visual Studio */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
@@ -276,6 +278,9 @@ int canGrzip(void);
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
+/* Return true if this platform can run the specified command. */
+int canRunCommand(const char *);
+
/* Return true if this platform can run the "lrzip" program. */
int canLrzip(void);
@@ -304,11 +309,19 @@ int is_LargeInode(const char *);
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
+/* Dump block of bytes to a file. */
+void dumpfile(const char *filename, void *, size_t);
+
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
/* Copies named reference file to the current directory. */
void copy_reference_file(const char *);
+/* Extracts a list of files to the current directory.
+ * List must be NULL terminated.
+ */
+void extract_reference_files(const char **);
+
/* Path to working directory for current test */
extern const char *testworkdir;
diff --git a/cpio/test/test_basic.c b/cpio/test/test_basic.c
index 7213062e..f3a04800 100644
--- a/cpio/test/test_basic.c
+++ b/cpio/test/test_basic.c
@@ -72,7 +72,7 @@ basic_cpio(const char *target,
return;
/* Use the cpio program to create an archive. */
- r = systemf("%s -o %s < filelist >%s/archive 2>%s/pack.err",
+ r = systemf("%s -R 1000:1000 -o %s < filelist >%s/archive 2>%s/pack.err",
testprog, pack_options, target, target);
failure("Error invoking %s -o %s", testprog, pack_options);
assertEqualInt(r, 0);
diff --git a/cpio/test/test_option_c.c b/cpio/test/test_option_c.c
index a634be10..fa47b7e2 100644
--- a/cpio/test/test_option_c.c
+++ b/cpio/test/test_option_c.c
@@ -65,18 +65,14 @@ DEFINE_TEST(test_option_c)
{
FILE *filelist;
int r;
- int uid = -1;
- int dev, ino, gid;
+ int uid = 1000;
+ int dev, ino, gid = 1000;
time_t t, now;
char *p, *e;
size_t s;
assertUmask(0);
-#if !defined(_WIN32)
- uid = getuid();
-#endif
-
/*
* Create an assortment of files.
* TODO: Extend this to cover more filetypes.
@@ -101,7 +97,7 @@ DEFINE_TEST(test_option_c)
/* Use the cpio program to create an archive. */
fclose(filelist);
- r = systemf("%s -oc <filelist >basic.out 2>basic.err", testprog);
+ r = systemf("%s -R 1000:1000 -oc <filelist >basic.out 2>basic.err", testprog);
/* Verify that nothing went to stderr. */
assertTextFileContents("1 block\n", "basic.err");
diff --git a/cpio/test/test_option_lz4.c b/cpio/test/test_option_lz4.c
index 889c1461..d430ac75 100644
--- a/cpio/test/test_option_lz4.c
+++ b/cpio/test/test_option_lz4.c
@@ -45,13 +45,25 @@ DEFINE_TEST(test_option_lz4)
"without lz4 support");
return;
}
- if (strstr(p, "Can't initialise filter") != NULL
- && !canLz4()) {
- skipping("This version of bsdtar uses an external lz4 program "
+ /* POSIX permits different handling of the spawnp
+ * system call used to launch the subsidiary
+ * program: */
+ /* Some systems fail immediately to spawn the new process. */
+ if (strstr(p, "Can't launch") != NULL && !canLz4()) {
+ skipping("This version of bsdcpio uses an external lz4 program "
"but no such program is available on this system.");
return;
}
- failure("--lz4 option is broken");
+ /* Some systems successfully spawn the new process,
+ * but fail to exec a program within that process.
+ * This results in failure at the first attempt to
+ * write. */
+ if (strstr(p, "Can't write") != NULL && !canLz4()) {
+ skipping("This version of bsdcpio uses an external lz4 program "
+ "but no such program is available on this system.");
+ return;
+ }
+ failure("--lz4 option is broken: %s", p);
assertEqualInt(r, 0);
return;
}
diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt
index f427e97d..4cc9a2ca 100644
--- a/libarchive/CMakeLists.txt
+++ b/libarchive/CMakeLists.txt
@@ -34,6 +34,7 @@ SET(libarchive_SOURCES
archive_entry_strmode.c
archive_entry_xattr.c
archive_getdate.c
+ archive_getdate.h
archive_hmac.c
archive_hmac_private.h
archive_match.c
diff --git a/libarchive/archive.h b/libarchive/archive.h
index 676ab3fd..371cf4d0 100644
--- a/libarchive/archive.h
+++ b/libarchive/archive.h
@@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define ARCHIVE_VERSION_NUMBER 3001002
+#define ARCHIVE_VERSION_NUMBER 3001900
#include <sys/stat.h>
#include <stddef.h> /* for wchar_t */
@@ -95,6 +95,11 @@ typedef ssize_t la_ssize_t;
# endif
#endif
+/* Large file support for Android */
+#ifdef __ANDROID__
+#include "android_lf.h"
+#endif
+
/*
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
* .lib. The default here assumes you're building a DLL. Only
@@ -149,7 +154,7 @@ __LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_ONLY_STRING "3.1.2"
+#define ARCHIVE_VERSION_ONLY_STRING "3.1.900a"
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
__LA_DECL const char * archive_version_string(void);
@@ -162,6 +167,16 @@ __LA_DECL const char * archive_version_string(void);
*/
__LA_DECL const char * archive_version_details(void);
+/*
+ * Returns NULL if libarchive was compiled without the associated library.
+ * Otherwise, returns the version number that libarchive was compiled
+ * against.
+ */
+__LA_DECL const char * archive_zlib_version(void);
+__LA_DECL const char * archive_liblzma_version(void);
+__LA_DECL const char * archive_bzlib_version(void);
+__LA_DECL const char * archive_liblz4_version(void);
+
/* Declare our basic types. */
struct archive;
struct archive_entry;
diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c
index 9b01df8f..f9615a64 100644
--- a/libarchive/archive_cryptor.c
+++ b/libarchive/archive_cryptor.c
@@ -31,7 +31,7 @@
#include "archive.h"
#include "archive_cryptor_private.h"
-#ifdef __APPLE__
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
static int
pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
@@ -114,7 +114,10 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
#endif
-#ifdef __APPLE__
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
+# define kCCAlgorithmAES kCCAlgorithmAES128
+# endif
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
@@ -253,7 +256,7 @@ aes_ctr_release(archive_crypto_ctx *ctx)
return 0;
}
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
static int
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h
index b62ec0c6..f629bc13 100644
--- a/libarchive/archive_cryptor_private.h
+++ b/libarchive/archive_cryptor_private.h
@@ -31,6 +31,13 @@
#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
#ifdef __APPLE__
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+# define ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+# endif
+#endif
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
#include <CommonCrypto/CommonCryptor.h>
#include <CommonCrypto/CommonKeyDerivation.h>
#define AES_BLOCK_SIZE 16
@@ -65,7 +72,7 @@ typedef struct {
unsigned encr_pos;
} archive_crypto_ctx;
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
#if defined(HAVE_NETTLE_PBKDF2_H)
#include <nettle/pbkdf2.h>
#endif
diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h
index 06740926..5d692731 100644
--- a/libarchive/archive_entry.h
+++ b/libarchive/archive_entry.h
@@ -29,7 +29,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
-#define ARCHIVE_VERSION_NUMBER 3001002
+#define ARCHIVE_VERSION_NUMBER 3001900
/*
* Note: archive_entry.h is for use outside of libarchive; the
@@ -75,6 +75,11 @@ typedef int64_t la_int64_t;
# define __LA_MODE_T mode_t
#endif
+/* Large file support for Android */
+#ifdef __ANDROID__
+#include "android_lf.h"
+#endif
+
/*
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
* .lib. The default here assumes you're building a DLL. Only
diff --git a/libarchive/archive_entry_copy_stat.c b/libarchive/archive_entry_copy_stat.c
index 37d4d6ed..ac83868e 100644
--- a/libarchive/archive_entry_copy_stat.c
+++ b/libarchive/archive_entry_copy_stat.c
@@ -44,6 +44,10 @@ archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
archive_entry_set_atime(entry, st->st_atime, st->st_atim.tv_nsec);
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
+#elif HAVE_STRUCT_STAT_ST_MTIME_NSEC
+ archive_entry_set_atime(entry, st->st_atime, st->st_atime_nsec);
+ archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_nsec);
+ archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);
diff --git a/libarchive/archive_getdate.c b/libarchive/archive_getdate.c
index aaa9d6fa..beb0cba2 100644
--- a/libarchive/archive_getdate.c
+++ b/libarchive/archive_getdate.c
@@ -38,8 +38,8 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <time.h>
-/* This file defines a single public function. */
-time_t __archive_get_date(time_t now, char *);
+#define __LIBARCHIVE_BUILD 1
+#include "archive_getdate.h"
/* Basic time units. */
#define EPOCH 1970
@@ -782,7 +782,7 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
* Tokenizer.
*/
static int
-nexttoken(char **in, time_t *value)
+nexttoken(const char **in, time_t *value)
{
char c;
char buff[64];
@@ -809,7 +809,7 @@ nexttoken(char **in, time_t *value)
/* Try the next token in the word table first. */
/* This allows us to match "2nd", for example. */
{
- char *src = *in;
+ const char *src = *in;
const struct LEXICON *tp;
unsigned i = 0;
@@ -894,7 +894,7 @@ difftm (struct tm *a, struct tm *b)
* TODO: tokens[] array should be dynamically sized.
*/
time_t
-__archive_get_date(time_t now, char *p)
+__archive_get_date(time_t now, const char *p)
{
struct token tokens[256];
struct gdstate _gds;
diff --git a/libarchive/archive_getdate.h b/libarchive/archive_getdate.h
new file mode 100644
index 00000000..666ff5ff
--- /dev/null
+++ b/libarchive/archive_getdate.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2003-2015 Tim Kientzle
+ * 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 __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 *);
+
+#endif
diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c
index 898853bd..12fca456 100644
--- a/libarchive/archive_hmac.c
+++ b/libarchive/archive_hmac.c
@@ -31,7 +31,7 @@
#include "archive.h"
#include "archive_hmac_private.h"
-#ifdef __APPLE__
+#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
@@ -129,7 +129,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
}
}
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
static int
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
diff --git a/libarchive/archive_hmac_private.h b/libarchive/archive_hmac_private.h
index 3e48bc3a..1f182d92 100644
--- a/libarchive/archive_hmac_private.h
+++ b/libarchive/archive_hmac_private.h
@@ -31,11 +31,18 @@
#define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
#ifdef __APPLE__
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+# define ARCHIVE_HMAC_USE_Apple_CommonCrypto
+# endif
+#endif
+
+#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
#include <CommonCrypto/CommonHMAC.h>
typedef CCHmacContext archive_hmac_sha1_ctx;
-#elif defined(_WIN32) && !defined(__CYGWIN__)
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
#include <bcrypt.h>
typedef struct {
@@ -46,7 +53,7 @@ typedef struct {
} archive_hmac_sha1_ctx;
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
#include <nettle/hmac.h>
typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx;
diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c
index 74aaacb5..4c41badf 100644
--- a/libarchive/archive_match.c
+++ b/libarchive/archive_match.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_private.h"
#include "archive_entry.h"
+#include "archive_getdate.h"
#include "archive_pathmatch.h"
#include "archive_rb.h"
#include "archive_string.h"
@@ -184,7 +185,6 @@ static int time_excluded(struct archive_match *,
struct archive_entry *);
static int validate_time_flag(struct archive *, int, const char *);
-time_t __archive_get_date(time_t now, const char *);
#define get_date __archive_get_date
static const struct archive_rb_tree_ops rb_ops_mbs = {
diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c
index 8af62393..dbf3e80e 100644
--- a/libarchive/archive_options.c
+++ b/libarchive/archive_options.c
@@ -42,9 +42,9 @@ _archive_set_option(struct archive *a,
archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
- mp = m != NULL && m[0] == '\0' ? NULL : m;
- op = o != NULL && o[0] == '\0' ? NULL : o;
- vp = v != NULL && v[0] == '\0' ? NULL : v;
+ mp = (m != NULL && m[0] != '\0') ? m : NULL;
+ op = (o != NULL && o[0] != '\0') ? o : NULL;
+ vp = (v != NULL && v[0] != '\0') ? v : NULL;
if (op == NULL && vp == NULL)
return (ARCHIVE_OK);
diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h
index faeb5efc..64595aec 100644
--- a/libarchive/archive_platform.h
+++ b/libarchive/archive_platform.h
@@ -126,6 +126,15 @@
#if !HAVE_DECL_INT64_MIN
#define INT64_MIN ((int64_t)(~INT64_MAX))
#endif
+#if !HAVE_DECL_UINTMAX_MAX
+#define UINTMAX_MAX (~(uintmax_t)0)
+#endif
+#if !HAVE_DECL_INTMAX_MAX
+#define INTMAX_MAX ((intmax_t)(UINTMAX_MAX >> 1))
+#endif
+#if !HAVE_DECL_INTMAX_MIN
+#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX))
+#endif
/*
* If this platform has <sys/acl.h>, acl_create(), acl_init(),
diff --git a/libarchive/archive_random.c b/libarchive/archive_random.c
index 57c49d5a..a20b9b11 100644
--- a/libarchive/archive_random.c
+++ b/libarchive/archive_random.c
@@ -62,6 +62,10 @@ static void arc4random_buf(void *, size_t);
#include <wincrypt.h>
#endif
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
/*
* Random number generator function.
* This simply calls arc4random_buf function if the platform provides it.
@@ -133,16 +137,15 @@ archive_random(void *buf, size_t nbytes)
#endif /* !__GNUC__ */
struct arc4_stream {
- u_int8_t i;
- u_int8_t j;
- u_int8_t s[256];
+ uint8_t i;
+ uint8_t j;
+ uint8_t s[256];
};
-static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
-
#define RANDOMDEV "/dev/urandom"
#define KEYSIZE 128
#ifdef HAVE_PTHREAD_H
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx);
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx);
#else
@@ -155,7 +158,7 @@ static struct arc4_stream rs;
static pid_t arc4_stir_pid;
static int arc4_count;
-static inline u_int8_t arc4_getbyte(void);
+static inline uint8_t arc4_getbyte(void);
static void arc4_stir(void);
static inline void
@@ -173,7 +176,7 @@ static inline void
arc4_addrandom(u_char *dat, int datlen)
{
int n;
- u_int8_t si;
+ uint8_t si;
rs.i--;
for (n = 0; n < 256; n++) {
@@ -235,10 +238,10 @@ arc4_stir_if_needed(void)
}
}
-static inline u_int8_t
+static inline uint8_t
arc4_getbyte(void)
{
- u_int8_t si, sj;
+ uint8_t si, sj;
rs.i = (rs.i + 1);
si = rs.s[rs.i];
diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
index 41842d4e..0bbacc8f 100644
--- a/libarchive/archive_read.c
+++ b/libarchive/archive_read.c
@@ -547,16 +547,20 @@ archive_read_open1(struct archive *_a)
* it wants to handle this stream. Repeat until we've finished
* building the pipeline.
*/
+
+/* We won't build a filter pipeline with more stages than this. */
+#define MAX_NUMBER_FILTERS 25
+
static int
choose_filters(struct archive_read *a)
{
- int number_bidders, i, bid, best_bid, n;
+ int number_bidders, i, bid, best_bid, number_filters;
struct archive_read_filter_bidder *bidder, *best_bidder;
struct archive_read_filter *filter;
ssize_t avail;
int r;
- for (n = 0; n < 25; ++n) {
+ for (number_filters = 0; number_filters < MAX_NUMBER_FILTERS; ++number_filters) {
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
best_bid = 0;
@@ -1157,7 +1161,7 @@ static const char *
_archive_filter_name(struct archive *_a, int n)
{
struct archive_read_filter *f = get_filter(_a, n);
- return f == NULL ? NULL : f->name;
+ return f != NULL ? f->name : NULL;
}
static int64_t
diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c
index 38303aa8..74fe353d 100644
--- a/libarchive/archive_read_disk_entry_from_file.c
+++ b/libarchive/archive_read_disk_entry_from_file.c
@@ -1046,7 +1046,7 @@ setup_sparse(struct archive_read_disk *a,
struct fiemap *fm;
struct fiemap_extent *fe;
int64_t size;
- int count, do_fiemap;
+ int count, do_fiemap, iters;
int exit_sts = ARCHIVE_OK;
if (archive_entry_filetype(entry) != AE_IFREG
@@ -1083,7 +1083,7 @@ setup_sparse(struct archive_read_disk *a,
fm->fm_extent_count = count;
do_fiemap = 1;
size = archive_entry_size(entry);
- for (;;) {
+ for (iters = 0; ; ++iters) {
int i, r;
r = ioctl(*fd, FS_IOC_FIEMAP, fm);
@@ -1093,8 +1093,13 @@ setup_sparse(struct archive_read_disk *a,
* version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
goto exit_setup_sparse;
}
- if (fm->fm_mapped_extents == 0)
+ if (fm->fm_mapped_extents == 0) {
+ if (iters == 0) {
+ /* Fully sparse file; insert a zero-length "data" entry */
+ archive_entry_sparse_add_entry(entry, 0, 0);
+ }
break;
+ }
fe = fm->fm_extents;
for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
@@ -1139,6 +1144,7 @@ setup_sparse(struct archive_read_disk *a,
off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
int exit_sts = ARCHIVE_OK;
+ int check_fully_sparse = 0;
if (archive_entry_filetype(entry) != AE_IFREG
|| archive_entry_size(entry) <= 0
@@ -1191,8 +1197,14 @@ setup_sparse(struct archive_read_disk *a,
while (off_s < size) {
off_s = lseek(*fd, off_s, SEEK_DATA);
if (off_s == (off_t)-1) {
- if (errno == ENXIO)
- break;/* no more hole */
+ if (errno == ENXIO) {
+ /* no more hole */
+ if (archive_entry_sparse_count(entry) == 0) {
+ /* Potentially a fully-sparse file. */
+ check_fully_sparse = 1;
+ }
+ break;
+ }
archive_set_error(&a->archive, errno,
"lseek(SEEK_HOLE) failed");
exit_sts = ARCHIVE_FAILED;
@@ -1216,6 +1228,14 @@ setup_sparse(struct archive_read_disk *a,
off_e - off_s);
off_s = off_e;
}
+
+ if (check_fully_sparse) {
+ if (lseek(*fd, 0, SEEK_HOLE) == 0 &&
+ lseek(*fd, 0, SEEK_END) == size) {
+ /* Fully sparse file; insert a zero-length "data" entry */
+ archive_entry_sparse_add_entry(entry, 0, 0);
+ }
+ }
exit_setup_sparse:
lseek(*fd, initial_off, SEEK_SET);
return (exit_sts);
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index dad91517..d1343949 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -717,6 +717,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
int r;
ssize_t bytes;
size_t buffbytes;
+ int empty_sparse_region = 0;
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
"archive_read_data_block");
@@ -798,6 +799,9 @@ _archive_read_data_block(struct archive *_a, const void **buff,
if ((int64_t)buffbytes > t->current_sparse->length)
buffbytes = t->current_sparse->length;
+ if (t->current_sparse->length == 0)
+ empty_sparse_region = 1;
+
/*
* Skip hole.
* TODO: Should we consider t->current_filesystem->xfer_align?
@@ -828,7 +832,15 @@ _archive_read_data_block(struct archive *_a, const void **buff,
}
} else
bytes = 0;
- if (bytes == 0) {
+ /*
+ * Return an EOF unless we've read a leading empty sparse region, which
+ * is used to represent fully-sparse files.
+ *
+ * TODO: it is not technically necessary to check for entry_tota == 0,
+ * but this simplifies some unit tests that expect to only read data
+ * regions with length > 0. Consider fixing these tests (test_sparse_basic).
+ */
+ if (bytes == 0 && !(empty_sparse_region && t->entry_total == 0)) {
/* Get EOF */
t->entry_eof = 1;
r = ARCHIVE_EOF;
@@ -1576,6 +1588,7 @@ setup_current_filesystem(struct archive_read_disk *a)
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
t->current_filesystem->name_max = sfs.f_namemax;
#else
+# if defined(_PC_NAME_MAX)
/* Mac OS X does not have f_namemax in struct statfs. */
if (tree_current_is_symblic_link_target(t)) {
if (tree_enter_working_dir(t) != 0) {
@@ -1585,6 +1598,9 @@ setup_current_filesystem(struct archive_read_disk *a)
nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
} else
nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
+# else
+ nm = -1;
+# endif
if (nm == -1)
t->current_filesystem->name_max = NAME_MAX;
else
diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
index 3a33c258..bfe933bf 100644
--- a/libarchive/archive_read_open_file.c
+++ b/libarchive/archive_read_open_file.c
@@ -83,8 +83,9 @@ archive_read_open_FILE(struct archive *a, FILE *f)
mine->f = f;
/*
* If we can't fstat() the file, it may just be that it's not
- * a file. (FILE * objects can wrap many kinds of I/O
- * streams, some of which don't support fileno()).)
+ * a file. (On some platforms, FILE * objects can wrap I/O
+ * streams that don't support fileno()). As a result, fileno()
+ * should be used cautiously.)
*/
if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
@@ -150,7 +151,10 @@ file_skip(struct archive *a, void *client_data, int64_t request)
skip = max_skip;
}
-#if HAVE_FSEEKO
+#ifdef __ANDROID__
+ /* fileno() isn't safe on all platforms ... see above. */
+ if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
+#elif HAVE_FSEEKO
if (fseeko(mine->f, skip, SEEK_CUR) != 0)
#elif HAVE__FSEEKI64
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c
index 622c960c..5611aa85 100644
--- a/libarchive/archive_read_open_filename.c
+++ b/libarchive/archive_read_open_filename.c
@@ -178,7 +178,7 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
#else
/*
* POSIX system does not support a wchar_t interface for
- * open() system call, so we have to translate a whcar_t
+ * open() system call, so we have to translate a wchar_t
* filename to multi-byte one and use it.
*/
struct archive_string fn;
diff --git a/libarchive/archive_read_support_filter_lz4.c b/libarchive/archive_read_support_filter_lz4.c
index db62cb35..e877917b 100644
--- a/libarchive/archive_read_support_filter_lz4.c
+++ b/libarchive/archive_read_support_filter_lz4.c
@@ -580,10 +580,19 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
prefix64k);
}
}
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ uncompressed_size = LZ4_decompress_safe_usingDict(
+ read_buf + 4,
+ state->out_block + prefix64k, (int)compressed_size,
+ state->flags.block_maximum_size,
+ state->out_block,
+ prefix64k);
+#else
uncompressed_size = LZ4_decompress_safe_withPrefix64k(
read_buf + 4,
state->out_block + prefix64k, (int)compressed_size,
state->flags.block_maximum_size);
+#endif
}
/* Check if an error happend in decompression process. */
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
index 8dc5607f..90901acb 100644
--- a/libarchive/archive_read_support_format_7zip.c
+++ b/libarchive/archive_read_support_format_7zip.c
@@ -1201,7 +1201,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
}
archive_set_error(&a->archive, err,
"Internal error initializing decompressor: %s",
- detail == NULL ? "??" : detail);
+ detail != NULL ? detail : "??");
zip->bzstream_valid = 0;
return (ARCHIVE_FAILED);
}
diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c
index 88979bb4..6450aac8 100644
--- a/libarchive/archive_read_support_format_rar.c
+++ b/libarchive/archive_read_support_format_rar.c
@@ -828,6 +828,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
char head_type;
int ret;
unsigned flags;
+ unsigned long crc32_expected;
a->archive.archive_format = ARCHIVE_FORMAT_RAR;
if (a->archive.archive_format_name == NULL)
@@ -940,36 +941,50 @@ archive_read_format_rar_read_header(struct archive_read *a,
skip = archive_le16dec(p + 5);
if (skip < 7) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Invalid header size");
+ "Invalid header size too small");
return (ARCHIVE_FATAL);
}
- if (skip > 7) {
- if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
- return (ARCHIVE_FATAL);
- p = h;
- }
if (flags & HD_ADD_SIZE_PRESENT)
{
if (skip < 7 + 4) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Invalid header size");
+ "Invalid header size too small");
return (ARCHIVE_FATAL);
}
- skip += archive_le32dec(p + 7);
if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
return (ARCHIVE_FATAL);
p = h;
+ skip += archive_le32dec(p + 7);
}
- crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
- if ((crc32_val & 0xffff) != archive_le16dec(p)) {
- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Header CRC error");
- return (ARCHIVE_FATAL);
+ /* Skip over the 2-byte CRC at the beginning of the header. */
+ crc32_expected = archive_le16dec(p);
+ __archive_read_consume(a, 2);
+ skip -= 2;
+
+ /* Skim the entire header and compute the CRC. */
+ crc32_val = 0;
+ while (skip > 0) {
+ size_t to_read = skip;
+ ssize_t did_read;
+ if (to_read > 32 * 1024) {
+ to_read = 32 * 1024;
+ }
+ if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
+ return (ARCHIVE_FATAL);
+ }
+ p = h;
+ crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
+ __archive_read_consume(a, did_read);
+ skip -= did_read;
+ }
+ if ((crc32_val & 0xffff) != crc32_expected) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Header CRC error");
+ return (ARCHIVE_FATAL);
}
- __archive_read_consume(a, skip);
if (head_type == ENDARC_HEAD)
- return (ARCHIVE_EOF);
+ return (ARCHIVE_EOF);
break;
case NEWSUB_HEAD:
diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c
index 6bd15f6b..46a59ea1 100644
--- a/libarchive/archive_read_support_format_warc.c
+++ b/libarchive/archive_read_support_format_warc.c
@@ -418,10 +418,11 @@ deconst(const void *c)
}
static char*
-xmemmem(const char *hay, const size_t hz, const char *ndl, const size_t nz)
+xmemmem(const char *hay, const size_t haysize,
+ const char *needle, const size_t needlesize)
{
- const char *const eoh = hay + hz;
- const char *const eon = ndl + nz;
+ const char *const eoh = hay + haysize;
+ const char *const eon = needle + needlesize;
const char *hp;
const char *np;
const char *cand;
@@ -433,9 +434,9 @@ xmemmem(const char *hay, const size_t hz, const char *ndl, const size_t nz)
* a 0-sized needle is defined to be found anywhere in haystack
* then run strchr() to find a candidate in HAYSTACK (i.e. a portion
* that happens to begin with *NEEDLE) */
- if (nz == 0UL) {
+ if (needlesize == 0UL) {
return deconst(hay);
- } else if ((hay = memchr(hay, *ndl, hz)) == NULL) {
+ } else if ((hay = memchr(hay, *needle, haysize)) == NULL) {
/* trivial */
return NULL;
}
@@ -444,11 +445,11 @@ xmemmem(const char *hay, const size_t hz, const char *ndl, const size_t nz)
* guaranteed to be at least one character long. Now computes the sum
* of characters values of needle together with the sum of the first
* needle_len characters of haystack. */
- for (hp = hay + 1U, np = ndl + 1U, hsum = *hay, nsum = *hay, eqp = 1U;
+ for (hp = hay + 1U, np = needle + 1U, hsum = *hay, nsum = *hay, eqp = 1U;
hp < eoh && np < eon;
hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++);
- /* HP now references the (NZ + 1)-th character. */
+ /* HP now references the (NEEDLESIZE + 1)-th character. */
if (np < eon) {
/* haystack is smaller than needle, :O */
return NULL;
@@ -464,10 +465,10 @@ xmemmem(const char *hay, const size_t hz, const char *ndl, const size_t nz)
hsum ^= *hp;
/* Since the sum of the characters is already known to be
- * equal at that point, it is enough to check just NZ - 1
+ * equal at that point, it is enough to check just NEEDLESIZE - 1
* characters for equality,
* also CAND is by design < HP, so no need for range checks */
- if (hsum == nsum && memcmp(cand, ndl, nz - 1U) == 0) {
+ if (hsum == nsum && memcmp(cand, needle, needlesize - 1U) == 0) {
return deconst(cand);
}
}
diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c
index 19c1b780..ab887505 100644
--- a/libarchive/archive_read_support_format_xar.c
+++ b/libarchive/archive_read_support_format_xar.c
@@ -1939,9 +1939,6 @@ unknowntag_start(struct archive_read *a, struct xar *xar, const char *name)
{
struct unknown_tag *tag;
-#if DEBUG
- fprintf(stderr, "unknowntag_start:%s\n", name);
-#endif
tag = malloc(sizeof(*tag));
if (tag == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
@@ -1951,6 +1948,9 @@ unknowntag_start(struct archive_read *a, struct xar *xar, const char *name)
archive_string_init(&(tag->name));
archive_strcpy(&(tag->name), name);
if (xar->unknowntags == NULL) {
+#if DEBUG
+ fprintf(stderr, "UNKNOWNTAG_START:%s\n", name);
+#endif
xar->xmlsts_unknown = xar->xmlsts;
xar->xmlsts = UNKNOWN;
}
@@ -1963,9 +1963,6 @@ unknowntag_end(struct xar *xar, const char *name)
{
struct unknown_tag *tag;
-#if DEBUG
- fprintf(stderr, "unknowntag_end:%s\n", name);
-#endif
tag = xar->unknowntags;
if (tag == NULL || name == NULL)
return;
@@ -1973,8 +1970,12 @@ unknowntag_end(struct xar *xar, const char *name)
xar->unknowntags = tag->next;
archive_string_free(&(tag->name));
free(tag);
- if (xar->unknowntags == NULL)
+ if (xar->unknowntags == NULL) {
+#if DEBUG
+ fprintf(stderr, "UNKNOWNTAG_END:%s\n", name);
+#endif
xar->xmlsts = xar->xmlsts_unknown;
+ }
}
}
@@ -2168,7 +2169,7 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list)
case FILE_ACL:
if (strcmp(name, "appleextended") == 0)
xar->xmlsts = FILE_ACL_APPLEEXTENDED;
- if (strcmp(name, "default") == 0)
+ else if (strcmp(name, "default") == 0)
xar->xmlsts = FILE_ACL_DEFAULT;
else if (strcmp(name, "access") == 0)
xar->xmlsts = FILE_ACL_ACCESS;
@@ -2690,9 +2691,9 @@ xml_data(void *userData, const char *s, int len)
#if DEBUG
{
char buff[1024];
- if (len > sizeof(buff)-1)
- len = sizeof(buff)-1;
- memcpy(buff, s, len);
+ if (len > (int)(sizeof(buff)-1))
+ len = (int)(sizeof(buff)-1);
+ strncpy(buff, s, len);
buff[len] = 0;
fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff);
}
diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c
index ea14d4d8..cc3d1c46 100644
--- a/libarchive/archive_util.c
+++ b/libarchive/archive_util.c
@@ -94,35 +94,81 @@ archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
+ const char *zlib = archive_zlib_version();
+ const char *liblzma = archive_liblzma_version();
+ const char *bzlib = archive_bzlib_version();
+ const char *liblz4 = archive_liblz4_version();
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
-#ifdef HAVE_ZLIB_H
- archive_strcat(&str, " zlib/");
- archive_strcat(&str, ZLIB_VERSION);
-#endif
-#ifdef HAVE_LZMA_H
- archive_strcat(&str, " liblzma/");
- archive_strcat(&str, LZMA_VERSION_STRING);
-#endif
-#ifdef HAVE_BZLIB_H
- {
- const char *p = BZ2_bzlibVersion();
+ if (zlib != NULL) {
+ archive_strcat(&str, " zlib/");
+ archive_strcat(&str, zlib);
+ }
+ if (liblzma) {
+ archive_strcat(&str, " liblzma/");
+ archive_strcat(&str, liblzma);
+ }
+ if (bzlib) {
+ const char *p = bzlib;
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
+ if (liblz4) {
+ archive_strcat(&str, " liblz4/");
+ archive_strcat(&str, liblz4);
+ }
+ }
+ return str.s;
+}
+
+const char *
+archive_zlib_version(void)
+{
+#ifdef HAVE_ZLIB_H
+ return ZLIB_VERSION;
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_liblzma_version(void)
+{
+#ifdef HAVE_LZMA_H
+ return LZMA_VERSION_STRING;
+#else
+ return NULL;
#endif
+}
+
+const char *
+archive_bzlib_version(void)
+{
+#ifdef HAVE_BZLIB_H
+ return BZ2_bzlibVersion();
+#else
+ return NULL;
+#endif
+}
+
+const char *
+archive_liblz4_version(void)
+{
#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
- archive_string_sprintf(&str, " liblz4/%d.%d.%d",
- LZ4_VERSION_MAJOR, LZ4_VERSION_MINOR, LZ4_VERSION_RELEASE);
+#define str(s) #s
+#define NUMBER(x) str(x)
+ return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
+#undef NUMBER
+#undef str
+#else
+ return NULL;
#endif
- }
- return str.s;
}
int
diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c
index 9f707f07..e3fa3357 100644
--- a/libarchive/archive_write.c
+++ b/libarchive/archive_write.c
@@ -725,7 +725,7 @@ static const char *
_archive_filter_name(struct archive *_a, int n)
{
struct archive_write_filter *f = filter_lookup(_a, n);
- return f == NULL ? NULL : f->name;
+ return f != NULL ? f->name : NULL;
}
static int64_t
diff --git a/libarchive/archive_write_add_filter_bzip2.c b/libarchive/archive_write_add_filter_bzip2.c
index 88da803a..68ed9579 100644
--- a/libarchive/archive_write_add_filter_bzip2.c
+++ b/libarchive/archive_write_add_filter_bzip2.c
@@ -105,7 +105,7 @@ archive_write_add_filter_bzip2(struct archive *_a)
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
return (ARCHIVE_OK);
#else
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate("bzip2");
if (data->pdata == NULL) {
free(data);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
diff --git a/libarchive/archive_write_add_filter_grzip.c b/libarchive/archive_write_add_filter_grzip.c
index 8dc287ea..371102d7 100644
--- a/libarchive/archive_write_add_filter_grzip.c
+++ b/libarchive/archive_write_add_filter_grzip.c
@@ -63,7 +63,7 @@ archive_write_add_filter_grzip(struct archive *_a)
archive_set_error(_a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate("grzip");
if (data->pdata == NULL) {
free(data);
archive_set_error(_a, ENOMEM, "Can't allocate memory");
diff --git a/libarchive/archive_write_add_filter_gzip.c b/libarchive/archive_write_add_filter_gzip.c
index da4607bb..04eb06c1 100644
--- a/libarchive/archive_write_add_filter_gzip.c
+++ b/libarchive/archive_write_add_filter_gzip.c
@@ -119,7 +119,7 @@ archive_write_add_filter_gzip(struct archive *_a)
data->compression_level = Z_DEFAULT_COMPRESSION;
return (ARCHIVE_OK);
#else
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate("gzip");
if (data->pdata == NULL) {
free(data);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
diff --git a/libarchive/archive_write_add_filter_lrzip.c b/libarchive/archive_write_add_filter_lrzip.c
index da1cf5e4..e215f890 100644
--- a/libarchive/archive_write_add_filter_lrzip.c
+++ b/libarchive/archive_write_add_filter_lrzip.c
@@ -69,7 +69,7 @@ archive_write_add_filter_lrzip(struct archive *_a)
archive_set_error(_a, ENOMEM, "Can't allocate memory");
return (ARCHIVE_FATAL);
}
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate("lrzip");
if (data->pdata == NULL) {
free(data);
archive_set_error(_a, ENOMEM, "Can't allocate memory");
diff --git a/libarchive/archive_write_add_filter_lz4.c b/libarchive/archive_write_add_filter_lz4.c
index e23e5e93..1d0ab8c5 100644
--- a/libarchive/archive_write_add_filter_lz4.c
+++ b/libarchive/archive_write_add_filter_lz4.c
@@ -137,7 +137,7 @@ archive_write_add_filter_lz4(struct archive *_a)
* We don't have lz4 library, and execute external lz4 program
* instead.
*/
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate("lz4");
if (data->pdata == NULL) {
free(data);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
@@ -160,10 +160,20 @@ archive_filter_lz4_options(struct archive_write_filter *f,
struct private_data *data = (struct private_data *)f->data;
if (strcmp(key, "compression-level") == 0) {
- if (value == NULL || !(value[0] >= '1' && value[0] <= '9') ||
+ int val;
+ if (value == NULL || !((val = value[0] - '0') >= 1 && val <= 9) ||
value[1] != '\0')
return (ARCHIVE_WARN);
- data->compression_level = value[0] - '0';
+
+#ifndef HAVE_LZ4HC_H
+ if(val >= 3)
+ {
+ archive_set_error(f->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "High compression not included in this build");
+ return (ARCHIVE_FATAL);
+ }
+#endif
+ data->compression_level = val;
return (ARCHIVE_OK);
}
if (strcmp(key, "stream-checksum") == 0) {
@@ -367,14 +377,20 @@ archive_filter_lz4_free(struct archive_write_filter *f)
struct private_data *data = (struct private_data *)f->data;
if (data->lz4_stream != NULL) {
- if (data->compression_level < 3)
+#ifdef HAVE_LZ4HC_H
+ if (data->compression_level >= 3)
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ LZ4_freeStreamHC(data->lz4_stream);
+#else
+ LZ4_freeHC(data->lz4_stream);
+#endif
+ else
+#endif
#if LZ4_VERSION_MINOR >= 3
LZ4_freeStream(data->lz4_stream);
#else
LZ4_free(data->lz4_stream);
#endif
- else
- LZ4_freeHC(data->lz4_stream);
}
free(data->out_buffer);
free(data->in_buffer_allocated);
@@ -481,13 +497,26 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p,
struct private_data *data = (struct private_data *)f->data;
unsigned int outsize;
- if (data->compression_level < 4)
- outsize = LZ4_compress_limitedOutput(p, data->out + 4,
- (int)length, (int)data->block_size);
- else
+#ifdef HAVE_LZ4HC_H
+ if (data->compression_level >= 3)
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ outsize = LZ4_compress_HC(p, data->out + 4,
+ (int)length, (int)data->block_size,
+ data->compression_level);
+#else
outsize = LZ4_compressHC2_limitedOutput(p, data->out + 4,
(int)length, (int)data->block_size,
data->compression_level);
+#endif
+ else
+#endif
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ outsize = LZ4_compress_default(p, data->out + 4,
+ (int)length, (int)data->block_size);
+#else
+ outsize = LZ4_compress_limitedOutput(p, data->out + 4,
+ (int)length, (int)data->block_size);
+#endif
if (outsize) {
/* The buffer is compressed. */
@@ -518,9 +547,17 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
struct private_data *data = (struct private_data *)f->data;
int outsize;
- if (data->compression_level < 3) {
+#define DICT_SIZE (64 * 1024)
+#ifdef HAVE_LZ4HC_H
+ if (data->compression_level >= 3) {
if (data->lz4_stream == NULL) {
- data->lz4_stream = LZ4_createStream();
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ data->lz4_stream = LZ4_createStreamHC();
+ LZ4_resetStreamHC(data->lz4_stream, data->compression_level);
+#else
+ data->lz4_stream =
+ LZ4_createHC(data->in_buffer_allocated);
+#endif
if (data->lz4_stream == NULL) {
archive_set_error(f->archive, ENOMEM,
"Can't allocate data for compression"
@@ -528,13 +565,23 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
return (ARCHIVE_FATAL);
}
}
- outsize = LZ4_compress_limitedOutput_continue(
+ else
+ LZ4_loadDictHC(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE);
+
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ outsize = LZ4_compress_HC_continue(
data->lz4_stream, p, data->out + 4, (int)length,
(int)data->block_size);
- } else {
+#else
+ outsize = LZ4_compressHC2_limitedOutput_continue(
+ data->lz4_stream, p, data->out + 4, (int)length,
+ (int)data->block_size, data->compression_level);
+#endif
+ } else
+#endif
+ {
if (data->lz4_stream == NULL) {
- data->lz4_stream =
- LZ4_createHC(data->in_buffer_allocated);
+ data->lz4_stream = LZ4_createStream();
if (data->lz4_stream == NULL) {
archive_set_error(f->archive, ENOMEM,
"Can't allocate data for compression"
@@ -542,9 +589,18 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
return (ARCHIVE_FATAL);
}
}
- outsize = LZ4_compressHC2_limitedOutput_continue(
+ else
+ LZ4_loadDict(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE);
+
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ outsize = LZ4_compress_fast_continue(
data->lz4_stream, p, data->out + 4, (int)length,
- (int)data->block_size, data->compression_level);
+ (int)data->block_size, 1);
+#else
+ outsize = LZ4_compress_limitedOutput_continue(
+ data->lz4_stream, p, data->out + 4, (int)length,
+ (int)data->block_size);
+#endif
}
if (outsize) {
@@ -568,14 +624,19 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
}
if (length == data->block_size) {
-#define DICT_SIZE (64 * 1024)
- if (data->compression_level < 3)
- LZ4_saveDict(data->lz4_stream,
- data->in_buffer_allocated, DICT_SIZE);
- else {
+#ifdef HAVE_LZ4HC_H
+ if (data->compression_level >= 3) {
+#if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
+ LZ4_saveDictHC(data->lz4_stream, data->in_buffer_allocated, DICT_SIZE);
+#else
LZ4_slideInputBufferHC(data->lz4_stream);
+#endif
data->in_buffer = data->in_buffer_allocated + DICT_SIZE;
}
+ else
+#endif
+ LZ4_saveDict(data->lz4_stream,
+ data->in_buffer_allocated, DICT_SIZE);
#undef DICT_SIZE
}
return (ARCHIVE_OK);
@@ -605,7 +666,7 @@ archive_filter_lz4_open(struct archive_write_filter *f)
if (data->block_checksum)
archive_strcat(&as, " -BX");
if (data->stream_checksum == 0)
- archive_strcat(&as, " -Sx");
+ archive_strcat(&as, " --no-frame-crc");
if (data->block_independence == 0)
archive_strcat(&as, " -BD");
diff --git a/libarchive/archive_write_add_filter_lzop.c b/libarchive/archive_write_add_filter_lzop.c
index c666551d..ad705c4a 100644
--- a/libarchive/archive_write_add_filter_lzop.c
+++ b/libarchive/archive_write_add_filter_lzop.c
@@ -173,7 +173,7 @@ archive_write_add_filter_lzop(struct archive *_a)
data->compression_level = 5;
return (ARCHIVE_OK);
#else
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate("lzop");
if (data->pdata == NULL) {
free(data);
archive_set_error(_a, ENOMEM, "Can't allocate memory");
diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c
index fc232da0..31a1b6f9 100644
--- a/libarchive/archive_write_add_filter_program.c
+++ b/libarchive/archive_write_add_filter_program.c
@@ -68,6 +68,7 @@ struct archive_write_program_data {
char *child_buf;
size_t child_buf_len, child_buf_avail;
+ char *program_name;
};
struct private_data {
@@ -105,7 +106,7 @@ archive_write_add_filter_program(struct archive *_a, const char *cmd)
if (data->cmd == NULL)
goto memerr;
- data->pdata = __archive_write_program_allocate();
+ data->pdata = __archive_write_program_allocate(cmd);
if (data->pdata == NULL)
goto memerr;
@@ -174,7 +175,7 @@ archive_compressor_program_free(struct archive_write_filter *f)
* Allocate resources for executing an external program.
*/
struct archive_write_program_data *
-__archive_write_program_allocate(void)
+__archive_write_program_allocate(const char *program)
{
struct archive_write_program_data *data;
@@ -183,6 +184,7 @@ __archive_write_program_allocate(void)
return (data);
data->child_stdin = -1;
data->child_stdout = -1;
+ data->program_name = strdup(program);
return (data);
}
@@ -231,7 +233,7 @@ __archive_write_program_open(struct archive_write_filter *f,
&data->child_stdout);
if (child == -1) {
archive_set_error(f->archive, EINVAL,
- "Can't initialise filter");
+ "Can't launch external program: %s", cmd);
return (ARCHIVE_FATAL);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -242,7 +244,7 @@ __archive_write_program_open(struct archive_write_filter *f,
close(data->child_stdout);
data->child_stdout = -1;
archive_set_error(f->archive, EINVAL,
- "Can't initialise filter");
+ "Can't launch external program: %s", cmd);
return (ARCHIVE_FATAL);
}
#else
@@ -334,7 +336,7 @@ __archive_write_program_write(struct archive_write_filter *f,
ret = child_write(f, data, buf, length);
if (ret == -1 || ret == 0) {
archive_set_error(f->archive, EIO,
- "Can't write to filter");
+ "Can't write to program: %s", data->program_name);
return (ARCHIVE_FATAL);
}
length -= ret;
@@ -373,7 +375,7 @@ __archive_write_program_close(struct archive_write_filter *f,
if (bytes_read == -1) {
archive_set_error(f->archive, errno,
- "Read from filter failed unexpectedly.");
+ "Error reading from program: %s", data->program_name);
ret = ARCHIVE_FATAL;
goto cleanup;
}
@@ -403,7 +405,7 @@ cleanup:
if (status != 0) {
archive_set_error(f->archive, EIO,
- "Filter exited with failure.");
+ "Error closing program: %s", data->program_name);
ret = ARCHIVE_FATAL;
}
r1 = __archive_write_close_filter(f->next_filter);
diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c
index 0fc61930..6737cd75 100644
--- a/libarchive/archive_write_disk_posix.c
+++ b/libarchive/archive_write_disk_posix.c
@@ -2386,6 +2386,9 @@ check_symlinks(struct archive_write_disk *a)
while ((*pn != '\0') && (*p == *pn))
++p, ++pn;
}
+ /* Skip the root directory if the path is absolute. */
+ if(pn == a->name && pn[0] == '/')
+ ++pn;
c = pn[0];
/* Keep going until we've checked the entire name. */
while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
@@ -2447,6 +2450,9 @@ check_symlinks(struct archive_write_disk *a)
return (ARCHIVE_FAILED);
}
}
+ pn[0] = c;
+ if (pn[0] != '\0')
+ pn++; /* Advance to the next segment. */
}
pn[0] = c;
/* We've checked and/or cleaned the whole path, so remember it. */
diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h
index 0c3cc0c6..0dfd1b1b 100644
--- a/libarchive/archive_write_private.h
+++ b/libarchive/archive_write_private.h
@@ -144,7 +144,7 @@ __archive_write_format_header_ustar(struct archive_write *, char buff[512],
struct archive_string_conv *);
struct archive_write_program_data;
-struct archive_write_program_data * __archive_write_program_allocate(void);
+struct archive_write_program_data * __archive_write_program_allocate(const char *program_name);
int __archive_write_program_free(struct archive_write_program_data *);
int __archive_write_program_open(struct archive_write_filter *,
struct archive_write_program_data *, const char *);
diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c
index 7847cb3c..fc6ccfe0 100644
--- a/libarchive/archive_write_set_format_7zip.c
+++ b/libarchive/archive_write_set_format_7zip.c
@@ -1450,6 +1450,10 @@ _7z_free(struct archive_write *a)
{
struct _7zip *zip = (struct _7zip *)a->format_data;
+ /* Close the temporary file. */
+ if (zip->temp_fd >= 0)
+ close(zip->temp_fd);
+
file_free_register(zip);
compression_end(&(a->archive), &(zip->stream));
free(zip->coder.props);
diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c
index 016f60f4..4d832fb6 100644
--- a/libarchive/archive_write_set_format_iso9660.c
+++ b/libarchive/archive_write_set_format_iso9660.c
@@ -197,7 +197,7 @@ struct isofile {
enum {
NO = 0,
BOOT_CATALOG,
- BOOT_IMAGE,
+ BOOT_IMAGE
} boot;
/*
@@ -850,7 +850,7 @@ enum dir_rec_type {
DIR_REC_VD, /* Stored in Volume Descriptor. */
DIR_REC_SELF, /* Stored as Current Directory. */
DIR_REC_PARENT, /* Stored as Parent Directory. */
- DIR_REC_NORMAL, /* Stored as Child. */
+ DIR_REC_NORMAL /* Stored as Child. */
};
/*
@@ -860,7 +860,7 @@ enum vdc {
VDC_STD,
VDC_LOWERCASE,
VDC_UCS2,
- VDC_UCS2_DIRECT,
+ VDC_UCS2_DIRECT
};
/*
@@ -897,7 +897,7 @@ struct idr {
enum char_type {
A_CHAR,
- D_CHAR,
+ D_CHAR
};
@@ -4004,7 +4004,7 @@ enum keytype {
KEY_FLG,
KEY_STR,
KEY_INT,
- KEY_HEX,
+ KEY_HEX
};
static void
set_option_info(struct archive_string *info, int *opt, const char *key,
diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c
index 687f8e48..6f7fe783 100644
--- a/libarchive/archive_write_set_format_pax.c
+++ b/libarchive/archive_write_set_format_pax.c
@@ -1036,22 +1036,12 @@ archive_write_pax_header(struct archive_write *a,
need_extension = 1;
/*
- * The following items are handled differently in "pax
- * restricted" format. In particular, in "pax restricted"
- * format they won't be added unless need_extension is
- * already set (we're already generating an extended header, so
- * may as well include these).
+ * Libarchive used to include these in extended headers for
+ * restricted pax format, but that confused people who
+ * expected ustar-like time semantics. So now we only include
+ * them in full pax format.
*/
- if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
- need_extension) {
-
- if (archive_entry_mtime(entry_main) < 0 ||
- archive_entry_mtime(entry_main) >= 0x7fffffff ||
- archive_entry_mtime_nsec(entry_main) != 0)
- add_pax_attr_time(&(pax->pax_header), "mtime",
- archive_entry_mtime(entry_main),
- archive_entry_mtime_nsec(entry_main));
-
+ if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED) {
if (archive_entry_ctime(entry_main) != 0 ||
archive_entry_ctime_nsec(entry_main) != 0)
add_pax_attr_time(&(pax->pax_header), "ctime",
@@ -1072,6 +1062,23 @@ archive_write_pax_header(struct archive_write *a,
"LIBARCHIVE.creationtime",
archive_entry_birthtime(entry_main),
archive_entry_birthtime_nsec(entry_main));
+ }
+
+ /*
+ * The following items are handled differently in "pax
+ * restricted" format. In particular, in "pax restricted"
+ * format they won't be added unless need_extension is
+ * already set (we're already generating an extended header, so
+ * may as well include these).
+ */
+ if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
+ need_extension) {
+ if (archive_entry_mtime(entry_main) < 0 ||
+ archive_entry_mtime(entry_main) >= 0x7fffffff ||
+ archive_entry_mtime_nsec(entry_main) != 0)
+ add_pax_attr_time(&(pax->pax_header), "mtime",
+ archive_entry_mtime(entry_main),
+ archive_entry_mtime_nsec(entry_main));
/* I use a star-compatible file flag attribute. */
p = archive_entry_fflags_text(entry_main);
diff --git a/libarchive/archive_write_set_format_warc.c b/libarchive/archive_write_set_format_warc.c
index 80abc6f4..ea66929a 100644
--- a/libarchive/archive_write_set_format_warc.c
+++ b/libarchive/archive_write_set_format_warc.c
@@ -186,16 +186,18 @@ _warc_header(struct archive_write *a, struct archive_entry *entry)
/* check whether warcinfo record needs outputting */
if (!w->omit_warcinfo) {
+ ssize_t r;
warc_essential_hdr_t wi = {
WT_INFO,
/*uri*/NULL,
/*urn*/NULL,
- /*rtm*/w->now,
- /*mtm*/w->now,
+ /*rtm*/0,
+ /*mtm*/0,
/*cty*/"application/warc-fields",
/*len*/sizeof(warcinfo) - 1U,
};
- ssize_t r;
+ wi.rtime = w->now;
+ wi.mtime = w->now;
archive_string_init(&hdr);
r = _popul_ehdr(&hdr, MAX_HDR_SIZE, wi);
@@ -226,14 +228,18 @@ _warc_header(struct archive_write *a, struct archive_entry *entry)
if (w->typ == AE_IFREG) {
warc_essential_hdr_t rh = {
WT_RSRC,
- /*uri*/archive_entry_pathname(entry),
+ /*uri*/NULL,
/*urn*/NULL,
- /*rtm*/w->now,
- /*mtm*/archive_entry_mtime(entry),
+ /*rtm*/0,
+ /*mtm*/0,
/*cty*/NULL,
- /*len*/(size_t)archive_entry_size(entry),
+ /*len*/0,
};
ssize_t r;
+ rh.tgturi = archive_entry_pathname(entry);
+ rh.rtime = w->now;
+ rh.mtime = archive_entry_mtime(entry);
+ rh.cntlen = (size_t)archive_entry_size(entry);
archive_string_init(&hdr);
r = _popul_ehdr(&hdr, MAX_HDR_SIZE, rh);
@@ -325,16 +331,16 @@ xstrftime(struct archive_string *as, const char *fmt, time_t t)
/** like strftime(3) but for time_t objects */
struct tm *rt;
#if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
- struct tm time;
+ struct tm timeHere;
#endif
char strtime[100];
size_t len;
#ifdef HAVE_GMTIME_R
- if ((rt = gmtime_r(&t, &time)) == NULL)
+ if ((rt = gmtime_r(&t, &timeHere)) == NULL)
return;
#elif defined(HAVE__GMTIME64_S)
- _gmtime64_s(&time, &t);
+ _gmtime64_s(&timeHere, &t);
#else
if ((rt = gmtime(&t)) == NULL)
return;
@@ -396,7 +402,7 @@ _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr)
* handle the minimum number following '%'.
* So we have to use snprintf function here instead
* of archive_string_snprintf function. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__) && !( defined(_MSC_VER) && _MSC_VER >= 1900)
#define snprintf _snprintf
#endif
snprintf(
diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c
index 4538befd..a2dbc039 100644
--- a/libarchive/archive_write_set_format_xar.c
+++ b/libarchive/archive_write_set_format_xar.c
@@ -1877,6 +1877,11 @@ xar_free(struct archive_write *a)
struct xar *xar;
xar = (struct xar *)a->format_data;
+
+ /* Close the temporary file. */
+ if (xar->temp_fd >= 0)
+ close(xar->temp_fd);
+
archive_string_free(&(xar->cur_dirstr));
archive_string_free(&(xar->tstr));
archive_string_free(&(xar->vstr));
diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c
index ed5a00b4..e4edb818 100644
--- a/libarchive/archive_write_set_format_zip.c
+++ b/libarchive/archive_write_set_format_zip.c
@@ -66,6 +66,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 20
#define ZIP_ENTRY_FLAG_LENGTH_AT_END (1<<3)
#define ZIP_ENTRY_FLAG_UTF8_NAME (1 << 11)
+#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff)
+#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000)
+
enum compression {
COMPRESSION_UNSPECIFIED = -1,
COMPRESSION_STORE = 0,
@@ -532,13 +535,13 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
if (zip->flags & ZIP_FLAG_AVOID_ZIP64) {
/* Reject entries over 4GB. */
if (archive_entry_size_is_set(entry)
- && (archive_entry_size(entry) > 0xffffffff)) {
+ && (archive_entry_size(entry) > ZIP_4GB_MAX)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Files > 4GB require Zip64 extensions");
return ARCHIVE_FAILED;
}
/* Reject entries if archive is > 4GB. */
- if (zip->written_bytes > 0xffffffff) {
+ if (zip->written_bytes > ZIP_4GB_MAX) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Archives > 4GB require Zip64 extensions");
return ARCHIVE_FAILED;
@@ -726,8 +729,8 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
* (compression might make file larger)
*/
if ((zip->flags & ZIP_FLAG_FORCE_ZIP64)
- || (zip->entry_uncompressed_size + additional_size > 0xffffffffLL)
- || (zip->entry_uncompressed_size > 0xff000000LL
+ || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX)
+ || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED
&& zip->entry_compression != COMPRESSION_STORE)) {
zip->entry_uses_zip64 = 1;
version_needed = 45;
@@ -785,8 +788,8 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
* are included only if these are 0xffffffff;
* THEREFORE these must be set this way, even if we
* know one of them is smaller. */
- archive_le32enc(local_header + 18, 0xffffffffLL);
- archive_le32enc(local_header + 22, 0xffffffffLL);
+ archive_le32enc(local_header + 18, ZIP_4GB_MAX);
+ archive_le32enc(local_header + 22, ZIP_4GB_MAX);
} else {
archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size);
archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size);
@@ -1214,22 +1217,22 @@ archive_write_zip_finish_entry(struct archive_write *a)
}
/* Append Zip64 extra data to central directory information. */
- if (zip->entry_compressed_written > 0xffffffffLL
- || zip->entry_uncompressed_written > 0xffffffffLL
- || zip->entry_offset > 0xffffffffLL) {
+ if (zip->entry_compressed_written > ZIP_4GB_MAX
+ || zip->entry_uncompressed_written > ZIP_4GB_MAX
+ || zip->entry_offset > ZIP_4GB_MAX) {
unsigned char zip64[32];
unsigned char *z = zip64, *zd;
memcpy(z, "\001\000\000\000", 4);
z += 4;
- if (zip->entry_uncompressed_written >= 0xffffffffLL) {
+ if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) {
archive_le64enc(z, zip->entry_uncompressed_written);
z += 8;
}
- if (zip->entry_compressed_written >= 0xffffffffLL) {
+ if (zip->entry_compressed_written >= ZIP_4GB_MAX) {
archive_le64enc(z, zip->entry_compressed_written);
z += 8;
}
- if (zip->entry_offset >= 0xffffffffLL) {
+ if (zip->entry_offset >= ZIP_4GB_MAX) {
archive_le64enc(z, zip->entry_offset);
z += 8;
}
@@ -1253,15 +1256,15 @@ archive_write_zip_finish_entry(struct archive_write *a)
archive_le32enc(zip->file_header + 16, zip->entry_crc32);
archive_le32enc(zip->file_header + 20,
(uint32_t)zipmin(zip->entry_compressed_written,
- ARCHIVE_LITERAL_LL(0xffffffff)));
+ ZIP_4GB_MAX));
archive_le32enc(zip->file_header + 24,
(uint32_t)zipmin(zip->entry_uncompressed_written,
- ARCHIVE_LITERAL_LL(0xffffffff)));
+ ZIP_4GB_MAX));
archive_le16enc(zip->file_header + 30,
(uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset));
archive_le32enc(zip->file_header + 42,
(uint32_t)zipmin(zip->entry_offset,
- ARCHIVE_LITERAL_LL(0xffffffff)));
+ ZIP_4GB_MAX));
return (ARCHIVE_OK);
}
@@ -1288,8 +1291,8 @@ archive_write_zip_close(struct archive_write *a)
offset_end = zip->written_bytes;
/* If central dir info is too large, write Zip64 end-of-cd */
- if (offset_end - offset_start > ARCHIVE_LITERAL_LL(0xffffffff)
- || offset_start > ARCHIVE_LITERAL_LL(0xffffffff)
+ if (offset_end - offset_start > ZIP_4GB_MAX
+ || offset_start > ZIP_4GB_MAX
|| zip->central_directory_entries > 0xffffUL
|| (zip->flags & ZIP_FLAG_FORCE_ZIP64)) {
/* Zip64 end-of-cd record */
@@ -1329,9 +1332,9 @@ archive_write_zip_close(struct archive_write *a)
archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU,
zip->central_directory_entries));
archive_le32enc(buff + 12,
- (uint32_t)zipmin(0xffffffffLL, (offset_end - offset_start)));
+ (uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start)));
archive_le32enc(buff + 16,
- (uint32_t)zipmin(0xffffffffLL, offset_start));
+ (uint32_t)zipmin(ZIP_4GB_MAX, offset_start));
ret = __archive_write_output(a, buff, 22);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
diff --git a/libarchive/libarchive-formats.5 b/libarchive/libarchive-formats.5
index 4a709b33..4587e39f 100644
--- a/libarchive/libarchive-formats.5
+++ b/libarchive/libarchive-formats.5
@@ -55,7 +55,7 @@ It can write POSIX-standard
.Dq ustar
and
.Dq pax interchange
-formats and a subset of the legacy GNU tar format.
+formats as well as v7 tar format and a subset of the legacy GNU tar format.
.Pp
All tar formats store each entry in one or more 512-byte records.
The first record is used for file metadata, including filename,
@@ -150,6 +150,30 @@ Archive entries are limited to 8 gigabytes in size.
Note that the pax interchange format has none of these restrictions.
The ustar format is old and widely supported.
It is recommended when compatibility is the primary concern.
+.It Cm v7
+The libarchive library can read and write the legacy v7 tar format.
+This format has the following limitations:
+.Bl -bullet -compact
+.It
+Only regular files, directories, and symbolic links can be archived.
+Block and character device nodes, FIFOs, and sockets cannot be archived.
+.It
+Path names in the archive are limited to 100 bytes.
+.It
+Symbolic links and hard links are stored in the archive with
+the name of the referenced file.
+This name is limited to 100 bytes.
+.It
+User and group information are stored as numeric IDs; there
+is no provision for storing user or group names.
+.It
+Extended attributes, file flags, and other extended
+security information cannot be stored.
+.It
+Archive entries are limited to 8 gigabytes in size.
+.El
+Generally, users should prefer the ustar format for portability
+as the v7 tar format is both less useful and less portable.
.El
.Pp
The libarchive library also reads a variety of commonly-used extensions to
diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
index cf31ae0a..ae5a1aa8 100644
--- a/libarchive/test/CMakeLists.txt
+++ b/libarchive/test/CMakeLists.txt
@@ -84,6 +84,7 @@ IF(ENABLE_TEST)
test_read_disk_entry_from_file.c
test_read_extract.c
test_read_file_nonexistent.c
+ test_read_filter_compress.c
test_read_filter_grzip.c
test_read_filter_lrzip.c
test_read_filter_lzop.c
@@ -170,7 +171,6 @@ IF(ENABLE_TEST)
test_read_format_zip_padded.c
test_read_format_zip_sfx.c
test_read_format_zip_traditional_encryption_data.c
- test_read_format_zip_utf8_paths.c
test_read_format_zip_winzip_aes.c
test_read_format_zip_winzip_aes_large.c
test_read_format_zip_zip64.c
@@ -186,6 +186,7 @@ IF(ENABLE_TEST)
test_tar_large.c
test_ustar_filename_encoding.c
test_ustar_filenames.c
+ test_warn_missing_hardlink_target.c
test_write_disk.c
test_write_disk_appledouble.c
test_write_disk_failures.c
diff --git a/libarchive/test/main.c b/libarchive/test/main.c
index 90fd302d..b39c2bf7 100644
--- a/libarchive/test/main.c
+++ b/libarchive/test/main.c
@@ -130,6 +130,13 @@ __FBSDID("$FreeBSD: head/lib/libarchive/test/main.c 201247 2009-12-30 05:59:21Z
/* Path to working directory for current test */
const char *testworkdir;
+#ifdef PROGRAM
+/* Pathname of exe to be tested. */
+const char *testprogfile;
+/* Name of exe to use in printf-formatted command strings. */
+/* On Windows, this includes leading/trailing quotes. */
+const char *testprog;
+#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
static void *GetFunctionKernel32(const char *);
@@ -1037,6 +1044,7 @@ assertion_file_contains_lines_any_order(const char *file, int line,
if (expected == NULL) {
failure_start(pathname, line, "Can't allocate memory");
failure_finish(NULL);
+ free(expected);
return (0);
}
for (i = 0; lines[i] != NULL; ++i) {
@@ -2188,6 +2196,7 @@ dumpfile(const char *filename, void *data, size_t len)
/* Read a uuencoded file from the reference directory, decode, and
* write the result into the current directory. */
+#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
void
extract_reference_file(const char *name)
@@ -2211,7 +2220,6 @@ extract_reference_file(const char *name)
break;
}
/* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while (fgets(buff, sizeof(buff), in) != NULL) {
char *p = buff;
@@ -2225,17 +2233,21 @@ extract_reference_file(const char *name)
int n = 0;
/* Write out 1-3 bytes from that. */
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
+ assert(VALID_UUDECODE(p[1]));
n = UUDECODE(*p++) << 18;
n |= UUDECODE(*p++) << 12;
fputc(n >> 16, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++) << 6;
fputc((n >> 8) & 0xFF, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++);
fputc(n & 0xFF, out);
--bytes;
@@ -2562,7 +2574,7 @@ get_refdir(const char *d)
failure:
printf("Unable to locate known reference file %s\n", KNOWNREF);
printf(" Checked following directories:\n%s\n", tried);
- printf("Use -r option to specify full path to libarchive/test directory\n");
+ printf("Use -r option to specify full path to reference directory\n");
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
DebugBreak();
#endif
@@ -2646,7 +2658,7 @@ main(int argc, char **argv)
exit(1);
}
memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir));
+ strlen(testprogdir) + 1);
memcpy(testprogdir, pwd, strlen(pwd));
testprogdir[strlen(pwd)] = '/';
}
diff --git a/libarchive/test/test.h b/libarchive/test/test.h
index f80565bc..ad3de27b 100644
--- a/libarchive/test/test.h
+++ b/libarchive/test/test.h
@@ -66,6 +66,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -84,12 +85,14 @@
/* Windows (including Visual Studio and MinGW but not Cygwin) */
#if defined(_WIN32) && !defined(__CYGWIN__)
#if !defined(__BORLANDC__)
+#undef chdir
+#define chdir _chdir
#define strdup _strdup
#endif
#endif
/* Visual Studio */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
@@ -201,7 +204,7 @@
assertion_make_hardlink(__FILE__, __LINE__, newfile, oldfile)
#define assertMakeSymlink(newfile, linkto) \
assertion_make_symlink(__FILE__, __LINE__, newfile, linkto)
-#define assertNodump(path) \
+#define assertNodump(path) \
assertion_nodump(__FILE__, __LINE__, path)
#define assertUmask(mask) \
assertion_umask(__FILE__, __LINE__, mask)
diff --git a/libarchive/test/test_archive_getdate.c b/libarchive/test/test_archive_getdate.c
index 3f8ad29f..9e91b83b 100644
--- a/libarchive/test/test_archive_getdate.c
+++ b/libarchive/test/test_archive_getdate.c
@@ -27,11 +27,13 @@ __FBSDID("$FreeBSD$");
#include <time.h>
+#define __LIBARCHIVE_BUILD 1
+#include "archive_getdate.h"
+
/*
* Verify that the getdate() function works.
*/
-time_t __archive_get_date(time_t, const char *);
#define get_date __archive_get_date
DEFINE_TEST(test_archive_getdate)
diff --git a/libarchive/test/test_archive_match_time.c b/libarchive/test/test_archive_match_time.c
index c951e0db..c6864b32 100644
--- a/libarchive/test/test_archive_match_time.c
+++ b/libarchive/test/test_archive_match_time.c
@@ -26,7 +26,8 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-time_t __archive_get_date(time_t, const char *);
+#define __LIBARCHIVE_BUILD 1
+#include "archive_getdate.h"
static void
test_newer_time(void)
diff --git a/libarchive/test/test_compat_zip.c b/libarchive/test/test_compat_zip.c
index 5720210f..bb6d92ef 100644
--- a/libarchive/test/test_compat_zip.c
+++ b/libarchive/test/test_compat_zip.c
@@ -25,12 +25,6 @@
#include "test.h"
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_compat_zip.c 196962 2009-09-08 05:02:41Z kientzle $");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
/* Copy this function for each test file and adjust it accordingly. */
DEFINE_TEST(test_compat_zip_1)
{
@@ -51,7 +45,7 @@ DEFINE_TEST(test_compat_zip_1)
/* Read second entry. */
r = archive_read_next_header(a, &ae);
- if (r == ARCHIVE_FATAL && !libz_enabled) {
+ if (r == ARCHIVE_FATAL && archive_zlib_version() == NULL) {
skipping("Skipping ZIP compression check: %s",
archive_error_string(a));
goto finish;
@@ -132,7 +126,7 @@ DEFINE_TEST(test_compat_zip_3)
/* Extract under a different name. */
archive_entry_set_pathname(ae, "test_3.txt");
- if(libz_enabled) {
+ if(archive_zlib_version() != NULL) {
char *p;
size_t s;
assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0));
diff --git a/libarchive/test/test_read_format_cab.c b/libarchive/test/test_read_format_cab.c
index 55e6d978..8f6adae6 100644
--- a/libarchive/test/test_read_format_cab.c
+++ b/libarchive/test/test_read_format_cab.c
@@ -25,12 +25,6 @@
#include "test.h"
__FBSDID("$FreeBSD");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
/*
Execute the following command to rebuild the data for this program:
tail -n +44 test_read_format_cab.c | /bin/sh
@@ -222,7 +216,7 @@ verify(const char *refname, enum comp_type comp)
assertEqualInt(33000, archive_entry_size(ae));
for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) {
ssize_t rsize = archive_read_data(a, buff, sizeof(buff));
- if (comp == MSZIP && rsize == ARCHIVE_FATAL && !libz_enabled) {
+ if (comp == MSZIP && rsize == ARCHIVE_FATAL && archive_zlib_version() == NULL) {
skipping("Skipping CAB format(MSZIP) check: %s",
archive_error_string(a));
goto finish;
@@ -288,7 +282,7 @@ verify2(const char *refname, enum comp_type comp)
char buff[128];
char zero[128];
- if (comp == MSZIP && !libz_enabled) {
+ if (comp == MSZIP && archive_zlib_version() == NULL) {
skipping("Skipping CAB format(MSZIP) check for %s",
refname);
return;
diff --git a/libarchive/test/test_read_format_zip.c b/libarchive/test/test_read_format_zip.c
index c4ba0045..da5b1378 100644
--- a/libarchive/test/test_read_format_zip.c
+++ b/libarchive/test/test_read_format_zip.c
@@ -26,12 +26,6 @@
#include "test.h"
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_read_format_zip.c 189482 2009-03-07 03:30:35Z kientzle $");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
/*
* The reference file for this has been manually tweaked so that:
* * file2 has length-at-end but file1 does not
@@ -67,7 +61,7 @@ verify_basic(struct archive *a, int seek_checks)
assertEqualInt(archive_entry_is_encrypted(ae), 0);
assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0);
failure("archive_read_data() returns number of bytes read");
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(18, archive_read_data(a, buff, 19));
assertEqualMem(buff, "hello\nhello\nhello\n", 18);
} else {
@@ -87,7 +81,7 @@ verify_basic(struct archive *a, int seek_checks)
}
assert(archive_entry_size_is_set(ae));
assertEqualInt(18, archive_entry_size(ae));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
failure("file2 has a bad CRC, so read should fail and not change buff");
memset(buff, 'a', 19);
assertEqualInt(ARCHIVE_WARN, archive_read_data(a, buff, 19));
@@ -155,7 +149,7 @@ verify_info_zip_ux(struct archive *a, int seek_checks)
failure("zip reader should read Info-ZIP New Unix Extra Field");
assertEqualInt(1001, archive_entry_uid(ae));
assertEqualInt(1001, archive_entry_gid(ae));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
failure("archive_read_data() returns number of bytes read");
assertEqualInt(18, archive_read_data(a, buff, 19));
assertEqualMem(buff, "hello\nhello\nhello\n", 18);
@@ -226,7 +220,7 @@ verify_extract_length_at_end(struct archive *a, int seek_checks)
assertEqualInt(0, archive_entry_size(ae));
}
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0));
assertFileContents("hello\x0A", 6, "hello.txt");
} else {
diff --git a/libarchive/test/test_read_format_zip_mac_metadata.c b/libarchive/test/test_read_format_zip_mac_metadata.c
index 3b5dae61..97aa427b 100644
--- a/libarchive/test/test_read_format_zip_mac_metadata.c
+++ b/libarchive/test/test_read_format_zip_mac_metadata.c
@@ -25,12 +25,6 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
/*
* Read a zip file that has a zip comment in the end of the central
* directory record.
@@ -90,7 +84,7 @@ DEFINE_TEST(test_read_format_zip_mac_metadata)
assertEqualIntA(a, ARCHIVE_OK, archive_read_set_option(a, "zip", "mac-ext", "1"));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualIntA(a, ARCHIVE_OK,
archive_read_next_header(a, &ae));
} else {
@@ -105,7 +99,7 @@ DEFINE_TEST(test_read_format_zip_mac_metadata)
assertEqualString("file3", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae));
failure("Mac metadata should be set");
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
const void *metadata;
if (assert((metadata = archive_entry_mac_metadata(ae, &s))
!= NULL)) {
diff --git a/libarchive/test/test_read_format_zip_msdos.c b/libarchive/test/test_read_format_zip_msdos.c
index 66da77c2..fe287e1a 100644
--- a/libarchive/test/test_read_format_zip_msdos.c
+++ b/libarchive/test/test_read_format_zip_msdos.c
@@ -30,6 +30,8 @@ DEFINE_TEST(test_read_format_zip_msdos)
const char *refname = "test_read_format_zip_msdos.zip";
struct archive *a;
struct archive_entry *ae;
+ char *p;
+ size_t s;
extract_reference_file(refname);
@@ -39,8 +41,10 @@ DEFINE_TEST(test_read_format_zip_msdos)
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 17));
+ /* 'ab' is marked as a directory in the central dir
+ * with MSDOS attribute info */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
- assertEqualString("a/", archive_entry_pathname(ae));
+ assertEqualString("ab/", archive_entry_pathname(ae));
assertEqualInt(AE_IFDIR | 0775, archive_entry_mode(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
@@ -52,12 +56,28 @@ DEFINE_TEST(test_read_format_zip_msdos)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/* Verify with streaming reader. */
-#if 0
p = slurpfile(&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));
assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
- verify_basic(a, 0);
-#endif
+
+ /*
+ * 'ab' is not marked as a directory in the local file header
+ * (local file headers lack external attribute info), so the
+ * streaming reader can only determine if something is a directory
+ * by whether the name ends in '/'.
+ */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("ab", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae));
+
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("a/gru\xCC\x88n.png", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG | 0664, archive_entry_mode(ae));
+
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ free(p);
}
diff --git a/libarchive/test/test_read_format_zip_msdos.zip.uu b/libarchive/test/test_read_format_zip_msdos.zip.uu
index 6e9fd9a6..1691ca97 100644
--- a/libarchive/test/test_read_format_zip_msdos.zip.uu
+++ b/libarchive/test/test_read_format_zip_msdos.zip.uu
@@ -1,7 +1,7 @@
begin 644 test_read_format_zip_msdos.zip
-M4$L#!!0``````&9A3D,````````````````"````82]02P,$"@``````M)QO
+M4$L#!!0``````&9A3D,````````````````"````86)02P,$"@``````M)QO
M/-&'5C4&````!@````P```!A+V=R=<R(;BYP;F=03D=%3D102P$"/P`4````
-M``!F84Y#`````````````````@`D`````````!``````````82\*`"``````
+M``!F84Y#`````````````````@`D`````````!``````````86(*`"``````
M``$`&`"N2J&TQ<C.`:Y*H;3%R,X!C?R@M,7(S@%02P$"/P`*``````"TG&\\
MT8=6-08````&````#````````````(`````@````82]G<G7,B&XN<&YG4$L%
3!@`````"``(`C@```%``````````
diff --git a/libarchive/test/test_read_format_zip_traditional_encryption_data.c b/libarchive/test/test_read_format_zip_traditional_encryption_data.c
index a88050cf..2700be15 100644
--- a/libarchive/test/test_read_format_zip_traditional_encryption_data.c
+++ b/libarchive/test/test_read_format_zip_traditional_encryption_data.c
@@ -26,12 +26,6 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
DEFINE_TEST(test_read_format_zip_traditional_encryption_data)
{
/* This file is password protected (Traditional PKWARE Enctypted).
@@ -130,7 +124,7 @@ DEFINE_TEST(test_read_format_zip_traditional_encryption_data)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(495, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED,
@@ -148,7 +142,7 @@ DEFINE_TEST(test_read_format_zip_traditional_encryption_data)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(495, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED,
diff --git a/libarchive/test/test_read_format_zip_utf8_paths.c b/libarchive/test/test_read_format_zip_utf8_paths.c
deleted file mode 100644
index a7034162..00000000
--- a/libarchive/test/test_read_format_zip_utf8_paths.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
- * 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$");
-
-static void
-verify(struct archive *a) {
- struct archive_entry *ae;
- const wchar_t *wp;
- int file, i;
-
- /*
- * Test file has a pattern to all names: They all have a
- * number followed by " - " and an accented character. This
- * archive was created by Windows and has regular filenames in
- * some MBCS and uses the Zip 0x7075 extension to hold UTF-8
- * pathnames. The code below checks that the correct
- * (Unicode) characters are decoded by comparing the number to
- * the expected accented character.
- */
-
- for (file = 0; file < 20; ++file) {
- assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
- assert((wp = archive_entry_pathname_w(ae)) != NULL);
- if (wp) {
- for (i = 0; wp[i] != 0; ++i) {
- if (wp[i] == '2') {
- failure("Unicode 'o with umlaut' expected");
- assertEqualInt(wp[i + 4], 0xF6);
- } else if (wp[i] == '3') {
- failure("Unicode 'a with umlaut' expected");
- assertEqualInt(wp[i + 4], 0xE4);
- } else if (wp[i] == '4') {
- failure("Unicode 'a with ring' expected");
- assertEqualInt(wp[i + 4], 0xE5);
- }
- }
- }
- }
- assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
-}
-
-DEFINE_TEST(test_read_format_zip_utf8_paths)
-{
- const char *refname = "test_read_format_zip_utf8_paths.zip";
- struct archive *a;
- char *p;
- size_t s;
-
- extract_reference_file(refname);
-
- /* Verify with seeking reader. */
- 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));
- verify(a);
- assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
-
- /* Verify with streaming reader. */
- p = slurpfile(&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));
- assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
- verify(a);
- assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
- assertEqualIntA(a, ARCHIVE_OK, archive_free(a));
-}
diff --git a/libarchive/test/test_read_format_zip_utf8_paths.zip.uu b/libarchive/test/test_read_format_zip_utf8_paths.zip.uu
deleted file mode 100644
index 7e6cd742..00000000
--- a/libarchive/test/test_read_format_zip_utf8_paths.zip.uu
+++ /dev/null
@@ -1,62 +0,0 @@
-begin 644 test_read_format_zip_utf8_paths.zip
-M4$L#!!0``````,(^9D5BZ95P"0````D````.````1FEL92`S("T@A"YT>'14
-M97-T(&9I;&502P,$%```````PCYF16+IE7`)````"0````X```!&:6QE(#0@
-M+2"&+G1X=%1E<W0@9FEL95!+`P04``````#"/F9%8NF5<`D````)````$P``
-M`$9O;&1E<B`Q+T9I;&4@,2YT>'1497-T(&9I;&502P,$%```````PCYF16+I
-ME7`)````"0```!<```!&;VQD97(@,2]&:6QE(#(@+2"4+G1X=%1E<W0@9FEL
-M95!+`P04``````#"/F9%8NF5<`D````)````%P```$9O;&1E<B`Q+T9I;&4@
-M,R`M((0N='AT5&5S="!F:6QE4$L#!!0``````,(^9D5BZ95P"0````D````7
-M````1F]L9&5R(#$O1FEL92`T("T@ABYT>'1497-T(&9I;&502P,$%```````
-MPCYF16+IE7`)````"0```!<```!&;VQD97(@,B`M()0O1FEL92`Q+G1X=%1E
-M<W0@9FEL95!+`P04``````#"/F9%8NF5<`D````)````&P```$9O;&1E<B`R
-M("T@E"]&:6QE(#(@+2"4+G1X=%1E<W0@9FEL95!+`P04``````#"/F9%8NF5
-M<`D````)````&P```$9O;&1E<B`R("T@E"]&:6QE(#,@+2"$+G1X=%1E<W0@
-M9FEL95!+`P04``````#"/F9%8NF5<`D````)````&P```$9O;&1E<B`R("T@
-ME"]&:6QE(#0@+2"&+G1X=%1E<W0@9FEL95!+`P04``````#"/F9%8NF5<`D`
-M```)````%P```$9O;&1E<B`S("T@A"]&:6QE(#$N='AT5&5S="!F:6QE4$L#
-M!!0``````,(^9D5BZ95P"0````D````;````1F]L9&5R(#,@+2"$+T9I;&4@
-M,B`M()0N='AT5&5S="!F:6QE4$L#!!0``````,(^9D5BZ95P"0````D````;
-M````1F]L9&5R(#,@+2"$+T9I;&4@,R`M((0N='AT5&5S="!F:6QE4$L#!!0`
-M`````,(^9D5BZ95P"0````D````;````1F]L9&5R(#,@+2"$+T9I;&4@-"`M
-M((8N='AT5&5S="!F:6QE4$L#!!0``````,(^9D5BZ95P"0````D````7````
-M1F]L9&5R(#0@+2"&+T9I;&4@,2YT>'1497-T(&9I;&502P,$%```````PCYF
-M16+IE7`)````"0```!L```!&;VQD97(@-"`M((8O1FEL92`R("T@E"YT>'14
-M97-T(&9I;&502P,$%```````PCYF16+IE7`)````"0```!L```!&;VQD97(@
-M-"`M((8O1FEL92`S("T@A"YT>'1497-T(&9I;&502P,$%```````PCYF16+I
-ME7`)````"0```!L```!&;VQD97(@-"`M((8O1FEL92`T("T@ABYT>'1497-T
-M(&9I;&502P,$%```````PCYF16+IE7`)````"0````H```!&:6QE(#$N='AT
-M5&5S="!F:6QE4$L#!!0``````,(^9D5BZ95P"0````D````.````1FEL92`R
-M("T@E"YT>'1497-T(&9I;&502P$"%``4``````#"/F9%8NF5<`D````)````
-M#@`````````!`"``````````1FEL92`S("T@A"YT>'102P$"%``4``````#"
-M/F9%8NF5<`D````)````#@`````````!`"`````U````1FEL92`T("T@ABYT
-M>'102P$"%``4``````#"/F9%8NF5<`D````)````$P`````````!`"````!J
-M````1F]L9&5R(#$O1FEL92`Q+G1X=%!+`0(4`!0``````,(^9D5BZ95P"0``
-M``D````7``````````$`(````*0```!&;VQD97(@,2]&:6QE(#(@+2"4+G1X
-M=%!+`0(4`!0``````,(^9D5BZ95P"0````D````7``````````$`(````.(`
-M``!&;VQD97(@,2]&:6QE(#,@+2"$+G1X=%!+`0(4`!0``````,(^9D5BZ95P
-M"0````D````7``````````$`(````"`!``!&;VQD97(@,2]&:6QE(#0@+2"&
-M+G1X=%!+`0(4`!0``````,(^9D5BZ95P"0````D````7``````````$`(```
-M`%X!``!&;VQD97(@,B`M()0O1FEL92`Q+G1X=%!+`0(4`!0``````,(^9D5B
-MZ95P"0````D````;``````````$`(````)P!``!&;VQD97(@,B`M()0O1FEL
-M92`R("T@E"YT>'102P$"%``4``````#"/F9%8NF5<`D````)````&P``````
-M```!`"````#>`0``1F]L9&5R(#(@+2"4+T9I;&4@,R`M((0N='AT4$L!`A0`
-M%```````PCYF16+IE7`)````"0```!L``````````0`@````(`(``$9O;&1E
-M<B`R("T@E"]&:6QE(#0@+2"&+G1X=%!+`0(4`!0``````,(^9D5BZ95P"0``
-M``D````7``````````$`(````&("``!&;VQD97(@,R`M((0O1FEL92`Q+G1X
-M=%!+`0(4`!0``````,(^9D5BZ95P"0````D````;``````````$`(````*`"
-M``!&;VQD97(@,R`M((0O1FEL92`R("T@E"YT>'102P$"%``4``````#"/F9%
-M8NF5<`D````)````&P`````````!`"````#B`@``1F]L9&5R(#,@+2"$+T9I
-M;&4@,R`M((0N='AT4$L!`A0`%```````PCYF16+IE7`)````"0```!L`````
-M`````0`@````)`,``$9O;&1E<B`S("T@A"]&:6QE(#0@+2"&+G1X=%!+`0(4
-M`!0``````,(^9D5BZ95P"0````D````7``````````$`(````&8#``!&;VQD
-M97(@-"`M((8O1FEL92`Q+G1X=%!+`0(4`!0``````,(^9D5BZ95P"0````D`
-M```;``````````$`(````*0#``!&;VQD97(@-"`M((8O1FEL92`R("T@E"YT
-M>'102P$"%``4``````#"/F9%8NF5<`D````)````&P`````````!`"````#F
-M`P``1F]L9&5R(#0@+2"&+T9I;&4@,R`M((0N='AT4$L!`A0`%```````PCYF
-M16+IE7`)````"0```!L``````````0`@````*`0``$9O;&1E<B`T("T@AB]&
-M:6QE(#0@+2"&+G1X=%!+`0(4`!0``````,(^9D5BZ95P"0````D````*````
-M``````$`(````&H$``!&:6QE(#$N='AT4$L!`A0`%```````PCYF16+IE7`)
-M````"0````X``````````0`@````FP0``$9I;&4@,B`M()0N='AT4$L%!@``
-0```4`!0`7`4``-`$````````
-`
-end
diff --git a/libarchive/test/test_read_format_zip_winzip_aes.c b/libarchive/test/test_read_format_zip_winzip_aes.c
index 6ffbc1dd..082337d7 100644
--- a/libarchive/test/test_read_format_zip_winzip_aes.c
+++ b/libarchive/test/test_read_format_zip_winzip_aes.c
@@ -26,12 +26,6 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
static void
test_winzip_aes(const char *refname, int need_libz)
{
@@ -116,7 +110,7 @@ test_winzip_aes(const char *refname, int need_libz)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (!need_libz || libz_enabled) {
+ if (!need_libz || archive_zlib_version() != NULL) {
assertEqualInt(512, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, 19));
diff --git a/libarchive/test/test_read_format_zip_winzip_aes_large.c b/libarchive/test/test_read_format_zip_winzip_aes_large.c
index aeaca7df..a40d5cf1 100644
--- a/libarchive/test/test_read_format_zip_winzip_aes_large.c
+++ b/libarchive/test/test_read_format_zip_winzip_aes_large.c
@@ -26,12 +26,6 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-#ifdef HAVE_LIBZ
-static const int libz_enabled = 1;
-#else
-static const int libz_enabled = 0;
-#endif
-
DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
{
const char *refname = "test_read_format_zip_winzip_aes256_large.zip";
@@ -143,7 +137,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(512, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED,
@@ -161,7 +155,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(512, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED,
@@ -179,7 +173,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(512, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED,
@@ -197,7 +191,7 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large)
assertEqualInt(1, archive_entry_is_data_encrypted(ae));
assertEqualInt(0, archive_entry_is_metadata_encrypted(ae));
assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a));
- if (libz_enabled) {
+ if (archive_zlib_version() != NULL) {
assertEqualInt(512, archive_read_data(a, buff, sizeof(buff)));
} else {
assertEqualInt(ARCHIVE_FAILED,
diff --git a/libarchive/test/test_read_too_many_filters.c b/libarchive/test/test_read_too_many_filters.c
index 37cab24b..fdd582ff 100644
--- a/libarchive/test/test_read_too_many_filters.c
+++ b/libarchive/test/test_read_too_many_filters.c
@@ -40,6 +40,10 @@ DEFINE_TEST(test_read_too_many_filters)
assertEqualIntA(a, ARCHIVE_FATAL,
archive_read_open_filename(a, name, 200));
- assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ // Can't assert the return value here:
+ // = Decompressing via zlib will return ARCHIVE_OK
+ // = Decompressing via external gzip will return ARCHIVE_WARN
+ // (Due to a dirty shutdown of the gzip program.)
+ archive_read_close(a);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
diff --git a/libarchive/test/test_sparse_basic.c b/libarchive/test/test_sparse_basic.c
index fc3d56c5..09c0c9f5 100644
--- a/libarchive/test/test_sparse_basic.c
+++ b/libarchive/test/test_sparse_basic.c
@@ -218,9 +218,19 @@ create_sparse_file(const char *path, const struct sparse *s)
{
char buff[1024];
int fd;
+ size_t total_size = 0;
+ const struct sparse *cur = s;
memset(buff, ' ', sizeof(buff));
assert((fd = open(path, O_CREAT | O_WRONLY, 0600)) != -1);
+
+ /* Handle holes at the end by extending the file */
+ while (cur->type != END) {
+ total_size += cur->size;
+ ++cur;
+ }
+ assert(ftruncate(fd, total_size) != -1);
+
while (s->type != END) {
if (s->type == HOLE) {
assert(lseek(fd, s->size, SEEK_CUR) != (off_t)-1);
@@ -249,7 +259,7 @@ create_sparse_file(const char *path, const struct sparse *s)
*/
static void
verify_sparse_file(struct archive *a, const char *path,
- const struct sparse *sparse, int blocks)
+ const struct sparse *sparse, int blocks, int expected_data_blocks)
{
struct archive_entry *ae;
const void *buff;
@@ -278,9 +288,10 @@ verify_sparse_file(struct archive *a, const char *path,
}
total = offset + bytes_read;
}
- if (!hole && data_blocks == 1)
- data_blocks = 0;/* There are no holes */
- assertEqualInt(blocks, data_blocks);
+ assertEqualInt(expected_data_blocks, data_blocks);
+
+ if (blocks > 1)
+ assert(hole); /* There must be a hole if > 1 blocks were encoded */
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
archive_entry_free(ae);
@@ -425,10 +436,11 @@ DEFINE_TEST(test_sparse_basic)
*/
assert((a = archive_read_disk_new()) != NULL);
- verify_sparse_file(a, "file0", sparse_file0, 5);
- verify_sparse_file(a, "file1", sparse_file1, 2);
- verify_sparse_file(a, "file2", sparse_file2, 20);
- verify_sparse_file(a, "file3", sparse_file3, 0);
+ verify_sparse_file(a, "file0", sparse_file0, 5, 5);
+ verify_sparse_file(a, "file1", sparse_file1, 2, 2);
+ verify_sparse_file(a, "file2", sparse_file2, 20, 20);
+ /* Encoded non sparse; expect a data block but no sparse entries. */
+ verify_sparse_file(a, "file3", sparse_file3, 0, 1);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
@@ -443,3 +455,37 @@ DEFINE_TEST(test_sparse_basic)
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
free(cwd);
}
+
+DEFINE_TEST(test_fully_sparse_files)
+{
+ char *cwd;
+ struct archive *a;
+
+ const struct sparse sparse_file[] = {
+ { HOLE, 409600 }, { END, 0 }
+ };
+ /* Check if the filesystem where CWD on can
+ * report the number of the holes of a sparse file. */
+#ifdef PATH_MAX
+ cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
+#else
+ cwd = getcwd(NULL, 0);
+#endif
+ if (!assert(cwd != NULL))
+ return;
+ if (!is_sparse_supported(cwd)) {
+ free(cwd);
+ skipping("This filesystem or platform do not support "
+ "the reporting of the holes of a sparse file through "
+ "API such as lseek(HOLE)");
+ return;
+ }
+
+ assert((a = archive_read_disk_new()) != NULL);
+
+ /* Fully sparse files are encoded with a zero-length "data" block. */
+ verify_sparse_file(a, "file0", sparse_file, 1, 1);
+
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+ free(cwd);
+}
diff --git a/libarchive/test/test_write_disk_secure.c b/libarchive/test/test_write_disk_secure.c
index 2c942068..7cd66c41 100644
--- a/libarchive/test/test_write_disk_secure.c
+++ b/libarchive/test/test_write_disk_secure.c
@@ -84,6 +84,27 @@ DEFINE_TEST(test_write_disk_secure)
archive_entry_free(ae);
assert(0 == archive_write_finish_entry(a));
+ /* Write an absolute symlink to /tmp. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_symlink");
+ archive_entry_set_mode(ae, S_IFLNK | 0777);
+ archive_entry_set_symlink(ae, "/tmp");
+ archive_write_disk_set_options(a, 0);
+ assert(0 == archive_write_header(a, ae));
+ assert(0 == archive_write_finish_entry(a));
+
+ /* With security checks enabled, this should fail. */
+ assert(archive_entry_clear(ae) != NULL);
+ archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_symlink/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp");
+ archive_entry_set_mode(ae, S_IFREG | 0777);
+ archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
+ failure("Extracting a file through an absolute symlink should fail here.");
+ assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp");
+ assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink"));
+ unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp");
+
/* Create another link. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "link_to_dir2");
@@ -105,6 +126,25 @@ DEFINE_TEST(test_write_disk_secure)
archive_entry_free(ae);
assert(0 == archive_write_finish_entry(a));
+ /* Create a nested symlink. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "dir/nested_link_to_dir");
+ archive_entry_set_mode(ae, S_IFLNK | 0777);
+ archive_entry_set_symlink(ae, "../dir");
+ archive_write_disk_set_options(a, 0);
+ assert(0 == archive_write_header(a, ae));
+ assert(0 == archive_write_finish_entry(a));
+
+ /* But with security checks enabled, this should fail. */
+ assert(archive_entry_clear(ae) != NULL);
+ archive_entry_copy_pathname(ae, "dir/nested_link_to_dir/filed");
+ archive_entry_set_mode(ae, S_IFREG | 0777);
+ archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
+ failure("Extracting a file through a symlink should fail here.");
+ assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
+ archive_entry_free(ae);
+ assert(0 == archive_write_finish_entry(a));
+
/*
* Without security checks, extracting a dir over a link to a
* dir should follow the link.
@@ -234,5 +274,8 @@ DEFINE_TEST(test_write_disk_secure)
assert(S_ISREG(st.st_mode));
failure("link_to_dir2/filec: st.st_mode=%o", st.st_mode);
assert((st.st_mode & 07777) == 0755);
+
+ failure("dir/filed: This file should not have been created");
+ assert(0 != lstat("dir/filed", &st));
#endif
}
diff --git a/libarchive/test/test_write_filter_lz4.c b/libarchive/test/test_write_filter_lz4.c
index ae4fc67f..46c7061e 100644
--- a/libarchive/test/test_write_filter_lz4.c
+++ b/libarchive/test/test_write_filter_lz4.c
@@ -43,14 +43,18 @@ DEFINE_TEST(test_write_filter_lz4)
assert((a = archive_write_new()) != NULL);
r = archive_write_add_filter_lz4(a);
- if (r != ARCHIVE_OK) {
- if (canLz4() && r == ARCHIVE_WARN)
- use_prog = 1;
- else {
+ if (archive_liblz4_version() == NULL) {
+ if (!canLz4()) {
skipping("lz4 writing not supported on this platform");
+ assertEqualInt(ARCHIVE_WARN, r);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
return;
+ } else {
+ assertEqualInt(ARCHIVE_WARN, r);
+ use_prog = 1;
}
+ } else {
+ assertEqualInt(ARCHIVE_OK, r);
}
buffsize = 2000000;
@@ -280,14 +284,18 @@ test_options(const char *options)
assert((a = archive_write_new()) != NULL);
r = archive_write_add_filter_lz4(a);
- if (r != ARCHIVE_OK) {
- if (canLz4() && r == ARCHIVE_WARN)
- use_prog = 1;
- else {
+ if (archive_liblz4_version() == NULL) {
+ if (!canLz4()) {
skipping("lz4 writing not supported on this platform");
+ assertEqualInt(ARCHIVE_WARN, r);
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
return;
+ } else {
+ assertEqualInt(ARCHIVE_WARN, r);
+ use_prog = 1;
}
+ } else {
+ assertEqualInt(ARCHIVE_OK, r);
}
buffsize = 2000000;
diff --git a/libarchive_fe/passphrase.c b/libarchive_fe/passphrase.c
index 96d8f0a7..c9eaba64 100644
--- a/libarchive_fe/passphrase.c
+++ b/libarchive_fe/passphrase.c
@@ -142,7 +142,7 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
# define _POSIX_VDISABLE VDISABLE
#endif
-static volatile sig_atomic_t signo[_NSIG];
+static volatile sig_atomic_t signo[SIGRTMAX];
static void
handler(int s)
@@ -168,7 +168,7 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
}
restart:
- for (i = 0; i < _NSIG; i++)
+ for (i = 0; i < SIGRTMAX; i++)
signo[i] = 0;
nr = -1;
save_errno = 0;
@@ -273,7 +273,7 @@ restart:
* If we were interrupted by a signal, resend it to ourselves
* now that we have restored the signal handlers.
*/
- for (i = 0; i < _NSIG; i++) {
+ for (i = 0; i < SIGRTMAX; i++) {
if (signo[i]) {
kill(getpid(), i);
switch (i) {
diff --git a/tar/bsdtar.1 b/tar/bsdtar.1
index 9e45f191..3c0c8deb 100644
--- a/tar/bsdtar.1
+++ b/tar/bsdtar.1
@@ -740,9 +740,9 @@ In list mode,
.Nm
will produce output similar to that of
.Xr ls 1 .
-Additional
+An additional
.Fl v
-options will provide additional detail.
+option will also provide ls-like details in create and extract mode.
.It Fl Fl version
Print version of
.Nm
diff --git a/tar/bsdtar.h b/tar/bsdtar.h
index c05bfe88..4b84ba18 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -201,3 +201,5 @@ int cset_write_add_filters(struct creation_set *,
const char * passphrase_callback(struct archive *, void *);
void passphrase_free(char *);
+void list_item_verbose(struct bsdtar *, FILE *,
+ struct archive_entry *);
diff --git a/tar/read.c b/tar/read.c
index 87392e5a..e94cb3da 100644
--- a/tar/read.c
+++ b/tar/read.c
@@ -84,8 +84,6 @@ struct progress_data {
struct archive_entry *entry;
};
-static void list_item_verbose(struct bsdtar *, FILE *,
- struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode, struct archive *);
static int unmatched_inclusions_warn(struct archive *matching, const char *);
@@ -354,6 +352,7 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
if (bsdtar->verbose > 1) {
/* GNU tar uses -tv format with -xvv */
+ safe_fprintf(stderr, "x ");
list_item_verbose(bsdtar, stderr, entry);
fflush(stderr);
} else if (bsdtar->verbose > 0) {
@@ -402,106 +401,6 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
}
-/*
- * Display information about the current file.
- *
- * The format here roughly duplicates the output of 'ls -l'.
- * This is based on SUSv2, where 'tar tv' is documented as
- * listing additional information in an "unspecified format,"
- * and 'pax -l' is documented as using the same format as 'ls -l'.
- */
-static void
-list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
-{
- char tmp[100];
- size_t w;
- const char *p;
- const char *fmt;
- time_t tim;
- static time_t now;
-
- /*
- * We avoid collecting the entire list in memory at once by
- * listing things as we see them. However, that also means we can't
- * just pre-compute the field widths. Instead, we start with guesses
- * and just widen them as necessary. These numbers are completely
- * arbitrary.
- */
- if (!bsdtar->u_width) {
- bsdtar->u_width = 6;
- bsdtar->gs_width = 13;
- }
- if (!now)
- time(&now);
- fprintf(out, "%s %d ",
- archive_entry_strmode(entry),
- archive_entry_nlink(entry));
-
- /* Use uname if it's present, else uid. */
- p = archive_entry_uname(entry);
- if ((p == NULL) || (*p == '\0')) {
- sprintf(tmp, "%lu ",
- (unsigned long)archive_entry_uid(entry));
- p = tmp;
- }
- w = strlen(p);
- if (w > bsdtar->u_width)
- bsdtar->u_width = w;
- fprintf(out, "%-*s ", (int)bsdtar->u_width, p);
-
- /* Use gname if it's present, else gid. */
- p = archive_entry_gname(entry);
- if (p != NULL && p[0] != '\0') {
- fprintf(out, "%s", p);
- w = strlen(p);
- } else {
- sprintf(tmp, "%lu",
- (unsigned long)archive_entry_gid(entry));
- w = strlen(tmp);
- fprintf(out, "%s", tmp);
- }
-
- /*
- * Print device number or file size, right-aligned so as to make
- * total width of group and devnum/filesize fields be gs_width.
- * If gs_width is too small, grow it.
- */
- if (archive_entry_filetype(entry) == AE_IFCHR
- || archive_entry_filetype(entry) == AE_IFBLK) {
- sprintf(tmp, "%lu,%lu",
- (unsigned long)archive_entry_rdevmajor(entry),
- (unsigned long)archive_entry_rdevminor(entry));
- } else {
- strcpy(tmp, tar_i64toa(archive_entry_size(entry)));
- }
- if (w + strlen(tmp) >= bsdtar->gs_width)
- bsdtar->gs_width = w+strlen(tmp)+1;
- fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp);
-
- /* Format the time using 'ls -l' conventions. */
- tim = archive_entry_mtime(entry);
-#define HALF_YEAR (time_t)365 * 86400 / 2
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */
-#else
-#define DAY_FMT "%e" /* Day number without leading zeros */
-#endif
- if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
- 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));
- fprintf(out, " %s ", tmp);
- safe_fprintf(out, "%s", archive_entry_pathname(entry));
-
- /* Extra information for links. */
- if (archive_entry_hardlink(entry)) /* Hard link */
- safe_fprintf(out, " link to %s",
- archive_entry_hardlink(entry));
- else if (archive_entry_symlink(entry)) /* Symbolic link */
- safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
-}
-
static int
unmatched_inclusions_warn(struct archive *matching, const char *msg)
{
diff --git a/tar/subst.c b/tar/subst.c
index fd6f8e22..4710e06a 100644
--- a/tar/subst.c
+++ b/tar/subst.c
@@ -236,64 +236,66 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
continue;
}
- if (regexec(&rule->re, name, 10, matches, 0))
- continue;
-
- got_match = 1;
- print_match |= rule->print;
- realloc_strncat(result, name, matches[0].rm_so);
-
- for (i = 0, j = 0; rule->result[i] != '\0'; ++i) {
- if (rule->result[i] == '~') {
- realloc_strncat(result, rule->result + j, i - j);
- realloc_strncat(result,
- name + matches[0].rm_so,
- matches[0].rm_eo - matches[0].rm_so);
- j = i + 1;
- continue;
- }
- if (rule->result[i] != '\\')
- continue;
-
- ++i;
- c = rule->result[i];
- switch (c) {
- case '~':
- case '\\':
- realloc_strncat(result, rule->result + j, i - j - 1);
- j = i;
+ while (1) {
+ if (regexec(&rule->re, name, 10, matches, 0))
break;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- realloc_strncat(result, rule->result + j, i - j - 1);
- if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
- free(*result);
- *result = NULL;
- return -1;
+
+ got_match = 1;
+ print_match |= rule->print;
+ realloc_strncat(result, name, matches[0].rm_so);
+
+ for (i = 0, j = 0; rule->result[i] != '\0'; ++i) {
+ if (rule->result[i] == '~') {
+ realloc_strncat(result, rule->result + j, i - j);
+ realloc_strncat(result,
+ name + matches[0].rm_so,
+ matches[0].rm_eo - matches[0].rm_so);
+ j = i + 1;
+ continue;
+ }
+ if (rule->result[i] != '\\')
+ continue;
+
+ ++i;
+ c = rule->result[i];
+ switch (c) {
+ case '~':
+ case '\\':
+ realloc_strncat(result, rule->result + j, i - j - 1);
+ j = i;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ realloc_strncat(result, rule->result + j, i - j - 1);
+ if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
+ free(*result);
+ *result = NULL;
+ return -1;
+ }
+ realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so);
+ j = i + 1;
+ break;
+ default:
+ /* Just continue; */
+ break;
}
- realloc_strncat(result, name + matches[c - '0'].rm_so, matches[c - '0'].rm_eo - matches[c - '0'].rm_so);
- j = i + 1;
- break;
- default:
- /* Just continue; */
- break;
- }
- }
+ }
- realloc_strcat(result, rule->result + j);
+ realloc_strcat(result, rule->result + j);
- name += matches[0].rm_eo;
+ name += matches[0].rm_eo;
- if (!rule->global)
- break;
+ if (!rule->global)
+ break;
+ }
}
if (got_match)
diff --git a/tar/test/main.c b/tar/test/main.c
index bef18f25..33a6364b 100644
--- a/tar/test/main.c
+++ b/tar/test/main.c
@@ -132,11 +132,13 @@ __FBSDID("$FreeBSD: src/usr.bin/tar/test/main.c,v 1.6 2008/11/05 06:40:53 kientz
/* Path to working directory for current test */
const char *testworkdir;
+#ifdef PROGRAM
/* Pathname of exe to be tested. */
const char *testprogfile;
/* Name of exe to use in printf-formatted command strings. */
/* On Windows, this includes leading/trailing quotes. */
const char *testprog;
+#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
static void *GetFunctionKernel32(const char *);
@@ -573,10 +575,10 @@ static void strdump(const char *e, const char *p, int ewidth, int utf8)
while (*p != '\0') {
unsigned int c = 0xff & *p++;
switch (c) {
- case '\a': printf("\a"); break;
- case '\b': printf("\b"); break;
- case '\n': printf("\n"); break;
- case '\r': printf("\r"); break;
+ case '\a': logprintf("\\a"); break;
+ case '\b': logprintf("\\b"); break;
+ case '\n': logprintf("\\n"); break;
+ case '\r': logprintf("\\r"); break;
default:
if (c >= 32 && c < 127)
logprintf("%c", c);
@@ -1069,7 +1071,8 @@ assertion_file_contains_lines_any_order(const char *file, int line,
free(expected);
return (0);
}
- for (j = 0, p = buff; p < buff + buff_size; p += 1 + strlen(p)) {
+ for (j = 0, p = buff; p < buff + buff_size;
+ p += 1 + strlen(p)) {
if (*p != '\0') {
actual[j] = p;
++j;
@@ -1921,6 +1924,18 @@ canGzip(void)
* Can this platform run the lrzip program?
*/
int
+canRunCommand(const char *cmd)
+{
+ static int tested = 0, value = 0;
+ if (!tested) {
+ tested = 1;
+ if (systemf("%s %s", cmd, redirectArgs) == 0)
+ value = 1;
+ }
+ return (value);
+}
+
+int
canLrzip(void)
{
static int tested = 0, value = 0;
@@ -2159,8 +2174,31 @@ slurpfile(size_t * sizep, const char *fmt, ...)
return (p);
}
+/*
+ * Slurp a file into memory for ease of comparison and testing.
+ * Returns size of file in 'sizep' if non-NULL, null-terminates
+ * data in memory for ease of use.
+ */
+void
+dumpfile(const char *filename, void *data, size_t len)
+{
+ ssize_t bytes_written;
+ FILE *f;
+
+ f = fopen(filename, "wb");
+ if (f == NULL) {
+ logprintf("Can't open file %s for writing\n", filename);
+ return;
+ }
+ bytes_written = fwrite(data, 1, len, f);
+ if (bytes_written < (ssize_t)len)
+ logprintf("Can't write file %s\n", filename);
+ fclose(f);
+}
+
/* Read a uuencoded file from the reference directory, decode, and
* write the result into the current directory. */
+#define VALID_UUDECODE(c) (c >= 32 && c <= 96)
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
void
extract_reference_file(const char *name)
@@ -2184,7 +2222,6 @@ extract_reference_file(const char *name)
break;
}
/* Now, decode the rest and write it. */
- /* Not a lot of error checking here; the input better be right. */
out = fopen(name, "wb");
while (fgets(buff, sizeof(buff), in) != NULL) {
char *p = buff;
@@ -2198,17 +2235,21 @@ extract_reference_file(const char *name)
int n = 0;
/* Write out 1-3 bytes from that. */
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
+ assert(VALID_UUDECODE(p[1]));
n = UUDECODE(*p++) << 18;
n |= UUDECODE(*p++) << 12;
fputc(n >> 16, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++) << 6;
fputc((n >> 8) & 0xFF, out);
--bytes;
}
if (bytes > 0) {
+ assert(VALID_UUDECODE(p[0]));
n |= UUDECODE(*p++);
fputc(n & 0xFF, out);
--bytes;
@@ -2263,6 +2304,14 @@ is_LargeInode(const char *file)
return (ino > 0xffffffff);
#endif
}
+
+void
+extract_reference_files(const char **names)
+{
+ while (names && *names)
+ extract_reference_file(*names++);
+}
+
/*
*
* TEST management
@@ -2334,7 +2383,7 @@ test_run(int i, const char *tmpdir)
case VERBOSITY_SUMMARY_ONLY: /* No per-test reports at all */
break;
case VERBOSITY_PASSFAIL: /* rest of line will include ok/FAIL marker */
- printf("%3d: %-50s", i, tests[i].name);
+ printf("%3d: %-64s", i, tests[i].name);
fflush(stdout);
break;
default: /* Title of test, details will follow */
@@ -2527,6 +2576,7 @@ get_refdir(const char *d)
failure:
printf("Unable to locate known reference file %s\n", KNOWNREF);
printf(" Checked following directories:\n%s\n", tried);
+ printf("Use -r option to specify full path to reference directory\n");
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
DebugBreak();
#endif
@@ -2610,7 +2660,7 @@ main(int argc, char **argv)
exit(1);
}
memmove(testprogdir + strlen(pwd) + 1, testprogdir,
- strlen(testprogdir));
+ strlen(testprogdir) + 1);
memcpy(testprogdir, pwd, strlen(pwd));
testprogdir[strlen(pwd)] = '/';
}
diff --git a/tar/test/test.h b/tar/test/test.h
index 68473851..78f96792 100644
--- a/tar/test/test.h
+++ b/tar/test/test.h
@@ -92,7 +92,7 @@
#endif
/* Visual Studio */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf sprintf_s
#endif
@@ -278,6 +278,9 @@ int canGrzip(void);
/* Return true if this platform can run the "gzip" program. */
int canGzip(void);
+/* Return true if this platform can run the specified command. */
+int canRunCommand(const char *);
+
/* Return true if this platform can run the "lrzip" program. */
int canLrzip(void);
@@ -306,11 +309,19 @@ int is_LargeInode(const char *);
/* Supports printf-style args: slurpfile(NULL, "%s/myfile", refdir); */
char *slurpfile(size_t *, const char *fmt, ...);
+/* Dump block of bytes to a file. */
+void dumpfile(const char *filename, void *, size_t);
+
/* Extracts named reference file to the current directory. */
void extract_reference_file(const char *);
/* Copies named reference file to the current directory. */
void copy_reference_file(const char *);
+/* Extracts a list of files to the current directory.
+ * List must be NULL terminated.
+ */
+void extract_reference_files(const char **);
+
/* Path to working directory for current test */
extern const char *testworkdir;
diff --git a/tar/test/test_leading_slash.c b/tar/test/test_leading_slash.c
index 350aa4a7..52646d00 100644
--- a/tar/test/test_leading_slash.c
+++ b/tar/test/test_leading_slash.c
@@ -36,6 +36,10 @@ DEFINE_TEST(test_leading_slash)
assertTextFileContents("foo\x0a", "foo/hardlink");
assertIsHardlink("foo/file", "foo/hardlink");
assertEmptyFile("test.out");
+#ifdef _WIN32
+ assertTextFileContents("bsdtar.exe: Removing leading '/' from member names\x0a", "test.err");
+#else
assertTextFileContents("bsdtar: Removing leading '/' from member names\x0a", "test.err");
+#endif
}
diff --git a/tar/test/test_option_lz4.c b/tar/test/test_option_lz4.c
index e933eb4a..5dc94521 100644
--- a/tar/test/test_option_lz4.c
+++ b/tar/test/test_option_lz4.c
@@ -45,13 +45,25 @@ DEFINE_TEST(test_option_lz4)
"without lz4 support");
return;
}
- if (strstr(p, "Can't initialise filter") != NULL
- && !canLz4()) {
+ /* POSIX permits different handling of the spawnp
+ * system call used to launch the subsidiary
+ * program: */
+ /* Some systems fail immediately to spawn the new process. */
+ if (strstr(p, "Can't launch") != NULL && !canLz4()) {
skipping("This version of bsdtar uses an external lz4 program "
"but no such program is available on this system.");
return;
}
- failure("--lz4 option is broken");
+ /* Some systems successfully spawn the new process,
+ * but fail to exec a program within that process.
+ * This results in failure at the first attempt to
+ * write. */
+ if (strstr(p, "Can't write") != NULL && !canLz4()) {
+ skipping("This version of bsdtar uses an external lz4 program "
+ "but no such program is available on this system.");
+ return;
+ }
+ failure("--lz4 option is broken: %s", p);
assertEqualInt(r, 0);
return;
}
diff --git a/tar/test/test_option_s.c b/tar/test/test_option_s.c
index a1f8697e..ee8332f3 100644
--- a/tar/test/test_option_s.c
+++ b/tar/test/test_option_s.c
@@ -82,9 +82,9 @@ DEFINE_TEST(test_option_s)
*/
assertMakeDir("test4", 0755);
systemf("%s -cf test4.tar in/d1/foo in/d1/bar",
- testprog, testprog);
+ testprog);
systemf("%s -xf test4.tar -s /foo/bar/ -s }bar}baz} -C test4",
- testprog, testprog);
+ testprog);
assertFileContents("foo", 3, "test4/in/d1/bar");
assertFileContents("bar", 3, "test4/in/d1/baz");
@@ -258,4 +258,23 @@ DEFINE_TEST(test_option_s)
assertFileContents("foo", 3, "test13a/in/d1/hardlink2");
assertIsHardlink("test13a/in/d1/foo", "test13a/in/d1/hardlink2");
/* TODO: See above; expand this test to verify renames at creation. */
+
+ /*
+ * Test 14: Global substitutions when extracting archive.
+ */
+ /* Global substitution. */
+ assertMakeDir("test14", 0755);
+ systemf("%s -cf test14.tar in/d1/foo in/d1/bar",
+ testprog);
+ systemf("%s -xf test14.tar -s /o/z/g -s /bar/baz/ -C test14",
+ testprog);
+ assertFileContents("foo", 3, "test14/in/d1/fzz");
+ assertFileContents("bar", 3, "test14/in/d1/baz");
+ /* Singular substitution. */
+ systemf("%s -cf test14.tar in/d1/foo in/d1/bar",
+ testprog);
+ systemf("%s -xf test14.tar -s /o/z/ -s /bar/baz/ -C test14",
+ testprog);
+ assertFileContents("foo", 3, "test14/in/d1/fzo");
+ assertFileContents("bar", 3, "test14/in/d1/baz");
}
diff --git a/tar/util.c b/tar/util.c
index 203aa6f9..9ff22f2b 100644
--- a/tar/util.c
+++ b/tar/util.c
@@ -647,3 +647,103 @@ passphrase_free(char *ppbuff)
free(ppbuff);
}
}
+
+/*
+ * Display information about the current file.
+ *
+ * The format here roughly duplicates the output of 'ls -l'.
+ * This is based on SUSv2, where 'tar tv' is documented as
+ * listing additional information in an "unspecified format,"
+ * and 'pax -l' is documented as using the same format as 'ls -l'.
+ */
+void
+list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
+{
+ char tmp[100];
+ size_t w;
+ const char *p;
+ const char *fmt;
+ time_t tim;
+ static time_t now;
+
+ /*
+ * We avoid collecting the entire list in memory at once by
+ * listing things as we see them. However, that also means we can't
+ * just pre-compute the field widths. Instead, we start with guesses
+ * and just widen them as necessary. These numbers are completely
+ * arbitrary.
+ */
+ if (!bsdtar->u_width) {
+ bsdtar->u_width = 6;
+ bsdtar->gs_width = 13;
+ }
+ if (!now)
+ time(&now);
+ fprintf(out, "%s %d ",
+ archive_entry_strmode(entry),
+ archive_entry_nlink(entry));
+
+ /* Use uname if it's present, else uid. */
+ p = archive_entry_uname(entry);
+ if ((p == NULL) || (*p == '\0')) {
+ sprintf(tmp, "%lu ",
+ (unsigned long)archive_entry_uid(entry));
+ p = tmp;
+ }
+ w = strlen(p);
+ if (w > bsdtar->u_width)
+ bsdtar->u_width = w;
+ fprintf(out, "%-*s ", (int)bsdtar->u_width, p);
+
+ /* Use gname if it's present, else gid. */
+ p = archive_entry_gname(entry);
+ if (p != NULL && p[0] != '\0') {
+ fprintf(out, "%s", p);
+ w = strlen(p);
+ } else {
+ sprintf(tmp, "%lu",
+ (unsigned long)archive_entry_gid(entry));
+ w = strlen(tmp);
+ fprintf(out, "%s", tmp);
+ }
+
+ /*
+ * Print device number or file size, right-aligned so as to make
+ * total width of group and devnum/filesize fields be gs_width.
+ * If gs_width is too small, grow it.
+ */
+ if (archive_entry_filetype(entry) == AE_IFCHR
+ || archive_entry_filetype(entry) == AE_IFBLK) {
+ sprintf(tmp, "%lu,%lu",
+ (unsigned long)archive_entry_rdevmajor(entry),
+ (unsigned long)archive_entry_rdevminor(entry));
+ } else {
+ strcpy(tmp, tar_i64toa(archive_entry_size(entry)));
+ }
+ if (w + strlen(tmp) >= bsdtar->gs_width)
+ bsdtar->gs_width = w+strlen(tmp)+1;
+ fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp);
+
+ /* Format the time using 'ls -l' conventions. */
+ tim = archive_entry_mtime(entry);
+#define HALF_YEAR (time_t)365 * 86400 / 2
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */
+#else
+#define DAY_FMT "%e" /* Day number without leading zeros */
+#endif
+ if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
+ 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));
+ fprintf(out, " %s ", tmp);
+ safe_fprintf(out, "%s", archive_entry_pathname(entry));
+
+ /* Extra information for links. */
+ if (archive_entry_hardlink(entry)) /* Hard link */
+ safe_fprintf(out, " link to %s",
+ archive_entry_hardlink(entry));
+ else if (archive_entry_symlink(entry)) /* Symbolic link */
+ safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
+}
diff --git a/tar/write.c b/tar/write.c
index beaf98a0..53b63834 100644
--- a/tar/write.c
+++ b/tar/write.c
@@ -694,7 +694,10 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
if (bsdtar->option_interactive &&
!yes("copy '%s'", archive_entry_pathname(in_entry)))
continue;
- if (bsdtar->verbose)
+ if (bsdtar->verbose > 1) {
+ safe_fprintf(stderr, "a ");
+ list_item_verbose(bsdtar, stderr, in_entry);
+ } else if (bsdtar->verbose > 0)
safe_fprintf(stderr, "a %s",
archive_entry_pathname(in_entry));
if (need_report())
@@ -914,11 +917,15 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
if (edit_pathname(bsdtar, entry))
continue;
- /* Display entry as we process it.
- * This format is required by SUSv2. */
- if (bsdtar->verbose)
+ /* Display entry as we process it. */
+ if (bsdtar->verbose > 1) {
+ safe_fprintf(stderr, "a ");
+ list_item_verbose(bsdtar, stderr, entry);
+ } else if (bsdtar->verbose > 0) {
+ /* This format is required by SUSv2. */
safe_fprintf(stderr, "a %s",
archive_entry_pathname(entry));
+ }
/* Non-regular files get archived with zero size. */
if (archive_entry_filetype(entry) != AE_IFREG)
@@ -962,11 +969,15 @@ write_entry(struct bsdtar *bsdtar, struct archive *a,
e = archive_write_header(a, entry);
if (e != ARCHIVE_OK) {
- if (!bsdtar->verbose)
+ if (bsdtar->verbose > 1) {
+ safe_fprintf(stderr, "a ");
+ list_item_verbose(bsdtar, stderr, entry);
+ lafe_warnc(0, ": %s", archive_error_string(a));
+ } else if (bsdtar->verbose > 0) {
lafe_warnc(0, "%s: %s",
archive_entry_pathname(entry),
archive_error_string(a));
- else
+ } else
fprintf(stderr, ": %s", archive_error_string(a));
}