Kaynağa Gözat

LibArchive 2016-04-30 (167e97be)

Code extracted from:

    https://github.com/libarchive/libarchive.git

at commit 167e97be1d35c1e0947d768adbf94712244aad6b (master).
LibArchive Upstream 9 yıl önce
ebeveyn
işleme
501345e470
58 değiştirilmiş dosya ile 1001 ekleme ve 345 silme
  1. 51 9
      CMakeLists.txt
  2. 31 3
      build/cmake/config.h.in
  3. 1 1
      build/version
  4. 1 0
      libarchive/CMakeLists.txt
  5. 29 13
      libarchive/archive.h
  6. 19 3
      libarchive/archive_cryptor.c
  7. 19 1
      libarchive/archive_cryptor_private.h
  8. 7 1
      libarchive/archive_endian.h
  9. 7 2
      libarchive/archive_entry.h
  10. 4 0
      libarchive/archive_entry_copy_stat.c
  11. 5 5
      libarchive/archive_getdate.c
  12. 39 0
      libarchive/archive_getdate.h
  13. 16 2
      libarchive/archive_hmac.c
  14. 20 2
      libarchive/archive_hmac_private.h
  15. 1 1
      libarchive/archive_match.c
  16. 3 3
      libarchive/archive_options.c
  17. 27 27
      libarchive/archive_pack_dev.c
  18. 1 2
      libarchive/archive_pack_dev.h
  19. 15 0
      libarchive/archive_platform.h
  20. 12 9
      libarchive/archive_random.c
  21. 7 3
      libarchive/archive_read.c
  22. 25 5
      libarchive/archive_read_disk_entry_from_file.c
  23. 34 1
      libarchive/archive_read_disk_posix.c
  24. 6 0
      libarchive/archive_read_filter.3
  25. 7 3
      libarchive/archive_read_open_file.c
  26. 1 1
      libarchive/archive_read_open_filename.c
  27. 9 0
      libarchive/archive_read_support_filter_lz4.c
  28. 1 1
      libarchive/archive_read_support_format_7zip.c
  29. 1 1
      libarchive/archive_read_support_format_lha.c
  30. 41 32
      libarchive/archive_read_support_format_mtree.c
  31. 30 15
      libarchive/archive_read_support_format_rar.c
  32. 10 9
      libarchive/archive_read_support_format_warc.c
  33. 12 11
      libarchive/archive_read_support_format_xar.c
  34. 77 12
      libarchive/archive_read_support_format_zip.c
  35. 2 1
      libarchive/archive_string.c
  36. 61 15
      libarchive/archive_util.c
  37. 1 1
      libarchive/archive_write.c
  38. 1 1
      libarchive/archive_write_add_filter_bzip2.c
  39. 1 1
      libarchive/archive_write_add_filter_grzip.c
  40. 1 1
      libarchive/archive_write_add_filter_gzip.c
  41. 1 1
      libarchive/archive_write_add_filter_lrzip.c
  42. 93 32
      libarchive/archive_write_add_filter_lz4.c
  43. 2 2
      libarchive/archive_write_add_filter_lzop.c
  44. 9 7
      libarchive/archive_write_add_filter_program.c
  45. 6 0
      libarchive/archive_write_disk_posix.c
  46. 15 2
      libarchive/archive_write_filter.3
  47. 87 28
      libarchive/archive_write_format.3
  48. 1 1
      libarchive/archive_write_private.h
  49. 4 0
      libarchive/archive_write_set_format_7zip.c
  50. 5 5
      libarchive/archive_write_set_format_iso9660.c
  51. 1 1
      libarchive/archive_write_set_format_mtree.c
  52. 22 15
      libarchive/archive_write_set_format_pax.c
  53. 17 11
      libarchive/archive_write_set_format_warc.c
  54. 5 0
      libarchive/archive_write_set_format_xar.c
  55. 24 21
      libarchive/archive_write_set_format_zip.c
  56. 10 9
      libarchive/archive_write_set_options.3
  57. 46 9
      libarchive/libarchive-formats.5
  58. 17 3
      libarchive/xxhash.c

+ 51 - 9
CMakeLists.txt

@@ -15,7 +15,7 @@ endif()
 #   RelWithDebInfo : Release build with Debug Info
 #   RelWithDebInfo : Release build with Debug Info
 #   MinSizeRel     : Release Min Size build
 #   MinSizeRel     : Release Min Size build
 IF(NOT CMAKE_BUILD_TYPE)
 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)
 ENDIF(NOT CMAKE_BUILD_TYPE)
 # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
 # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
 # value type is "UNINITIALIZED".
 # value type is "UNINITIALIZED".
@@ -119,6 +119,20 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^Clang$")
   SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes")
   SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes")
   SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual")
   SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual")
 ENDIF (CMAKE_C_COMPILER_ID MATCHES "^Clang$")
 ENDIF (CMAKE_C_COMPILER_ID MATCHES "^Clang$")
+IF (CMAKE_C_COMPILER_ID MATCHES "^XL$")
+  SET(CMAKE_C_COMPILER "xlc_r")
+  SET(CMAKE_REQUIRED_FLAGS "-qflag=e:e -qformat=sec")
+  #################################################################
+  # Set compile flags for all build types.
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qflag=e:e -qformat=sec")
+  #################################################################
+  # Set compile flags for debug build.
+  # This is added into CMAKE_C_FLAGS when CMAKE_BUILD_TYPE is "Debug"
+  SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g")
+  SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qhalt=w")
+  SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qflag=w:w")
+  SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -qinfo=pro:use")
+ENDIF(CMAKE_C_COMPILER_ID MATCHES "^XL$")
 IF (MSVC)
 IF (MSVC)
   #################################################################
   #################################################################
   # Set compile flags for debug build.
   # Set compile flags for debug build.
@@ -190,7 +204,7 @@ OPTION(ENABLE_INSTALL "Enable installing of libraries" ON)
 
 
 SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
 SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
 SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
 SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
-SET(WINDOWS_VERSION "" CACHE STRING "Set Windows version to use (Windows only)")
+SET(WINDOWS_VERSION "WIN7" CACHE STRING "Set Windows version to use (Windows only)")
 
 
 IF(ENABLE_COVERAGE)
 IF(ENABLE_COVERAGE)
 	include(LibarchiveCodeCoverage)
 	include(LibarchiveCodeCoverage)
@@ -202,22 +216,35 @@ ENDIF(ENABLE_TEST)
 
 
 IF(WIN32)
 IF(WIN32)
   IF(WINDOWS_VERSION STREQUAL "WIN8")
   IF(WINDOWS_VERSION STREQUAL "WIN8")
+    SET(NTDDI_VERSION 0x06020000)
+    SET(_WIN32_WINNT 0x0602)
     SET(WINVER 0x0602)
     SET(WINVER 0x0602)
   ELSEIF(WINDOWS_VERSION STREQUAL "WIN7")
   ELSEIF(WINDOWS_VERSION STREQUAL "WIN7")
+    SET(NTDDI_VERSION 0x06010000)
+    SET(_WIN32_WINNT 0x0601)
     SET(WINVER 0x0601)
     SET(WINVER 0x0601)
   ELSEIF(WINDOWS_VERSION STREQUAL "WS08")
   ELSEIF(WINDOWS_VERSION STREQUAL "WS08")
+    SET(NTDDI_VERSION 0x06000100)
+    SET(_WIN32_WINNT 0x0600)
     SET(WINVER 0x0600)
     SET(WINVER 0x0600)
   ELSEIF(WINDOWS_VERSION STREQUAL "VISTA")
   ELSEIF(WINDOWS_VERSION STREQUAL "VISTA")
+    SET(NTDDI_VERSION 0x06000000)
+    SET(_WIN32_WINNT 0x0600)
     SET(WINVER 0x0600)
     SET(WINVER 0x0600)
   ELSEIF(WINDOWS_VERSION STREQUAL "WS03")
   ELSEIF(WINDOWS_VERSION STREQUAL "WS03")
+    SET(NTDDI_VERSION 0x05020000)
+    SET(_WIN32_WINNT 0x0502)
     SET(WINVER 0x0502)
     SET(WINVER 0x0502)
   ELSEIF(WINDOWS_VERSION STREQUAL "WINXP")
   ELSEIF(WINDOWS_VERSION STREQUAL "WINXP")
+    SET(NTDDI_VERSION 0x05010000)
+    SET(_WIN32_WINNT 0x0501)
     SET(WINVER 0x0501)
     SET(WINVER 0x0501)
   ELSE(WINDOWS_VERSION STREQUAL "WIN8")
   ELSE(WINDOWS_VERSION STREQUAL "WIN8")
-    # The default is to use Windows 2000 API.
-    SET(WINVER 0x0500)
+    # Default to Windows Server 2003 API if we don't recognize the specifier
+    SET(NTDDI_VERSION 0x05020000)
+    SET(_WIN32_WINNT 0x0502)
+    SET(WINVER 0x0502)
   ENDIF(WINDOWS_VERSION STREQUAL "WIN8")
   ENDIF(WINDOWS_VERSION STREQUAL "WIN8")
-  SET(_WIN32_WINNT ${WINVER})
 ENDIF(WIN32)
 ENDIF(WIN32)
 
 
 IF(MSVC)
 IF(MSVC)
@@ -613,12 +640,17 @@ IF(ENABLE_NETTLE)
   FIND_PACKAGE(Nettle)
   FIND_PACKAGE(Nettle)
   IF(NETTLE_FOUND)
   IF(NETTLE_FOUND)
     SET(HAVE_LIBNETTLE 1)
     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})
     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/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)
   ENDIF(NETTLE_FOUND)
   MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
   MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
   MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
   MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
@@ -632,6 +664,8 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
   FIND_PACKAGE(OpenSSL)
   FIND_PACKAGE(OpenSSL)
   IF(OPENSSL_FOUND)
   IF(OPENSSL_FOUND)
     SET(HAVE_LIBCRYPTO 1)
     SET(HAVE_LIBCRYPTO 1)
+    INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+    LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY})
   ENDIF(OPENSSL_FOUND)
   ENDIF(OPENSSL_FOUND)
 ELSE()
 ELSE()
   SET(OPENSSL_FOUND FALSE) # Override cached value
   SET(OPENSSL_FOUND FALSE) # Override cached value
@@ -850,6 +884,9 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
       SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
       SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
     ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
     ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
            CMAKE_C_COMPILER_ID MATCHES "^Clang$")
            CMAKE_C_COMPILER_ID MATCHES "^Clang$")
+    IF (CMAKE_C_COMPILER_ID MATCHES "^XL$")
+      SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -qhalt=w -qflag=w:w")
+    ENDIF (CMAKE_C_COMPILER_ID MATCHES "^XL$")
     IF (MSVC)
     IF (MSVC)
       # NOTE: /WX option is the same as gcc's -Werror option.
       # NOTE: /WX option is the same as gcc's -Werror option.
       SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
       SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX")
@@ -1279,10 +1316,15 @@ ENDIF(HAVE_INTTYPES_H)
 CHECK_SYMBOL_EXISTS(EFTYPE           "errno.h"    HAVE_EFTYPE)
 CHECK_SYMBOL_EXISTS(EFTYPE           "errno.h"    HAVE_EFTYPE)
 CHECK_SYMBOL_EXISTS(EILSEQ           "errno.h"    HAVE_EILSEQ)
 CHECK_SYMBOL_EXISTS(EILSEQ           "errno.h"    HAVE_EILSEQ)
 CHECK_SYMBOL_EXISTS(D_MD_ORDER       "langinfo.h" HAVE_D_MD_ORDER)
 CHECK_SYMBOL_EXISTS(D_MD_ORDER       "langinfo.h" HAVE_D_MD_ORDER)
