From 4f4fe6e50bb3dbe59f9bc3cc848cbd07dead324d Mon Sep 17 00:00:00 2001 From: LibArchive Upstream Date: Sat, 31 Dec 2011 13:54:34 -0500 Subject: [PATCH] libarchive 3.0.2-r4051 (reduced) Extract upstream libarchive using the following shell code. url=https://libarchive.googlecode.com/svn/release/3.0 v=3.0.2 r=4051 paths=" CMakeLists.txt COPYING CTestConfig.cmake build/cmake build/pkgconfig build/utils build/version libarchive/*.* " date=$(svn log -q -c$r $url | sed -n "/^r/ {s/[^|]*|[^|]*|//;p;}") svn export -r$r $url libarchive-$v-r$r && mkdir libarchive-$v-r$r-reduced && (cd libarchive-$v-r$r && tar c $paths) | (cd libarchive-$v-r$r-reduced && tar x) echo "r$r date: $date" --- CMakeLists.txt | 19 +- build/cmake/AddTest28.cmake | 107 -- build/version | 2 +- libarchive/archive.h | 19 +- libarchive/archive_entry.3 | 2 +- libarchive/archive_entry.h | 2 +- libarchive/archive_entry_acl.3 | 2 +- libarchive/archive_entry_linkify.3 | 2 +- libarchive/archive_entry_paths.3 | 2 +- libarchive/archive_entry_perms.3 | 2 +- libarchive/archive_entry_stat.3 | 2 +- libarchive/archive_entry_time.3 | 2 +- libarchive/archive_read.3 | 2 +- libarchive/archive_read.c | 16 - libarchive/archive_read_data.3 | 16 +- libarchive/archive_read_data_into_fd.c | 2 +- libarchive/archive_read_disk.3 | 4 +- .../archive_read_disk_entry_from_file.c | 2 +- libarchive/archive_read_disk_posix.c | 2 + libarchive/archive_read_extract.3 | 2 +- libarchive/archive_read_filter.3 | 2 +- libarchive/archive_read_format.3 | 2 +- libarchive/archive_read_free.3 | 2 +- libarchive/archive_read_header.3 | 2 +- libarchive/archive_read_new.3 | 2 +- libarchive/archive_read_open.3 | 2 +- libarchive/archive_read_set_options.3 | 2 +- libarchive/archive_read_support_format_7zip.c | 1015 +++++++++-------- .../archive_read_support_format_iso9660.c | 6 +- libarchive/archive_read_support_format_zip.c | 35 +- libarchive/archive_string.c | 51 +- libarchive/archive_util.3 | 2 +- libarchive/archive_windows.c | 42 +- libarchive/archive_windows.h | 3 +- libarchive/archive_write.3 | 2 +- libarchive/archive_write_blocksize.3 | 2 +- libarchive/archive_write_data.3 | 2 +- libarchive/archive_write_disk.3 | 2 +- libarchive/archive_write_disk_windows.c | 28 +- libarchive/archive_write_filter.3 | 2 +- libarchive/archive_write_finish_entry.3 | 2 +- libarchive/archive_write_format.3 | 2 +- libarchive/archive_write_free.3 | 2 +- libarchive/archive_write_header.3 | 2 +- libarchive/archive_write_new.3 | 2 +- libarchive/archive_write_open.3 | 2 +- libarchive/archive_write_set_format_7zip.c | 40 +- libarchive/archive_write_set_format_xar.c | 17 +- libarchive/archive_write_set_format_zip.c | 84 +- libarchive/archive_write_set_options.3 | 2 +- libarchive/cpio.5 | 50 +- libarchive/filter_fork_windows.c | 48 +- libarchive/libarchive-formats.5 | 2 +- libarchive/libarchive_changes.3 | 2 +- libarchive/tar.5 | 2 +- 55 files changed, 824 insertions(+), 850 deletions(-) delete mode 100644 build/cmake/AddTest28.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index aed3c0a8b..60672ce64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,12 +2,12 @@ # PROJECT(libarchive C) # -CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin) endif() -SET(CMAKE_BUILD_TYPE "Debug") +SET(CMAKE_BUILD_TYPE "Release") # On MacOS, prefer MacPorts libraries to system libraries. # I haven't come up with a compelling argument for this to be conditional. @@ -38,9 +38,10 @@ SET(LIBARCHIVE_VERSION_STRING "${VERSION}") # INTERFACE_VERSION increments with every release # libarchive 2.7 == interface version 9 = 2 + 7 # libarchive 2.8 == interface version 10 = 2 + 8 -# libarchive 3.0 == interface version 11 -# libarchive 3.x == interface version 11 + x -math(EXPR INTERFACE_VERSION "11 + ${_minor}") +# libarchive 2.9 == interface version 11 = 2 + 9 +# libarchive 3.0 == interface version 12 +# libarchive 3.x == interface version 12 + x +math(EXPR INTERFACE_VERSION "12 + ${_minor}") # Set SOVERSION == Interface version # ?? Should there be more here ?? @@ -50,17 +51,13 @@ SET(SOVERSION "${INTERFACE_VERSION}") # aggressive about diagnosing build problems; this can get # relaxed somewhat in final shipping versions. IF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") - ADD_DEFINITIONS(-Wall -Werror) - SET(CMAKE_REQUIRED_FLAGS "-Wall -Werror") + ADD_DEFINITIONS(-Wall) + SET(CMAKE_REQUIRED_FLAGS "-Wall") ENDIF ("CMAKE_C_COMPILER_ID" MATCHES "^GNU$") # Enable CTest/CDash support include(CTest) -# Provide ADD_TEST_28 macro to approximate CMake 2.8 ADD_TEST(NAME). -# TODO: Require CMake 2.8 and drop this workaround (perhaps late 2010). -INCLUDE(AddTest28) - OPTION(ENABLE_NETTLE "Enable use of Nettle" ON) OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) OPTION(ENABLE_TAR "Enable tar building" ON) diff --git a/build/cmake/AddTest28.cmake b/build/cmake/AddTest28.cmake deleted file mode 100644 index ab26a9a9b..000000000 --- a/build/cmake/AddTest28.cmake +++ /dev/null @@ -1,107 +0,0 @@ -# - Macro approximating the CMake 2.8 ADD_TEST(NAME) signature. -# ADD_TEST_28(NAME COMMAND [arg1 [arg2 ...]]) -# - The name of the test -# - The test executable -# [argN...] - Arguments to the test executable -# This macro approximates the ADD_TEST(NAME) signature provided in -# CMake 2.8 but works with CMake 2.6 too. See CMake 2.8 documentation -# of ADD_TEST()for details. -# -# This macro automatically replaces a that names an -# executable target with the target location. A generator expression -# of the form "$" is supported in both the command -# and arguments of the test. Howerver, this macro only works for -# targets without per-config output name properties set. -# -# Example usage: -# add_test(NAME mytest COMMAND testDriver --exe $) -# This creates a test "mytest" whose command runs a testDriver tool -# passing the full path to the executable file produced by target -# "myexe". - -#============================================================================= -# Copyright 2009 Kitware, Inc. -# 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 -# in this position and unchanged. -# 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. -#============================================================================= - -CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3) - -# CMake 2.8 supports ADD_TEST(NAME) natively. -IF(NOT "${CMAKE_VERSION}" VERSION_LESS "2.8") - MACRO(ADD_TEST_28) - ADD_TEST(${ARGV}) - ENDMACRO() - RETURN() -ENDIF() - -# Simulate ADD_TEST(NAME) signature from CMake 2.8. -MACRO(ADD_TEST_28 NAME name COMMAND command) - # Enforce the signature. - IF(NOT "x${NAME}" STREQUAL "xNAME") - MESSAGE(FATAL_ERROR "First ADD_TEST_28 argument must be \"NAME\"") - ENDIF() - IF(NOT "x${COMMAND}" STREQUAL "xCOMMAND") - MESSAGE(FATAL_ERROR "Third ADD_TEST_28 argument must be \"COMMAND\"") - ENDIF() - - # Perform "COMMAND myexe ..." substitution. - SET(cmd "${command}") - IF(TARGET "${cmd}") - _ADD_TEST_28_GET_EXE(${cmd} cmd) - ENDIF() - - # Perform "COMMAND ... $ ..." substitution. - SET(target_file "\\$") - SET(args) - FOREACH(ARG ${cmd} ${ARGN}) - SET(arg "${ARG}") - IF("${arg}" MATCHES "${target_file}") - STRING(REGEX REPLACE "${target_file}" "\\1" tgt "${arg}") - IF(TARGET "${tgt}") - _ADD_TEST_28_GET_EXE(${tgt} exe) - STRING(REGEX REPLACE "${target_file}" "${exe}" arg "${arg}") - ENDIF() - ENDIF() - LIST(APPEND args "${arg}") - ENDFOREACH() - - # Invoke old ADD_TEST() signature with transformed arguments. - ADD_TEST(${name} ${args}) -ENDMACRO() - -# Get the test-time location of an executable target. -MACRO(_ADD_TEST_28_GET_EXE tgt exe_var) - # The LOCATION property gives a build-time location. - GET_TARGET_PROPERTY(${exe_var} ${tgt} LOCATION) - - # In single-configuration generatrs the build-time and test-time - # locations are the same because there is no per-config variable - # reference. In multi-configuration generators the following - # substitution converts the build-time configuration variable - # reference to a test-time configuration variable reference. - IF(CMAKE_CONFIGURATION_TYPES) - STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CTEST_CONFIGURATION_TYPE}" - ${exe_var} "${${exe_var}}") - ENDIF(CMAKE_CONFIGURATION_TYPES) -ENDMACRO() diff --git a/build/version b/build/version index 6ff875b3a..ee575c8f5 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3000001b +3000002 diff --git a/libarchive/archive.h b/libarchive/archive.h index 14c2aed98..13cbe7948 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -124,27 +124,16 @@ extern "C" { * 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 >= 2012108. - * - * This single-number format was introduced with libarchive 1.9.0 in - * the libarchive 1.x family and libarchive 2.2.4 in the libarchive - * 2.x family. The following may be useful if you really want to do - * feature detection for earlier libarchive versions (which defined - * ARCHIVE_API_VERSION and ARCHIVE_API_FEATURE instead): - * - * #ifndef ARCHIVE_VERSION_NUMBER - * #define ARCHIVE_VERSION_NUMBER \ - * (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000) - * #endif + * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3000001 +#define ARCHIVE_VERSION_NUMBER 3000002 __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_STRING "libarchive 3.0.1b" +#define ARCHIVE_VERSION_STRING "libarchive 3.0.2" __LA_DECL const char * archive_version_string(void); /* Declare our basic types. */ @@ -447,8 +436,6 @@ __LA_DECL int archive_read_data_block(struct archive *a, * 'into_fd': writes data to specified filedes */ __LA_DECL int archive_read_data_skip(struct archive *); -__LA_DECL int archive_read_data_into_buffer(struct archive *, - void *buffer, __LA_SSIZE_T len); __LA_DECL int archive_read_data_into_fd(struct archive *, int fd); /* diff --git a/libarchive/archive_entry.3 b/libarchive/archive_entry.3 index 1bd7cfb24..10e3c34cc 100644 --- a/libarchive/archive_entry.3 +++ b/libarchive/archive_entry.3 @@ -26,7 +26,7 @@ .\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $ .\" .Dd Feburary 22, 2010 -.Dt archive_entry 3 +.Dt ARCHIVE_ENTRY 3 .Os .Sh NAME .Nm archive_entry_clear , diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index fcd76573c..533dc7f81 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -29,7 +29,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3000001 +#define ARCHIVE_VERSION_NUMBER 3000002 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive/archive_entry_acl.3 b/libarchive/archive_entry_acl.3 index 896b35afd..93906e798 100644 --- a/libarchive/archive_entry_acl.3 +++ b/libarchive/archive_entry_acl.3 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" .Dd February 21, 2010 -.Dt archive_entry_acl 3 +.Dt ARCHIVE_ENTRY_ACL 3 .Os .Sh NAME .Nm archive_entry_acl_add_entry , diff --git a/libarchive/archive_entry_linkify.3 b/libarchive/archive_entry_linkify.3 index 6b1b9a53e..a34b095e7 100644 --- a/libarchive/archive_entry_linkify.3 +++ b/libarchive/archive_entry_linkify.3 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" .Dd February 20, 2010 -.Dt archive_entry_linkify 3 +.Dt ARCHIVE_ENTRY_LINKIFY 3 .Os .Sh NAME .Nm archive_entry_linkresolver , diff --git a/libarchive/archive_entry_paths.3 b/libarchive/archive_entry_paths.3 index 05243c070..621f65518 100644 --- a/libarchive/archive_entry_paths.3 +++ b/libarchive/archive_entry_paths.3 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" .Dd February 22, 2010 -.Dt archive_entry_paths 3 +.Dt ARCHIVE_ENTRY_PATHS 3 .Os .Sh NAME .Nm archive_entry_hardlink , diff --git a/libarchive/archive_entry_perms.3 b/libarchive/archive_entry_perms.3 index 452a19f3b..164af9731 100644 --- a/libarchive/archive_entry_perms.3 +++ b/libarchive/archive_entry_perms.3 @@ -24,7 +24,7 @@ .\" SUCH DAMAGE. .\" .Dd February 22, 2010 -.Dt archive_entry_perms 3 +.Dt ARCHIVE_ENTRY_PERMS 3 .Os .Sh NAME .Nm archive_entry_gid , diff --git a/libarchive/archive_entry_stat.3 b/libarchive/archive_entry_stat.3 index a988ecfc5..36a7efb23 100644 --- a/libarchive/archive_entry_stat.3 +++ b/libarchive/archive_entry_stat.3 @@ -23,7 +23,7 @@ .\" SUCH DAMAGE. .\" .Dd May 12, 2008 -.Dt archive_entry 3 +.Dt ARCHIVE_ENTRY 3 .Os .Sh NAME .Nm archive_entry_stat , diff --git a/libarchive/archive_entry_time.3 b/libarchive/archive_entry_time.3 index 7787ca579..85a8209e8 100644 --- a/libarchive/archive_entry_time.3 +++ b/libarchive/archive_entry_time.3 @@ -26,7 +26,7 @@ .\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $ .\" .Dd February 21, 2010 -.Dt archive_entry_time 3 +.Dt ARCHIVE_ENTRY_TIME 3 .Os .Sh NAME .Nm archive_entry_atime , diff --git a/libarchive/archive_read.3 b/libarchive/archive_read.3 index 70527fb48..52851925c 100644 --- a/libarchive/archive_read.3 +++ b/libarchive/archive_read.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ .\" .Dd March 23, 2011 -.Dt archive_read 3 +.Dt ARCHIVE_READ 3 .Os .Sh NAME .Nm archive_read diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index 441be5316..b1d491435 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -668,22 +668,6 @@ archive_read_data(struct archive *_a, void *buff, size_t s) return (bytes_read); } -#if ARCHIVE_API_VERSION < 3 -/* - * Obsolete function provided for compatibility only. Note that the API - * of this function doesn't allow the caller to detect if the remaining - * data from the archive entry is shorter than the buffer provided, or - * even if an error occurred while reading data. - */ -int -archive_read_data_into_buffer(struct archive *a, void *d, ssize_t len) -{ - - archive_read_data(a, d, len); - return (ARCHIVE_OK); -} -#endif - /* * Skip over all remaining data in this entry. */ diff --git a/libarchive/archive_read_data.3 b/libarchive/archive_read_data.3 index a5898e7b8..78d049782 100644 --- a/libarchive/archive_read_data.3 +++ b/libarchive/archive_read_data.3 @@ -25,15 +25,12 @@ .\" $FreeBSD$ .\" .Dd March 22, 2011 -.Dt archive_read_data 3 +.Dt ARCHIVE_READ_DATA 3 .Os .Sh NAME .Nm archive_read_data .Nm archive_read_data_block , .Nm archive_read_data_skip , -.\" #if ARCHIVE_API_VERSION < 3 -.Nm archive_read_data_into_buffer , -.\" #endif .Nm archive_read_data_into_fd .Nd functions for reading streaming archives .Sh SYNOPSIS @@ -49,10 +46,6 @@ .Fc .Ft int .Fn archive_read_data_skip "struct archive *" -.\" #if ARCHIVE_API_VERSION < 3 -.Ft int -.Fn archive_read_data_into_buffer "struct archive *" "void *" "ssize_t len" -.\" #endif .Ft int .Fn archive_read_data_into_fd "struct archive *" "int fd" .\" @@ -84,13 +77,6 @@ to skip all of the data for this archive entry. Note that this function is invoked automatically by .Fn archive_read_next_header2 if the previous entry was not completely consumed. -.\" #if ARCHIVE_API_VERSION < 3 -.It Fn archive_read_data_into_buffer -This function is deprecated and will be removed. -Use -.Fn archive_read_data -instead. -.\" #endif .It Fn archive_read_data_into_fd A convenience function that repeatedly calls .Fn archive_read_data_block diff --git a/libarchive/archive_read_data_into_fd.c b/libarchive/archive_read_data_into_fd.c index 04d3ab07d..14f941070 100644 --- a/libarchive/archive_read_data_into_fd.c +++ b/libarchive/archive_read_data_into_fd.c @@ -45,7 +45,7 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.16 2008/0 /* * This implementation minimizes copying of data and is sparse-file aware. */ -int +static int pad_to(struct archive *a, int fd, int can_lseek, size_t nulls_size, const char *nulls, int64_t target_offset, int64_t actual_offset) diff --git a/libarchive/archive_read_disk.3 b/libarchive/archive_read_disk.3 index d3b6101d7..3c49bffc8 100644 --- a/libarchive/archive_read_disk.3 +++ b/libarchive/archive_read_disk.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $ .\" .Dd March 10, 2009 -.Dt archive_read_disk 3 +.Dt ARCHIVE_READ_DISK 3 .Os .Sh NAME .Nm archive_read_disk_new , @@ -283,7 +283,7 @@ and first appeared in The .Nm libarchive library was written by -.An Tim Kientzle Aq kientzle@freebsd.org . +.An Tim Kientzle Aq kientzle@FreeBSD.org . .Sh BUGS The .Dq standard diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index cc3915170..8ce88b380 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -246,7 +246,7 @@ archive_read_disk_entry_from_file(struct archive *_a, return (r); } -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(HAVE_COPYFILE_H) /* * The Mac OS "copyfile()" API copies the extended metadata for a * file into a separate file in AppleDouble format (see RFC 1740). diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 7a9c3d867..b81ab30fe 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -1321,9 +1321,11 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->synthetic = 0; #endif +#if defined(MNT_NOATIME) if (sfs.f_flags & MNT_NOATIME) t->current_filesystem->noatime = 1; else +#endif t->current_filesystem->noatime = 0; #if defined(HAVE_READDIR_R) diff --git a/libarchive/archive_read_extract.3 b/libarchive/archive_read_extract.3 index 950248e07..882c6e199 100644 --- a/libarchive/archive_read_extract.3 +++ b/libarchive/archive_read_extract.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 22, 2011 -.Dt archive_read_extract 3 +.Dt ARCHIVE_READ_EXTRACT 3 .Os .Sh NAME .Nm archive_read_extract , diff --git a/libarchive/archive_read_filter.3 b/libarchive/archive_read_filter.3 index 7b506ccc2..1cfa21599 100644 --- a/libarchive/archive_read_filter.3 +++ b/libarchive/archive_read_filter.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 19, 2011 -.Dt archive_read_filter 3 +.Dt ARCHIVE_READ_FILTER 3 .Os .Sh NAME .Nm archive_read_support_filter_all , diff --git a/libarchive/archive_read_format.3 b/libarchive/archive_read_format.3 index 3b5abf33a..e707e05f6 100644 --- a/libarchive/archive_read_format.3 +++ b/libarchive/archive_read_format.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ .\" .Dd March 19, 2011 -.Dt archive_read_format 3 +.Dt ARCHIVE_READ_FORMAT 3 .Os .Sh NAME .Nm archive_read_support_format_7zip , diff --git a/libarchive/archive_read_free.3 b/libarchive/archive_read_free.3 index 5838e20c9..f5f2515a8 100644 --- a/libarchive/archive_read_free.3 +++ b/libarchive/archive_read_free.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ .\" .Dd March 20, 2011 -.Dt archive_read_free 3 +.Dt ARCHIVE_READ_FREE 3 .Os .Sh NAME .Nm archive_read_close , diff --git a/libarchive/archive_read_header.3 b/libarchive/archive_read_header.3 index f8543f7ac..999e963cf 100644 --- a/libarchive/archive_read_header.3 +++ b/libarchive/archive_read_header.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 22, 2011 -.Dt archive_read_header 3 +.Dt ARCHIVE_READ_HEADER 3 .Os .Sh NAME .Nm archive_read_next_header , diff --git a/libarchive/archive_read_new.3 b/libarchive/archive_read_new.3 index d2d986227..e04406aa6 100644 --- a/libarchive/archive_read_new.3 +++ b/libarchive/archive_read_new.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ .\" .Dd March 20, 2011 -.Dt archive_read_new 3 +.Dt ARCHIVE_READ_NEW 3 .Os .Sh NAME .Nm archive_read_new diff --git a/libarchive/archive_read_open.3 b/libarchive/archive_read_open.3 index ff156416f..09c057568 100644 --- a/libarchive/archive_read_open.3 +++ b/libarchive/archive_read_open.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $ .\" .Dd March 19, 2011 -.Dt archive_read_open 3 +.Dt ARCHIVE_READ_OPEN 3 .Os .Sh NAME .Nm archive_read_open , diff --git a/libarchive/archive_read_set_options.3 b/libarchive/archive_read_set_options.3 index 2079d2e26..81efb08b5 100644 --- a/libarchive/archive_read_set_options.3 +++ b/libarchive/archive_read_set_options.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd April 13, 2009 -.Dt archive_read_options 3 +.Dt ARCHIVE_READ_OPTIONS 3 .Os .Sh NAME .Nm archive_read_set_filter_option , diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index f581ee560..330ba6ace 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -204,6 +204,10 @@ struct _7zip { /* Structural information about the archive. */ struct _7z_stream_info si; + int header_is_being_read; + int header_is_encoded; + uint64_t header_bytes_remaining; + unsigned long header_crc32; /* Header offset to check that reading pointes of the file contens * will not exceed the header. */ uint64_t header_offset; @@ -228,6 +232,7 @@ struct _7zip { char end_of_entry; /* Uncompressed buffer control. */ +#define UBUFF_SIZE (64 * 1024) unsigned char *uncompressed_buffer; unsigned char *uncompressed_buffer_pointer; size_t uncompressed_buffer_size; @@ -288,6 +293,10 @@ struct _7zip { uint32_t bcj_state; size_t odd_bcj_size; unsigned char odd_bcj[4]; + /* Decoding BCJ data. */ + size_t bcj_prevPosT; + uint32_t bcj_prevMask; + uint32_t bcj_ip; /* Decoding BCJ2 data. */ size_t main_stream_bytes_remaining; @@ -324,12 +333,11 @@ static int archive_read_format_7zip_read_header(struct archive_read *, struct archive_entry *); static int check_7zip_header_in_sfx(const char *); static unsigned long decode_codec_id(const unsigned char *, size_t); -static ssize_t decode_header_image(struct archive_read *, struct _7zip *, - struct _7z_stream_info *, const unsigned char *, uint64_t, - const void **); +static int decode_encoded_header_info(struct archive_read *, + struct _7z_stream_info *); static int decompress(struct archive_read *, struct _7zip *, void *, size_t *, const void *, size_t *); -static ssize_t extract_pack_stream(struct archive_read *); +static ssize_t extract_pack_stream(struct archive_read *, size_t); static void fileTimeToUtc(uint64_t, time_t *, long *); static uint64_t folder_uncompressed_size(struct _7z_folder *); static void free_CodersInfo(struct _7z_coders_info *); @@ -341,39 +349,39 @@ static void free_StreamsInfo(struct _7z_stream_info *); static void free_SubStreamsInfo(struct _7z_substream_info *); static int free_decompression(struct archive_read *, struct _7zip *); static ssize_t get_uncompressed_data(struct archive_read *, const void **, - size_t); + size_t, size_t); +static const unsigned char * header_bytes(struct archive_read *, size_t); static int init_decompression(struct archive_read *, struct _7zip *, const struct _7z_coder *, const struct _7z_coder *); -static int parse_7zip_uint64(const unsigned char *, size_t, uint64_t *); -static int read_Bools(unsigned char *, size_t, const unsigned char *, +static int parse_7zip_uint64(struct archive_read *, uint64_t *); +static int read_Bools(struct archive_read *, unsigned char *, size_t); +static int read_CodersInfo(struct archive_read *, + struct _7z_coders_info *); +static int read_Digests(struct archive_read *, struct _7z_digests *, size_t); -static int read_CodersInfo(struct _7z_coders_info *, - const unsigned char *, size_t); -static int read_Digests(struct _7z_digests *, size_t, - const unsigned char *, size_t); -static int read_Folder(struct _7z_folder *, const unsigned char *, - size_t); -static int read_Header(struct _7zip *, struct _7z_header_info *, - const unsigned char *, size_t); -static int read_PackInfo(struct _7z_pack_info *, const unsigned char *, - size_t); -static int read_StreamsInfo(struct _7zip *, struct _7z_stream_info *, - const unsigned char *, size_t); -static int read_SubStreamsInfo(struct _7z_substream_info *, - struct _7z_folder *, size_t, const unsigned char *, - size_t); -static int read_Times(struct _7zip *, struct _7z_header_info *, int, - const unsigned char *, size_t); +static int read_Folder(struct archive_read *, struct _7z_folder *); +static int read_Header(struct archive_read *, struct _7z_header_info *, + int); +static int read_PackInfo(struct archive_read *, struct _7z_pack_info *); +static int read_StreamsInfo(struct archive_read *, + struct _7z_stream_info *); +static int read_SubStreamsInfo(struct archive_read *, + struct _7z_substream_info *, struct _7z_folder *, size_t); +static int read_Times(struct archive_read *, struct _7z_header_info *, + int); static void read_consume(struct archive_read *); -static ssize_t read_stream(struct archive_read *, const void **, size_t); +static ssize_t read_stream(struct archive_read *, const void **, size_t, + size_t); +static int seek_pack(struct archive_read *); static int64_t skip_stream(struct archive_read *, size_t); static int skip_sfx(struct archive_read *, ssize_t); static int slurp_central_directory(struct archive_read *, struct _7zip *, struct _7z_header_info *); static int setup_decode_folder(struct archive_read *, struct _7z_folder *, int); -static size_t x86_Convert(uint8_t *, size_t, uint32_t, uint32_t *); -ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t); +static void x86_Init(struct _7zip *); +static size_t x86_Convert(struct _7zip *, uint8_t *, size_t); +static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t); int @@ -641,16 +649,16 @@ archive_read_format_7zip_read_header(struct archive_read *a, int r; /* - * Symbolic-name is recorded as its contents. We have to read the - * contents at this time. + * Symbolic-name is recorded as its contents. We have to + * read the contents at this time. */ while (zip->entry_bytes_remaining > 0) { const void *buff; size_t size; int64_t offset; - r = archive_read_format_7zip_read_data(a, &buff, &size, - &offset); + r = archive_read_format_7zip_read_data(a, &buff, + &size, &offset); if (r < ARCHIVE_WARN) return (r); symname = realloc(symname, symsize + size + 1); @@ -663,13 +671,15 @@ archive_read_format_7zip_read_header(struct archive_read *a, symsize += size; } if (symsize == 0) { - /* If there is no synname, handle it as a regular file. */ + /* If there is no synname, handle it as a regular + * file. */ zip_entry->mode &= ~AE_IFMT; zip_entry->mode |= AE_IFREG; archive_entry_set_mode(entry, zip_entry->mode); } else { symname[symsize] = '\0'; - archive_entry_copy_symlink(entry, (const char *)symname); + archive_entry_copy_symlink(entry, + (const char *)symname); free(symname); } archive_entry_set_size(entry, 0); @@ -706,7 +716,7 @@ archive_read_format_7zip_read_data(struct archive_read *a, return (ARCHIVE_EOF); } - bytes = read_stream(a, buff, zip->entry_bytes_remaining); + bytes = read_stream(a, buff, zip->entry_bytes_remaining, 0); if (bytes < 0) return ((int)bytes); if (bytes == 0) { @@ -929,6 +939,8 @@ init_decompression(struct archive_read *a, struct _7zip *zip, } zip->codec2 = coder2->codec; zip->bcj_state = 0; + if (coder2->codec == _7Z_X86) + x86_Init(zip); } break; default: @@ -990,7 +1002,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, fi++; } else /* Use our filter. */ - zip->bcj_state = 0; + x86_Init(zip); break; case _7Z_X86_BCJ2: /* Use our filter. */ @@ -1213,6 +1225,14 @@ decompress(struct archive_read *a, struct _7zip *zip, if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) { int i; + + /* Do not copy out the BCJ remaining bytes when the output + * buffer size is less than five bytes. */ + if (o_avail_in != 0 && t_avail_out < 5 && zip->odd_bcj_size) { + *used = 0; + *outbytes = 0; + return (ret); + } for (i = 0; zip->odd_bcj_size > 0 && t_avail_out; i++) { *t_next_out++ = zip->odd_bcj[i]; t_avail_out--; @@ -1233,7 +1253,7 @@ decompress(struct archive_read *a, struct _7zip *zip, /* * Decord a remaining decompressed main stream for BCJ2. */ - if (zip->tmp_stream_bytes_remaining > 0) { + if (zip->tmp_stream_bytes_remaining) { ssize_t bytes; size_t remaining = zip->tmp_stream_bytes_remaining; bytes = Bcj2_Decode(zip, t_next_out, t_avail_out); @@ -1249,7 +1269,8 @@ decompress(struct archive_read *a, struct _7zip *zip, if (o_avail_in == 0 || t_avail_out == 0) { *used = 0; *outbytes = o_avail_out - t_avail_out; - if (o_avail_in == 0) + if (o_avail_in == 0 && + zip->tmp_stream_bytes_remaining) ret = ARCHIVE_EOF; return (ret); } @@ -1440,7 +1461,7 @@ decompress(struct archive_read *a, struct _7zip *zip, * Decord BCJ. */ if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) { - size_t l = x86_Convert(buff, *outbytes, 0, &(zip->bcj_state)); + size_t l = x86_Convert(zip, buff, *outbytes); zip->odd_bcj_size = *outbytes - l; if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 && o_avail_in && ret != ARCHIVE_EOF) { @@ -1520,49 +1541,48 @@ free_decompression(struct archive_read *a, struct _7zip *zip) } static int -parse_7zip_uint64(const unsigned char *p, size_t len, uint64_t *val) +parse_7zip_uint64(struct archive_read *a, uint64_t *val) { - const unsigned char *_p = p; + const unsigned char *p; unsigned char avail, mask; int i; - if (len-- == 0) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - avail = *p++; + avail = *p; mask = 0x80; *val = 0; for (i = 0; i < 8; i++) { if (avail & mask) { - if (len-- == 0) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - *val |= ((uint64_t)*p++) << (8 * i); + *val |= ((uint64_t)*p) << (8 * i); mask >>= 1; continue; } *val += (avail & (mask -1)) << (8 * i); break; } - return (p - _p); + return (0); } static int -read_Bools(unsigned char *data, size_t num, const unsigned char *p, size_t len) +read_Bools(struct archive_read *a, unsigned char *data, size_t num) { - const unsigned char *_p = p; - unsigned i, mask = 0, avail; + const unsigned char *p; + unsigned i, mask = 0, avail = 0; for (i = 0; i < num; i++) { if (mask == 0) { - if (len == 0) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - avail = *p++; - len--; + avail = *p; mask = 0x80; } data[i] = (avail & mask)?1:0; mask >>= 1; } - return (p - _p); + return (0); } static void @@ -1573,16 +1593,13 @@ free_Digest(struct _7z_digests *d) } static int -read_Digests(struct _7z_digests *d, size_t num, const unsigned char *p, - size_t len) +read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num) { - const unsigned char *_p = p; + const unsigned char *p; unsigned i; memset(d, 0, sizeof(*d)); - if (len == 0) - return (-1); d->defineds = malloc(num); if (d->defineds == NULL) @@ -1590,13 +1607,11 @@ read_Digests(struct _7z_digests *d, size_t num, const unsigned char *p, /* * Read Bools. */ - len--; - if (*p++ == 0) { - int r = read_Bools(d->defineds, num, p, len); - if (r < 0) + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == 0) { + if (read_Bools(a, d->defineds, num) < 0) return (-1); - p += r; - len -= r; } else /* All are defined */ memset(d->defineds, 1, num); @@ -1604,17 +1619,15 @@ read_Digests(struct _7z_digests *d, size_t num, const unsigned char *p, d->digests = calloc(num, sizeof(*d->digests)); if (d->digests == NULL) return (-1); - if (len < 4 * num) - return (-1); for (i = 0; i < num; i++) { if (d->defineds[i]) { + if ((p = header_bytes(a, 4)) == NULL) + return (-1); d->digests[i] = archive_le32dec(p); - p += 4; - len -= 4; } } - return (p - _p); + return (0); } static void @@ -1626,62 +1639,55 @@ free_PackInfo(struct _7z_pack_info *pi) } static int -read_PackInfo(struct _7z_pack_info *pi, const unsigned char *p, size_t len) +read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi) { - const unsigned char *_p = p; + const unsigned char *p; unsigned i; - int r; memset(pi, 0, sizeof(*pi)); - if (len < 3 || *p++ != kPackInfo) - return (-1); - --len; - /* * Read PackPos. */ - r = parse_7zip_uint64(p, len, &(pi->pos)); - if (r < 0) - return (r); - p += r; - len -= r; + if (parse_7zip_uint64(a, &(pi->pos)) < 0) + return (-1); /* * Read NumPackStreams. */ - r = parse_7zip_uint64(p, len, &(pi->numPackStreams)); - if (r < 0 || pi->numPackStreams == 0) - return (r); - p += r; - len -= r; + if (parse_7zip_uint64(a, &(pi->numPackStreams)) < 0) + return (-1); + if (pi->numPackStreams == 0) + return (-1); + if (1000000 < pi->numPackStreams) + return (-1); /* * Read PackSizes[num] */ - if (len >= 1 && *p == kEnd) - /* PackSizes[num] are not present. */ - return (p - _p + 1); - if (len < 1 + pi->numPackStreams || *p++ != kSize) + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kEnd) + /* PackSizes[num] are not present. */ + return (0); + if (*p != kSize) return (-1); - --len; pi->sizes = calloc(pi->numPackStreams, sizeof(uint64_t)); pi->positions = calloc(pi->numPackStreams, sizeof(uint64_t)); if (pi->sizes == NULL || pi->positions == NULL) return (-1); for (i = 0; i < pi->numPackStreams; i++) { - r = parse_7zip_uint64(p, len, &(pi->sizes[i])); - if (r < 0) + if (parse_7zip_uint64(a, &(pi->sizes[i])) < 0) return (-1); - p += r; - len -= r; } /* * Read PackStreamDigests[num] */ - if (len >= 1 && *p == kEnd) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kEnd) { /* PackStreamDigests[num] are not present. */ pi->digest.defineds = calloc(pi->numPackStreams, sizeof(*pi->digest.defineds)); @@ -1689,25 +1695,23 @@ read_PackInfo(struct _7z_pack_info *pi, const unsigned char *p, size_t len) calloc(pi->numPackStreams, sizeof(*pi->digest.digests)); if (pi->digest.defineds == NULL || pi->digest.digests == NULL) return (-1); - return (p - _p + 1); + return (0); } - if (len < 1 + pi->numPackStreams || *p++ != kSize) + if (*p != kSize) return (-1); - --len; - r = read_Digests(&(pi->digest), pi->numPackStreams, p, len); - if (r < 0) + if (read_Digests(a, &(pi->digest), pi->numPackStreams) < 0) return (-1); - p += r; - len -= r; /* * Must be marked by kEnd. */ - if (len == 0 || *p++ != kEnd) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - return (p - _p); + if (*p != kEnd) + return (-1); + return (0); } static void @@ -1727,12 +1731,12 @@ free_Folder(struct _7z_folder *f) } static int -read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) +read_Folder(struct archive_read *a, struct _7z_folder *f) { - const unsigned char *_p = p; + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; uint64_t numInStreamsTotal = 0; uint64_t numOutStreamsTotal = 0; - int r; unsigned i; memset(f, 0, sizeof(*f)); @@ -1740,11 +1744,11 @@ read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) /* * Read NumCoders. */ - r = parse_7zip_uint64(p, len, &(f->numCoders)); - if (r < 0) + if (parse_7zip_uint64(a, &(f->numCoders)) < 0) + return (-1); + if (f->numCoders > 4) + /* Too many coders. */ return (-1); - p += r; - len -= r; f->coders = calloc(f->numCoders, sizeof(*f->coders)); if (f->coders == NULL) @@ -1753,7 +1757,7 @@ read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) size_t codec_size; int simple, attr; - if (len == 0) + if ((p = header_bytes(a, 1)) == NULL) return (-1); /* * 0:3 CodecIdSize @@ -1768,46 +1772,37 @@ read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) attr = *p & 0x20; if (*p & 0x80) return (-1);/* Not supported. */ - p++; - len--; /* * Read Decompression Method IDs. */ - if (len < codec_size) + if ((p = header_bytes(a, codec_size)) == NULL) return (-1); f->coders[i].codec = decode_codec_id(p, codec_size); - p += codec_size; - len -= codec_size; if (simple) { f->coders[i].numInStreams = 1; f->coders[i].numOutStreams = 1; } else { - r = parse_7zip_uint64(p, len, - &(f->coders[i].numInStreams)); - if (r < 0) + if (parse_7zip_uint64( + a, &(f->coders[i].numInStreams)) < 0) return (-1); - p += r; - len -= r; - r = parse_7zip_uint64(p, len, - &(f->coders[i].numOutStreams)); - if (r < 0) + if (1000000 < f->coders[i].numInStreams) + return (-1); + if (parse_7zip_uint64( + a, &(f->coders[i].numOutStreams)) < 0) + return (-1); + if (1000000 < f->coders[i].numOutStreams) return (-1); - p += r; - len -= r; } if (attr) { - r = parse_7zip_uint64(p, len, - &(f->coders[i].propertiesSize)); - if (r < 0) + if (parse_7zip_uint64( + a, &(f->coders[i].propertiesSize)) < 0) return (-1); - p += r; - len -= r; - - if (len < f->coders[i].propertiesSize) + if ((p = header_bytes( + a, f->coders[i].propertiesSize)) == NULL) return (-1); f->coders[i].properties = malloc(f->coders[i].propertiesSize); @@ -1815,8 +1810,6 @@ read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) return (-1); memcpy(f->coders[i].properties, p, f->coders[i].propertiesSize); - p += f->coders[i].propertiesSize; - len -= f->coders[i].propertiesSize; } numInStreamsTotal += f->coders[i].numInStreams; @@ -1828,20 +1821,20 @@ read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) return (-1); f->numBindPairs = numOutStreamsTotal - 1; + if (zip->header_bytes_remaining < f->numBindPairs) + return (-1); f->bindPairs = calloc(f->numBindPairs, sizeof(*f->bindPairs)); if (f->bindPairs == NULL) return (-1); for (i = 0; i < f->numBindPairs; i++) { - r = parse_7zip_uint64(p, len, &(f->bindPairs[i].inIndex)); - if (r < 0) + if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0) return (-1); - p += r; - len -= r; - r = parse_7zip_uint64(p, len, &(f->bindPairs[i].outIndex)); - if (r < 0) + if (1000000 < f->bindPairs[i].inIndex) + return (-1); + if (parse_7zip_uint64(a, &(f->bindPairs[i].outIndex)) < 0) + return (-1); + if (1000000 < f->bindPairs[i].outIndex) return (-1); - p += r; - len -= r; } f->numPackedStreams = numInStreamsTotal - f->numBindPairs; @@ -1864,17 +1857,16 @@ read_Folder(struct _7z_folder *f, const unsigned char *p, size_t len) f->packedStreams[0] = i; } else { for (i = 0; i < f->numPackedStreams; i++) { - r = parse_7zip_uint64(p, len, &(f->packedStreams[i])); - if (r < 0) + if (parse_7zip_uint64(a, &(f->packedStreams[i])) < 0) + return (-1); + if (1000000 < f->packedStreams[i]) return (-1); - p += r; - len -= r; } } f->numInStreams = numInStreamsTotal; f->numOutStreams = numOutStreamsTotal; - return (p - _p); + return (0); } static void @@ -1890,65 +1882,55 @@ free_CodersInfo(struct _7z_coders_info *ci) } static int -read_CodersInfo(struct _7z_coders_info *ci, const unsigned char *p, size_t len) +read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci) { - const unsigned char *_p = p; + const unsigned char *p; struct _7z_digests digest; - unsigned i, external; - int r; + unsigned i; memset(ci, 0, sizeof(*ci)); memset(&digest, 0, sizeof(digest)); - if (len < 3 || *p++ != kUnPackInfo) + if ((p = header_bytes(a, 1)) == NULL) goto failed; - --len; - - if (len < 3 || *p++ != kFolder) + if (*p != kFolder) goto failed; - --len; /* * Read NumFolders. */ - r = parse_7zip_uint64(p, len, &(ci->numFolders)); - if (r < 0) + if (parse_7zip_uint64(a, &(ci->numFolders)) < 0) goto failed; - p += r; - len -= r; + if (1000000 < ci->numFolders) + return (-1); /* * Read External. */ - if (len == 0) + if ((p = header_bytes(a, 1)) == NULL) goto failed; - external = *p++; - len --; - switch (external) { + switch (*p) { case 0: ci->folders = calloc(ci->numFolders, sizeof(*ci->folders)); if (ci->folders == NULL) return (-1); for (i = 0; i < ci->numFolders; i++) { - r = read_Folder(&(ci->folders[i]), p, len); - if (r < 0) + if (read_Folder(a, &(ci->folders[i])) < 0) goto failed; - p += r; - len -= r; } break; case 1: - r = parse_7zip_uint64(p, len, &(ci->dataStreamIndex)); - if (r < 0) - return (r); - p += r; - len -= r; + if (parse_7zip_uint64(a, &(ci->dataStreamIndex)) < 0) + return (-1); + if (1000000 < ci->dataStreamIndex) + return (-1); break; } - if (len < 1 + ci->numFolders || *p++ != kCodersUnPackSize) + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kCodersUnPackSize) goto failed; - --len; for (i = 0; i < ci->numFolders; i++) { struct _7z_folder *folder = &(ci->folders[i]); @@ -1959,30 +1941,22 @@ read_CodersInfo(struct _7z_coders_info *ci, const unsigned char *p, size_t len) if (folder->unPackSize == NULL) goto failed; for (j = 0; j < folder->numOutStreams; j++) { - r = parse_7zip_uint64(p, len, - &(folder->unPackSize[j])); - if (r < 0) + if (parse_7zip_uint64(a, &(folder->unPackSize[j])) < 0) goto failed; - p += r; - len -= r; } } /* * Read CRCs. */ - if (len == 0) + if ((p = header_bytes(a, 1)) == NULL) goto failed; if (*p == kEnd) - return (p - _p + 1); - if (len < 1 + ci->numFolders || *p++ != kCRC) + return (0); + if (*p != kCRC) goto failed; - --len; - r = read_Digests(&digest, ci->numFolders, p, len); - if (r < 0) + if (read_Digests(a, &digest, ci->numFolders) < 0) goto failed; - p += r; - len -= r; for (i = 0; i < ci->numFolders; i++) { ci->folders[i].digest_defined = digest.defineds[i]; ci->folders[i].digest = digest.digests[i]; @@ -1991,10 +1965,12 @@ read_CodersInfo(struct _7z_coders_info *ci, const unsigned char *p, size_t len) /* * Must be kEnd. */ - if (len == 0 || *p++ != kEnd) + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kEnd) goto failed; free_Digest(&digest); - return (p - _p); + return (0); failed: free_Digest(&digest); return (-1); @@ -2027,44 +2003,37 @@ free_SubStreamsInfo(struct _7z_substream_info *ss) } static int -read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, - size_t numFolders, const unsigned char *p, size_t len) +read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, + struct _7z_folder *f, size_t numFolders) { - const unsigned char *_p = p; + const unsigned char *p; uint64_t *usizes; size_t unpack_streams; - int r, type; + int type; unsigned i; uint32_t numDigests; memset(ss, 0, sizeof(*ss)); - if (len < 2 || *p++ != kSubStreamsInfo) - return (-1); - --len; - for (i = 0; i < numFolders; i++) f[i].numUnpackStreams = 1; - if (len < 1) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - type = *p++; - --len; + type = *p; if (type == kNumUnPackStream) { unpack_streams = 0; for (i = 0; i < numFolders; i++) { - r = parse_7zip_uint64(p, len, &(f[i].numUnpackStreams)); - if (r < 0) + if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0) + return (-1); + if (1000000 < f[i].numUnpackStreams) return (-1); - p += r; - len -= r; unpack_streams += f[i].numUnpackStreams; } - if (len < 1) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - type = *p++; - --len; + type = *p; } else unpack_streams = numFolders; @@ -2092,11 +2061,8 @@ read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, sum = 0; if (type == kSize) { for (pack = 1; pack < f[i].numUnpackStreams; pack++) { - r = parse_7zip_uint64(p, len, usizes); - if (r < 0) + if (parse_7zip_uint64(a, usizes) < 0) return (-1); - p += r; - len -= r; sum += *usizes++; } } @@ -2104,10 +2070,9 @@ read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, } if (type == kSize) { - if (len < 1) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - type = *p++; - --len; + type = *p; } for (i = 0; i < unpack_streams; i++) { @@ -2117,8 +2082,7 @@ read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, numDigests = 0; for (i = 0; i < numFolders; i++) { - if (f[i].numUnpackStreams != 1 || - !f[i].digest_defined) + if (f[i].numUnpackStreams != 1 || !f[i].digest_defined) numDigests += f[i].numUnpackStreams; } @@ -2129,13 +2093,10 @@ read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, int di = 0; memset(&tmpDigests, 0, sizeof(tmpDigests)); - r = read_Digests(&(tmpDigests), numDigests, p, len); - if (r < 0) { + if (read_Digests(a, &(tmpDigests), numDigests) < 0) { free_Digest(&tmpDigests); return (-1); } - p += r; - len -= r; for (i = 0; i < numFolders; i++) { if (f[i].numUnpackStreams == 1 && f[i].digest_defined) { *digestsDefined++ = 1; @@ -2153,10 +2114,9 @@ read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, } } free_Digest(&tmpDigests); - if (len < 1) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - type = *p++; - --len; + type = *p; } /* @@ -2164,7 +2124,7 @@ read_SubStreamsInfo(struct _7z_substream_info *ss, struct _7z_folder *f, */ if (type != kEnd) return (-1); - return (p - _p); + return (0); } static void @@ -2176,24 +2136,24 @@ free_StreamsInfo(struct _7z_stream_info *si) } static int -read_StreamsInfo(struct _7zip *zip, struct _7z_stream_info *si, - const unsigned char *p, size_t len) +read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si) { - const unsigned char *_p = p; + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; unsigned i; - int r; memset(si, 0, sizeof(*si)); - if (len > 0 && *p == kPackInfo) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kPackInfo) { uint64_t packPos; - r = read_PackInfo(&(si->pi), p, len); - if (r < 0) + if (read_PackInfo(a, &(si->pi)) < 0) return (-1); - p += r; - len -= r; + if (si->pi.positions == NULL || si->pi.sizes == NULL) + return (-1); /* * Calculate packed stream positions. */ @@ -2204,16 +2164,15 @@ read_StreamsInfo(struct _7zip *zip, struct _7z_stream_info *si, if (packPos > zip->header_offset) return (-1); } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); } - if (len > 0 && *p == kUnPackInfo) { + if (*p == kUnPackInfo) { uint32_t packIndex; struct _7z_folder *f; - r = read_CodersInfo(&(si->ci), p, len); - if (r < 0) + if (read_CodersInfo(a, &(si->ci)) < 0) return (-1); - p += r; - len -= r; /* * Calculate packed stream indexes. @@ -2226,22 +2185,24 @@ read_StreamsInfo(struct _7zip *zip, struct _7z_stream_info *si, if (packIndex > si->pi.numPackStreams) return (-1); } - } - if (len > 0 && *p == kSubStreamsInfo) { - r = read_SubStreamsInfo(&(si->ss), - si->ci.folders, si->ci.numFolders, p, len); - if (r < 0) + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + if (*p == kSubStreamsInfo) { + if (read_SubStreamsInfo(a, &(si->ss), + si->ci.folders, si->ci.numFolders) < 0) + return (-1); + if ((p = header_bytes(a, 1)) == NULL) return (-1); - p += r; - len -= r; } /* * Must be kEnd. */ - if (len == 0 || *p++ != kEnd) + if (*p != kEnd) return (-1); - return (p - _p); + return (0); } static void @@ -2254,71 +2215,69 @@ free_Header(struct _7z_header_info *h) } static int -read_Header(struct _7zip *zip, struct _7z_header_info *h, - const unsigned char *p, size_t len) +read_Header(struct archive_read *a, struct _7z_header_info *h, + int check_header_id) { - const unsigned char *_p = p; + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; struct _7z_folder *folders; struct _7z_stream_info *si = &(zip->si); struct _7zip_entry *entries; uint32_t folderIndex, indexInFolder; unsigned i; - int eindex, empty_streams, r, sindex; + int eindex, empty_streams, sindex; - if (len < 2 || *p++ != kHeader) - return (-1); - len--; + if (check_header_id) { + /* + * Read Header. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p != kHeader) + return (-1); + } /* * Read ArchiveProperties. */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); if (*p == kArchiveProperties) { - p++; - len--; - for (;;) { uint64_t size; - int atype = *p++; - len--; - if (atype == 0) - break; - r = parse_7zip_uint64(p, len, &size); - if (r < 0 || len < r + size) + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == 0) + break; + if (parse_7zip_uint64(a, &size) < 0) return (-1); - p += r + size; - len -= r + size; } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); } /* * Read MainStreamsInfo. */ if (*p == kMainStreamsInfo) { - p++; - len--; - r = read_StreamsInfo(zip, &(zip->si), p, len); - if (r < 0) + if (read_StreamsInfo(a, &(zip->si)) < 0) + return (-1); + if ((p = header_bytes(a, 1)) == NULL) return (-1); - p += r; - len -= r; } - if (len == 0) - return (-1); if (*p == kEnd) - return (p - _p + 1); + return (0); /* * Read FilesInfo. */ - if (len < 2 || *p++ != kFilesInfo) + if (*p != kFilesInfo) return (-1); - len--; - r = parse_7zip_uint64(p, len, &(zip->numFiles)); - if (r < 0) + if (parse_7zip_uint64(a, &(zip->numFiles)) < 0) return (-1); - p += r; - len -= r; + if (1000000 < zip->numFiles) + return (-1); zip->entries = calloc(zip->numFiles, sizeof(*zip->entries)); if (zip->entries == NULL) @@ -2331,20 +2290,17 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, uint64_t size; size_t ll; - if (len < 1) + if ((p = header_bytes(a, 1)) == NULL) return (-1); - type = *p++; - len--; + type = *p; if (type == kEnd) break; - r = parse_7zip_uint64(p, len, &size); - if (r < 0 || len < size) + if (parse_7zip_uint64(a, &size) < 0) + return (-1); + if (zip->header_bytes_remaining < size) return (-1); - p += r; - len -= r; ll = (size_t)size; - len -= ll; switch (type) { case kEmptyStream: @@ -2352,12 +2308,9 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, sizeof(*h->emptyStreamBools)); if (h->emptyStreamBools == NULL) return (-1); - r = read_Bools(h->emptyStreamBools, zip->numFiles, - p, ll); - if (r < 0) + if (read_Bools( + a, h->emptyStreamBools, zip->numFiles) < 0) return (-1); - p += r; - ll -= r; empty_streams = 0; for (i = 0; i < zip->numFiles; i++) { if (h->emptyStreamBools[i]) @@ -2369,48 +2322,59 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, sizeof(*h->emptyFileBools)); if (h->emptyFileBools == NULL) return (-1); - r = read_Bools(h->emptyFileBools, empty_streams, - p, len); - if (r < 0) + if (read_Bools(a, h->emptyFileBools, empty_streams) < 0) return (-1); - p += r; - ll -= r; break; case kAnti: h->antiBools = calloc(empty_streams, sizeof(*h->antiBools)); if (h->antiBools == NULL) return (-1); - r = read_Bools(h->antiBools, empty_streams, p, len); - if (r < 0) + if (read_Bools(a, h->antiBools, empty_streams) < 0) return (-1); - p += r; - ll -= r; break; case kCTime: case kATime: case kMTime: - r = read_Times(zip, h, type, p, ll); - if (r < 0) + if (read_Times(a, h, type) < 0) return (-1); - p += r; - ll -= r; break; case kName: { unsigned char *np; - size_t nl; + size_t nl, nb; - if (ll < 1) + /* Skip one byte. */ + if ((p = header_bytes(a, 1)) == NULL) return (-1); - p++; ll--;/* Skip one byte. */ + ll--; + if ((ll & 1) || ll < zip->numFiles * 4) return (-1); zip->entry_names = malloc(ll); if (zip->entry_names == NULL) return (-1); - memcpy(zip->entry_names, p, ll); + np = zip->entry_names; + nb = ll; + /* + * Copy whole file names. + * NOTE: This loop prevents from expanding + * the uncompressed buffer in order not to + * use extra memory resource. + */ + while (nb) { + size_t b; + if (nb > UBUFF_SIZE) + b = UBUFF_SIZE; + else + b = nb; + if ((p = header_bytes(a, b)) == NULL) + return (-1); + memcpy(np, p, b); + np += b; + nb -= b; + } np = zip->entry_names; nl = ll; @@ -2437,11 +2401,9 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, { int allAreDefined; - if (ll < 2) + if ((p = header_bytes(a, 2)) == NULL) return (-1); - allAreDefined = *p++; - --ll; - p++; --ll;/* Skip one byte. */ + allAreDefined = *p; h->attrBools = calloc(zip->numFiles, sizeof(*h->attrBools)); if (h->attrBools == NULL) @@ -2449,29 +2411,24 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, if (allAreDefined) memset(h->attrBools, 1, zip->numFiles); else { - r = read_Bools(h->attrBools, - zip->numFiles, p, ll); - if (r < 0) + if (read_Bools(a, h->attrBools, + zip->numFiles) < 0) return (-1); - p += r; - ll -= r; } for (i = 0; i < zip->numFiles; i++) { if (h->attrBools[i]) { - if (ll < 4) + if ((p = header_bytes(a, 4)) == NULL) return (-1); entries[i].attr = archive_le32dec(p); - p += 4; - ll -= 4; } } break; } default: + if (header_bytes(a, ll) == NULL) + return (-1); break; } - /* Skip remaining data. */ - p += ll; } /* @@ -2481,8 +2438,7 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, eindex = sindex = 0; folderIndex = indexInFolder = 0; for (i = 0; i < zip->numFiles; i++) { - if (h->emptyStreamBools == NULL || - h->emptyStreamBools[i] == 0) + if (h->emptyStreamBools == NULL || h->emptyStreamBools[i] == 0) entries[i].flg |= HAS_STREAM; /* The high 16 bits of attributes is a posix file mode. */ entries[i].mode = entries[i].attr >> 16; @@ -2556,7 +2512,7 @@ read_Header(struct _7zip *zip, struct _7z_header_info *h, } } - return (p - _p); + return (0); } #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) @@ -2577,50 +2533,44 @@ fileTimeToUtc(uint64_t fileTime, time_t *time, long *ns) } static int -read_Times(struct _7zip *zip, struct _7z_header_info *h, int type, - const unsigned char *p, size_t len) +read_Times(struct archive_read *a, struct _7z_header_info *h, int type) { - const unsigned char *_p = p; + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; struct _7zip_entry *entries = zip->entries; unsigned char *timeBools; - int r; - int allAreDefined, external; + int allAreDefined; unsigned i; timeBools = calloc(zip->numFiles, sizeof(*timeBools)); if (timeBools == NULL) return (-1); - if (len < 1) + /* Read allAreDefined. */ + if ((p = header_bytes(a, 1)) == NULL) goto failed; - allAreDefined = *p++; - len--; + allAreDefined = *p; if (allAreDefined) memset(timeBools, 1, zip->numFiles); else { - r = read_Bools(timeBools, zip->numFiles, p, len); - if (r < 0) + if (read_Bools(a, timeBools, zip->numFiles) < 0) goto failed; - p += r; - len -= r; } - if (len < 1) + /* Read external. */ + if ((p = header_bytes(a, 1)) == NULL) goto failed; - external = *p++; - len--; - if (external) { - r = parse_7zip_uint64(p, len, &(h->dataIndex)); - if (r < 0) + if (*p) { + if (parse_7zip_uint64(a, &(h->dataIndex)) < 0) goto failed; - p += r; - len -= r; + if (1000000 < h->dataIndex) + return (-1); } for (i = 0; i < zip->numFiles; i++) { if (!timeBools[i]) continue; - if (len < 8) + if ((p = header_bytes(a, 8)) == NULL) goto failed; switch (type) { case kCTime: @@ -2642,29 +2592,22 @@ read_Times(struct _7zip *zip, struct _7z_header_info *h, int type, entries[i].flg |= MTIME_IS_SET; break; } - p += 8; - len -= 8; } free(timeBools); - return (p - _p); + return (0); failed: free(timeBools); return (-1); } -static ssize_t -decode_header_image(struct archive_read *a, struct _7zip *zip, - struct _7z_stream_info *si, const unsigned char *p, uint64_t len, - const void **image) +static int +decode_encoded_header_info(struct archive_read *a, struct _7z_stream_info *si) { - const unsigned char *v; - size_t vsize; - int r; + struct _7zip *zip = (struct _7zip *)a->format->data; errno = 0; - r = read_StreamsInfo(zip, si, p, len); - if (r < 0) { + if (read_StreamsInfo(a, si) < 0) { if (errno == ENOMEM) archive_set_error(&a->archive, -1, "Couldn't allocate memory"); @@ -2686,79 +2629,40 @@ decode_header_image(struct archive_read *a, struct _7zip *zip, return (ARCHIVE_FATAL); } - r = setup_decode_folder(a, si->ci.folders, 1); - if (r != ARCHIVE_OK) - return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} - /* Get an uncompressed header size. */ - vsize = (size_t)zip->folder_outbytes_remaining; +static const unsigned char * +header_bytes(struct archive_read *a, size_t rbytes) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; - /* - * Allocate an uncompressed buffer for the header image. - */ - zip->uncompressed_buffer_size = 64 * 1024; - if (vsize > zip->uncompressed_buffer_size) - zip->uncompressed_buffer_size = vsize; - zip->uncompressed_buffer = malloc(zip->uncompressed_buffer_size); - if (zip->uncompressed_buffer == NULL) { - archive_set_error(&a->archive, ENOMEM, - "No memory for 7-Zip decompression"); - return (ARCHIVE_FATAL); - } + if (zip->header_bytes_remaining < rbytes) + return (NULL); + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); - /* Get the bytes we can read to decode the header. */ - zip->pack_stream_inbytes_remaining = si->pi.sizes[0]; - - /* Seek the read point. */ - if (__archive_read_seek(a, si->pi.pos + zip->seek_base, SEEK_SET) < 0) - return (ARCHIVE_FATAL); - zip->header_offset = si->pi.pos; - - /* Extract a pack stream. */ - r = extract_pack_stream(a); - if (r < 0) - return (r); - for (;;) { + if (zip->header_is_encoded == 0) { + p = __archive_read_ahead(a, rbytes, NULL); + if (p == NULL) + return (NULL); + zip->header_bytes_remaining -= rbytes; + zip->pack_stream_bytes_unconsumed = rbytes; + } else { + const void *buff; ssize_t bytes; - - bytes = get_uncompressed_data(a, image, vsize); - if (bytes < 0) - return (r); - if (bytes != vsize) { - if (*image != zip->uncompressed_buffer) { - /* This might happen if the coder was COPY. - * We have to make sure we read a full plain - * header image. */ - if (NULL==__archive_read_ahead(a, vsize, NULL)) - return (ARCHIVE_FATAL); - continue; - } else { - archive_set_error(&a->archive, -1, - "Malformed 7-Zip archive file"); - return (ARCHIVE_FATAL); - } - } - break; - } - v = *image; - /* Clean up variables which will not be used for decoding the - * archive header */ - zip->pack_stream_remaining = 0; - zip->pack_stream_index = 0; - zip->folder_outbytes_remaining = 0; - zip->uncompressed_buffer_bytes_remaining = 0; - zip->pack_stream_bytes_unconsumed = 0; - - /* Check the header CRC. */ - if (si->ci.folders[0].digest_defined){ - uint32_t c = crc32(0, v, vsize); - if (c != si->ci.folders[0].digest) { - archive_set_error(&a->archive, -1, "Header CRC error"); - return (ARCHIVE_FATAL); - } + bytes = read_stream(a, &buff, rbytes, rbytes); + if (bytes <= 0) + return (NULL); + zip->header_bytes_remaining -= bytes; + p = buff; } - return ((ssize_t)vsize); + + /* Update checksum */ + zip->header_crc32 = crc32(zip->header_crc32, p, rbytes); + return (p); } static int @@ -2766,13 +2670,11 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, struct _7z_header_info *header) { const unsigned char *p; - const void *image; - uint64_t len; uint64_t next_header_offset; uint64_t next_header_size; uint32_t next_header_crc; - ssize_t bytes_avail, image_bytes; - int r; + ssize_t bytes_avail; + int check_header_crc, r; if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) return (ARCHIVE_FATAL); @@ -2782,7 +2684,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, r = skip_sfx(a, bytes_avail); if (r < ARCHIVE_WARN) return (r); - if ((p = __archive_read_ahead(a, 32, NULL)) == NULL) + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) return (ARCHIVE_FATAL); } zip->seek_base += 32; @@ -2810,45 +2712,71 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); return (ARCHIVE_FATAL); } - if (__archive_read_seek(a, next_header_offset + zip->seek_base, - SEEK_SET) < 0) - return (ARCHIVE_FATAL); + __archive_read_consume(a, 32); + if (next_header_offset != 0) { + if (bytes_avail >= next_header_offset) + __archive_read_consume(a, next_header_offset); + else if (__archive_read_seek(a, + next_header_offset + zip->seek_base, SEEK_SET) < 0) + return (ARCHIVE_FATAL); + } + zip->stream_offset = next_header_offset; zip->header_offset = next_header_offset; + zip->header_bytes_remaining = next_header_size; + zip->header_crc32 = 0; + zip->header_is_encoded = 0; + zip->header_is_being_read = 1; + check_header_crc = 1; - if ((p = __archive_read_ahead(a, next_header_size, NULL)) == NULL) - return (ARCHIVE_FATAL); - - if (crc32(0, p, next_header_size) != next_header_crc) { - archive_set_error(&a->archive, -1, "Damaged 7-Zip archive"); + if ((p = header_bytes(a, 1)) == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); return (ARCHIVE_FATAL); } - - len = next_header_size; /* Parse ArchiveProperties. */ switch (p[0]) { case kEncodedHeader: - p++; - len--; - /* * The archive has an encoded header and we have to decode it * in order to parse the header correctly. */ - image_bytes = - decode_header_image(a, zip, &(zip->si), p, len, &image); + r = decode_encoded_header_info(a, &(zip->si)); + + /* Check the EncodedHeader CRC.*/ + if (r == 0 && zip->header_crc32 != next_header_crc) { + archive_set_error(&a->archive, -1, + "Damaged 7-Zip archive"); + r = -1; + } + if (r == 0) { + if (zip->si.ci.folders[0].digest_defined) + next_header_crc = zip->si.ci.folders[0].digest; + else + check_header_crc = 0; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + r = setup_decode_folder(a, zip->si.ci.folders, 1); + if (r == 0) { + zip->header_bytes_remaining = + zip->folder_outbytes_remaining; + r = seek_pack(a); + } + } + /* Clean up StreamsInfo. */ free_StreamsInfo(&(zip->si)); memset(&(zip->si), 0, sizeof(zip->si)); - if (image_bytes < 0) + if (r < 0) return (ARCHIVE_FATAL); - p = image; - len = image_bytes; + zip->header_is_encoded = 1; + zip->header_crc32 = 0; /* FALL THROUGH */ case kHeader: /* * Parse the header. */ errno = 0; - r = read_Header(zip, header, p, len); + r = read_Header(a, header, zip->header_is_encoded); if (r < 0) { if (errno == ENOMEM) archive_set_error(&a->archive, -1, @@ -2858,7 +2786,18 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, "Damaged 7-Zip archive"); return (ARCHIVE_FATAL); } - if (len - r == 0 || p[r] != kEnd) { + + /* + * Must be kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL ||*p != kEnd) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* Check the Header CRC.*/ + if (check_header_crc && zip->header_crc32 != next_header_crc) { archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); return (ARCHIVE_FATAL); @@ -2869,24 +2808,21 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, "Unexpected Property ID = %X", p[0]); return (ARCHIVE_FATAL); } - zip->stream_offset = -1; - /* - * If the uncompressed buffer was allocated more than 64K for - * the header image, release it. - */ - if (zip->uncompressed_buffer != NULL && - zip->uncompressed_buffer_size != 64 * 1024) { - free(zip->uncompressed_buffer); - zip->uncompressed_buffer = NULL; - zip->uncompressed_buffer_size = 0; - } + /* Clean up variables be used for decoding the archive header */ + zip->pack_stream_remaining = 0; + zip->pack_stream_index = 0; + zip->folder_outbytes_remaining = 0; + zip->uncompressed_buffer_bytes_remaining = 0; + zip->pack_stream_bytes_unconsumed = 0; + zip->header_is_being_read = 0; return (ARCHIVE_OK); } static ssize_t -get_uncompressed_data(struct archive_read *a, const void **buff, size_t size) +get_uncompressed_data(struct archive_read *a, const void **buff, size_t size, + size_t minimum) { struct _7zip *zip = (struct _7zip *)a->format->data; ssize_t bytes_avail; @@ -2922,6 +2858,15 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size) return (ARCHIVE_FATAL); } else { /* Packed mode. */ + if (minimum > zip->uncompressed_buffer_bytes_remaining) { + /* + * If remaining uncompressed data size is less than + * the minimum size, fill the buffer up to the + * minimum size. + */ + if (extract_pack_stream(a, minimum) < 0) + return (ARCHIVE_FATAL); + } if (size > zip->uncompressed_buffer_bytes_remaining) bytes_avail = (ssize_t) zip->uncompressed_buffer_bytes_remaining; @@ -2935,14 +2880,16 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size) } static ssize_t -extract_pack_stream(struct archive_read *a) +extract_pack_stream(struct archive_read *a, size_t minimum) { struct _7zip *zip = (struct _7zip *)a->format->data; ssize_t bytes_avail; int r; if (zip->codec == _7Z_COPY && zip->codec2 == -1) { - if (__archive_read_ahead(a, 1, &bytes_avail) == NULL + if (minimum == 0) + minimum = 1; + if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL || bytes_avail <= 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -2961,7 +2908,11 @@ extract_pack_stream(struct archive_read *a) /* If the buffer hasn't been allocated, allocate it now. */ if (zip->uncompressed_buffer == NULL) { - zip->uncompressed_buffer_size = 64 * 1024; + zip->uncompressed_buffer_size = UBUFF_SIZE; + if (zip->uncompressed_buffer_size < minimum) { + zip->uncompressed_buffer_size = minimum + 1023; + zip->uncompressed_buffer_size &= ~0x3ff; + } zip->uncompressed_buffer = malloc(zip->uncompressed_buffer_size); if (zip->uncompressed_buffer == NULL) { @@ -2969,8 +2920,46 @@ extract_pack_stream(struct archive_read *a) "No memory for 7-Zip decompression"); return (ARCHIVE_FATAL); } - } - zip->uncompressed_buffer_bytes_remaining = 0; + zip->uncompressed_buffer_bytes_remaining = 0; + } else if (zip->uncompressed_buffer_size < minimum || + zip->uncompressed_buffer_bytes_remaining < minimum) { + /* + * Make sure the uncompressed buffer can have bytes + * at least `minimum' bytes. + * NOTE: This case happen when reading the header. + */ + size_t used; + if (zip->uncompressed_buffer_pointer != 0) + used = zip->uncompressed_buffer_pointer - + zip->uncompressed_buffer; + else + used = 0; + if (zip->uncompressed_buffer_size < minimum) { + /* + * Expand the uncompressed buffer up to + * the minimum size. + */ + zip->uncompressed_buffer_size = minimum + 1023; + zip->uncompressed_buffer_size &= ~0x3ff; + zip->uncompressed_buffer = + realloc(zip->uncompressed_buffer, + zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + } + /* + * Move unconsumed bytes to the head. + */ + if (used) { + memmove(zip->uncompressed_buffer, + zip->uncompressed_buffer + used, + zip->uncompressed_buffer_bytes_remaining); + } + } else + zip->uncompressed_buffer_bytes_remaining = 0; zip->uncompressed_buffer_pointer = NULL; for (;;) { size_t bytes_in, bytes_out; @@ -3025,6 +3014,10 @@ extract_pack_stream(struct archive_read *a) if (zip->uncompressed_buffer_bytes_remaining == zip->uncompressed_buffer_size) break; + if (zip->codec2 == _7Z_X86 && zip->odd_bcj_size && + zip->uncompressed_buffer_bytes_remaining + 5 > + zip->uncompressed_buffer_size) + break; if (zip->pack_stream_inbytes_remaining == 0 && zip->folder_outbytes_remaining == 0) break; @@ -3035,6 +3028,11 @@ extract_pack_stream(struct archive_read *a) } read_consume(a); } + if (zip->uncompressed_buffer_bytes_remaining < minimum) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } zip->uncompressed_buffer_pointer = zip->uncompressed_buffer; return (ARCHIVE_OK); } @@ -3065,7 +3063,8 @@ seek_pack(struct archive_read *a) } static ssize_t -read_stream(struct archive_read *a, const void **buff, size_t size) +read_stream(struct archive_read *a, const void **buff, size_t size, + size_t minimum) { struct _7zip *zip = (struct _7zip *)a->format->data; uint64_t skip_bytes = 0; @@ -3073,29 +3072,36 @@ read_stream(struct archive_read *a, const void **buff, size_t size) if (zip->uncompressed_buffer_bytes_remaining == 0) { if (zip->pack_stream_inbytes_remaining > 0) { - r = extract_pack_stream(a); + r = extract_pack_stream(a, 0); if (r < 0) return (r); - return (get_uncompressed_data(a, buff, size)); + return (get_uncompressed_data(a, buff, size, minimum)); } else if (zip->folder_outbytes_remaining > 0) { /* Extract a remaining pack stream. */ - r = extract_pack_stream(a); + r = extract_pack_stream(a, 0); if (r < 0) return (r); - return (get_uncompressed_data(a, buff, size)); + return (get_uncompressed_data(a, buff, size, minimum)); } } else - return (get_uncompressed_data(a, buff, size)); + return (get_uncompressed_data(a, buff, size, minimum)); /* * Current pack stream has been consumed. */ if (zip->pack_stream_remaining == 0) { + if (zip->header_is_being_read) { + /* Invalid sequence. This might happen when + * reading a malformed archive. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + /* * All current folder's pack streams have been * consumed. Switch to next folder. */ - if (zip->folder_index == 0 && (zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes || zip->folder_index != zip->entry->folderIndex)) { @@ -3127,7 +3133,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size) return (r); /* Extract a new pack stream. */ - r = extract_pack_stream(a); + r = extract_pack_stream(a, 0); if (r < 0) return (r); @@ -3139,12 +3145,12 @@ read_stream(struct archive_read *a, const void **buff, size_t size) if (zip->uncompressed_buffer_bytes_remaining == 0) { if (zip->pack_stream_inbytes_remaining > 0) { - r = extract_pack_stream(a); + r = extract_pack_stream(a, 0); if (r < 0) return (r); } else if (zip->folder_outbytes_remaining > 0) { /* Extract a remaining pack stream. */ - r = extract_pack_stream(a); + r = extract_pack_stream(a, 0); if (r < 0) return (r); } else { @@ -3154,7 +3160,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size) return (ARCHIVE_FATAL); } } - skipped = get_uncompressed_data(a, buff, skip_bytes); + skipped = get_uncompressed_data(a, buff, skip_bytes, 0); if (skipped < 0) return (skipped); skip_bytes -= skipped; @@ -3162,7 +3168,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size) read_consume(a); } - return (get_uncompressed_data(a, buff, size)); + return (get_uncompressed_data(a, buff, size, minimum)); } static int @@ -3336,11 +3342,12 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, /* Extract a sub stream. */ while (zip->pack_stream_inbytes_remaining > 0) { - r = extract_pack_stream(a); + r = extract_pack_stream(a, 0); if (r < 0) return (r); bytes = get_uncompressed_data(a, &buff, - zip->uncompressed_buffer_bytes_remaining); + zip->uncompressed_buffer_bytes_remaining, + 0); if (bytes < 0) return ((int)bytes); memcpy(b[i]+s[i], buff, bytes); @@ -3412,7 +3419,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes) } while (bytes) { - skipped_bytes = read_stream(a, &p, bytes); + skipped_bytes = read_stream(a, &p, bytes, 0); if (skipped_bytes < 0) return (skipped_bytes); if (skipped_bytes == 0) { @@ -3438,18 +3445,30 @@ skip_stream(struct archive_read *a, size_t skip_bytes) #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) -static const unsigned char kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; -static const unsigned char kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; +static void +x86_Init(struct _7zip *zip) +{ + zip->bcj_state = 0; + zip->bcj_prevPosT = (size_t)0 - 1; + zip->bcj_prevMask = 0; + zip->bcj_ip = 5; +} static size_t -x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state) +x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) { - size_t bufferPos = 0, prevPosT; - uint32_t prevMask = *state & 0x7; + static const uint8_t kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; + static const uint8_t kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + size_t bufferPos, prevPosT; + uint32_t ip, prevMask; + if (size < 5) return 0; - ip += 5; - prevPosT = (size_t)0 - 1; + + bufferPos = 0; + prevPosT = zip->bcj_prevPosT; + prevMask = zip->bcj_prevMask; + ip = zip->bcj_ip; for (;;) { uint8_t *p = data + bufferPos; @@ -3508,9 +3527,9 @@ x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state) bufferPos++; } } - prevPosT = bufferPos - prevPosT; - *state = ((prevPosT > 3) ? - 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); + zip->bcj_prevPosT = prevPosT; + zip->bcj_prevMask = prevMask; + zip->bcj_ip += bufferPos; return (bufferPos); } @@ -3545,7 +3564,7 @@ x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state) #define UPDATE_0(p) zip->bcj2_range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; #define UPDATE_1(p) zip->bcj2_range -= bound; zip->bcj2_code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; -ssize_t +static ssize_t Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) { size_t inPos = 0, outPos = 0; diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index a1bed4f0b..4f68ef85f 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -1962,7 +1962,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, (parent->re || parent->re_descendant)) file->re_descendant = 1; if (file->cl_offset) { - struct file_info *p; + struct file_info *r; if (parent == NULL || parent->parent == NULL) { archive_set_error(&a->archive, @@ -1990,8 +1990,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent, * Sanity check: cl_offset does not point at its * the parents or itself. */ - for (p = parent; p; p = p->parent) { - if (p->offset == file->cl_offset) { + for (r = parent; r; r = r->parent) { + if (r->offset == file->cl_offset) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index de0e434b2..a8124223b 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -112,6 +112,8 @@ struct zip { }; #define ZIP_LENGTH_AT_END 8 +#define ZIP_ENCRYPTED (1<<0) +#define ZIP_STRONG_ENCRYPTED (1<<6) #define ZIP_UTF8_NAME (1<<11) static int archive_read_format_zip_streamable_bid(struct archive_read *, int); @@ -356,7 +358,32 @@ archive_read_format_zip_seekable_read_header(struct archive_read *a, typically faster (easier for I/O layer to optimize). */ __archive_read_seek(a, zip->entry->local_header_offset, SEEK_SET); zip->unconsumed = 0; - return zip_read_local_file_header(a, entry, zip); + r = zip_read_local_file_header(a, entry, zip); + if (r != ARCHIVE_OK) + return r; + if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) { + const void *p; + size_t linkname_length = archive_entry_size(entry); + + archive_entry_set_size(entry, 0); + p = __archive_read_ahead(a, linkname_length, NULL); + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated Zip file"); + return ARCHIVE_FATAL; + } + + if (archive_entry_copy_symlink_l(entry, p, linkname_length, + NULL) != 0) { + /* NOTE: If the last argument is NULL, this will + * fail only by memeory allocation failure. */ + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Symlink"); + return (ARCHIVE_FATAL); + } + /* TODO: handle character-set issues? */ + } + return ARCHIVE_OK; } static int @@ -722,6 +749,12 @@ archive_read_format_zip_read_data(struct archive_read *a, if (AE_IFREG != (zip->entry->mode & AE_IFMT)) return (ARCHIVE_EOF); + if (zip->entry->flags & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Encrypted file is unsupported"); + return (ARCHIVE_FAILED); + } + __archive_read_consume(a, zip->unconsumed); zip->unconsumed = 0; diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index 5e95dd7c9..4dec82d62 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -212,7 +212,7 @@ static struct archive_string * archive_string_append(struct archive_string *as, const char *p, size_t s) { if (archive_string_ensure(as, as->length + s + 1) == NULL) - __archive_errx(1, "Out of memory"); + return (NULL); memcpy(as->s + as->length, p, s); as->length += s; as->s[as->length] = 0; @@ -223,7 +223,7 @@ static struct archive_wstring * archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s) { if (archive_wstring_ensure(as, as->length + s + 1) == NULL) - __archive_errx(1, "Out of memory"); + return (NULL); wmemcpy(as->s + as->length, p, s); as->length += s; as->s[as->length] = 0; @@ -233,13 +233,15 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s) void archive_string_concat(struct archive_string *dest, struct archive_string *src) { - archive_string_append(dest, src->s, src->length); + if (archive_string_append(dest, src->s, src->length) == NULL) + __archive_errx(1, "Out of memory"); } void archive_wstring_concat(struct archive_wstring *dest, struct archive_wstring *src) { - archive_wstring_append(dest, src->s, src->length); + if (archive_wstring_append(dest, src->s, src->length) == NULL) + __archive_errx(1, "Out of memory"); } void @@ -346,7 +348,9 @@ archive_strncat(struct archive_string *as, const void *_p, size_t n) pp++; s++; } - return (archive_string_append(as, p, s)); + if ((as = archive_string_append(as, p, s)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); } struct archive_wstring * @@ -362,7 +366,9 @@ archive_wstrncat(struct archive_wstring *as, const wchar_t *p, size_t n) pp++; s++; } - return (archive_wstring_append(as, p, s)); + if ((as = archive_wstring_append(as, p, s)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); } struct archive_string * @@ -387,13 +393,17 @@ archive_wstrcat(struct archive_wstring *as, const wchar_t *p) struct archive_string * archive_strappend_char(struct archive_string *as, char c) { - return (archive_string_append(as, &c, 1)); + if ((as = archive_string_append(as, &c, 1)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); } struct archive_wstring * archive_wstrappend_wchar(struct archive_wstring *as, wchar_t c) { - return (archive_wstring_append(as, &c, 1)); + if ((as = archive_wstring_append(as, &c, 1)) == NULL) + __archive_errx(1, "Out of memory"); + return (as); } /* @@ -2080,14 +2090,8 @@ archive_strncat_in_locale(struct archive_string *as, const void *_p, size_t n, */ if (sc == NULL) { length = mbsnbytes(_p, n); - /* - * archive_string_append() will call archive_string_ensure() - * but we cannot know if that call is failed or not. so - * we call archive_string_ensure() here. - */ - if (archive_string_ensure(as, as->length + length + 1) == NULL) - return (-1); - archive_string_append(as, _p, length); + if (archive_string_append(as, _p, length) == NULL) + return (-1);/* No memory */ return (0); } @@ -2338,7 +2342,8 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, * And then this checks all copied MBS can be WCS if so returns 0. */ if (sc->same) { - archive_string_append(as, _p, length); + if (archive_string_append(as, _p, length) == NULL) + return (-1);/* No memory */ return (invalid_mbs(_p, length, sc)); } @@ -4115,10 +4120,14 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes, * characters because Windows platform cannot make locale UTF-8. */ if (sc == NULL) { - archive_string_append(&(aes->aes_mbs), - mbs, mbsnbytes(mbs, len)); - aes->aes_set = AES_SET_MBS; - r = 0; + if (archive_string_append(&(aes->aes_mbs), + mbs, mbsnbytes(mbs, len)) == NULL) { + aes->aes_set = 0; + r = -1; + } else { + aes->aes_set = AES_SET_MBS; + r = 0; + } #if defined(HAVE_ICONV) } else if (sc != NULL && sc->cd_w != (iconv_t)-1) { /* diff --git a/libarchive/archive_util.3 b/libarchive/archive_util.3 index e07ac956c..cd05d03f1 100644 --- a/libarchive/archive_util.3 +++ b/libarchive/archive_util.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_util.3 201098 2009-12-28 02:58:14Z kientzle $ .\" .Dd January 8, 2005 -.Dt archive_util 3 +.Dt ARCHIVE_UTIL 3 .Os .Sh NAME .Nm archive_clear_error , diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index af104b86a..0bb2a8094 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -135,6 +135,11 @@ __la_win_permissive_name_w(const wchar_t *wname) l = GetFullPathNameW(wname, 0, NULL, NULL); if (l == 0) return (NULL); + /* NOTE: GetFullPathNameW has a bug that if the length of the file + * name is just one that return imcomplete buffer size. Thus, we + * have to add three to the size to allocate a sufficient buffer + * size for the full-pathname of the file name. */ + l += 3; wnp = malloc(l * sizeof(wchar_t)); if (wnp == NULL) return (NULL); @@ -229,27 +234,6 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, return (handle); } -/* - * This fcntl is limited implementation. - */ -int -__la_fcntl(int fd, int cmd, int val) -{ - HANDLE handle; - - handle = (HANDLE)_get_osfhandle(fd); - if (GetFileType(handle) == FILE_TYPE_PIPE) { - if (cmd == F_SETFL && val == 0) { - DWORD mode = PIPE_WAIT; - if (SetNamedPipeHandleState( - handle, &mode, NULL, NULL) != 0) - return (0); - } - } - errno = EINVAL; - return (-1); -} - /* This can exceed MAX_PATH limitation. */ int __la_open(const char *path, int flags, ...) @@ -368,22 +352,6 @@ __la_read(int fd, void *buf, size_t nbytes) if (nbytes == 0) return (0); handle = (HANDLE)_get_osfhandle(fd); - if (GetFileType(handle) == FILE_TYPE_PIPE) { - DWORD sta; - if (GetNamedPipeHandleState( - handle, &sta, NULL, NULL, NULL, NULL, 0) != 0 && - (sta & PIPE_NOWAIT) == 0) { - DWORD avail = -1; - int cnt = 3; - - while (PeekNamedPipe( - handle, NULL, 0, NULL, &avail, NULL) != 0 && - avail == 0 && --cnt) - Sleep(100); - if (avail == 0) - return (0); - } - } r = ReadFile(handle, buf, (uint32_t)nbytes, &bytes_read, NULL); if (r == 0) { diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h index b26811e54..cfb3e97d2 100644 --- a/libarchive/archive_windows.h +++ b/libarchive/archive_windows.h @@ -90,7 +90,7 @@ /* Alias the Windows _function to the POSIX equivalent. */ #define close _close -#define fcntl __la_fcntl +#define fcntl(fd, cmd, flg) /* No operation. */ #ifndef fileno #define fileno _fileno #endif @@ -243,7 +243,6 @@ /* Replacement POSIX function */ -extern int __la_fcntl(int fd, int cmd, int val); extern int __la_fstat(int fd, struct stat *st); extern int __la_lstat(const char *path, struct stat *st); extern int __la_open(const char *path, int flags, ...); diff --git a/libarchive/archive_write.3 b/libarchive/archive_write.3 index 1fa4245a4..f87386a8b 100644 --- a/libarchive/archive_write.3 +++ b/libarchive/archive_write.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ .\" .Dd March 23, 2011 -.Dt archive_write 3 +.Dt ARCHIVE_WRITE 3 .Os .Sh NAME .Nm archive_write diff --git a/libarchive/archive_write_blocksize.3 b/libarchive/archive_write_blocksize.3 index 239fa922a..96c75382a 100644 --- a/libarchive/archive_write_blocksize.3 +++ b/libarchive/archive_write_blocksize.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 23, 2011 -.Dt archive_write_blocksize 3 +.Dt ARCHIVE_WRITE_BLOCKSIZE 3 .Os .Sh NAME .Nm archive_write_get_bytes_per_block , diff --git a/libarchive/archive_write_data.3 b/libarchive/archive_write_data.3 index 2c98b3e78..fc399bc30 100644 --- a/libarchive/archive_write_data.3 +++ b/libarchive/archive_write_data.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ .\" .Dd March 23, 2011 -.Dt archive_write 3 +.Dt ARCHIVE_WRITE 3 .Os .Sh NAME .Nm archive_write_data diff --git a/libarchive/archive_write_disk.3 b/libarchive/archive_write_disk.3 index 90bbdcf95..ffadb04fe 100644 --- a/libarchive/archive_write_disk.3 +++ b/libarchive/archive_write_disk.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: src/lib/libarchive/archive_write_disk.3,v 1.4 2008/09/04 05:22:00 kientzle Exp $ .\" .Dd August 5, 2008 -.Dt archive_write_disk 3 +.Dt ARCHIVE_WRITE_DISK 3 .Os .Sh NAME .Nm archive_write_disk_new , diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 9df9ddc72..2dc2d92e8 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -542,11 +542,36 @@ la_CreateHardLinkW(wchar_t *linkname, wchar_t *target) { static BOOLEAN (WINAPI *f)(LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES); static int set; + BOOL ret; + if (!set) { set = 1; f = la_GetFunctionKernel32("CreateHardLinkW"); } - return f == NULL ? 0 : (*f)(linkname, target, NULL); + if (!f) + return (0); + ret = (*f)(linkname, target, NULL); + if (!ret) { + /* Under windows 2000, it is necessary to remove + * the "\\?\" prefix. */ +#define IS_UNC(name) ((name[0] == L'U' || name[0] == L'u') && \ + (name[1] == L'N' || name[1] == L'n') && \ + (name[2] == L'C' || name[2] == L'c') && \ + name[3] == L'\\') + if (!wcsncmp(linkname,L"\\\\?\\", 4)) { + linkname += 4; + if (IS_UNC(linkname)) + linkname += 4; + } + if (!wcsncmp(target,L"\\\\?\\", 4)) { + target += 4; + if (IS_UNC(target)) + target += 4; + } +#undef IS_UNC + ret = (*f)(linkname, target, NULL); + } + return (ret); } static int @@ -2207,6 +2232,7 @@ create_dir(struct archive_write_disk *a, wchar_t *path) le->fixup |=TODO_MODE_BASE; le->mode = mode_final; } + free(full); return (ARCHIVE_OK); } else { la_dosmaperr(GetLastError()); diff --git a/libarchive/archive_write_filter.3 b/libarchive/archive_write_filter.3 index f084a51db..00438d405 100644 --- a/libarchive/archive_write_filter.3 +++ b/libarchive/archive_write_filter.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 23, 2011 -.Dt archive_write_filter 3 +.Dt ARCHIVE_WRITE_FILTER 3 .Os .Sh NAME .Nm archive_write_add_filter_bzip2 , diff --git a/libarchive/archive_write_finish_entry.3 b/libarchive/archive_write_finish_entry.3 index 06c002ebe..3add60129 100644 --- a/libarchive/archive_write_finish_entry.3 +++ b/libarchive/archive_write_finish_entry.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ .\" .Dd March 23, 2011 -.Dt archive_write_finish_entry 3 +.Dt ARCHIVE_WRITE_FINISH_ENTRY 3 .Os .Sh NAME .Nm archive_write_finish_entry diff --git a/libarchive/archive_write_format.3 b/libarchive/archive_write_format.3 index b3e7e3535..e12e7d865 100644 --- a/libarchive/archive_write_format.3 +++ b/libarchive/archive_write_format.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 23, 2011 -.Dt archive_write_format 3 +.Dt ARCHIVE_WRITE_FORMAT 3 .Os .Sh NAME .Nm archive_write_set_format_cpio , diff --git a/libarchive/archive_write_free.3 b/libarchive/archive_write_free.3 index d939780dd..27efe18b0 100644 --- a/libarchive/archive_write_free.3 +++ b/libarchive/archive_write_free.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 23, 2011 -.Dt archive_write_free 3 +.Dt ARCHIVE_WRITE_FREE 3 .Os .Sh NAME .Nm archive_write_close , diff --git a/libarchive/archive_write_header.3 b/libarchive/archive_write_header.3 index f76175b0f..423b38e46 100644 --- a/libarchive/archive_write_header.3 +++ b/libarchive/archive_write_header.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 23, 2011 -.Dt archive_write_header 3 +.Dt ARCHIVE_WRITE_HEADER 3 .Os .Sh NAME .Nm archive_write_header diff --git a/libarchive/archive_write_new.3 b/libarchive/archive_write_new.3 index 76515bba8..d626ccb73 100644 --- a/libarchive/archive_write_new.3 +++ b/libarchive/archive_write_new.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 23, 2011 -.Dt archive_write_new 3 +.Dt ARCHIVE_WRITE_NEW 3 .Os .Sh NAME .Nm archive_write_new diff --git a/libarchive/archive_write_open.3 b/libarchive/archive_write_open.3 index ab2d4841c..0d12cb3b3 100644 --- a/libarchive/archive_write_open.3 +++ b/libarchive/archive_write_open.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ .\" .Dd March 23, 2011 -.Dt archive_write 3 +.Dt ARCHIVE_WRITE 3 .Os .Sh NAME .Nm archive_write_open , diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index f405d1f92..022b3a42f 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -96,7 +96,7 @@ enum la_zaction { }; /* - * Universal zstream. + * A stream object of universal compressor. */ struct la_zstream { const uint8_t *next_in; @@ -154,8 +154,8 @@ struct file { #define HAS_STREAM (1<<4) struct { - time_t time; - long time_ns; + time_t time; + long time_ns; } times[3]; #define MTIME 0 #define ATIME 1 @@ -455,6 +455,7 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry) zip->total_number_entry++; zip->total_bytes_entry_name += file->name_len + 2; if (file->size == 0) { + /* Count up the number of empty files. */ zip->total_number_empty_entry++; if (file->dir) zip->total_number_dir_entry++; @@ -488,6 +489,9 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry) zip->entry_bytes_remaining = file->size; zip->entry_crc32 = 0; + /* + * Store a symbolic link name as file contents. + */ if (archive_entry_filetype(entry) == AE_IFLNK) { ssize_t bytes; const void *p = (const void *)archive_entry_symlink(entry); @@ -501,6 +505,9 @@ _7z_write_header(struct archive_write *a, struct archive_entry *entry) return (r); } +/* + * Write data to a temporary file. + */ static int write_to_temp(struct archive_write *a, const void *buff, size_t s) { @@ -719,19 +726,22 @@ _7z_close(struct archive_write *a) zip->total_number_nonempty_entry = zip->total_number_entry - zip->total_number_empty_entry; + /* Connect an empty file list. */ *zip->file_list.last = zip->empty_list.first; zip->file_list.last = zip->empty_list.last; + /* Connect a directory file list. */ ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) { file_register(zip, (struct file *)n); } /* * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for - * the header. + * the compression type for encoding the header. */ #if HAVE_LZMA_H header_compression = _7Z_LZMA1; - /* If the stored file is only one, do not encode the header. */ + /* If the stored file is only one, do not encode the header. + * This is the same way 7z command does. */ if (zip->total_number_entry == 1) header_compression = _7Z_COPY; #else @@ -823,6 +833,9 @@ _7z_close(struct archive_write *a) return (r); } +/* + * Encode 64 bits value into 7-Zip's encoded UINT64 value. + */ static int enc_uint64(struct archive_write *a, uint64_t val) { @@ -1586,6 +1599,9 @@ compression_unsupported_encoder(struct archive *a, } #endif +/* + * _7_COPY compressor. + */ static int compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm) { @@ -1631,6 +1647,9 @@ compression_end_copy(struct archive *a, struct la_zstream *lastrm) return (ARCHIVE_OK); } +/* + * _7_DEFLATE compressor. + */ #ifdef HAVE_ZLIB_H static int compression_init_encoder_deflate(struct archive *a, @@ -1741,6 +1760,9 @@ compression_init_encoder_deflate(struct archive *a, } #endif +/* + * _7_BZIP2 compressor. + */ #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) static int compression_init_encoder_bzip2(struct archive *a, @@ -1860,6 +1882,9 @@ compression_init_encoder_bzip2(struct archive *a, } #endif +/* + * _7_LZMA1, _7_LZMA2 compressor. + */ #if defined(HAVE_LZMA_H) static int compression_init_encoder_lzma(struct archive *a, @@ -2047,7 +2072,7 @@ compression_init_encoder_lzma2(struct archive *a, #endif /* - * PPMd compression. + * _7_PPMD compressor. */ static void * ppmd_alloc(void *p, size_t size) @@ -2201,6 +2226,9 @@ compression_end_ppmd(struct archive *a, struct la_zstream *lastrm) return (ARCHIVE_OK); } +/* + * Universal compressor initializer. + */ static int _7z_compression_init_encoder(struct archive_write *a, unsigned compression, int compression_level) diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index 4447f5a8f..bb9b55184 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -684,21 +684,24 @@ xar_write_data(struct archive_write *a, const void *buff, size_t s) archive_string_empty(&(xar->cur_file->script)); if (rsize > 2 && b[0] == '#' && b[1] == '!') { - char path[PATH_MAX]; size_t i, end, off; - end = sizeof(path); - if (end > rsize) - end = rsize; off = 2; if (b[off] == ' ') off++; +#ifdef PATH_MAX + if ((rsize - off) > PATH_MAX) + end = off + PATH_MAX; + else +#endif + end = rsize; + /* Find the end of a script path. */ for (i = off; i < end && b[i] != '\0' && b[i] != '\n' && b[i] != '\r' && b[i] != ' ' && b[i] != '\t'; i++) - path[i - off] = b[i]; - path[i - off] = '\0'; - archive_strcpy(&(xar->cur_file->script), path); + ; + archive_strncpy(&(xar->cur_file->script), b + off, + i - off); } } #endif diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 588c7f4cb..f07a14f47 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -96,11 +96,13 @@ enum compression { #endif }; -static ssize_t archive_write_zip_data(struct archive_write *, const void *buff, size_t s); +static ssize_t archive_write_zip_data(struct archive_write *, + const void *buff, size_t s); static int archive_write_zip_close(struct archive_write *); static int archive_write_zip_free(struct archive_write *); static int archive_write_zip_finish_entry(struct archive_write *); -static int archive_write_zip_header(struct archive_write *, struct archive_entry *); +static int archive_write_zip_header(struct archive_write *, + struct archive_entry *); static int archive_write_zip_options(struct archive_write *, const char *, const char *); static unsigned int dos_time(const time_t); @@ -270,7 +272,8 @@ archive_write_set_format_zip(struct archive *_a) zip = (struct zip *) calloc(1, sizeof(*zip)); if (zip == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate zip data"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); return (ARCHIVE_FATAL); } zip->central_directory = NULL; @@ -284,7 +287,8 @@ archive_write_set_format_zip(struct archive *_a) zip->len_buf = 65536; zip->buf = malloc(zip->len_buf); if (zip->buf == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate compression buffer"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate compression buffer"); return (ARCHIVE_FATAL); } #else @@ -335,7 +339,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) /* Entries other than a regular file or a folder are skipped. */ type = archive_entry_filetype(entry); - if ((type != AE_IFREG) & (type != AE_IFDIR)) { + if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filetype not supported"); return ARCHIVE_FAILED; @@ -410,8 +414,20 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) /* Initialize the CRC variable and potentially the local crc32(). */ l->crc32 = crc32(0, NULL, 0); - l->compression = zip->compression; - l->compressed_size = 0; + if (type == AE_IFLNK) { + const char *p = archive_entry_symlink(l->entry); + if (p != NULL) + size = strlen(p); + else + size = 0; + zip->remaining_data_bytes = 0; + archive_entry_set_size(l->entry, size); + l->compression = COMPRESSION_STORE; + l->compressed_size = size; + } else { + l->compression = zip->compression; + l->compressed_size = 0; + } l->next = NULL; if (zip->central_directory == NULL) { zip->central_directory = l; @@ -420,22 +436,24 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) } zip->central_directory_end = l; - /* Store the offset of this header for later use in central directory. */ + /* Store the offset of this header for later use in central + * directory. */ l->offset = zip->written_bytes; memset(&h, 0, sizeof(h)); archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER); archive_le16enc(&h.version, ZIP_VERSION_EXTRACT); archive_le16enc(&h.flags, l->flags); - archive_le16enc(&h.compression, zip->compression); + archive_le16enc(&h.compression, l->compression); archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry))); archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); - switch (zip->compression) { + switch (l->compression) { case COMPRESSION_STORE: - /* Setting compressed and uncompressed sizes even when specification says - * to set to zero when using data descriptors. Otherwise the end of the - * data for an entry is rather difficult to find. */ + /* Setting compressed and uncompressed sizes even when + * specification says to set to zero when using data + * descriptors. Otherwise the end of the data for an + * entry is rather difficult to find. */ archive_le32enc(&h.compressed_size, size); archive_le32enc(&h.uncompressed_size, size); break; @@ -448,8 +466,8 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) zip->stream.opaque = Z_NULL; zip->stream.next_out = zip->buf; zip->stream.avail_out = zip->len_buf; - if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { + if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { archive_set_error(&a->archive, ENOMEM, "Can't init deflate compressor"); return (ARCHIVE_FATAL); @@ -495,6 +513,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(e); + if (type == AE_IFLNK) { + const unsigned char *p; + + p = (const unsigned char *)archive_entry_symlink(l->entry); + ret = __archive_write_output(a, p, size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += size; + l->crc32 = crc32(l->crc32, p, size); + } + if (ret2 != ARCHIVE_OK) return (ret2); return (ARCHIVE_OK); @@ -512,7 +541,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (s == 0) return 0; - switch (zip->compression) { + switch (l->compression) { case COMPRESSION_STORE: ret = __archive_write_output(a, buff, s); if (ret != ARCHIVE_OK) return (ret); @@ -530,7 +559,8 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (ret == Z_STREAM_ERROR) return (ARCHIVE_FATAL); if (zip->stream.avail_out == 0) { - ret = __archive_write_output(a, zip->buf, zip->len_buf); + ret = __archive_write_output(a, zip->buf, + zip->len_buf); if (ret != ARCHIVE_OK) return (ret); l->compressed_size += zip->len_buf; @@ -564,7 +594,7 @@ archive_write_zip_finish_entry(struct archive_write *a) size_t reminder; #endif - switch(zip->compression) { + switch(l->compression) { case COMPRESSION_STORE: break; #if HAVE_ZLIB_H @@ -614,7 +644,8 @@ archive_write_zip_close(struct archive_write *a) l = zip->central_directory; /* - * Formatting central directory file header fields that are fixed for all entries. + * Formatting central directory file header fields that are + * fixed for all entries. * Fields not used (and therefor 0) are: * * - comment_length @@ -634,18 +665,23 @@ archive_write_zip_close(struct archive_write *a) while (l != NULL) { archive_le16enc(&h.flags, l->flags); archive_le16enc(&h.compression, l->compression); - archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(l->entry))); + archive_le32enc(&h.timedate, + dos_time(archive_entry_mtime(l->entry))); archive_le32enc(&h.crc32, l->crc32); archive_le32enc(&h.compressed_size, l->compressed_size); - archive_le32enc(&h.uncompressed_size, archive_entry_size(l->entry)); - archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); + archive_le32enc(&h.uncompressed_size, + archive_entry_size(l->entry)); + archive_le16enc(&h.filename_length, + (uint16_t)path_length(l->entry)); archive_le16enc(&h.extra_length, sizeof(e)); - archive_le16enc(&h.attributes_external[2], archive_entry_mode(l->entry)); + archive_le16enc(&h.attributes_external[2], + archive_entry_mode(l->entry)); archive_le32enc(&h.offset, l->offset); /* Formatting extra data. */ archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP); - archive_le16enc(&e.time_size, sizeof(e.mtime) + sizeof(e.time_flag)); + archive_le16enc(&e.time_size, + sizeof(e.mtime) + sizeof(e.time_flag)); e.time_flag[0] = 0x07; archive_le32enc(&e.mtime, archive_entry_mtime(l->entry)); archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); diff --git a/libarchive/archive_write_set_options.3 b/libarchive/archive_write_set_options.3 index 7e5cf212b..9a8ea3dbf 100644 --- a/libarchive/archive_write_set_options.3 +++ b/libarchive/archive_write_set_options.3 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/archive_write.3 201110 2009-12-28 03:31:29Z kientzle $ .\" .Dd Feb 27, 2010 -.Dt archive_write_options 3 +.Dt ARCHIVE_WRITE_OPTIONS 3 .Os .Sh NAME .Nm archive_write_set_filter_option , diff --git a/libarchive/cpio.5 b/libarchive/cpio.5 index f54462818..13a4445b7 100644 --- a/libarchive/cpio.5 +++ b/libarchive/cpio.5 @@ -268,31 +268,6 @@ data, including ACLs and extended attributes, as special entries in cpio archives. .Pp XXX Others? XXX -.Sh BUGS -The -.Dq CRC -format is mis-named, as it uses a simple checksum and -not a cyclic redundancy check. -.Pp -The old binary format is limited to 16 bits for user id, -group id, device, and inode numbers. -It is limited to 4 gigabyte file sizes. -.Pp -The old ASCII format is limited to 18 bits for -the user id, group id, device, and inode numbers. -It is limited to 8 gigabyte file sizes. -.Pp -The new ASCII format is limited to 4 gigabyte file sizes. -.Pp -None of the cpio formats store user or group names, -which are essential when moving files between systems with -dissimilar user or group numbering. -.Pp -Especially when writing older cpio variants, it may be necessary -to map actual device/inode values to synthesized values that -fit the available fields. -With very large filesystems, this may be necessary even for -the newer formats. .Sh SEE ALSO .Xr cpio 1 , .Xr tar 5 @@ -323,3 +298,28 @@ license. The character format was adopted as part of .St -p1003.1-88 . XXX when did "newc" appear? Who invented it? When did HP come out with their variant? When did Sun introduce ACLs and extended attributes? XXX +.Sh BUGS +The +.Dq CRC +format is mis-named, as it uses a simple checksum and +not a cyclic redundancy check. +.Pp +The old binary format is limited to 16 bits for user id, +group id, device, and inode numbers. +It is limited to 4 gigabyte file sizes. +.Pp +The old ASCII format is limited to 18 bits for +the user id, group id, device, and inode numbers. +It is limited to 8 gigabyte file sizes. +.Pp +The new ASCII format is limited to 4 gigabyte file sizes. +.Pp +None of the cpio formats store user or group names, +which are essential when moving files between systems with +dissimilar user or group numbering. +.Pp +Especially when writing older cpio variants, it may be necessary +to map actual device/inode values to synthesized values that +fit the available fields. +With very large filesystems, this may be necessary even for +the newer formats. diff --git a/libarchive/filter_fork_windows.c b/libarchive/filter_fork_windows.c index 38b7097ee..272e56c6b 100644 --- a/libarchive/filter_fork_windows.c +++ b/libarchive/filter_fork_windows.c @@ -32,69 +32,73 @@ pid_t __archive_create_child(const char *path, int *child_stdin, int *child_stdout) { - HANDLE childStdout[2], childStdin[2], childStdinWr, childStdoutRd; + HANDLE childStdout[2], childStdin[2],childStderr; SECURITY_ATTRIBUTES secAtts; STARTUPINFO staInfo; PROCESS_INFORMATION childInfo; char cmd[MAX_PATH]; - DWORD mode; secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); secAtts.bInheritHandle = TRUE; secAtts.lpSecurityDescriptor = NULL; if (CreatePipe(&childStdout[0], &childStdout[1], &secAtts, 0) == 0) goto fail; - if (DuplicateHandle(GetCurrentProcess(), childStdout[0], - GetCurrentProcess(), &childStdoutRd, 0, FALSE, - DUPLICATE_SAME_ACCESS) == 0) { + if (!SetHandleInformation(childStdout[0], HANDLE_FLAG_INHERIT, 0)) + { CloseHandle(childStdout[0]); CloseHandle(childStdout[1]); goto fail; } - CloseHandle(childStdout[0]); - if (CreatePipe(&childStdin[0], &childStdin[1], &secAtts, 0) == 0) { - CloseHandle(childStdoutRd); + CloseHandle(childStdout[0]); CloseHandle(childStdout[1]); goto fail; } - - if (DuplicateHandle(GetCurrentProcess(), childStdin[1], - GetCurrentProcess(), &childStdinWr, 0, FALSE, - DUPLICATE_SAME_ACCESS) == 0) { - CloseHandle(childStdoutRd); + if (!SetHandleInformation(childStdin[1], HANDLE_FLAG_INHERIT, 0)) + { + CloseHandle(childStdout[0]); + CloseHandle(childStdout[1]); + CloseHandle(childStdin[0]); + CloseHandle(childStdin[1]); + goto fail; + } + if (DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_ERROR_HANDLE), + GetCurrentProcess(), &childStderr, 0, TRUE, + DUPLICATE_SAME_ACCESS) == 0) { + CloseHandle(childStdout[0]); CloseHandle(childStdout[1]); CloseHandle(childStdin[0]); CloseHandle(childStdin[1]); goto fail; } - CloseHandle(childStdin[1]); memset(&staInfo, 0, sizeof(staInfo)); staInfo.cb = sizeof(staInfo); + staInfo.hStdError = childStderr; staInfo.hStdOutput = childStdout[1]; staInfo.hStdInput = childStdin[0]; staInfo.wShowWindow = SW_HIDE; - staInfo.dwFlags = STARTF_USEFILLATTRIBUTE | STARTF_USECOUNTCHARS | - STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + staInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; strncpy(cmd, path, sizeof(cmd)-1); cmd[sizeof(cmd)-1] = '\0'; if (CreateProcessA(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &staInfo, &childInfo) == 0) { - CloseHandle(childStdoutRd); + CloseHandle(childStdout[0]); CloseHandle(childStdout[1]); CloseHandle(childStdin[0]); - CloseHandle(childStdinWr); + CloseHandle(childStdin[1]); + CloseHandle(childStderr); goto fail; } WaitForInputIdle(childInfo.hProcess, INFINITE); CloseHandle(childInfo.hProcess); CloseHandle(childInfo.hThread); - mode = PIPE_NOWAIT; - SetNamedPipeHandleState(childStdoutRd, &mode, NULL, NULL); - *child_stdout = _open_osfhandle((intptr_t)childStdoutRd, _O_RDONLY); - *child_stdin = _open_osfhandle((intptr_t)childStdinWr, _O_WRONLY); + *child_stdout = _open_osfhandle((intptr_t)childStdout[0], _O_RDONLY); + *child_stdin = _open_osfhandle((intptr_t)childStdin[1], _O_WRONLY); + + CloseHandle(childStdout[1]); + CloseHandle(childStdin[0]); return (childInfo.dwProcessId); diff --git a/libarchive/libarchive-formats.5 b/libarchive/libarchive-formats.5 index bd6bfe743..d223bf853 100644 --- a/libarchive/libarchive-formats.5 +++ b/libarchive/libarchive-formats.5 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/libarchive-formats.5 201077 2009-12-28 01:50:23Z kientzle $ .\" .Dd December 27, 2009 -.Dt libarchive-formats 5 +.Dt LIBARCHIVE-FORMATS 5 .Os .Sh NAME .Nm libarchive-formats diff --git a/libarchive/libarchive_changes.3 b/libarchive/libarchive_changes.3 index 349eab92e..6ee6af245 100644 --- a/libarchive/libarchive_changes.3 +++ b/libarchive/libarchive_changes.3 @@ -25,7 +25,7 @@ .\" $FreeBSD$ .\" .Dd March 27, 2011 -.Dt libarchive_changes 3 +.Dt LIBARCHIVE_CHANGES 3 .Os .Sh NAME .Nm changes in libarchive interface diff --git a/libarchive/tar.5 b/libarchive/tar.5 index e55999bda..65875bd61 100644 --- a/libarchive/tar.5 +++ b/libarchive/tar.5 @@ -25,7 +25,7 @@ .\" $FreeBSD: head/lib/libarchive/tar.5 201077 2009-12-28 01:50:23Z kientzle $ .\" .Dd December 27, 2009 -.Dt tar 5 +.Dt TAR 5 .Os .Sh NAME .Nm tar