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"
This commit is contained in:
LibArchive Upstream
2012-01-05 08:52:42 -05:00
committed by Brad King
parent 2f4a3792bb
commit 4f4fe6e50b
55 changed files with 820 additions and 846 deletions
+8 -11
View File
@@ -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)
-107
View File
@@ -1,107 +0,0 @@
# - Macro approximating the CMake 2.8 ADD_TEST(NAME) signature.
# ADD_TEST_28(NAME <name> COMMAND <command> [arg1 [arg2 ...]])
# <name> - The name of the test
# <command> - 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 <command> that names an
# executable target with the target location. A generator expression
# of the form "$<TARGET_FILE:tgt>" 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 $<TARGET_FILE:myexe>)
# 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 ... $<TARGET_FILE:myexe> ..." substitution.
SET(target_file "\\$<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()
+1 -1
View File
@@ -1 +1 @@
3000001b
3000002
+3 -16
View File
@@ -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);
/*
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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
-16
View File
@@ -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.
*/
+1 -15
View File
@@ -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
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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
@@ -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).
+2
View File
@@ -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)
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+514 -495
View File
@@ -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)
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
if (*p == kEnd)
/* PackSizes[num] are not present. */
return (p - _p + 1);
if (len < 1 + pi->numPackStreams || *p++ != kSize)
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 ((p = header_bytes(a, 1)) == NULL)
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 == 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)
if ((p = header_bytes(a, 1)) == NULL)
return (-1);
if (*p == 0)
break;
r = parse_7zip_uint64(p, len, &size);
if (r < 0 || len < r + size)
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;
@@ -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");
+34 -1
View File
@@ -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;
+30 -21
View File
@@ -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) {
/*
+1 -1
View File
@@ -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 ,
+5 -37
View File
@@ -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) {
+1 -2
View File
@@ -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, ...);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 ,
+27 -1
View File
@@ -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());
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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 ,
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 ,
+34 -6
View File
@@ -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)
+10 -7
View File
@@ -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
+60 -24
View File
@@ -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);
+1 -1
View File
@@ -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 ,
+25 -25
View File
@@ -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.
+25 -21
View File
@@ -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,
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(childStdoutRd);
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);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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