+CHECK_SYMBOL_EXISTS(INT32_MAX        "${headers}" HAVE_DECL_INT32_MAX)
+CHECK_SYMBOL_EXISTS(INT32_MIN        "${headers}" HAVE_DECL_INT32_MIN)
 CHECK_SYMBOL_EXISTS(INT64_MAX        "${headers}" HAVE_DECL_INT64_MAX)
 CHECK_SYMBOL_EXISTS(INT64_MAX        "${headers}" HAVE_DECL_INT64_MAX)
 CHECK_SYMBOL_EXISTS(INT64_MIN        "${headers}" HAVE_DECL_INT64_MIN)
 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(UINT32_MAX       "${headers}" HAVE_DECL_UINT32_MAX)
 CHECK_SYMBOL_EXISTS(UINT64_MAX       "${headers}" HAVE_DECL_UINT64_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(SIZE_MAX         "${headers}" HAVE_DECL_SIZE_MAX)
 CHECK_SYMBOL_EXISTS(SSIZE_MAX        "limits.h"   HAVE_DECL_SSIZE_MAX)
 CHECK_SYMBOL_EXISTS(SSIZE_MAX        "limits.h"   HAVE_DECL_SSIZE_MAX)
 
 

+ 31 - 3
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. */
 /* Define intmax_t and uintmax_t if they are not already defined. */
 #if !defined(HAVE_INTMAX_T)
 #if !defined(HAVE_INTMAX_T)
 typedef int64_t intmax_t;
 typedef int64_t intmax_t;
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
 #endif
 #endif
 
 
 #if !defined(HAVE_UINTMAX_T)
 #if !defined(HAVE_UINTMAX_T)
@@ -364,6 +362,14 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the `cygwin_conv_path' function. */
 /* Define to 1 if you have the `cygwin_conv_path' function. */
 #cmakedefine HAVE_CYGWIN_CONV_PATH 1
 #cmakedefine HAVE_CYGWIN_CONV_PATH 1
 
 
+/* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you
+   don't. */
+#cmakedefine HAVE_DECL_INT32_MAX 1
+
+/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you
+   don't. */
+#cmakedefine HAVE_DECL_INT32_MIN 1
+
 /* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
 /* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you
    don't. */
    don't. */
 #cmakedefine HAVE_DECL_INT64_MAX 1
 #cmakedefine HAVE_DECL_INT64_MAX 1
@@ -372,6 +378,14 @@ typedef uint64_t uintmax_t;
    don't. */
    don't. */
 #cmakedefine HAVE_DECL_INT64_MIN 1
 #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
 /* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you
    don't. */
    don't. */
 #cmakedefine HAVE_DECL_SIZE_MAX 1
 #cmakedefine HAVE_DECL_SIZE_MAX 1
@@ -392,6 +406,10 @@ typedef uint64_t uintmax_t;
    don't. */
    don't. */
 #cmakedefine HAVE_DECL_UINT64_MAX 1
 #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. */
 /* Define to 1 if you have the <direct.h> header file. */
 #cmakedefine HAVE_DIRECT_H 1
 #cmakedefine HAVE_DIRECT_H 1
 
 
@@ -733,6 +751,12 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
 /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
 #cmakedefine HAVE_NDIR_H 1
 #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. */
 /* Define to 1 if you have the <nettle/md5.h> header file. */
 #cmakedefine HAVE_NETTLE_MD5_H 1
 #cmakedefine HAVE_NETTLE_MD5_H 1
 
 
@@ -1147,7 +1171,11 @@ typedef uint64_t uintmax_t;
 /* Define for large files, on AIX-style hosts. */
 /* Define for large files, on AIX-style hosts. */
 #cmakedefine _LARGE_FILES ${_LARGE_FILES}
 #cmakedefine _LARGE_FILES ${_LARGE_FILES}
 
 
-/* Define for Windows to use Windows 2000+ APIs. */
+/* Define to control Windows SDK version */
+#ifndef NTDDI_VERSION
+#cmakedefine NTDDI_VERSION ${NTDDI_VERSION}
+#endif // NTDDI_VERSION
+
 #ifndef _WIN32_WINNT
 #ifndef _WIN32_WINNT
 #cmakedefine _WIN32_WINNT ${_WIN32_WINNT}
 #cmakedefine _WIN32_WINNT ${_WIN32_WINNT}
 #endif // _WIN32_WINNT
 #endif // _WIN32_WINNT

+ 1 - 1
build/version

@@ -1 +1 @@
-3001002
+3002000

+ 1 - 0
libarchive/CMakeLists.txt

@@ -34,6 +34,7 @@ SET(libarchive_SOURCES
   archive_entry_strmode.c
   archive_entry_strmode.c
   archive_entry_xattr.c
   archive_entry_xattr.c
   archive_getdate.c
   archive_getdate.c
+  archive_getdate.h
   archive_hmac.c
   archive_hmac.c
   archive_hmac_private.h
   archive_hmac_private.h
   archive_match.c
   archive_match.c

+ 29 - 13
libarchive/archive.h

@@ -28,9 +28,20 @@
 #ifndef ARCHIVE_H_INCLUDED
 #ifndef ARCHIVE_H_INCLUDED
 #define	ARCHIVE_H_INCLUDED
 #define	ARCHIVE_H_INCLUDED
 
 
+/*
+ * The version number is expressed as a single integer that makes it
+ * easy to compare versions at build time: for version a.b.c, the
+ * version number is printf("%d%03d%03d",a,b,c).  For example, if you
+ * know your application requires version 2.12.108 or later, you can
+ * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
+ */
+/* Note: Compiler will complain if this does not match archive_entry.h! */
+#define	ARCHIVE_VERSION_NUMBER 3002000
+
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <stddef.h>  /* for wchar_t */
 #include <stddef.h>  /* for wchar_t */
 #include <stdio.h> /* For FILE * */
 #include <stdio.h> /* For FILE * */
+#include <time.h> /* For time_t */
 
 
 /*
 /*
  * Note: archive.h is for use outside of libarchive; the configuration
  * Note: archive.h is for use outside of libarchive; the configuration
@@ -41,7 +52,7 @@
  */
  */
 #if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
 #if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
 # include <stdint.h>
 # include <stdint.h>
-#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS)
+#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__)
 # include <inttypes.h>
 # include <inttypes.h>
 #endif
 #endif
 
 
@@ -56,7 +67,7 @@
 typedef __int64 la_int64_t;
 typedef __int64 la_int64_t;
 # else
 # else
 # include <unistd.h>  /* ssize_t */
 # include <unistd.h>  /* ssize_t */
-#  if defined(_SCO_DS)
+#  if defined(_SCO_DS) || defined(__osf__)
 typedef long long la_int64_t;
 typedef long long la_int64_t;
 #  else
 #  else
 typedef int64_t la_int64_t;
 typedef int64_t la_int64_t;
@@ -85,6 +96,11 @@ typedef ssize_t la_ssize_t;
 # endif
 # endif
 #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
  * On Windows, define LIBARCHIVE_STATIC if you're building or using a
  * .lib.  The default here assumes you're building a DLL.  Only
  * .lib.  The default here assumes you're building a DLL.  Only
@@ -134,22 +150,12 @@ extern "C" {
  * header and library are very different, you should expect some
  * header and library are very different, you should expect some
  * strangeness.  Don't do that.
  * strangeness.  Don't do that.
  */
  */
-
-/*
- * The version number is expressed as a single integer that makes it
- * easy to compare versions at build time: for version a.b.c, the
- * version number is printf("%d%03d%03d",a,b,c).  For example, if you
- * know your application requires version 2.12.108 or later, you can
- * assert that ARCHIVE_VERSION_NUMBER >= 2012108.
- */
-/* Note: Compiler will complain if this does not match archive_entry.h! */
-#define	ARCHIVE_VERSION_NUMBER 3001002
 __LA_DECL int		archive_version_number(void);
 __LA_DECL int		archive_version_number(void);
 
 
 /*
 /*
  * Textual name/version of the library, useful for version displays.
  * Textual name/version of the library, useful for version displays.
  */
  */
-#define	ARCHIVE_VERSION_ONLY_STRING "3.1.2"
+#define	ARCHIVE_VERSION_ONLY_STRING "3.2.0"
 #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 #define	ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
 __LA_DECL const char *	archive_version_string(void);
 __LA_DECL const char *	archive_version_string(void);
 
 
@@ -162,6 +168,16 @@ __LA_DECL const char *	archive_version_string(void);
  */
  */
 __LA_DECL const char *	archive_version_details(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. */
 /* Declare our basic types. */
 struct archive;
 struct archive;
 struct archive_entry;
 struct archive_entry;

+ 19 - 3
libarchive/archive_cryptor.c

@@ -31,7 +31,20 @@
 #include "archive.h"
 #include "archive.h"
 #include "archive_cryptor_private.h"
 #include "archive_cryptor_private.h"
 
 
-#ifdef __APPLE__
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * this file will normally define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_cryptor_build_hack(void) {
+	return 0;
+}
+
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
 
 
 static int
 static int
 pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
 pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
@@ -114,7 +127,10 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
 
 
 #endif
 #endif
 
 
-#ifdef __APPLE__
+#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
+# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
+#  define kCCAlgorithmAES kCCAlgorithmAES128
+# endif
 
 
 static int
 static int
 aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
 aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
@@ -253,7 +269,7 @@ aes_ctr_release(archive_crypto_ctx *ctx)
 	return 0;
 	return 0;
 }
 }
 
 
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
 
 
 static int
 static int
 aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
 aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)

+ 19 - 1
libarchive/archive_cryptor_private.h

@@ -30,7 +30,25 @@
 #ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
 #ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
 #define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
 #define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED
 
 
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * the archive_cryptor.c file will normally define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_cryptor_build_hack(void);
+
 #ifdef __APPLE__
 #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/CommonCryptor.h>
 #include <CommonCrypto/CommonKeyDerivation.h>
 #include <CommonCrypto/CommonKeyDerivation.h>
 #define AES_BLOCK_SIZE	16
 #define AES_BLOCK_SIZE	16
@@ -65,7 +83,7 @@ typedef struct {
 	unsigned	encr_pos;
 	unsigned	encr_pos;
 } archive_crypto_ctx;
 } archive_crypto_ctx;
 
 
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
 #if defined(HAVE_NETTLE_PBKDF2_H)
 #if defined(HAVE_NETTLE_PBKDF2_H)
 #include <nettle/pbkdf2.h>
 #include <nettle/pbkdf2.h>
 #endif
 #endif

+ 7 - 1
libarchive/archive_endian.h

@@ -44,10 +44,16 @@
  * - Watcom C++ in C code.  (For any version?)
  * - Watcom C++ in C code.  (For any version?)
  * - SGI MIPSpro
  * - SGI MIPSpro
  * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
  * - Microsoft Visual C++ 6.0 (supposedly newer versions too)
+ * - IBM VisualAge 6 (XL v6)
+ * - Sun WorkShop C (SunPro) before 5.9
  */
  */
 #if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
 #if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
 #define	inline
 #define	inline
-#elif defined(_MSC_VER)
+#elif defined(__IBMC__) && __IBMC__ < 700
+#define	inline
+#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590
+#define inline
+#elif defined(_MSC_VER) || defined(__osf__)
 #define inline __inline
 #define inline __inline
 #endif
 #endif
 
 

+ 7 - 2
libarchive/archive_entry.h

@@ -29,7 +29,7 @@
 #define	ARCHIVE_ENTRY_H_INCLUDED
 #define	ARCHIVE_ENTRY_H_INCLUDED
 
 
 /* Note: Compiler will complain if this does not match archive.h! */
 /* Note: Compiler will complain if this does not match archive.h! */
-#define	ARCHIVE_VERSION_NUMBER 3001002
+#define	ARCHIVE_VERSION_NUMBER 3002000
 
 
 /*
 /*
  * Note: archive_entry.h is for use outside of libarchive; the
  * Note: archive_entry.h is for use outside of libarchive; the
@@ -57,7 +57,7 @@
 typedef __int64 la_int64_t;
 typedef __int64 la_int64_t;
 # else
 # else
 #include <unistd.h>
 #include <unistd.h>
-#  if defined(_SCO_DS)
+#  if defined(_SCO_DS) || defined(__osf__)
 typedef long long la_int64_t;
 typedef long long la_int64_t;
 #  else
 #  else
 typedef int64_t la_int64_t;
 typedef int64_t la_int64_t;
@@ -75,6 +75,11 @@ typedef int64_t la_int64_t;
 # define	__LA_MODE_T	mode_t
 # define	__LA_MODE_T	mode_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
  * On Windows, define LIBARCHIVE_STATIC if you're building or using a
  * .lib.  The default here assumes you're building a DLL.  Only
  * .lib.  The default here assumes you're building a DLL.  Only

+ 4 - 0
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_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_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
 	archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.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
 #elif HAVE_STRUCT_STAT_ST_MTIME_N
 	archive_entry_set_atime(entry, st->st_atime, st->st_atime_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);
 	archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);

+ 5 - 5
libarchive/archive_getdate.c

@@ -38,8 +38,8 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <string.h>
 #include <time.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. */
 /* Basic time units. */
 #define	EPOCH		1970
 #define	EPOCH		1970
@@ -782,7 +782,7 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
  * Tokenizer.
  * Tokenizer.
  */
  */
 static int
 static int
-nexttoken(char **in, time_t *value)
+nexttoken(const char **in, time_t *value)
 {
 {
 	char	c;
 	char	c;
 	char	buff[64];
 	char	buff[64];
@@ -809,7 +809,7 @@ nexttoken(char **in, time_t *value)
 		/* Try the next token in the word table first. */
 		/* Try the next token in the word table first. */
 		/* This allows us to match "2nd", for example. */
 		/* This allows us to match "2nd", for example. */
 		{
 		{
-			char *src = *in;
+			const char *src = *in;
 			const struct LEXICON *tp;
 			const struct LEXICON *tp;
 			unsigned i = 0;
 			unsigned i = 0;
 
 
@@ -894,7 +894,7 @@ difftm (struct tm *a, struct tm *b)
  * TODO: tokens[] array should be dynamically sized.
  * TODO: tokens[] array should be dynamically sized.
  */
  */
 time_t
 time_t
-__archive_get_date(time_t now, char *p)
+__archive_get_date(time_t now, const char *p)
 {
 {
 	struct token	tokens[256];
 	struct token	tokens[256];
 	struct gdstate	_gds;
 	struct gdstate	_gds;

+ 39 - 0
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

+ 16 - 2
libarchive/archive_hmac.c

@@ -31,7 +31,21 @@
 #include "archive.h"
 #include "archive.h"
 #include "archive_hmac_private.h"
 #include "archive_hmac_private.h"
 
 
-#ifdef __APPLE__
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * the archive_hmac.c file is expected to define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_hmac_build_hack(void) {
+	return 0;
+}
+
+
+#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
 
 
 static int
 static int
 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
@@ -129,7 +143,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
 	}
 	}
 }
 }
 
 
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
 
 
 static int
 static int
 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)

+ 20 - 2
libarchive/archive_hmac_private.h

@@ -30,12 +30,30 @@
 #ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED
 #ifndef ARCHIVE_HMAC_PRIVATE_H_INCLUDED
 #define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
 #define ARCHIVE_HMAC_PRIVATE_H_INCLUDED
 
 
+/*
+ * On systems that do not support any recognized crypto libraries,
+ * the archive_hmac.c file is expected to define no usable symbols.
+ *
+ * But some compilers and linkers choke on empty object files, so
+ * define a public symbol that will always exist.  This could
+ * be removed someday if this file gains another always-present
+ * symbol definition.
+ */
+int __libarchive_hmac_build_hack(void);
+
 #ifdef __APPLE__
 #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>
 #include <CommonCrypto/CommonHMAC.h>
 
 
 typedef	CCHmacContext archive_hmac_sha1_ctx;
 typedef	CCHmacContext archive_hmac_sha1_ctx;
 
 
-#elif defined(_WIN32) && !defined(__CYGWIN__)
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
 #include <bcrypt.h>
 #include <bcrypt.h>
 
 
 typedef struct {
 typedef struct {
@@ -46,7 +64,7 @@ typedef struct {
 
 
 } archive_hmac_sha1_ctx;
 } archive_hmac_sha1_ctx;
 
 
-#elif defined(HAVE_LIBNETTLE)
+#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
 #include <nettle/hmac.h>
 #include <nettle/hmac.h>
 
 
 typedef	struct hmac_sha1_ctx archive_hmac_sha1_ctx;
 typedef	struct hmac_sha1_ctx archive_hmac_sha1_ctx;

+ 1 - 1
libarchive/archive_match.c

@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include "archive.h"
 #include "archive.h"
 #include "archive_private.h"
 #include "archive_private.h"
 #include "archive_entry.h"
 #include "archive_entry.h"
+#include "archive_getdate.h"
 #include "archive_pathmatch.h"
 #include "archive_pathmatch.h"
 #include "archive_rb.h"
 #include "archive_rb.h"
 #include "archive_string.h"
 #include "archive_string.h"
@@ -184,7 +185,6 @@ static int	time_excluded(struct archive_match *,
 		    struct archive_entry *);
 		    struct archive_entry *);
 static int	validate_time_flag(struct archive *, int, const char *);
 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
 #define get_date __archive_get_date
 
 
 static const struct archive_rb_tree_ops rb_ops_mbs = {
 static const struct archive_rb_tree_ops rb_ops_mbs = {

+ 3 - 3
libarchive/archive_options.c

@@ -42,9 +42,9 @@ _archive_set_option(struct archive *a,
 
 
 	archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
 	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)
 	if (op == NULL && vp == NULL)
 		return (ARCHIVE_OK);
 		return (ARCHIVE_OK);

+ 27 - 27
libarchive/archive_pack_dev.c

@@ -103,15 +103,15 @@ static const char tooManyFields[] = "too many fields for format";
 
 
 /* exported */
 /* exported */
 dev_t
 dev_t
-pack_native(int n, u_long numbers[], const char **error)
+pack_native(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = apd_makedev(numbers[0], numbers[1]);
 		dev = apd_makedev(numbers[0], numbers[1]);
-		if ((u_long)major(dev) != numbers[0])
+		if ((unsigned long)major(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		else if ((u_long)minor(dev) != numbers[1])
+		else if ((unsigned long)minor(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -120,15 +120,15 @@ pack_native(int n, u_long numbers[], const char **error)
 
 
 
 
 static dev_t
 static dev_t
-pack_netbsd(int n, u_long numbers[], const char **error)
+pack_netbsd(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_netbsd(numbers[0], numbers[1]);
 		dev = makedev_netbsd(numbers[0], numbers[1]);
-		if ((u_long)major_netbsd(dev) != numbers[0])
+		if ((unsigned long)major_netbsd(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		else if ((u_long)minor_netbsd(dev) != numbers[1])
+		else if ((unsigned long)minor_netbsd(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -142,15 +142,15 @@ pack_netbsd(int n, u_long numbers[], const char **error)
 					 (((y) << 0) & 0xffff00ff)))
 					 (((y) << 0) & 0xffff00ff)))
 
 
 static dev_t
 static dev_t
-pack_freebsd(int n, u_long numbers[], const char **error)
+pack_freebsd(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_freebsd(numbers[0], numbers[1]);
 		dev = makedev_freebsd(numbers[0], numbers[1]);
-		if ((u_long)major_freebsd(dev) != numbers[0])
+		if ((unsigned long)major_freebsd(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)minor_freebsd(dev) != numbers[1])
+		if ((unsigned long)minor_freebsd(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -164,15 +164,15 @@ pack_freebsd(int n, u_long numbers[], const char **error)
 					 (((y) << 0) & 0x000000ff)))
 					 (((y) << 0) & 0x000000ff)))
 
 
 static dev_t
 static dev_t
-pack_8_8(int n, u_long numbers[], const char **error)
+pack_8_8(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_8_8(numbers[0], numbers[1]);
 		dev = makedev_8_8(numbers[0], numbers[1]);
-		if ((u_long)major_8_8(dev) != numbers[0])
+		if ((unsigned long)major_8_8(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)minor_8_8(dev) != numbers[1])
+		if ((unsigned long)minor_8_8(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -186,15 +186,15 @@ pack_8_8(int n, u_long numbers[], const char **error)
 					 (((y) <<  0) & 0x000fffff)))
 					 (((y) <<  0) & 0x000fffff)))
 
 
 static dev_t
 static dev_t
-pack_12_20(int n, u_long numbers[], const char **error)
+pack_12_20(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_12_20(numbers[0], numbers[1]);
 		dev = makedev_12_20(numbers[0], numbers[1]);
-		if ((u_long)major_12_20(dev) != numbers[0])
+		if ((unsigned long)major_12_20(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)minor_12_20(dev) != numbers[1])
+		if ((unsigned long)minor_12_20(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -208,15 +208,15 @@ pack_12_20(int n, u_long numbers[], const char **error)
 					 (((y) <<  0) & 0x0003ffff)))
 					 (((y) <<  0) & 0x0003ffff)))
 
 
 static dev_t
 static dev_t
-pack_14_18(int n, u_long numbers[], const char **error)
+pack_14_18(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_14_18(numbers[0], numbers[1]);
 		dev = makedev_14_18(numbers[0], numbers[1]);
-		if ((u_long)major_14_18(dev) != numbers[0])
+		if ((unsigned long)major_14_18(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)minor_14_18(dev) != numbers[1])
+		if ((unsigned long)minor_14_18(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -230,15 +230,15 @@ pack_14_18(int n, u_long numbers[], const char **error)
 					 (((y) <<  0) & 0x00ffffff)))
 					 (((y) <<  0) & 0x00ffffff)))
 
 
 static dev_t
 static dev_t
-pack_8_24(int n, u_long numbers[], const char **error)
+pack_8_24(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_8_24(numbers[0], numbers[1]);
 		dev = makedev_8_24(numbers[0], numbers[1]);
-		if ((u_long)major_8_24(dev) != numbers[0])
+		if ((unsigned long)major_8_24(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)minor_8_24(dev) != numbers[1])
+		if ((unsigned long)minor_8_24(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;
@@ -254,23 +254,23 @@ pack_8_24(int n, u_long numbers[], const char **error)
 					 (((z) <<  0) & 0x000000ff)))
 					 (((z) <<  0) & 0x000000ff)))
 
 
 static dev_t
 static dev_t
-pack_bsdos(int n, u_long numbers[], const char **error)
+pack_bsdos(int n, unsigned long numbers[], const char **error)
 {
 {
 	dev_t dev = 0;
 	dev_t dev = 0;
 
 
 	if (n == 2) {
 	if (n == 2) {
 		dev = makedev_12_20(numbers[0], numbers[1]);
 		dev = makedev_12_20(numbers[0], numbers[1]);
-		if ((u_long)major_12_20(dev) != numbers[0])
+		if ((unsigned long)major_12_20(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)minor_12_20(dev) != numbers[1])
+		if ((unsigned long)minor_12_20(dev) != numbers[1])
 			*error = iMinorError;
 			*error = iMinorError;
 	} else if (n == 3) {
 	} else if (n == 3) {
 		dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
 		dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
-		if ((u_long)major_12_12_8(dev) != numbers[0])
+		if ((unsigned long)major_12_12_8(dev) != numbers[0])
 			*error = iMajorError;
 			*error = iMajorError;
-		if ((u_long)unit_12_12_8(dev) != numbers[1])
+		if ((unsigned long)unit_12_12_8(dev) != numbers[1])
 			*error = "invalid unit number";
 			*error = "invalid unit number";
-		if ((u_long)subunit_12_12_8(dev) != numbers[2])
+		if ((unsigned long)subunit_12_12_8(dev) != numbers[2])
 			*error = "invalid subunit number";
 			*error = "invalid subunit number";
 	} else
 	} else
 		*error = tooManyFields;
 		*error = tooManyFields;

+ 1 - 2
libarchive/archive_pack_dev.h

@@ -34,8 +34,7 @@
 #ifndef	_PACK_DEV_H
 #ifndef	_PACK_DEV_H
 #define	_PACK_DEV_H
 #define	_PACK_DEV_H
 
 
-typedef	dev_t pack_t(int, u_long [], const char **);
-typedef unsigned long u_long;
+typedef	dev_t pack_t(int, unsigned long [], const char **);
 
 
 pack_t	*pack_find(const char *);
 pack_t	*pack_find(const char *);
 pack_t	 pack_native;
 pack_t	 pack_native;

+ 15 - 0
libarchive/archive_platform.h

@@ -117,6 +117,12 @@
 #if !HAVE_DECL_UINT32_MAX
 #if !HAVE_DECL_UINT32_MAX
 #define	UINT32_MAX (~(uint32_t)0)
 #define	UINT32_MAX (~(uint32_t)0)
 #endif
 #endif
+#if !HAVE_DECL_INT32_MAX
+#define	INT32_MAX ((int32_t)(UINT32_MAX >> 1))
+#endif
+#if !HAVE_DECL_INT32_MIN
+#define	INT32_MIN ((int32_t)(~INT32_MAX))
+#endif
 #if !HAVE_DECL_UINT64_MAX
 #if !HAVE_DECL_UINT64_MAX
 #define	UINT64_MAX (~(uint64_t)0)
 #define	UINT64_MAX (~(uint64_t)0)
 #endif
 #endif
@@ -126,6 +132,15 @@
 #if !HAVE_DECL_INT64_MIN
 #if !HAVE_DECL_INT64_MIN
 #define	INT64_MIN ((int64_t)(~INT64_MAX))
 #define	INT64_MIN ((int64_t)(~INT64_MAX))
 #endif
 #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(),
  * If this platform has <sys/acl.h>, acl_create(), acl_init(),

+ 12 - 9
libarchive/archive_random.c

@@ -62,6 +62,10 @@ static void arc4random_buf(void *, size_t);
 #include <wincrypt.h>
 #include <wincrypt.h>
 #endif
 #endif
 
 
+#ifndef O_CLOEXEC
+#define O_CLOEXEC	0
+#endif
+
 /*
 /*
  * Random number generator function.
  * Random number generator function.
  * This simply calls arc4random_buf function if the platform provides it.
  * This simply calls arc4random_buf function if the platform provides it.
@@ -133,16 +137,15 @@ archive_random(void *buf, size_t nbytes)
 #endif				/* !__GNUC__ */
 #endif				/* !__GNUC__ */
 
 
 struct arc4_stream {
 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	RANDOMDEV	"/dev/urandom"
 #define	KEYSIZE		128
 #define	KEYSIZE		128
 #ifdef HAVE_PTHREAD_H
 #ifdef HAVE_PTHREAD_H
+static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
 #define	_ARC4_LOCK()	pthread_mutex_lock(&arc4random_mtx);
 #define	_ARC4_LOCK()	pthread_mutex_lock(&arc4random_mtx);
 #define	_ARC4_UNLOCK()  pthread_mutex_unlock(&arc4random_mtx);
 #define	_ARC4_UNLOCK()  pthread_mutex_unlock(&arc4random_mtx);
 #else
 #else
@@ -155,7 +158,7 @@ static struct arc4_stream rs;
 static pid_t arc4_stir_pid;
 static pid_t arc4_stir_pid;
 static int arc4_count;
 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 void arc4_stir(void);
 
 
 static inline void
 static inline void
@@ -173,7 +176,7 @@ static inline void
 arc4_addrandom(u_char *dat, int datlen)
 arc4_addrandom(u_char *dat, int datlen)
 {
 {
 	int     n;
 	int     n;
-	u_int8_t si;
+	uint8_t si;
 
 
 	rs.i--;
 	rs.i--;
 	for (n = 0; n < 256; n++) {
 	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)
 arc4_getbyte(void)
 {
 {
-	u_int8_t si, sj;
+	uint8_t si, sj;
 
 
 	rs.i = (rs.i + 1);
 	rs.i = (rs.i + 1);
 	si = rs.s[rs.i];
 	si = rs.s[rs.i];

+ 7 - 3
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
  * it wants to handle this stream.  Repeat until we've finished
  * building the pipeline.
  * building the pipeline.
  */
  */
+
+/* We won't build a filter pipeline with more stages than this. */
+#define MAX_NUMBER_FILTERS 25
+
 static int
 static int
 choose_filters(struct archive_read *a)
 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_bidder *bidder, *best_bidder;
 	struct archive_read_filter *filter;
 	struct archive_read_filter *filter;
 	ssize_t avail;
 	ssize_t avail;
 	int r;
 	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]);
 		number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]);
 
 
 		best_bid = 0;
 		best_bid = 0;
@@ -1157,7 +1161,7 @@ static const char *
 _archive_filter_name(struct archive *_a, int n)
 _archive_filter_name(struct archive *_a, int n)
 {
 {
 	struct archive_read_filter *f = get_filter(_a, 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
 static int64_t

+ 25 - 5
libarchive/archive_read_disk_entry_from_file.c

@@ -1046,7 +1046,7 @@ setup_sparse(struct archive_read_disk *a,
 	struct fiemap *fm;
 	struct fiemap *fm;
 	struct fiemap_extent *fe;
 	struct fiemap_extent *fe;
 	int64_t size;
 	int64_t size;
-	int count, do_fiemap;
+	int count, do_fiemap, iters;
 	int exit_sts = ARCHIVE_OK;
 	int exit_sts = ARCHIVE_OK;
 
 
 	if (archive_entry_filetype(entry) != AE_IFREG
 	if (archive_entry_filetype(entry) != AE_IFREG
@@ -1083,7 +1083,7 @@ setup_sparse(struct archive_read_disk *a,
 	fm->fm_extent_count = count;
 	fm->fm_extent_count = count;
 	do_fiemap = 1;
 	do_fiemap = 1;
 	size = archive_entry_size(entry);
 	size = archive_entry_size(entry);
-	for (;;) {
+	for (iters = 0; ; ++iters) {
 		int i, r;
 		int i, r;
 
 
 		r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
 		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. */
 			 * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
 			goto exit_setup_sparse;
 			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;
 			break;
+		}
 		fe = fm->fm_extents;
 		fe = fm->fm_extents;
 		for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
 		for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
 			if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
 			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 initial_off; /* FreeBSD/Solaris only, so off_t okay here */
 	off_t off_s, off_e; /* 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 exit_sts = ARCHIVE_OK;
+	int check_fully_sparse = 0;
 
 
 	if (archive_entry_filetype(entry) != AE_IFREG
 	if (archive_entry_filetype(entry) != AE_IFREG
 	    || archive_entry_size(entry) <= 0
 	    || archive_entry_size(entry) <= 0
@@ -1191,8 +1197,14 @@ setup_sparse(struct archive_read_disk *a,
 	while (off_s < size) {
 	while (off_s < size) {
 		off_s = lseek(*fd, off_s, SEEK_DATA);
 		off_s = lseek(*fd, off_s, SEEK_DATA);
 		if (off_s == (off_t)-1) {
 		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,
 			archive_set_error(&a->archive, errno,
 			    "lseek(SEEK_HOLE) failed");
 			    "lseek(SEEK_HOLE) failed");
 			exit_sts = ARCHIVE_FAILED;
 			exit_sts = ARCHIVE_FAILED;
@@ -1216,6 +1228,14 @@ setup_sparse(struct archive_read_disk *a,
 			off_e - off_s);
 			off_e - off_s);
 		off_s = off_e;
 		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:
 exit_setup_sparse:
 	lseek(*fd, initial_off, SEEK_SET);
 	lseek(*fd, initial_off, SEEK_SET);
 	return (exit_sts);
 	return (exit_sts);

+ 34 - 1
libarchive/archive_read_disk_posix.c

@@ -717,6 +717,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
 	int r;
 	int r;
 	ssize_t bytes;
 	ssize_t bytes;
 	size_t buffbytes;
 	size_t buffbytes;
+	int empty_sparse_region = 0;
 
 
 	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
 	archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_DATA,
 	    "archive_read_data_block");
 	    "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)
 	if ((int64_t)buffbytes > t->current_sparse->length)
 		buffbytes = t->current_sparse->length;
 		buffbytes = t->current_sparse->length;
 
 
+	if (t->current_sparse->length == 0)
+		empty_sparse_region = 1;
+
 	/*
 	/*
 	 * Skip hole.
 	 * Skip hole.
 	 * TODO: Should we consider t->current_filesystem->xfer_align?
 	 * TODO: Should we consider t->current_filesystem->xfer_align?
@@ -828,7 +832,11 @@ _archive_read_data_block(struct archive *_a, const void **buff,
 		}
 		}
 	} else
 	} else
 		bytes = 0;
 		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.
+	*/
+	if (bytes == 0 && !empty_sparse_region) {
 		/* Get EOF */
 		/* Get EOF */
 		t->entry_eof = 1;
 		t->entry_eof = 1;
 		r = ARCHIVE_EOF;
 		r = ARCHIVE_EOF;
@@ -1576,6 +1584,7 @@ setup_current_filesystem(struct archive_read_disk *a)
 #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
 #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
 	t->current_filesystem->name_max = sfs.f_namemax;
 	t->current_filesystem->name_max = sfs.f_namemax;
 #else
 #else
+# if defined(_PC_NAME_MAX)
 	/* Mac OS X does not have f_namemax in struct statfs. */
 	/* Mac OS X does not have f_namemax in struct statfs. */
 	if (tree_current_is_symblic_link_target(t)) {
 	if (tree_current_is_symblic_link_target(t)) {
 		if (tree_enter_working_dir(t) != 0) {
 		if (tree_enter_working_dir(t) != 0) {
@@ -1585,6 +1594,9 @@ setup_current_filesystem(struct archive_read_disk *a)
 		nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
 		nm = pathconf(tree_current_access_path(t), _PC_NAME_MAX);
 	} else
 	} else
 		nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
 		nm = fpathconf(tree_current_dir_fd(t), _PC_NAME_MAX);
+# else
+	nm = -1;
+# endif
 	if (nm == -1)
 	if (nm == -1)
 		t->current_filesystem->name_max = NAME_MAX;
 		t->current_filesystem->name_max = NAME_MAX;
 	else
 	else
@@ -1681,7 +1693,9 @@ setup_current_filesystem(struct archive_read_disk *a)
 {
 {
 	struct tree *t = a->tree;
 	struct tree *t = a->tree;
 	struct statfs sfs;
 	struct statfs sfs;
+#if defined(HAVE_STATVFS)
 	struct statvfs svfs;
 	struct statvfs svfs;
+#endif
 	int r, vr = 0, xr = 0;
 	int r, vr = 0, xr = 0;
 
 
 	if (tree_current_is_symblic_link_target(t)) {
 	if (tree_current_is_symblic_link_target(t)) {
@@ -1698,7 +1712,9 @@ setup_current_filesystem(struct archive_read_disk *a)
 			    "openat failed");
 			    "openat failed");
 			return (ARCHIVE_FAILED);
 			return (ARCHIVE_FAILED);
 		}
 		}
+#if defined(HAVE_FSTATVFS)
 		vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */
 		vr = fstatvfs(fd, &svfs);/* for f_flag, mount flags */
+#endif
 		r = fstatfs(fd, &sfs);
 		r = fstatfs(fd, &sfs);
 		if (r == 0)
 		if (r == 0)
 			xr = get_xfer_size(t, fd, NULL);
 			xr = get_xfer_size(t, fd, NULL);
@@ -1708,14 +1724,18 @@ setup_current_filesystem(struct archive_read_disk *a)
 			archive_set_error(&a->archive, errno, "fchdir failed");
 			archive_set_error(&a->archive, errno, "fchdir failed");
 			return (ARCHIVE_FAILED);
 			return (ARCHIVE_FAILED);
 		}
 		}
+#if defined(HAVE_STATVFS)
 		vr = statvfs(tree_current_access_path(t), &svfs);
 		vr = statvfs(tree_current_access_path(t), &svfs);
+#endif
 		r = statfs(tree_current_access_path(t), &sfs);
 		r = statfs(tree_current_access_path(t), &sfs);
 		if (r == 0)
 		if (r == 0)
 			xr = get_xfer_size(t, -1, tree_current_access_path(t));
 			xr = get_xfer_size(t, -1, tree_current_access_path(t));
 #endif
 #endif
 	} else {
 	} else {
 #ifdef HAVE_FSTATFS
 #ifdef HAVE_FSTATFS
+#if defined(HAVE_FSTATVFS)
 		vr = fstatvfs(tree_current_dir_fd(t), &svfs);
 		vr = fstatvfs(tree_current_dir_fd(t), &svfs);
+#endif
 		r = fstatfs(tree_current_dir_fd(t), &sfs);
 		r = fstatfs(tree_current_dir_fd(t), &sfs);
 		if (r == 0)
 		if (r == 0)
 			xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
 			xr = get_xfer_size(t, tree_current_dir_fd(t), NULL);
@@ -1724,7 +1744,9 @@ setup_current_filesystem(struct archive_read_disk *a)
 			archive_set_error(&a->archive, errno, "fchdir failed");
 			archive_set_error(&a->archive, errno, "fchdir failed");
 			return (ARCHIVE_FAILED);
 			return (ARCHIVE_FAILED);
 		}
 		}
+#if defined(HAVE_STATVFS)
 		vr = statvfs(".", &svfs);
 		vr = statvfs(".", &svfs);
+#endif
 		r = statfs(".", &sfs);
 		r = statfs(".", &sfs);
 		if (r == 0)
 		if (r == 0)
 			xr = get_xfer_size(t, -1, ".");
 			xr = get_xfer_size(t, -1, ".");
@@ -1737,10 +1759,17 @@ setup_current_filesystem(struct archive_read_disk *a)
 		return (ARCHIVE_FAILED);
 		return (ARCHIVE_FAILED);
 	} else if (xr == 1) {
 	} else if (xr == 1) {
 		/* pathconf(_PC_REX_*) operations are not supported. */
 		/* pathconf(_PC_REX_*) operations are not supported. */
+#if defined(HAVE_STATVFS)
 		t->current_filesystem->xfer_align = svfs.f_frsize;
 		t->current_filesystem->xfer_align = svfs.f_frsize;
 		t->current_filesystem->max_xfer_size = -1;
 		t->current_filesystem->max_xfer_size = -1;
 		t->current_filesystem->min_xfer_size = svfs.f_bsize;
 		t->current_filesystem->min_xfer_size = svfs.f_bsize;
 		t->current_filesystem->incr_xfer_size = svfs.f_bsize;
 		t->current_filesystem->incr_xfer_size = svfs.f_bsize;
+#else
+		t->current_filesystem->xfer_align = sfs.f_frsize;
+		t->current_filesystem->max_xfer_size = -1;
+		t->current_filesystem->min_xfer_size = sfs.f_bsize;
+		t->current_filesystem->incr_xfer_size = sfs.f_bsize;
+#endif
 	}
 	}
 	switch (sfs.f_type) {
 	switch (sfs.f_type) {
 	case AFS_SUPER_MAGIC:
 	case AFS_SUPER_MAGIC:
@@ -1765,7 +1794,11 @@ setup_current_filesystem(struct archive_read_disk *a)
 	}
 	}
 
 
 #if defined(ST_NOATIME)
 #if defined(ST_NOATIME)
+#if defined(HAVE_STATVFS)
 	if (svfs.f_flag & ST_NOATIME)
 	if (svfs.f_flag & ST_NOATIME)
+#else
+	if (sfs.f_flag & ST_NOATIME)
+#endif
 		t->current_filesystem->noatime = 1;
 		t->current_filesystem->noatime = 1;
 	else
 	else
 #endif
 #endif

+ 6 - 0
libarchive/archive_read_filter.3

@@ -53,8 +53,12 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Ft int
 .Fn archive_read_support_filter_compress "struct archive *"
 .Fn archive_read_support_filter_compress "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_read_support_filter_grzip "struct archive *"
+.Ft int
 .Fn archive_read_support_filter_gzip "struct archive *"
 .Fn archive_read_support_filter_gzip "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_read_support_filter_lrzip "struct archive *"
+.Ft int
 .Fn archive_read_support_filter_lz4 "struct archive *"
 .Fn archive_read_support_filter_lz4 "struct archive *"
 .Ft int
 .Ft int
 .Fn archive_read_support_filter_lzma "struct archive *"
 .Fn archive_read_support_filter_lzma "struct archive *"
@@ -86,7 +90,9 @@ Streaming Archive Library (libarchive, -larchive)
 .It Xo
 .It Xo
 .Fn archive_read_support_filter_bzip2 ,
 .Fn archive_read_support_filter_bzip2 ,
 .Fn archive_read_support_filter_compress ,
 .Fn archive_read_support_filter_compress ,
+.Fn archive_read_support_filter_grzip ,
 .Fn archive_read_support_filter_gzip ,
 .Fn archive_read_support_filter_gzip ,
+.Fn archive_read_support_filter_lrzip ,
 .Fn archive_read_support_filter_lz4 ,
 .Fn archive_read_support_filter_lz4 ,
 .Fn archive_read_support_filter_lzma ,
 .Fn archive_read_support_filter_lzma ,
 .Fn archive_read_support_filter_lzop ,
 .Fn archive_read_support_filter_lzop ,

+ 7 - 3
libarchive/archive_read_open_file.c

@@ -83,8 +83,9 @@ archive_read_open_FILE(struct archive *a, FILE *f)
 	mine->f = f;
 	mine->f = f;
 	/*
 	/*
 	 * If we can't fstat() the file, it may just be that it's not
 	 * 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)) {
 	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);
 		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;
 			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)
 	if (fseeko(mine->f, skip, SEEK_CUR) != 0)
 #elif HAVE__FSEEKI64
 #elif HAVE__FSEEKI64
 	if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
 	if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)

+ 1 - 1
libarchive/archive_read_open_filename.c

@@ -178,7 +178,7 @@ archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
 #else
 #else
 		/*
 		/*
 		 * POSIX system does not support a wchar_t interface for
 		 * 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.
 		 * filename to multi-byte one and use it.
 		 */
 		 */
 		struct archive_string fn;
 		struct archive_string fn;

+ 9 - 0
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);
 				    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(
 		uncompressed_size = LZ4_decompress_safe_withPrefix64k(
 		    read_buf + 4,
 		    read_buf + 4,
 		    state->out_block + prefix64k, (int)compressed_size,
 		    state->out_block + prefix64k, (int)compressed_size,
 		    state->flags.block_maximum_size);
 		    state->flags.block_maximum_size);
+#endif
 	}
 	}
 
 
 	/* Check if an error happend in decompression process. */
 	/* Check if an error happend in decompression process. */

+ 1 - 1
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,
 			archive_set_error(&a->archive, err,
 			    "Internal error initializing decompressor: %s",
 			    "Internal error initializing decompressor: %s",
-			    detail == NULL ? "??" : detail);
+			    detail != NULL ? detail : "??");
 			zip->bzstream_valid = 0;
 			zip->bzstream_valid = 0;
 			return (ARCHIVE_FAILED);
 			return (ARCHIVE_FAILED);
 		}
 		}

+ 1 - 1
libarchive/archive_read_support_format_lha.c

@@ -1712,7 +1712,7 @@ lha_crc16(uint16_t crc, const void *pp, size_t len)
 	for (;len >= 8; len -= 8) {
 	for (;len >= 8; len -= 8) {
 		/* This if statement expects compiler optimization will
 		/* This if statement expects compiler optimization will
 		 * remove the stament which will not be executed. */
 		 * remove the stament which will not be executed. */
-#ifdef _MSC_VER  /* Visual Studio */
+#if defined(_MSC_VER) && _MSC_VER >= 1400  /* Visual Studio */
 #  define bswap16(x) _byteswap_ushort(x)
 #  define bswap16(x) _byteswap_ushort(x)
 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \
 #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \
       || defined(__clang__)
       || defined(__clang__)

+ 41 - 32
libarchive/archive_read_support_format_mtree.c

@@ -148,9 +148,12 @@ get_time_t_max(void)
 		return (~(time_t)0);
 		return (~(time_t)0);
 	} else {
 	} else {
 		/* Time_t is signed. */
 		/* Time_t is signed. */
-		const uintmax_t max_unsigned_time_t = (uintmax_t)(~(time_t)0);
-		const uintmax_t max_signed_time_t = max_unsigned_time_t >> 1;
-		return (time_t)max_signed_time_t;
+		/* Assume it's the same as int64_t or int32_t */
+		if (sizeof(time_t) == sizeof(int64_t)) {
+			return (time_t)INT64_MAX;
+		} else {
+			return (time_t)INT32_MAX;
+		}
 	}
 	}
 #endif
 #endif
 }
 }
@@ -166,10 +169,11 @@ get_time_t_min(void)
 		return (time_t)0;
 		return (time_t)0;
 	} else {
 	} else {
 		/* Time_t is signed. */
 		/* Time_t is signed. */
-		const uintmax_t max_unsigned_time_t = (uintmax_t)(~(time_t)0);
-		const uintmax_t max_signed_time_t = max_unsigned_time_t >> 1;
-		const intmax_t min_signed_time_t = (intmax_t)~max_signed_time_t;
-		return (time_t)min_signed_time_t;
+		if (sizeof(time_t) == sizeof(int64_t)) {
+			return (time_t)INT64_MIN;
+		} else {
+			return (time_t)INT32_MIN;
+		}
 	}
 	}
 #endif
 #endif
 }
 }
@@ -852,8 +856,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
 	struct mtree_entry *entry;
 	struct mtree_entry *entry;
 	struct mtree_option *iter;
 	struct mtree_option *iter;
 	const char *next, *eq, *name, *end;
 	const char *next, *eq, *name, *end;
-	size_t len;
-	int r;
+	size_t name_len, len;
+	int r, i;
 
 
 	if ((entry = malloc(sizeof(*entry))) == NULL) {
 	if ((entry = malloc(sizeof(*entry))) == NULL) {
 		archive_set_error(&a->archive, errno, "Can't allocate memory");
 		archive_set_error(&a->archive, errno, "Can't allocate memory");
@@ -873,43 +877,48 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
 	*last_entry = entry;
 	*last_entry = entry;
 
 
 	if (is_form_d) {
 	if (is_form_d) {
-		/*
-		 * This form places the file name as last parameter.
-		 */
-		name = line + line_len -1;
+		/* Filename is last item on line. */
+		/* Adjust line_len to trim trailing whitespace */
 		while (line_len > 0) {
 		while (line_len > 0) {
-			if (*name != '\r' && *name != '\n' &&
-			    *name != '\t' && *name != ' ')
+			char last_character = line[line_len - 1];
+			if (last_character == '\r'
+			    || last_character == '\n'
+			    || last_character == '\t'
+			    || last_character == ' ') {
+				line_len--;
+			} else {
 				break;
 				break;
-			name--;
-			line_len--;
+			}
 		}
 		}
-		len = 0;
-		while (line_len > 0) {
-			if (*name == '\r' || *name == '\n' ||
-			    *name == '\t' || *name == ' ') {
-				name++;
-				break;
+		/* Name starts after the last whitespace separator */
+		name = line;
+		for (i = 0; i < line_len; i++) {
+			if (line[i] == '\r'
+			    || line[i] == '\n'
+			    || line[i] == '\t'
+			    || line[i] == ' ') {
+				name = line + i + 1;
 			}
 			}
-			name--;
-			line_len--;
-			len++;
 		}
 		}
+		name_len = line + line_len - name;
 		end = name;
 		end = name;
 	} else {
 	} else {
-		len = strcspn(line, " \t\r\n");
+		/* Filename is first item on line */
+		name_len = strcspn(line, " \t\r\n");
 		name = line;
 		name = line;
-		line += len;
+		line += name_len;
 		end = line + line_len;
 		end = line + line_len;
 	}
 	}
+	/* name/name_len is the name within the line. */
+	/* line..end brackets the entire line except the name */
 
 
-	if ((entry->name = malloc(len + 1)) == NULL) {
+	if ((entry->name = malloc(name_len + 1)) == NULL) {
 		archive_set_error(&a->archive, errno, "Can't allocate memory");
 		archive_set_error(&a->archive, errno, "Can't allocate memory");
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 
 
-	memcpy(entry->name, name, len);
-	entry->name[len] = '\0';
+	memcpy(entry->name, name, name_len);
+	entry->name[name_len] = '\0';
 	parse_escapes(entry->name, entry);
 	parse_escapes(entry->name, entry);
 
 
 	for (iter = *global; iter != NULL; iter = iter->next) {
 	for (iter = *global; iter != NULL; iter = iter->next) {
@@ -1561,7 +1570,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
 			int64_t m;
 			int64_t m;
 			int64_t my_time_t_max = get_time_t_max();
 			int64_t my_time_t_max = get_time_t_max();
 			int64_t my_time_t_min = get_time_t_min();
 			int64_t my_time_t_min = get_time_t_min();
-			long ns;
+			long ns = 0;
 
 
 			*parsed_kws |= MTREE_HAS_MTIME;
 			*parsed_kws |= MTREE_HAS_MTIME;
 			m = mtree_atol10(&val);
 			m = mtree_atol10(&val);

+ 30 - 15
libarchive/archive_read_support_format_rar.c

@@ -828,6 +828,7 @@ archive_read_format_rar_read_header(struct archive_read *a,
   char head_type;
   char head_type;
   int ret;
   int ret;
   unsigned flags;
   unsigned flags;
+  unsigned long crc32_expected;
 
 
   a->archive.archive_format = ARCHIVE_FORMAT_RAR;
   a->archive.archive_format = ARCHIVE_FORMAT_RAR;
   if (a->archive.archive_format_name == NULL)
   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);
       skip = archive_le16dec(p + 5);
       if (skip < 7) {
       if (skip < 7) {
         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-          "Invalid header size");
+          "Invalid header size too small");
         return (ARCHIVE_FATAL);
         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 (flags & HD_ADD_SIZE_PRESENT)
       {
       {
         if (skip < 7 + 4) {
         if (skip < 7 + 4) {
           archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
           archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-            "Invalid header size");
+            "Invalid header size too small");
           return (ARCHIVE_FATAL);
           return (ARCHIVE_FATAL);
         }
         }
-        skip += archive_le32dec(p + 7);
         if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
         if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
           return (ARCHIVE_FATAL);
           return (ARCHIVE_FATAL);
         p = h;
         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)
       if (head_type == ENDARC_HEAD)
-        return (ARCHIVE_EOF);
+	      return (ARCHIVE_EOF);
       break;
       break;
 
 
     case NEWSUB_HEAD:
     case NEWSUB_HEAD:

+ 10 - 9
libarchive/archive_read_support_format_warc.c

@@ -418,10 +418,11 @@ deconst(const void *c)
 }
 }
 
 
 static char*
 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 *hp;
 	const char *np;
 	const char *np;
 	const char *cand;
 	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
          * 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
          * then run strchr() to find a candidate in HAYSTACK (i.e. a portion
          * that happens to begin with *NEEDLE) */
          * that happens to begin with *NEEDLE) */
-	if (nz == 0UL) {
+	if (needlesize == 0UL) {
 		return deconst(hay);
 		return deconst(hay);
-	} else if ((hay = memchr(hay, *ndl, hz)) == NULL) {
+	} else if ((hay = memchr(hay, *needle, haysize)) == NULL) {
 		/* trivial */
 		/* trivial */
 		return NULL;
 		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
 	 * guaranteed to be at least one character long.  Now computes the sum
 	 * of characters values of needle together with the sum of the first
 	 * of characters values of needle together with the sum of the first
 	 * needle_len characters of haystack. */
 	 * 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;
 	     hp < eoh && np < eon;
 	     hsum ^= *hp, nsum ^= *np, eqp &= *hp == *np, hp++, np++);
 	     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) {
 	if (np < eon) {
 		/* haystack is smaller than needle, :O */
 		/* haystack is smaller than needle, :O */
 		return NULL;
 		return NULL;
@@ -464,10 +465,10 @@ xmemmem(const char *hay, const size_t hz, const char *ndl, const size_t nz)
 		hsum ^= *hp;
 		hsum ^= *hp;
 
 
 		/* Since the sum of the characters is already known to be
 		/* 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,
 		 * characters for equality,
 		 * also CAND is by design < HP, so no need for range checks */
 		 * 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);
 			return deconst(cand);
 		}
 		}
 	}
 	}

+ 12 - 11
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;
 	struct unknown_tag *tag;
 
 
-#if DEBUG
-	fprintf(stderr, "unknowntag_start:%s\n", name);
-#endif
 	tag = malloc(sizeof(*tag));
 	tag = malloc(sizeof(*tag));
 	if (tag == NULL) {
 	if (tag == NULL) {
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");
 		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_string_init(&(tag->name));
 	archive_strcpy(&(tag->name), name);
 	archive_strcpy(&(tag->name), name);
 	if (xar->unknowntags == NULL) {
 	if (xar->unknowntags == NULL) {
+#if DEBUG
+		fprintf(stderr, "UNKNOWNTAG_START:%s\n", name);
+#endif
 		xar->xmlsts_unknown = xar->xmlsts;
 		xar->xmlsts_unknown = xar->xmlsts;
 		xar->xmlsts = UNKNOWN;
 		xar->xmlsts = UNKNOWN;
 	}
 	}
@@ -1963,9 +1963,6 @@ unknowntag_end(struct xar *xar, const char *name)
 {
 {
 	struct unknown_tag *tag;
 	struct unknown_tag *tag;
 
 
-#if DEBUG
-	fprintf(stderr, "unknowntag_end:%s\n", name);
-#endif
 	tag = xar->unknowntags;
 	tag = xar->unknowntags;
 	if (tag == NULL || name == NULL)
 	if (tag == NULL || name == NULL)
 		return;
 		return;
@@ -1973,8 +1970,12 @@ unknowntag_end(struct xar *xar, const char *name)
 		xar->unknowntags = tag->next;
 		xar->unknowntags = tag->next;
 		archive_string_free(&(tag->name));
 		archive_string_free(&(tag->name));
 		free(tag);
 		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;
 			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:
 	case FILE_ACL:
 		if (strcmp(name, "appleextended") == 0)
 		if (strcmp(name, "appleextended") == 0)
 			xar->xmlsts = FILE_ACL_APPLEEXTENDED;
 			xar->xmlsts = FILE_ACL_APPLEEXTENDED;
-		if (strcmp(name, "default") == 0)
+		else if (strcmp(name, "default") == 0)
 			xar->xmlsts = FILE_ACL_DEFAULT;
 			xar->xmlsts = FILE_ACL_DEFAULT;
 		else if (strcmp(name, "access") == 0)
 		else if (strcmp(name, "access") == 0)
 			xar->xmlsts = FILE_ACL_ACCESS;
 			xar->xmlsts = FILE_ACL_ACCESS;
@@ -2690,9 +2691,9 @@ xml_data(void *userData, const char *s, int len)
 #if DEBUG
 #if DEBUG
 	{
 	{
 		char buff[1024];
 		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;
 		buff[len] = 0;
 		fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff);
 		fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff);
 	}
 	}

+ 77 - 12
libarchive/archive_read_support_format_zip.c

@@ -39,7 +39,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102
  *
  *
  * History of this code: The streaming Zip reader was first added to
  * History of this code: The streaming Zip reader was first added to
  * libarchive in January 2005.  Support for seekable input sources was
  * libarchive in January 2005.  Support for seekable input sources was
- * added in Nov 2011.
+ * added in Nov 2011.  Zip64 support (including a significant code
+ * refactoring) was added in 2014.
  */
  */
 
 
 #ifdef HAVE_ERRNO_H
 #ifdef HAVE_ERRNO_H
@@ -419,8 +420,9 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
 		unsigned short datasize = archive_le16dec(p + offset + 2);
 		unsigned short datasize = archive_le16dec(p + offset + 2);
 
 
 		offset += 4;
 		offset += 4;
-		if (offset + datasize > extra_length)
+		if (offset + datasize > extra_length) {
 			break;
 			break;
+		}
 #ifdef DEBUG
 #ifdef DEBUG
 		fprintf(stderr, "Header id 0x%04x, length %d\n",
 		fprintf(stderr, "Header id 0x%04x, length %d\n",
 		    headerid, datasize);
 		    headerid, datasize);
@@ -555,7 +557,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
 			 *  if bitmap & 1, 2 byte "version made by"
 			 *  if bitmap & 1, 2 byte "version made by"
 			 *  if bitmap & 2, 2 byte "internal file attributes"
 			 *  if bitmap & 2, 2 byte "internal file attributes"
 			 *  if bitmap & 4, 4 byte "external file attributes"
 			 *  if bitmap & 4, 4 byte "external file attributes"
-			 *  if bitmap * 7, 2 byte comment length + n byte comment
+			 *  if bitmap & 8, 2 byte comment length + n byte comment
 			 */
 			 */
 			int bitmap, bitmap_last;
 			int bitmap, bitmap_last;
 
 
@@ -604,6 +606,19 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
 				if (zip_entry->system == 3) {
 				if (zip_entry->system == 3) {
 					zip_entry->mode
 					zip_entry->mode
 					    = external_attributes >> 16;
 					    = external_attributes >> 16;
+				} else if (zip_entry->system == 0) {
+					// Interpret MSDOS directory bit
+					if (0x10 == (external_attributes & 0x10)) {
+						zip_entry->mode = AE_IFDIR | 0775;
+					} else {
+						zip_entry->mode = AE_IFREG | 0664;
+					}
+					if (0x01 == (external_attributes & 0x01)) {
+						// Read-only bit; strip write permissions
+						zip_entry->mode &= 0555;
+					}
+				} else {
+					zip_entry->mode = 0;
 				}
 				}
 				offset += 4;
 				offset += 4;
 				datasize -= 4;
 				datasize -= 4;
@@ -810,6 +825,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 	}
 	}
 	__archive_read_consume(a, filename_length);
 	__archive_read_consume(a, filename_length);
 
 
+	/* Read the extra data. */
+	if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) {
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+		    "Truncated ZIP file header");
+		return (ARCHIVE_FATAL);
+	}
+
+	process_extra(h, extra_length, zip_entry);
+	__archive_read_consume(a, extra_length);
+
 	/* Work around a bug in Info-Zip: When reading from a pipe, it
 	/* Work around a bug in Info-Zip: When reading from a pipe, it
 	 * stats the pipe instead of synthesizing a file entry. */
 	 * stats the pipe instead of synthesizing a file entry. */
 	if ((zip_entry->mode & AE_IFMT) == AE_IFIFO) {
 	if ((zip_entry->mode & AE_IFMT) == AE_IFIFO) {
@@ -843,16 +868,31 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 		}
 		}
 	}
 	}
 
 
-	/* Read the extra data. */
-	if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) {
-		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
-		    "Truncated ZIP file header");
-		return (ARCHIVE_FATAL);
+	/* Make sure directories end in '/' */
+	if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) {
+		wp = archive_entry_pathname_w(entry);
+		if (wp != NULL) {
+			len = wcslen(wp);
+			if (len > 0 && wp[len - 1] != L'/') {
+				struct archive_wstring s;
+				archive_string_init(&s);
+				archive_wstrcat(&s, wp);
+				archive_wstrappend_wchar(&s, L'/');
+				archive_entry_copy_pathname_w(entry, s.s);
+			}
+		} else {
+			cp = archive_entry_pathname(entry);
+			len = (cp != NULL)?strlen(cp):0;
+			if (len > 0 && cp[len - 1] != '/') {
+				struct archive_string s;
+				archive_string_init(&s);
+				archive_strcat(&s, cp);
+				archive_strappend_char(&s, '/');
+				archive_entry_set_pathname(entry, s.s);
+			}
+		}
 	}
 	}
 
 
-	process_extra(h, extra_length, zip_entry);
-	__archive_read_consume(a, extra_length);
-
 	if (zip_entry->flags & LA_FROM_CENTRAL_DIRECTORY) {
 	if (zip_entry->flags & LA_FROM_CENTRAL_DIRECTORY) {
 		/* If this came from the central dir, it's size info
 		/* If this came from the central dir, it's size info
 		 * is definitive, so ignore the length-at-end flag. */
 		 * is definitive, so ignore the length-at-end flag. */
@@ -2614,9 +2654,21 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
 		/* If we can't guess the mode, leave it zero here;
 		/* If we can't guess the mode, leave it zero here;
 		   when we read the local file header we might get
 		   when we read the local file header we might get
 		   more information. */
 		   more information. */
-		zip_entry->mode = 0;
 		if (zip_entry->system == 3) {
 		if (zip_entry->system == 3) {
 			zip_entry->mode = external_attributes >> 16;
 			zip_entry->mode = external_attributes >> 16;
+		} else if (zip_entry->system == 0) {
+			// Interpret MSDOS directory bit
+			if (0x10 == (external_attributes & 0x10)) {
+				zip_entry->mode = AE_IFDIR | 0775;
+			} else {
+				zip_entry->mode = AE_IFREG | 0664;
+			}
+			if (0x01 == (external_attributes & 0x01)) {
+				// Read-only bit; strip write permissions
+				zip_entry->mode &= 0555;
+			}
+		} else {
+			zip_entry->mode = 0;
 		}
 		}
 
 
 		/* We're done with the regular data; get the filename and
 		/* We're done with the regular data; get the filename and
@@ -2726,6 +2778,11 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
 
 
 	switch(rsrc->compression) {
 	switch(rsrc->compression) {
 	case 0:  /* No compression. */
 	case 0:  /* No compression. */
+		if (rsrc->uncompressed_size != rsrc->compressed_size) {
+			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+			    "Malformed OS X metadata entry: inconsistent size");
+			return (ARCHIVE_FATAL);
+		}
 #ifdef HAVE_ZLIB_H
 #ifdef HAVE_ZLIB_H
 	case 8: /* Deflate compression. */
 	case 8: /* Deflate compression. */
 #endif
 #endif
@@ -2746,6 +2803,12 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
 		    (intmax_t)rsrc->uncompressed_size);
 		    (intmax_t)rsrc->uncompressed_size);
 		return (ARCHIVE_WARN);
 		return (ARCHIVE_WARN);
 	}
 	}
+	if (rsrc->compressed_size > (4 * 1024 * 1024)) {
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+		    "Mac metadata is too large: %jd > 4M bytes",
+		    (intmax_t)rsrc->compressed_size);
+		return (ARCHIVE_WARN);
+	}
 
 
 	metadata = malloc((size_t)rsrc->uncompressed_size);
 	metadata = malloc((size_t)rsrc->uncompressed_size);
 	if (metadata == NULL) {
 	if (metadata == NULL) {
@@ -2784,6 +2847,8 @@ zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
 			bytes_avail = remaining_bytes;
 			bytes_avail = remaining_bytes;
 		switch(rsrc->compression) {
 		switch(rsrc->compression) {
 		case 0:  /* No compression. */
 		case 0:  /* No compression. */
+			if ((size_t)bytes_avail > metadata_bytes)
+				bytes_avail = metadata_bytes;
 			memcpy(mp, p, bytes_avail);
 			memcpy(mp, p, bytes_avail);
 			bytes_used = (size_t)bytes_avail;
 			bytes_used = (size_t)bytes_avail;
 			metadata_bytes -= bytes_used;
 			metadata_bytes -= bytes_used;

+ 2 - 1
libarchive/archive_string.c

@@ -737,7 +737,8 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
 			}
 			}
 			if (count == 0)
 			if (count == 0)
 				ret = -1;
 				ret = -1;
-		} while (0);
+			break;
+		} while (1);
 	}
 	}
 	as->length += count;
 	as->length += count;
 	as->s[as->length] = '\0';
 	as->s[as->length] = '\0';

+ 61 - 15
libarchive/archive_util.c

@@ -94,35 +94,81 @@ archive_version_details(void)
 {
 {
 	static struct archive_string str;
 	static struct archive_string str;
 	static int init = 0;
 	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) {
 	if (!init) {
 		archive_string_init(&str);
 		archive_string_init(&str);
 
 
 		archive_strcat(&str, ARCHIVE_VERSION_STRING);
 		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, ',');
 			const char *sep = strchr(p, ',');
 			if (sep == NULL)
 			if (sep == NULL)
 				sep = p + strlen(p);
 				sep = p + strlen(p);
 			archive_strcat(&str, " bz2lib/");
 			archive_strcat(&str, " bz2lib/");
 			archive_strncat(&str, p, sep - p);
 			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
 #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)
 #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
 #endif
-	}
-	return str.s;
 }
 }
 
 
 int
 int

+ 1 - 1
libarchive/archive_write.c

@@ -725,7 +725,7 @@ static const char *
 _archive_filter_name(struct archive *_a, int n)
 _archive_filter_name(struct archive *_a, int n)
 {
 {
 	struct archive_write_filter *f = filter_lookup(_a, 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
 static int64_t

+ 1 - 1
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)
 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 #else
 #else
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate("bzip2");
 	if (data->pdata == NULL) {
 	if (data->pdata == NULL) {
 		free(data);
 		free(data);
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");

+ 1 - 1
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");
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate("grzip");
 	if (data->pdata == NULL) {
 	if (data->pdata == NULL) {
 		free(data);
 		free(data);
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");

+ 1 - 1
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;
 	data->compression_level = Z_DEFAULT_COMPRESSION;
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 #else
 #else
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate("gzip");
 	if (data->pdata == NULL) {
 	if (data->pdata == NULL) {
 		free(data);
 		free(data);
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");

+ 1 - 1
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");
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate("lrzip");
 	if (data->pdata == NULL) {
 	if (data->pdata == NULL) {
 		free(data);
 		free(data);
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");

+ 93 - 32
libarchive/archive_write_add_filter_lz4.c

@@ -54,14 +54,14 @@ __FBSDID("$FreeBSD$");
 
 
 struct private_data {
 struct private_data {
 	int		 compression_level;
 	int		 compression_level;
-	uint8_t		 header_written:1;
-	uint8_t		 version_number:1;
-	uint8_t		 block_independence:1;
-	uint8_t		 block_checksum:1;
-	uint8_t		 stream_size:1;
-	uint8_t		 stream_checksum:1;
-	uint8_t		 preset_dictionary:1;
-	uint8_t		 block_maximum_size:3;
+	unsigned	 header_written:1;
+	unsigned	 version_number:1;
+	unsigned	 block_independence:1;
+	unsigned	 block_checksum:1;
+	unsigned	 stream_size:1;
+	unsigned	 stream_checksum:1;
+	unsigned	 preset_dictionary:1;
+	unsigned	 block_maximum_size:3;
 #if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
 #if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2
 	int64_t		 total_in;
 	int64_t		 total_in;
 	char		*out;
 	char		*out;
@@ -137,7 +137,7 @@ archive_write_add_filter_lz4(struct archive *_a)
 	 * We don't have lz4 library, and execute external lz4 program
 	 * We don't have lz4 library, and execute external lz4 program
 	 * instead.
 	 * instead.
 	 */
 	 */
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate("lz4");
 	if (data->pdata == NULL) {
 	if (data->pdata == NULL) {
 		free(data);
 		free(data);
 		archive_set_error(&a->archive, ENOMEM, "Out of memory");
 		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;
 	struct private_data *data = (struct private_data *)f->data;
 
 
 	if (strcmp(key, "compression-level") == 0) {
 	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')
 		    value[1] != '\0')
 			return (ARCHIVE_WARN);
 			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);
 		return (ARCHIVE_OK);
 	}
 	}
 	if (strcmp(key, "stream-checksum") == 0) {
 	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;
 	struct private_data *data = (struct private_data *)f->data;
 
 
 	if (data->lz4_stream != NULL) {
 	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
 #if LZ4_VERSION_MINOR >= 3
 			LZ4_freeStream(data->lz4_stream);
 			LZ4_freeStream(data->lz4_stream);
 #else
 #else
 			LZ4_free(data->lz4_stream);
 			LZ4_free(data->lz4_stream);
 #endif
 #endif
-		else
-			LZ4_freeHC(data->lz4_stream);
 	}
 	}
 	free(data->out_buffer);
 	free(data->out_buffer);
 	free(data->in_buffer_allocated);
 	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;
 	struct private_data *data = (struct private_data *)f->data;
 	unsigned int outsize;
 	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,
 		outsize = LZ4_compressHC2_limitedOutput(p, data->out + 4,
 		    (int)length, (int)data->block_size,
 		    (int)length, (int)data->block_size,
 		    data->compression_level);
 		    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) {
 	if (outsize) {
 		/* The buffer is compressed. */
 		/* 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;
 	struct private_data *data = (struct private_data *)f->data;
 	int outsize;
 	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) {
 		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) {
 			if (data->lz4_stream == NULL) {
 				archive_set_error(f->archive, ENOMEM,
 				archive_set_error(f->archive, ENOMEM,
 				    "Can't allocate data for compression"
 				    "Can't allocate data for compression"
@@ -528,13 +565,23 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
 				return (ARCHIVE_FATAL);
 				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,
 		    data->lz4_stream, p, data->out + 4, (int)length,
 		    (int)data->block_size);
 		    (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) {
 		if (data->lz4_stream == NULL) {
-			data->lz4_stream =
-			    LZ4_createHC(data->in_buffer_allocated);
+			data->lz4_stream = LZ4_createStream();
 			if (data->lz4_stream == NULL) {
 			if (data->lz4_stream == NULL) {
 				archive_set_error(f->archive, ENOMEM,
 				archive_set_error(f->archive, ENOMEM,
 				    "Can't allocate data for compression"
 				    "Can't allocate data for compression"
@@ -542,9 +589,18 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
 				return (ARCHIVE_FATAL);
 				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,
 		    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) {
 	if (outsize) {
@@ -568,14 +624,19 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p,
 	}
 	}
 
 
 	if (length == data->block_size) {
 	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);
 			LZ4_slideInputBufferHC(data->lz4_stream);
+#endif
 			data->in_buffer = data->in_buffer_allocated + DICT_SIZE;
 			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
 #undef DICT_SIZE
 	}
 	}
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
@@ -605,7 +666,7 @@ archive_filter_lz4_open(struct archive_write_filter *f)
 	if (data->block_checksum)
 	if (data->block_checksum)
 		archive_strcat(&as, " -BX");
 		archive_strcat(&as, " -BX");
 	if (data->stream_checksum == 0)
 	if (data->stream_checksum == 0)
-		archive_strcat(&as, " -Sx");
+		archive_strcat(&as, " --no-frame-crc");
 	if (data->block_independence == 0)
 	if (data->block_independence == 0)
 		archive_strcat(&as, " -BD");
 		archive_strcat(&as, " -BD");
 
 

+ 2 - 2
libarchive/archive_write_add_filter_lzop.c

@@ -85,7 +85,7 @@ static int archive_write_lzop_free(struct archive_write_filter *);
 #if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
 #if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H)
 /* Maximum block size. */
 /* Maximum block size. */
 #define BLOCK_SIZE			(256 * 1024)
 #define BLOCK_SIZE			(256 * 1024)
-/* Block infomation is composed of uncompressed size(4 bytes),
+/* Block information is composed of uncompressed size(4 bytes),
  * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes)
  * compressed size(4 bytes) and the checksum of uncompressed data(4 bytes)
  * in this lzop writer. */
  * in this lzop writer. */
 #define BLOCK_INfO_SIZE			12
 #define BLOCK_INfO_SIZE			12
@@ -173,7 +173,7 @@ archive_write_add_filter_lzop(struct archive *_a)
 	data->compression_level = 5;
 	data->compression_level = 5;
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 #else
 #else
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate("lzop");
 	if (data->pdata == NULL) {
 	if (data->pdata == NULL) {
 		free(data);
 		free(data);
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");
 		archive_set_error(_a, ENOMEM, "Can't allocate memory");

+ 9 - 7
libarchive/archive_write_add_filter_program.c

@@ -68,6 +68,7 @@ struct archive_write_program_data {
 
 
 	char		*child_buf;
 	char		*child_buf;
 	size_t		 child_buf_len, child_buf_avail;
 	size_t		 child_buf_len, child_buf_avail;
+	char		*program_name;
 };
 };
 
 
 struct private_data {
 struct private_data {
@@ -105,7 +106,7 @@ archive_write_add_filter_program(struct archive *_a, const char *cmd)
 	if (data->cmd == NULL)
 	if (data->cmd == NULL)
 		goto memerr;
 		goto memerr;
 
 
-	data->pdata = __archive_write_program_allocate();
+	data->pdata = __archive_write_program_allocate(cmd);
 	if (data->pdata == NULL)
 	if (data->pdata == NULL)
 		goto memerr;
 		goto memerr;
 
 
@@ -174,7 +175,7 @@ archive_compressor_program_free(struct archive_write_filter *f)
  * Allocate resources for executing an external program.
  * Allocate resources for executing an external program.
  */
  */
 struct archive_write_program_data *
 struct archive_write_program_data *
-__archive_write_program_allocate(void)
+__archive_write_program_allocate(const char *program)
 {
 {
 	struct archive_write_program_data *data;
 	struct archive_write_program_data *data;
 
 
@@ -183,6 +184,7 @@ __archive_write_program_allocate(void)
 		return (data);
 		return (data);
 	data->child_stdin = -1;
 	data->child_stdin = -1;
 	data->child_stdout = -1;
 	data->child_stdout = -1;
+	data->program_name = strdup(program);
 	return (data);
 	return (data);
 }
 }
 
 
@@ -231,7 +233,7 @@ __archive_write_program_open(struct archive_write_filter *f,
 		    &data->child_stdout);
 		    &data->child_stdout);
 	if (child == -1) {
 	if (child == -1) {
 		archive_set_error(f->archive, EINVAL,
 		archive_set_error(f->archive, EINVAL,
-		    "Can't initialise filter");
+		    "Can't launch external program: %s", cmd);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -242,7 +244,7 @@ __archive_write_program_open(struct archive_write_filter *f,
 		close(data->child_stdout);
 		close(data->child_stdout);
 		data->child_stdout = -1;
 		data->child_stdout = -1;
 		archive_set_error(f->archive, EINVAL,
 		archive_set_error(f->archive, EINVAL,
-		    "Can't initialise filter");
+		    "Can't launch external program: %s", cmd);
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);
 	}
 	}
 #else
 #else
@@ -334,7 +336,7 @@ __archive_write_program_write(struct archive_write_filter *f,
 		ret = child_write(f, data, buf, length);
 		ret = child_write(f, data, buf, length);
 		if (ret == -1 || ret == 0) {
 		if (ret == -1 || ret == 0) {
 			archive_set_error(f->archive, EIO,
 			archive_set_error(f->archive, EIO,
-			    "Can't write to filter");
+			    "Can't write to program: %s", data->program_name);
 			return (ARCHIVE_FATAL);
 			return (ARCHIVE_FATAL);
 		}
 		}
 		length -= ret;
 		length -= ret;
@@ -373,7 +375,7 @@ __archive_write_program_close(struct archive_write_filter *f,
 
 
 		if (bytes_read == -1) {
 		if (bytes_read == -1) {
 			archive_set_error(f->archive, errno,
 			archive_set_error(f->archive, errno,
-			    "Read from filter failed unexpectedly.");
+			    "Error reading from program: %s", data->program_name);
 			ret = ARCHIVE_FATAL;
 			ret = ARCHIVE_FATAL;
 			goto cleanup;
 			goto cleanup;
 		}
 		}
@@ -403,7 +405,7 @@ cleanup:
 
 
 	if (status != 0) {
 	if (status != 0) {
 		archive_set_error(f->archive, EIO,
 		archive_set_error(f->archive, EIO,
-		    "Filter exited with failure.");
+		    "Error closing program: %s", data->program_name);
 		ret = ARCHIVE_FATAL;
 		ret = ARCHIVE_FATAL;
 	}
 	}
 	r1 = __archive_write_close_filter(f->next_filter);
 	r1 = __archive_write_close_filter(f->next_filter);

+ 6 - 0
libarchive/archive_write_disk_posix.c

@@ -2386,6 +2386,9 @@ check_symlinks(struct archive_write_disk *a)
 		while ((*pn != '\0') && (*p == *pn))
 		while ((*pn != '\0') && (*p == *pn))
 			++p, ++pn;
 			++p, ++pn;
 	}
 	}
+	/* Skip the root directory if the path is absolute. */
+	if(pn == a->name && pn[0] == '/')
+		++pn;
 	c = pn[0];
 	c = pn[0];
 	/* Keep going until we've checked the entire name. */
 	/* Keep going until we've checked the entire name. */
 	while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
 	while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
@@ -2447,6 +2450,9 @@ check_symlinks(struct archive_write_disk *a)
 				return (ARCHIVE_FAILED);
 				return (ARCHIVE_FAILED);
 			}
 			}
 		}
 		}
+		pn[0] = c;
+		if (pn[0] != '\0')
+			pn++; /* Advance to the next segment. */
 	}
 	}
 	pn[0] = c;
 	pn[0] = c;
 	/* We've checked and/or cleaned the whole path, so remember it. */
 	/* We've checked and/or cleaned the whole path, so remember it. */

+ 15 - 2
libarchive/archive_write_filter.3

@@ -29,9 +29,12 @@
 .Os
 .Os
 .Sh NAME
 .Sh NAME
 .Nm archive_write_add_filter_b64encode ,
 .Nm archive_write_add_filter_b64encode ,
+.Nm archive_write_add_filter_by_name ,
 .Nm archive_write_add_filter_bzip2 ,
 .Nm archive_write_add_filter_bzip2 ,
 .Nm archive_write_add_filter_compress ,
 .Nm archive_write_add_filter_compress ,
+.Nm archive_write_add_filter_grzip ,
 .Nm archive_write_add_filter_gzip ,
 .Nm archive_write_add_filter_gzip ,
+.Nm archive_write_add_filter_lrzip ,
 .Nm archive_write_add_filter_lz4 ,
 .Nm archive_write_add_filter_lz4 ,
 .Nm archive_write_add_filter_lzip ,
 .Nm archive_write_add_filter_lzip ,
 .Nm archive_write_add_filter_lzma ,
 .Nm archive_write_add_filter_lzma ,
@@ -51,8 +54,12 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Ft int
 .Fn archive_write_add_filter_compress "struct archive *"
 .Fn archive_write_add_filter_compress "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_write_add_filter_grzip "struct archive *"
+.Ft int
 .Fn archive_write_add_filter_gzip "struct archive *"
 .Fn archive_write_add_filter_gzip "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_write_add_filter_lrzip "struct archive *"
+.Ft int
 .Fn archive_write_add_filter_lz4 "struct archive *"
 .Fn archive_write_add_filter_lz4 "struct archive *"
 .Ft int
 .Ft int
 .Fn archive_write_add_filter_lzip "struct archive *"
 .Fn archive_write_add_filter_lzip "struct archive *"
@@ -71,19 +78,25 @@ Streaming Archive Library (libarchive, -larchive)
 .Sh DESCRIPTION
 .Sh DESCRIPTION
 .Bl -tag -width indent
 .Bl -tag -width indent
 .It Xo
 .It Xo
-.Fn archive_write_add_filter_b64encode ,
 .Fn archive_write_add_filter_bzip2 ,
 .Fn archive_write_add_filter_bzip2 ,
 .Fn archive_write_add_filter_compress ,
 .Fn archive_write_add_filter_compress ,
+.Fn archive_write_add_filter_grzip ,
 .Fn archive_write_add_filter_gzip ,
 .Fn archive_write_add_filter_gzip ,
+.Fn archive_write_add_filter_lrzip ,
 .Fn archive_write_add_filter_lz4 ,
 .Fn archive_write_add_filter_lz4 ,
 .Fn archive_write_add_filter_lzip ,
 .Fn archive_write_add_filter_lzip ,
 .Fn archive_write_add_filter_lzma ,
 .Fn archive_write_add_filter_lzma ,
 .Fn archive_write_add_filter_lzop ,
 .Fn archive_write_add_filter_lzop ,
-.Fn archive_write_add_filter_uuencode ,
 .Fn archive_write_add_filter_xz ,
 .Fn archive_write_add_filter_xz ,
 .Xc
 .Xc
 The resulting archive will be compressed as specified.
 The resulting archive will be compressed as specified.
 Note that the compressed output is always properly blocked.
 Note that the compressed output is always properly blocked.
+.It Xo
+.Fn archive_write_add_filter_b64encode ,
+.Fn archive_write_add_filter_uuencode ,
+.Xc
+The output will be encoded as specified.
+The encoded output is always properly blocked.
 .It Fn archive_write_add_filter_none
 .It Fn archive_write_add_filter_none
 This is never necessary.
 This is never necessary.
 It is provided only for backwards compatibility.
 It is provided only for backwards compatibility.

+ 87 - 28
libarchive/archive_write_format.3

@@ -28,23 +28,63 @@
 .Dt ARCHIVE_WRITE_FORMAT 3
 .Dt ARCHIVE_WRITE_FORMAT 3
 .Os
 .Os
 .Sh NAME
 .Sh NAME
+.Nm archive_write_set_format ,
+.Nm archive_write_set_format_7zip ,
+.Nm archive_write_set_format_ar ,
+.Nm archive_write_set_format_ar_bsd ,
+.Nm archive_write_set_format_ar_svr4 ,
+.Nm archive_write_set_format_by_name ,
 .Nm archive_write_set_format_cpio ,
 .Nm archive_write_set_format_cpio ,
+.Nm archive_write_set_format_cpio_newc ,
+.Nm archive_write_set_format_filter_by_ext ,
+.Nm archive_write_set_format_filter_by_ext_def ,
+.Nm archive_write_set_format_gnutar ,
+.Nm archive_write_set_format_iso9660 ,
+.Nm archive_write_set_format_mtree ,
+.Nm archive_write_set_format_mtree_classic ,
+.Nm archive_write_set_format_mtree_default ,
 .Nm archive_write_set_format_pax ,
 .Nm archive_write_set_format_pax ,
 .Nm archive_write_set_format_pax_restricted ,
 .Nm archive_write_set_format_pax_restricted ,
 .Nm archive_write_set_format_raw ,
 .Nm archive_write_set_format_raw ,
 .Nm archive_write_set_format_shar ,
 .Nm archive_write_set_format_shar ,
 .Nm archive_write_set_format_shar_dump ,
 .Nm archive_write_set_format_shar_dump ,
 .Nm archive_write_set_format_ustar ,
 .Nm archive_write_set_format_ustar ,
-.Nm archive_write_set_format_filter_by_ext ,
-.Nm archive_write_set_format_filter_by_ext_def
+.Nm archive_write_set_format_v7tar ,
+.Nm archive_write_set_format_warc ,
+.Nm archive_write_set_format_xar ,
+.Nm archive_write_set_format_zip ,
 .Nd functions for creating archives
 .Nd functions for creating archives
 .Sh LIBRARY
 .Sh LIBRARY
 Streaming Archive Library (libarchive, -larchive)
 Streaming Archive Library (libarchive, -larchive)
 .Sh SYNOPSIS
 .Sh SYNOPSIS
 .In archive.h
 .In archive.h
 .Ft int
 .Ft int
+.Fn archive_write_set_format "struct archive *" "int code"
+.Ft int
+.Fn archive_write_set_format_7zip "struct archive *"
+.Ft int
+.Fn archive_write_set_format_ar "struct archive *"
+.Ft int
+.Fn archive_write_set_format_ar_bsd "struct archive *"
+.Ft int
+.Fn archive_write_set_format_ar_svr4 "struct archive *"
+.Ft int
+.Fn archive_write_set_format_by_name "struct archive *" "const char *name"
+.Ft int
 .Fn archive_write_set_format_cpio "struct archive *"
 .Fn archive_write_set_format_cpio "struct archive *"
 .Ft int
 .Ft int
+.Fn archive_write_set_format_cpio_newc "struct archive *"
+.Ft int
+.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *filename"
+.Ft int
+.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *filename" "const char *def_ext"
+.Ft int
+.Fn archive_write_set_format_gnutar "struct archive *"
+.Ft int
+.Fn archive_write_set_format_iso9660 "struct archive *"
+.Ft int
+.Fn archive_write_set_format_mtree "struct archive *"
+.Ft int
 .Fn archive_write_set_format_pax "struct archive *"
 .Fn archive_write_set_format_pax "struct archive *"
 .Ft int
 .Ft int
 .Fn archive_write_set_format_pax_restricted "struct archive *"
 .Fn archive_write_set_format_pax_restricted "struct archive *"
@@ -57,42 +97,60 @@ Streaming Archive Library (libarchive, -larchive)
 .Ft int
 .Ft int
 .Fn archive_write_set_format_ustar "struct archive *"
 .Fn archive_write_set_format_ustar "struct archive *"
 .Ft int
 .Ft int
-.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *"
+.Fn archive_write_set_format_v7tar "struct archive *"
+.Ft int
+.Fn archive_write_set_format_warc "struct archive *"
 .Ft int
 .Ft int
-.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *" "const char *"
+.Fn archive_write_set_format_xar "struct archive *"
+.Ft int
+.Fn archive_write_set_format_zip "struct archive *"
 .Sh DESCRIPTION
 .Sh DESCRIPTION
 These functions set the format that will be used for the archive.
 These functions set the format that will be used for the archive.
 .Pp
 .Pp
-The library can write
-POSIX octet-oriented cpio format archives,
-POSIX-standard
-.Dq pax interchange
-format archives,
-traditional
-.Dq shar
-archives,
-enhanced
-.Dq dump
-shar archives that store a variety of file attributes and handle binary files,
-and
-POSIX-standard
-.Dq ustar
-archives.
-The pax interchange format is a backwards-compatible tar format that
-adds key/value attributes to each entry and supports arbitrary
-filenames, linknames, uids, sizes, etc.
-.Dq Restricted pax interchange format
-is the library default; this is the same as pax format, but suppresses
-the pax extended header for most normal files.
-In most cases, this will result in ordinary ustar archives.
+The library can write a variety of common archive formats.
+
 .Bl -tag -width indent
 .Bl -tag -width indent
+.It Fn archive_write_set_format
+Sets the format based on the format code (see
+.Pa archive.h
+for the full list of format codes).
+In particular, this can be used in conjunction with
+.Fn archive_format
+to create a new archive with the same format as an existing archive.
+.It Fn archive_write_set_format_by_name
+Sets the corresponding format based on the common name.
 .It Xo
 .It Xo
 .Fn archive_write_set_format_filter_by_ext ,
 .Fn archive_write_set_format_filter_by_ext ,
 .Fn archive_write_set_format_filter_by_ext_def
 .Fn archive_write_set_format_filter_by_ext_def
 .Xc
 .Xc
-Format and filter for archive can be set automatically, based on output file name extension.
-The functions are platform dependent.
+Sets both filters and format based on the output filename.
 Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
 Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
+.It Xo
+.Fn archive_write_set_format_7zip
+.Fn archive_write_set_format_ar_bsd ,
+.Fn archive_write_set_format_ar_svr4 ,
+.Fn archive_write_set_format_cpio
+.Fn archive_write_set_format_cpio_newc
+.Fn archive_write_set_format_gnutar
+.Fn archive_write_set_format_iso9660
+.Fn archive_write_set_format_mtree
+.Fn archive_write_set_format_mtree_classic
+.Fn archive_write_set_format_pax
+.Fn archive_write_set_format_pax_restricted
+.Fn archive_write_set_format_raw
+.Fn archive_write_set_format_shar
+.Fn archive_write_set_format_shar_dump
+.Fn archive_write_set_format_ustar
+.Fn archive_write_set_format_v7tar
+.Fn archive_write_set_format_warc
+.Fn archive_write_set_format_xar
+.Fn archive_write_set_format_zip
+.Xc
+Set the format as specified.
+More details on the formats supported by libarchive can be found in the
+.Xr libarchive-formats 5
+manual page.
+.El
 .\"
 .\"
 .Sh RETURN VALUES
 .Sh RETURN VALUES
 These functions return
 These functions return
@@ -113,5 +171,6 @@ functions.
 .Xr archive_write 3 ,
 .Xr archive_write 3 ,
 .Xr archive_write_set_options 3 ,
 .Xr archive_write_set_options 3 ,
 .Xr cpio 5 ,
 .Xr cpio 5 ,
+.Xr libarchive-formats 5 ,
 .Xr mtree 5 ,
 .Xr mtree 5 ,
 .Xr tar 5
 .Xr tar 5

+ 1 - 1
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_string_conv *);
 
 
 struct archive_write_program_data;
 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_free(struct archive_write_program_data *);
 int	__archive_write_program_open(struct archive_write_filter *,
 int	__archive_write_program_open(struct archive_write_filter *,
 	    struct archive_write_program_data *, const char *);
 	    struct archive_write_program_data *, const char *);

+ 4 - 0
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;
 	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);
 	file_free_register(zip);
 	compression_end(&(a->archive), &(zip->stream));
 	compression_end(&(a->archive), &(zip->stream));
 	free(zip->coder.props);
 	free(zip->coder.props);

+ 5 - 5
libarchive/archive_write_set_format_iso9660.c

@@ -197,7 +197,7 @@ struct isofile {
 	enum {
 	enum {
 		NO = 0,
 		NO = 0,
 		BOOT_CATALOG,
 		BOOT_CATALOG,
-		BOOT_IMAGE,
+		BOOT_IMAGE
 	} boot;
 	} boot;
 
 
 	/*
 	/*
@@ -850,7 +850,7 @@ enum dir_rec_type {
 	DIR_REC_VD,		/* Stored in Volume Descriptor.	*/
 	DIR_REC_VD,		/* Stored in Volume Descriptor.	*/
 	DIR_REC_SELF,		/* Stored as Current Directory.	*/
 	DIR_REC_SELF,		/* Stored as Current Directory.	*/
 	DIR_REC_PARENT,		/* Stored as Parent 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_STD,
 	VDC_LOWERCASE,
 	VDC_LOWERCASE,
 	VDC_UCS2,
 	VDC_UCS2,
-	VDC_UCS2_DIRECT,
+	VDC_UCS2_DIRECT
 };
 };
 
 
 /*
 /*
@@ -897,7 +897,7 @@ struct idr {
 
 
 enum char_type {
 enum char_type {
 	A_CHAR,
 	A_CHAR,
-	D_CHAR,
+	D_CHAR
 };
 };
 
 
 
 
@@ -4004,7 +4004,7 @@ enum keytype {
 	KEY_FLG,
 	KEY_FLG,
 	KEY_STR,
 	KEY_STR,
 	KEY_INT,
 	KEY_INT,
-	KEY_HEX,
+	KEY_HEX
 };
 };
 static void
 static void
 set_option_info(struct archive_string *info, int *opt, const char *key,
 set_option_info(struct archive_string *info, int *opt, const char *key,

+ 1 - 1
libarchive/archive_write_set_format_mtree.c

@@ -1115,7 +1115,7 @@ write_mtree_entry_tree(struct archive_write *a)
 	do {
 	do {
 		if (mtree->output_global_set) {
 		if (mtree->output_global_set) {
 			/*
 			/*
-			 * Collect attribute infomation to know which value
+			 * Collect attribute information to know which value
 			 * is frequently used among the children.
 			 * is frequently used among the children.
 			 */
 			 */
 			attr_counter_set_reset(mtree);
 			attr_counter_set_reset(mtree);

+ 22 - 15
libarchive/archive_write_set_format_pax.c

@@ -1036,22 +1036,12 @@ archive_write_pax_header(struct archive_write *a,
 		need_extension = 1;
 		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  ||
 		if (archive_entry_ctime(entry_main) != 0  ||
 		    archive_entry_ctime_nsec(entry_main) != 0)
 		    archive_entry_ctime_nsec(entry_main) != 0)
 			add_pax_attr_time(&(pax->pax_header), "ctime",
 			add_pax_attr_time(&(pax->pax_header), "ctime",
@@ -1072,6 +1062,23 @@ archive_write_pax_header(struct archive_write *a,
 			    "LIBARCHIVE.creationtime",
 			    "LIBARCHIVE.creationtime",
 			    archive_entry_birthtime(entry_main),
 			    archive_entry_birthtime(entry_main),
 			    archive_entry_birthtime_nsec(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. */
 		/* I use a star-compatible file flag attribute. */
 		p = archive_entry_fflags_text(entry_main);
 		p = archive_entry_fflags_text(entry_main);

+ 17 - 11
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 */
 	/* check whether warcinfo record needs outputting */
 	if (!w->omit_warcinfo) {
 	if (!w->omit_warcinfo) {
+		ssize_t r;
 		warc_essential_hdr_t wi = {
 		warc_essential_hdr_t wi = {
 			WT_INFO,
 			WT_INFO,
 			/*uri*/NULL,
 			/*uri*/NULL,
 			/*urn*/NULL,
 			/*urn*/NULL,
-			/*rtm*/w->now,
-			/*mtm*/w->now,
+			/*rtm*/0,
+			/*mtm*/0,
 			/*cty*/"application/warc-fields",
 			/*cty*/"application/warc-fields",
 			/*len*/sizeof(warcinfo) - 1U,
 			/*len*/sizeof(warcinfo) - 1U,
 		};
 		};
-		ssize_t r;
+		wi.rtime = w->now;
+		wi.mtime = w->now;
 
 
 		archive_string_init(&hdr);
 		archive_string_init(&hdr);
 		r = _popul_ehdr(&hdr, MAX_HDR_SIZE, wi);
 		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) {
 	if (w->typ == AE_IFREG) {
 		warc_essential_hdr_t rh = {
 		warc_essential_hdr_t rh = {
 			WT_RSRC,
 			WT_RSRC,
-			/*uri*/archive_entry_pathname(entry),
+			/*uri*/NULL,
 			/*urn*/NULL,
 			/*urn*/NULL,
-			/*rtm*/w->now,
-			/*mtm*/archive_entry_mtime(entry),
+			/*rtm*/0,
+			/*mtm*/0,
 			/*cty*/NULL,
 			/*cty*/NULL,
-			/*len*/(size_t)archive_entry_size(entry),
+			/*len*/0,
 		};
 		};
 		ssize_t r;
 		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);
 		archive_string_init(&hdr);
 		r = _popul_ehdr(&hdr, MAX_HDR_SIZE, rh);
 		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 */
 /** like strftime(3) but for time_t objects */
 	struct tm *rt;
 	struct tm *rt;
 #if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
 #if defined(HAVE_GMTIME_R) || defined(HAVE__GMTIME64_S)
-	struct tm time;
+	struct tm timeHere;
 #endif
 #endif
 	char strtime[100];
 	char strtime[100];
 	size_t len;
 	size_t len;
 
 
 #ifdef HAVE_GMTIME_R
 #ifdef HAVE_GMTIME_R
-	if ((rt = gmtime_r(&t, &time)) == NULL)
+	if ((rt = gmtime_r(&t, &timeHere)) == NULL)
 		return;
 		return;
 #elif defined(HAVE__GMTIME64_S)
 #elif defined(HAVE__GMTIME64_S)
-	_gmtime64_s(&time, &t);
+	_gmtime64_s(&timeHere, &t);
 #else
 #else
 	if ((rt = gmtime(&t)) == NULL)
 	if ((rt = gmtime(&t)) == NULL)
 		return;
 		return;
@@ -396,7 +402,7 @@ _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr)
 		 * handle the minimum number following '%'.
 		 * handle the minimum number following '%'.
 		 * So we have to use snprintf function here instead
 		 * So we have to use snprintf function here instead
 		 * of archive_string_snprintf function. */
 		 * of archive_string_snprintf function. */
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__) && !( defined(_MSC_VER) && _MSC_VER >= 1900)
 #define snprintf _snprintf
 #define snprintf _snprintf
 #endif
 #endif
 		snprintf(
 		snprintf(

+ 5 - 0
libarchive/archive_write_set_format_xar.c

@@ -1877,6 +1877,11 @@ xar_free(struct archive_write *a)
 	struct xar *xar;
 	struct xar *xar;
 
 
 	xar = (struct xar *)a->format_data;
 	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->cur_dirstr));
 	archive_string_free(&(xar->tstr));
 	archive_string_free(&(xar->tstr));
 	archive_string_free(&(xar->vstr));
 	archive_string_free(&(xar->vstr));

+ 24 - 21
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_LENGTH_AT_END	(1<<3)
 #define ZIP_ENTRY_FLAG_UTF8_NAME	(1 << 11)
 #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 {
 enum compression {
 	COMPRESSION_UNSPECIFIED = -1,
 	COMPRESSION_UNSPECIFIED = -1,
 	COMPRESSION_STORE = 0,
 	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) {
 	if (zip->flags & ZIP_FLAG_AVOID_ZIP64) {
 		/* Reject entries over 4GB. */
 		/* Reject entries over 4GB. */
 		if (archive_entry_size_is_set(entry)
 		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,
 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 			    "Files > 4GB require Zip64 extensions");
 			    "Files > 4GB require Zip64 extensions");
 			return ARCHIVE_FAILED;
 			return ARCHIVE_FAILED;
 		}
 		}
 		/* Reject entries if archive is > 4GB. */
 		/* 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,
 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 			    "Archives > 4GB require Zip64 extensions");
 			    "Archives > 4GB require Zip64 extensions");
 			return ARCHIVE_FAILED;
 			return ARCHIVE_FAILED;
@@ -726,8 +729,8 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 		 *    (compression might make file larger)
 		 *    (compression might make file larger)
 		 */
 		 */
 		if ((zip->flags & ZIP_FLAG_FORCE_ZIP64)
 		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_compression != COMPRESSION_STORE)) {
 			zip->entry_uses_zip64 = 1;
 			zip->entry_uses_zip64 = 1;
 			version_needed = 45;
 			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;
 		 * are included only if these are 0xffffffff;
 		 * THEREFORE these must be set this way, even if we
 		 * THEREFORE these must be set this way, even if we
 		 * know one of them is smaller. */
 		 * 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 {
 	} else {
 		archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size);
 		archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size);
 		archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size);
 		archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size);
@@ -820,7 +823,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 	archive_le16enc(zip->file_header + 28, (uint16_t)filename_length);
 	archive_le16enc(zip->file_header + 28, (uint16_t)filename_length);
 	/* Following Info-Zip, store mode in the "external attributes" field. */
 	/* Following Info-Zip, store mode in the "external attributes" field. */
 	archive_le32enc(zip->file_header + 38,
 	archive_le32enc(zip->file_header + 38,
-	    archive_entry_mode(zip->entry) << 16);
+	    ((uint32_t)archive_entry_mode(zip->entry)) << 16);
 	e = cd_alloc(zip, filename_length);
 	e = cd_alloc(zip, filename_length);
 	/* If (e == NULL) XXXX */
 	/* If (e == NULL) XXXX */
 	copy_path(zip->entry, e);
 	copy_path(zip->entry, e);
@@ -939,7 +942,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 		}
 		}
 		if (included & 4) {
 		if (included & 4) {
 			archive_le32enc(e,  /* external file attributes */
 			archive_le32enc(e,  /* external file attributes */
-			    archive_entry_mode(zip->entry) << 16);
+			    ((uint32_t)archive_entry_mode(zip->entry)) << 16);
 			e += 4;
 			e += 4;
 		}
 		}
 		if (included & 8) {
 		if (included & 8) {
@@ -1214,22 +1217,22 @@ archive_write_zip_finish_entry(struct archive_write *a)
 	}
 	}
 
 
 	/* Append Zip64 extra data to central directory information. */
 	/* 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 zip64[32];
 		unsigned char *z = zip64, *zd;
 		unsigned char *z = zip64, *zd;
 		memcpy(z, "\001\000\000\000", 4);
 		memcpy(z, "\001\000\000\000", 4);
 		z += 4;
 		z += 4;
-		if (zip->entry_uncompressed_written >= 0xffffffffLL) {
+		if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) {
 			archive_le64enc(z, zip->entry_uncompressed_written);
 			archive_le64enc(z, zip->entry_uncompressed_written);
 			z += 8;
 			z += 8;
 		}
 		}
-		if (zip->entry_compressed_written >= 0xffffffffLL) {
+		if (zip->entry_compressed_written >= ZIP_4GB_MAX) {
 			archive_le64enc(z, zip->entry_compressed_written);
 			archive_le64enc(z, zip->entry_compressed_written);
 			z += 8;
 			z += 8;
 		}
 		}
-		if (zip->entry_offset >= 0xffffffffLL) {
+		if (zip->entry_offset >= ZIP_4GB_MAX) {
 			archive_le64enc(z, zip->entry_offset);
 			archive_le64enc(z, zip->entry_offset);
 			z += 8;
 			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 + 16, zip->entry_crc32);
 	archive_le32enc(zip->file_header + 20,
 	archive_le32enc(zip->file_header + 20,
 		(uint32_t)zipmin(zip->entry_compressed_written,
 		(uint32_t)zipmin(zip->entry_compressed_written,
-				 ARCHIVE_LITERAL_LL(0xffffffff)));
+				 ZIP_4GB_MAX));
 	archive_le32enc(zip->file_header + 24,
 	archive_le32enc(zip->file_header + 24,
 		(uint32_t)zipmin(zip->entry_uncompressed_written,
 		(uint32_t)zipmin(zip->entry_uncompressed_written,
-				 ARCHIVE_LITERAL_LL(0xffffffff)));
+				 ZIP_4GB_MAX));
 	archive_le16enc(zip->file_header + 30,
 	archive_le16enc(zip->file_header + 30,
 	    (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset));
 	    (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset));
 	archive_le32enc(zip->file_header + 42,
 	archive_le32enc(zip->file_header + 42,
 		(uint32_t)zipmin(zip->entry_offset,
 		(uint32_t)zipmin(zip->entry_offset,
-				 ARCHIVE_LITERAL_LL(0xffffffff)));
+				 ZIP_4GB_MAX));
 
 
 	return (ARCHIVE_OK);
 	return (ARCHIVE_OK);
 }
 }
@@ -1288,8 +1291,8 @@ archive_write_zip_close(struct archive_write *a)
 	offset_end = zip->written_bytes;
 	offset_end = zip->written_bytes;
 
 
 	/* If central dir info is too large, write Zip64 end-of-cd */
 	/* 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->central_directory_entries > 0xffffUL
 	    || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) {
 	    || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) {
 	  /* Zip64 end-of-cd record */
 	  /* 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,
 	archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU,
 		zip->central_directory_entries));
 		zip->central_directory_entries));
 	archive_le32enc(buff + 12,
 	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,
 	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);
 	ret = __archive_write_output(a, buff, 22);
 	if (ret != ARCHIVE_OK)
 	if (ret != ARCHIVE_OK)
 		return (ARCHIVE_FATAL);
 		return (ARCHIVE_FATAL);

+ 10 - 9
libarchive/archive_write_set_options.3

@@ -101,7 +101,12 @@ and
 .Ar value
 .Ar value
 will be provided to the filter or reader named
 will be provided to the filter or reader named
 .Ar module .
 .Ar module .
-The return value will be that of the module.
+The return value will be either
+.Cm ARCHIVE_OK
+if the option was successfully handled or
+.Cm ARCHIVE_WARN
+if the option was unrecognized by the module or could otherwise
+not be handled.
 If there is no such module,
 If there is no such module,
 .Cm ARCHIVE_FAILED
 .Cm ARCHIVE_FAILED
 will be returned.
 will be returned.
@@ -123,9 +128,7 @@ will be returned if any module accepts the option, and
 .Cm ARCHIVE_FAILED
 .Cm ARCHIVE_FAILED
 in all other cases.
 in all other cases.
 .\"
 .\"
-.It Xo
-.Fn archive_write_set_option
-.Xc
+.It Fn archive_write_set_option
 Calls
 Calls
 .Fn archive_write_set_format_option ,
 .Fn archive_write_set_format_option ,
 then
 then
@@ -137,9 +140,7 @@ will be returned
 immediately.
 immediately.
 Otherwise, greater of the two values will be returned.
 Otherwise, greater of the two values will be returned.
 .\"
 .\"
-.It Xo
-.Fn archive_write_set_options
-.Xc
+.It Fn archive_write_set_options
 .Ar options
 .Ar options
 is a comma-separated list of options.
 is a comma-separated list of options.
 If
 If
@@ -255,7 +256,7 @@ If the
 .Ar value
 .Ar value
 is
 is
 .Cm hd ,
 .Cm hd ,
-then the the boot image is assumed to be a bootable hard disk image.
+then the boot image is assumed to be a bootable hard disk image.
 If the
 If the
 .Ar value
 .Ar value
 is
 is
@@ -456,7 +457,7 @@ archive_write_open_filename(a, filename, blocksize);
 .Ed
 .Ed
 .\"
 .\"
 .Sh ERRORS
 .Sh ERRORS
-Detailed error codes and textual descriptions are available from the
+More detailed error codes and textual descriptions are available from the
 .Fn archive_errno
 .Fn archive_errno
 and
 and
 .Fn archive_error_string
 .Fn archive_error_string

+ 46 - 9
libarchive/libarchive-formats.5

@@ -55,7 +55,7 @@ It can write POSIX-standard
 .Dq ustar
 .Dq ustar
 and
 and
 .Dq pax interchange
 .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
 .Pp
 All tar formats store each entry in one or more 512-byte records.
 All tar formats store each entry in one or more 512-byte records.
 The first record is used for file metadata, including filename,
 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.
 Note that the pax interchange format has none of these restrictions.
 The ustar format is old and widely supported.
 The ustar format is old and widely supported.
 It is recommended when compatibility is the primary concern.
 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
 .El
 .Pp
 .Pp
 The libarchive library also reads a variety of commonly-used extensions to
 The libarchive library also reads a variety of commonly-used extensions to
@@ -211,7 +235,7 @@ This format stores the header contents as octal values in ASCII.
 It is standard, portable, and immune from byte-order confusion.
 It is standard, portable, and immune from byte-order confusion.
 File sizes and mtime are limited to 33 bits (8GB file size),
 File sizes and mtime are limited to 33 bits (8GB file size),
 other fields are limited to 18 bits.
 other fields are limited to 18 bits.
-.It Cm SVR4
+.It Cm SVR4/newc
 The libarchive library can read both CRC and non-CRC variants of
 The libarchive library can read both CRC and non-CRC variants of
 this format.
 this format.
 The SVR4 format uses eight-digit hexadecimal values for
 The SVR4 format uses eight-digit hexadecimal values for
@@ -364,8 +388,10 @@ area adjacent to the entry.
 Libarchive can read both extensions,
 Libarchive can read both extensions,
 including archives that may include both types of long filenames.
 including archives that may include both types of long filenames.
 Programs using libarchive can write GNU/SVR4 format
 Programs using libarchive can write GNU/SVR4 format
-if they provide a filename table to be written into
-the archive before any of the entries.
+if they provide an entry called
+.Pa //
+containing a filename table to be written into the archive
+before any of the entries.
 Any entries whose names are not in the filename table
 Any entries whose names are not in the filename table
 will be written using BSD-style long filenames.
 will be written using BSD-style long filenames.
 This can cause problems for programs such as
 This can cause problems for programs such as
@@ -406,18 +432,29 @@ using libarchive.
 If it cannot locate and open the file on disk, libarchive
 If it cannot locate and open the file on disk, libarchive
 will return an error for any attempt to read the entry
 will return an error for any attempt to read the entry
 body.
 body.
-.Ss LHA
-XXX Information about libarchive's LHA support XXX
+.Ss 7-Zip
+Libarchive can read and write 7-Zip format archives.
+TODO: Need more information
 .Ss CAB
 .Ss CAB
-XXX Information about libarchive's CAB support XXX
-.Ss XAR
-XXX Information about libarchive's XAR support XXX
+Libarchive can read Microsoft Cabinet (
+.Dq CAB )
+format archives.
+TODO: Need more information.
+.Ss LHA
+TODO: Information about libarchive's LHA support
 .Ss RAR
 .Ss RAR
 Libarchive has limited support for reading RAR format archives.
 Libarchive has limited support for reading RAR format archives.
 Currently, libarchive can read RARv3 format archives
 Currently, libarchive can read RARv3 format archives
 which have been either created uncompressed, or compressed using
 which have been either created uncompressed, or compressed using
 any of the compression methods supported by the RARv3 format.
 any of the compression methods supported by the RARv3 format.
 Libarchive can also read self-extracting RAR archives.
 Libarchive can also read self-extracting RAR archives.
+.Ss Warc
+Libarchive can read and write
+.Dq web archives .
+TODO: Need more information
+.Ss XAR
+Libarchive can read and write the XAR format used by many Apple tools.
+TODO: Need more information
 .Sh SEE ALSO
 .Sh SEE ALSO
 .Xr ar 1 ,
 .Xr ar 1 ,
 .Xr cpio 1 ,
 .Xr cpio 1 ,

+ 17 - 3
libarchive/xxhash.c

@@ -29,8 +29,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 You can contact the author at :
 You can contact the author at :
 - xxHash source repository : http://code.google.com/p/xxhash/
 - xxHash source repository : http://code.google.com/p/xxhash/
 */
 */
+#include <stdlib.h>
+#include <string.h>
 
 
 #include "archive_platform.h"
 #include "archive_platform.h"
+#include "archive_xxhash.h"
+
 #ifdef HAVE_LIBLZ4
 #ifdef HAVE_LIBLZ4
 
 
 /***************************************
 /***************************************
@@ -83,11 +87,8 @@ You can contact the author at :
 /***************************************
 /***************************************
 ** Includes & Memory related functions
 ** Includes & Memory related functions
 ****************************************/
 ****************************************/
-#include "archive_xxhash.h"
-#include <stdlib.h>
 #define XXH_malloc malloc
 #define XXH_malloc malloc
 #define XXH_free free
 #define XXH_free free
-#include <string.h>
 #define XXH_memcpy memcpy
 #define XXH_memcpy memcpy
 
 
 
 
@@ -497,4 +498,17 @@ struct archive_xxhash __archive_xxhash = {
 	XXH32_update,
 	XXH32_update,
 	XXH32_digest
 	XXH32_digest
 };
 };
+#else
+
+/*
+ * Define an empty version of the struct if we aren't using the LZ4 library.
+ */
+const
+struct archive_xxhash __archive_xxhash = {
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
 #endif /* HAVE_LIBLZ4 */
 #endif /* HAVE_LIBLZ4 */