Merge branch 'libarchive-upstream' into update-libarchive

Resolve conflicts in favor of the upstream side where possible.
Resolve a logical conflict in archive_windows.h where the upstream
port to Watcom was done slightly differently from ours.
This commit is contained in:
Brad King 2014-04-03 14:37:54 -04:00
commit 2f1978632b
54 changed files with 4055 additions and 1995 deletions

View File

@ -32,7 +32,7 @@ SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}")
SET(LIBARCHIVE_VERSION_STRING "${VERSION}")
# INTERFACE_VERSION increments with every release
# libarchive 2.7 == interface version 9 = 2 + 7
# libarchive 2.7 == interface version 9 = 2 + 7
# libarchive 2.8 == interface version 10 = 2 + 8
# libarchive 2.9 == interface version 11 = 2 + 9
# libarchive 3.0 == interface version 12
@ -69,9 +69,22 @@ include(CTest)
OPTION(ENABLE_NETTLE "Enable use of Nettle" ON)
OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON)
OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON)
OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON)
OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON)
OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON)
OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON)
OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON)
OPTION(ENABLE_TAR "Enable tar building" ON)
OPTION(ENABLE_TAR_SHARED "Enable dynamic build of tar" FALSE)
OPTION(ENABLE_CPIO "Enable cpio building" ON)
OPTION(ENABLE_CPIO_SHARED "Enable dynamic build of cpio" FALSE)
OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
OPTION(ENABLE_ACL "Enable ACL support" ON)
OPTION(ENABLE_ICONV "Enable iconv support" ON)
OPTION(ENABLE_TEST "Enable unit and regression tests" ON)
OPTION(ENABLE_COVERAGE "Enable code coverage (GCC only, automatically sets ENABLE_TEST to ON)" FALSE)
IF(WIN32)
IF(MSVC60)
@ -190,7 +203,7 @@ IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
#--- zconf.h.orig 2005-07-21 00:40:26.000000000
#+++ zconf.h 2009-01-19 11:39:10.093750000
#@@ -286,7 +286,7 @@
#
#
# #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# # include <sys/types.h> /* for off_t */
#-# include <unistd.h> /* for SEEK_* and off_t */
@ -204,7 +217,11 @@ SET(ADDITIONAL_LIBS "")
#
# Find ZLIB
#
FIND_PACKAGE(ZLIB)
IF(ENABLE_ZLIB)
FIND_PACKAGE(ZLIB)
ELSE()
SET(ZLIB_FOUND FALSE) # Override cached value
ENDIF()
IF(ZLIB_FOUND)
SET(HAVE_LIBZ 1)
SET(HAVE_ZLIB_H 1)
@ -239,7 +256,11 @@ ENDIF(ZLIB_FOUND)
#
# Find BZip2
#
FIND_PACKAGE(BZip2)
IF(ENABLE_BZip2)
FIND_PACKAGE(BZip2)
ELSE()
SET(BZIP2_FOUND FALSE) # Override cached value
ENDIF()
IF(BZIP2_FOUND)
SET(HAVE_LIBBZ2 1)
SET(HAVE_BZLIB_H 1)
@ -263,7 +284,13 @@ IF(0) # CMake does not need LZMA or LZO2 support in libarchive
#
# Find LZMA
#
FIND_PACKAGE(LZMA)
IF(ENABLE_LZMA)
FIND_PACKAGE(LZMA)
ELSE()
SET(LZMA_FOUND FALSE) # Override cached value
SET(LZMADEC_FOUND FALSE) # Override cached value
ENDIF()
IF(LZMA_FOUND)
SET(HAVE_LIBLZMA 1)
SET(HAVE_LZMA_H 1)
@ -283,6 +310,8 @@ ELSEIF(LZMADEC_FOUND)
SET(HAVE_LZMADEC_H 1)
INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR})
LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES})
ELSE(LZMA_FOUND)
# LZMA not found and will not be used.
ENDIF(LZMA_FOUND)
#
# Find LZO2
@ -510,16 +539,10 @@ main(int argc, char **argv)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}")
IF(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_ADD_LINKER_FLAGS
"-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_ADD_LINKER_FLAGS)
ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c
CMAKE_FLAGS ${CHECK_CRYPTO_ADD_LINKER_FLAGS}
CMAKE_FLAGS
"${TRY_CRYPTO_REQUIRED_LIBS}"
"${TRY_CRYPTO_REQUIRED_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
@ -604,16 +627,10 @@ main(int argc, char **argv)
FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN")
IF(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS
"-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS:STRING=${CMAKE_REQUIRED_LINKER_FLAGS}")
ELSE(CMAKE_REQUIRED_LINKER_FLAGS)
SET(CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS)
ENDIF(CMAKE_REQUIRED_LINKER_FLAGS)
TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN
${CMAKE_BINARY_DIR}
${SOURCE_FILE}
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" ${CHECK_CRYPTO_WIN_ADD_LINKER_FLAGS}
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
OUTPUT_VARIABLE OUTPUT)
IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
@ -1030,13 +1047,13 @@ CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG)
CHECK_TYPE_SIZE("__int64" __INT64)
CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64)
CHECK_TYPE_SIZE(int16_t INT16_T)
CHECK_TYPE_SIZE(int16_t INT16_T)
CHECK_TYPE_SIZE(int32_t INT32_T)
CHECK_TYPE_SIZE(int64_t INT64_T)
CHECK_TYPE_SIZE(intmax_t INTMAX_T)
CHECK_TYPE_SIZE(uint8_t UINT8_T)
CHECK_TYPE_SIZE(uint16_t UINT16_T)
CHECK_TYPE_SIZE(uint32_t UINT32_T)
CHECK_TYPE_SIZE(uint8_t UINT8_T)
CHECK_TYPE_SIZE(uint16_t UINT16_T)
CHECK_TYPE_SIZE(uint32_t UINT32_T)
CHECK_TYPE_SIZE(uint64_t UINT64_T)
CHECK_TYPE_SIZE(uintmax_t UINTMAX_T)
@ -1279,6 +1296,9 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
# Handle generation of the libarchive.pc file for pkg-config
INCLUDE(CreatePkgConfigFile)
#
# Register installation of PDF documents.
#

View File

@ -0,0 +1,31 @@
# - Generate a libarchive.pc like autotools for pkg-config
#
# Set the required variables (we use the same input file as autotools)
SET(prefix ${CMAKE_INSTALL_PREFIX})
SET(exec_prefix \${prefix})
SET(libdir \${exec_prefix}/lib)
SET(includedir \${prefix}/include)
# Now, this is not particularly pretty, nor is it terribly accurate...
# Loop over all our additional libs
FOREACH(mylib ${ADDITIONAL_LIBS})
# Extract the filename from the absolute path
GET_FILENAME_COMPONENT(mylib_name ${mylib} NAME_WE)
# Strip the lib prefix
STRING(REGEX REPLACE "^lib" "" mylib_name ${mylib_name})
# Append it to our LIBS string
SET(LIBS "${LIBS} -l${mylib_name}")
ENDFOREACH()
# libxml2 is easier, since it's already using pkg-config
FOREACH(mylib ${PC_LIBXML_STATIC_LDFLAGS})
SET(LIBS "${LIBS} ${mylib}")
ENDFOREACH()
# FIXME: The order of the libraries doesn't take dependencies into account,
# thus there's a good chance it'll make some binutils versions unhappy...
# This only affects Libs.private (looked up for static builds) though.
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in
${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc
@ONLY)
# And install it, of course ;).
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc
DESTINATION "lib/pkgconfig")

View File

@ -0,0 +1,68 @@
#################################################################
# Adds a build target called "coverage" for code coverage.
#
# This compiles the code using special GCC flags, run the tests,
# and then generates a nice HTML output. This new "coverage" make
# target will only be available if you build using GCC in Debug
# mode. If any of the required programs (lcov and genhtml) were
# not found, a FATAL_ERROR message is printed.
#
# If not already done, this code will set ENABLE_TEST to ON.
#
# To build the code coverage and open it in your browser do this:
#
# mkdir debug
# cd debug
# cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON ..
# make -j4
# make coverage
# xdg-open coverage/index.html
#################################################################
# Find programs we need
FIND_PROGRAM(LCOV_EXECUTABLE lcov DOC "Full path to lcov executable")
FIND_PROGRAM(GENHTML_EXECUTABLE genhtml DOC "Full path to genhtml executable")
MARK_AS_ADVANCED(LCOV_EXECUTABLE GENHTML_EXECUTABLE)
# Check, compiler, build types and programs are available
IF(NOT CMAKE_COMPILER_IS_GNUCC)
MESSAGE(FATAL_ERROR "Coverage can only be built on GCC")
ELSEIF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
MESSAGE(FATAL_ERROR "Coverage can only be built in Debug mode")
ELSEIF(NOT LCOV_EXECUTABLE)
MESSAGE(FATAL_ERROR "lcov executable not found")
ELSEIF(NOT GENHTML_EXECUTABLE)
MESSAGE(FATAL_ERROR "genhtml executable not found")
ENDIF(NOT CMAKE_COMPILER_IS_GNUCC)
# Enable testing if not already done
SET(ENABLE_TEST ON)
#################################################################
# Set special compiler and linker flags for test coverage
#################################################################
# 0. Enable debug: -g
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
# 1. Disable optimizations: -O0
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
# 2. Enable all kind of warnings:
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W")
# 3. Enable special coverage flag (HINT: --coverage is a synonym for -fprofile-arcs -ftest-coverage)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
#################################################################
ADD_CUSTOM_TARGET(coverage
COMMAND ${CMAKE_COMMAND} -E echo "Beginning test coverage. Output is written to coverage.log."
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-1/5: Reset all execution counts to zero"
COMMAND ${LCOV_EXECUTABLE} --directory . --zerocounters > coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-2/5: Run testrunner"
COMMAND ${CMAKE_CTEST_COMMAND} >> coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-3/5: Collect coverage data"
COMMAND ${LCOV_EXECUTABLE} --capture --directory . --output-file "./coverage.info" >> coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-4/5: Generate HTML from coverage data"
COMMAND ${GENHTML_EXECUTABLE} "coverage.info" --title="libarchive-${LIBARCHIVE_VERSION_STRING}" --show-details --legend --output-directory "./coverage" >> coverage.log 2>&1
COMMAND ${CMAKE_COMMAND} -E echo "COVERAGE-STEP-5/5: Open test coverage HTML output in browser: xdg-open ./coverage/index.html"
COMMENT "Runs testrunner and generates coverage output (formats: .info and .html)")

View File

@ -1112,8 +1112,13 @@ typedef uint64_t uintmax_t;
#cmakedefine _LARGE_FILES ${_LARGE_FILES}
/* Define for Windows to use Windows 2000+ APIs. */
#ifndef _WIN32_WINNT
#cmakedefine _WIN32_WINNT ${_WIN32_WINNT}
#endif // _WIN32_WINNT
#ifndef WINVER
#cmakedefine WINVER ${WINVER}
#endif // WINVER
/* Define to empty if `const' does not conform to ANSI C. */
#cmakedefine const ${const}

View File

@ -35,6 +35,8 @@ SET(libarchive_SOURCES
archive_match.c
archive_options.c
archive_options_private.h
archive_pack_dev.h
archive_pack_dev.c
archive_pathmatch.c
archive_pathmatch.h
archive_platform.h
@ -125,6 +127,7 @@ SET(libarchive_SOURCES
archive_write_set_format_iso9660.c
archive_write_set_format_mtree.c
archive_write_set_format_pax.c
archive_write_set_format_raw.c
archive_write_set_format_shar.c
archive_write_set_format_ustar.c
archive_write_set_format_v7tar.c

View File

@ -137,6 +137,11 @@ __LA_DECL int archive_version_number(void);
#define ARCHIVE_VERSION_STRING "libarchive 3.1.2"
__LA_DECL const char * archive_version_string(void);
/*
* Detailed textual name/version of the library and its dependencies.
*/
__LA_DECL const char * archive_version_details(void);
/* Declare our basic types. */
struct archive;
struct archive_entry;
@ -289,6 +294,30 @@ typedef int archive_switch_callback(struct archive *, void *_client_data1,
#define ARCHIVE_FORMAT_RAR 0xD0000
#define ARCHIVE_FORMAT_7ZIP 0xE0000
/*
* Codes returned by archive_read_format_capabilities().
*
* This list can be extended with values between 0 and 0xffff.
* The original purpose of this list was to let different archive
* format readers expose their general capabilities in terms of
* encryption.
*/
#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */
#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */
#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */
/*
* Codes returned by archive_read_has_encrypted_entries().
*
* In case the archive does not support encryption detection at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader
* for some other reason (e.g. not enough bytes read) cannot say if
* there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW
* is returned.
*/
#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2
#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1
/*-
* Basic outline for reading an archive:
* 1) Ask archive_read_new for an archive reader object.
@ -374,7 +403,15 @@ __LA_DECL int archive_read_support_format_rar(struct archive *);
__LA_DECL int archive_read_support_format_raw(struct archive *);
__LA_DECL int archive_read_support_format_tar(struct archive *);
__LA_DECL int archive_read_support_format_xar(struct archive *);
/* archive_read_support_format_zip() enables both streamable and seekable
* zip readers. */
__LA_DECL int archive_read_support_format_zip(struct archive *);
/* Reads Zip archives as stream from beginning to end. Doesn't
* correctly handle SFX ZIP files or ZIP archives that have been modified
* in-place. */
__LA_DECL int archive_read_support_format_zip_streamable(struct archive *);
/* Reads starting from central directory; requires seekable input. */
__LA_DECL int archive_read_support_format_zip_seekable(struct archive *);
/* Functions to manually set the format and filters to be used. This is
* useful to bypass the bidding process when the format and filters to use
@ -470,6 +507,32 @@ __LA_DECL int archive_read_next_header2(struct archive *,
*/
__LA_DECL __LA_INT64_T archive_read_header_position(struct archive *);
/*
* Returns 1 if the archive contains at least one encrypted entry.
* If the archive format not support encryption at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
* If for any other reason (e.g. not enough data read so far)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
* reader is uncertain or totally uncapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
*
* NOTE: If the metadata/header of an archive is also encrypted, you
* cannot rely on the number of encrypted entries. That is why this
* function does not return the number of encrypted entries but#
* just shows that there are some.
*/
__LA_DECL int archive_read_has_encrypted_entries(struct archive *);
/*
* Returns a bitmask of capabilities that are supported by the archive format reader.
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
*/
__LA_DECL int archive_read_format_capabilities(struct archive *);
/* Read data from the body of an entry. Similar to read(2). */
__LA_DECL __LA_SSIZE_T archive_read_data(struct archive *,
void *, size_t);
@ -674,6 +737,7 @@ __LA_DECL int archive_write_set_format_mtree_classic(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
__LA_DECL int archive_write_set_format_raw(struct archive *);
__LA_DECL int archive_write_set_format_shar(struct archive *);
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
__LA_DECL int archive_write_set_format_ustar(struct archive *);
@ -883,6 +947,10 @@ __LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *,
int (*_metadata_filter_func)(struct archive *, void *,
struct archive_entry *), void *_client_data);
/* Simplified cleanup interface;
* This calls archive_read_free() or archive_write_free() as needed. */
__LA_DECL int archive_free(struct archive *);
/*
* Accessor functions to read/set various information in
* the struct archive object:
@ -1029,6 +1097,10 @@ __LA_DECL int archive_match_include_gname(struct archive *, const char *);
__LA_DECL int archive_match_include_gname_w(struct archive *,
const wchar_t *);
/* Utility functions */
/* Convenience function to sort a NULL terminated list of strings */
__LA_DECL int archive_utility_string_sort(char **);
#ifdef __cplusplus
}
#endif

View File

@ -201,6 +201,9 @@ archive_entry_clone(struct archive_entry *entry)
entry2->ae_set = entry->ae_set;
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
/* Copy encryption status */
entry2->encryption = entry->encryption;
/* Copy ACL data over. */
archive_acl_copy(&entry2->acl, &entry->acl);
@ -695,6 +698,24 @@ _archive_entry_uname_l(struct archive_entry *entry,
return (archive_mstring_get_mbs_l(&entry->ae_uname, p, len, sc));
}
int
archive_entry_is_data_encrypted(struct archive_entry *entry)
{
return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA);
}
int
archive_entry_is_metadata_encrypted(struct archive_entry *entry)
{
return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA);
}
int
archive_entry_is_encrypted(struct archive_entry *entry)
{
return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA));
}
/*
* Functions to set archive_entry properties.
*/
@ -1216,6 +1237,26 @@ archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name)
return (0);
}
void
archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted)
{
if (is_encrypted) {
entry->encryption |= AE_ENCRYPTION_DATA;
} else {
entry->encryption &= ~AE_ENCRYPTION_DATA;
}
}
void
archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted)
{
if (is_encrypted) {
entry->encryption |= AE_ENCRYPTION_METADATA;
} else {
entry->encryption &= ~AE_ENCRYPTION_METADATA;
}
}
int
_archive_entry_copy_uname_l(struct archive_entry *entry,
const char *name, size_t len, struct archive_string_conv *sc)

View File

@ -43,10 +43,6 @@
#include <stddef.h> /* for wchar_t */
#include <time.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif
/* Get a suitable 64-bit integer type. */
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
# define __LA_INT64_T __int64
@ -235,6 +231,9 @@ __LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
/*
* Set fields in an archive_entry.
@ -306,6 +305,8 @@ __LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
/*
* Routines to bulk copy fields to/from a platform-native "struct
* stat." Libarchive used to just store a struct stat inside of each

View File

@ -154,6 +154,11 @@ struct archive_entry {
/* Not used within libarchive; useful for some clients. */
struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */
#define AE_ENCRYPTION_NONE 0
#define AE_ENCRYPTION_DATA 1
#define AE_ENCRYPTION_METADATA 2
char encryption;
void *mac_metadata;
size_t mac_metadata_size;

View File

@ -58,7 +58,7 @@ archive_entry_sparse_add_entry(struct archive_entry *entry,
if (offset < 0 || length < 0)
/* Invalid value */
return;
if (offset + length < 0 ||
if (offset > INT64_MAX - length ||
offset + length > archive_entry_size(entry))
/* A value of "length" parameter is too large. */
return;

View File

@ -369,8 +369,8 @@ relunitphrase(struct gdstate *gds)
&& gds->tokenp[1].token == tSEC_UNIT) {
/* "1 day" */
gds->HaveRel++;
gds->RelSeconds += gds->tokenp[1].value * gds->tokenp[2].value;
gds->tokenp += 3;
gds->RelSeconds += gds->tokenp[0].value * gds->tokenp[1].value;
gds->tokenp += 2;
return 1;
}
if (gds->tokenp[0].token == '-'
@ -403,7 +403,7 @@ relunitphrase(struct gdstate *gds)
/* "now", "tomorrow" */
gds->HaveRel++;
gds->RelSeconds += gds->tokenp[0].value;
++gds->tokenp;
gds->tokenp += 1;
return 1;
}
if (gds->tokenp[0].token == tMONTH_UNIT) {
@ -1022,10 +1022,11 @@ int
main(int argc, char **argv)
{
time_t d;
time_t now = time(NULL);
while (*++argv != NULL) {
(void)printf("Input: %s\n", *argv);
d = get_date(*argv);
d = get_date(now, *argv);
if (d == -1)
(void)printf("Bad format - couldn't convert.\n");
else

View File

@ -1152,7 +1152,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
{
/* NOTE: stat() on Windows cannot handle nano seconds. */
HANDLE h;
WIN32_FIND_DATA d;
WIN32_FIND_DATAA d;
if (path == NULL || *path == '\0') {
archive_set_error(&(a->archive), EINVAL, "pathname is empty");

View File

@ -0,0 +1,329 @@
/* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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.
*/
/* Originally from NetBSD's mknod(8) source. */
#include "archive_platform.h"
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
#if !defined(lint)
__RCSID("$NetBSD$");
#endif /* not lint */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "archive_pack_dev.h"
static pack_t pack_netbsd;
static pack_t pack_freebsd;
static pack_t pack_8_8;
static pack_t pack_12_20;
static pack_t pack_14_18;
static pack_t pack_8_24;
static pack_t pack_bsdos;
static int compare_format(const void *, const void *);
static const char iMajorError[] = "invalid major number";
static const char iMinorError[] = "invalid minor number";
static const char tooManyFields[] = "too many fields for format";
/* This is blatantly stolen from libarchive/archive_entry.c,
* in an attempt to get this to play nice on MinGW... */
#if !defined(HAVE_MAJOR) && !defined(major)
/* Replacement for major/minor/makedev. */
#define major(x) ((int)(0x00ff & ((x) >> 8)))
#define minor(x) ((int)(0xffff00ff & (x)))
#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min)))
#endif
/* Play games to come up with a suitable makedev() definition. */
#ifdef __QNXNTO__
/* QNX. <sigh> */
#include <sys/netmgr.h>
#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min))
#elif defined makedev
/* There's a "makedev" macro. */
#define apd_makedev(maj, min) makedev((maj), (min))
#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
/* Windows. <sigh> */
#define apd_makedev(maj, min) mkdev((maj), (min))
#else
/* There's a "makedev" function. */
#define apd_makedev(maj, min) makedev((maj), (min))
#endif
/* exported */
dev_t
pack_native(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = apd_makedev(numbers[0], numbers[1]);
if ((u_long)major(dev) != numbers[0])
*error = iMajorError;
else if ((u_long)minor(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
static dev_t
pack_netbsd(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_netbsd(numbers[0], numbers[1]);
if ((u_long)major_netbsd(dev) != numbers[0])
*error = iMajorError;
else if ((u_long)minor_netbsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0))
#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0xffff00ff)))
static dev_t
pack_freebsd(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_freebsd(numbers[0], numbers[1]);
if ((u_long)major_freebsd(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_freebsd(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8))
#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \
(((y) << 0) & 0x000000ff)))
static dev_t
pack_8_8(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_8_8(numbers[0], numbers[1]);
if ((u_long)major_8_8(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_8_8(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0))
#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 0) & 0x000fffff)))
static dev_t
pack_12_20(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((u_long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18))
#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0))
#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \
(((y) << 0) & 0x0003ffff)))
static dev_t
pack_14_18(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_14_18(numbers[0], numbers[1]);
if ((u_long)major_14_18(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_14_18(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24))
#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0))
#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \
(((y) << 0) & 0x00ffffff)))
static dev_t
pack_8_24(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_8_24(numbers[0], numbers[1]);
if ((u_long)major_8_24(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_8_24(dev) != numbers[1])
*error = iMinorError;
} else
*error = tooManyFields;
return (dev);
}
#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20))
#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8))
#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0))
#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \
(((y) << 8) & 0x000fff00) | \
(((z) << 0) & 0x000000ff)))
static dev_t
pack_bsdos(int n, u_long numbers[], const char **error)
{
dev_t dev = 0;
if (n == 2) {
dev = makedev_12_20(numbers[0], numbers[1]);
if ((u_long)major_12_20(dev) != numbers[0])
*error = iMajorError;
if ((u_long)minor_12_20(dev) != numbers[1])
*error = iMinorError;
} else if (n == 3) {
dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]);
if ((u_long)major_12_12_8(dev) != numbers[0])
*error = iMajorError;
if ((u_long)unit_12_12_8(dev) != numbers[1])
*error = "invalid unit number";
if ((u_long)subunit_12_12_8(dev) != numbers[2])
*error = "invalid subunit number";
} else
*error = tooManyFields;
return (dev);
}
/* list of formats and pack functions */
/* this list must be sorted lexically */
static struct format {
const char *name;
pack_t *pack;
} formats[] = {
{"386bsd", pack_8_8},
{"4bsd", pack_8_8},
{"bsdos", pack_bsdos},
{"freebsd", pack_freebsd},
{"hpux", pack_8_24},
{"isc", pack_8_8},
{"linux", pack_8_8},
{"native", pack_native},
{"netbsd", pack_netbsd},
{"osf1", pack_12_20},
{"sco", pack_8_8},
{"solaris", pack_14_18},
{"sunos", pack_8_8},
{"svr3", pack_8_8},
{"svr4", pack_14_18},
{"ultrix", pack_8_8},
};
static int
compare_format(const void *key, const void *element)
{
const char *name;
const struct format *format;
name = key;
format = element;
return (strcmp(name, format->name));
}
pack_t *
pack_find(const char *name)
{
struct format *format;
format = bsearch(name, formats,
sizeof(formats)/sizeof(formats[0]),
sizeof(formats[0]), compare_format);
if (format == 0)
return (NULL);
return (format->pack);
}

View File

@ -0,0 +1,50 @@
/* $NetBSD: pack_dev.h,v 1.8 2013/06/14 16:28:20 tsutsui Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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.
*/
/* Originally from NetBSD's mknod(8) source. */
#ifndef _PACK_DEV_H
#define _PACK_DEV_H
typedef dev_t pack_t(int, u_long [], const char **);
typedef unsigned long u_long;
pack_t *pack_find(const char *);
pack_t pack_native;
#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8)))
#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \
(((x) & 0x000000ff) >> 0)))
#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \
(((y) << 12) & 0xfff00000) | \
(((y) << 0) & 0x000000ff)))
#endif /* _PACK_DEV_H */

View File

@ -66,15 +66,18 @@
* headers as required.
*/
/* Get a real definition for __FBSDID if we can */
/* Get a real definition for __FBSDID or __RCSID if we can */
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
/* If not, define it so as to avoid dangling semicolons. */
/* If not, define them so as to avoid dangling semicolons. */
#ifndef __FBSDID
#define __FBSDID(a) struct _undefined_hack
#endif
#ifndef __RCSID
#define __RCSID(a) struct _undefined_hack
#endif
/* Old glibc mbsnrtowcs fails assertions in our use case. */
#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1

View File

@ -746,6 +746,59 @@ archive_read_header_position(struct archive *_a)
return (a->header_position);
}
/*
* Returns 1 if the archive contains at least one encrypted entry.
* If the archive format not support encryption at all
* ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned.
* If for any other reason (e.g. not enough data read so far)
* we cannot say whether there are encrypted entries, then
* ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned.
* In general, this function will return values below zero when the
* reader is uncertain or totally uncapable of encryption support.
* When this function returns 0 you can be sure that the reader
* supports encryption detection but no encrypted entries have
* been found yet.
*
* NOTE: If the metadata/header of an archive is also encrypted, you
* cannot rely on the number of encrypted entries. That is why this
* function does not return the number of encrypted entries but#
* just shows that there are some.
*/
int
archive_read_has_encrypted_entries(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
int format_supports_encryption = archive_read_format_capabilities(_a)
& (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
if (!_a || !format_supports_encryption) {
/* Format in general doesn't support encryption */
return ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED;
}
/* A reader potentially has read enough data now. */
if (a->format && a->format->has_encrypted_entries) {
return (a->format->has_encrypted_entries)(a);
}
/* For any other reason we cannot say how many entries are there. */
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
/*
* Returns a bitmask of capabilities that are supported by the archive format reader.
* If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned.
*/
int
archive_read_format_capabilities(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
if (a && a->format && a->format->format_capabilties) {
return (a->format->format_capabilties)(a);
}
return ARCHIVE_READ_FORMAT_CAPS_NONE;
}
/*
* Read data from an archive entry, using a read(2)-style interface.
* This is a convenience routine that just calls
@ -1094,7 +1147,9 @@ __archive_read_register_format(struct archive_read *a,
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *))
int (*cleanup)(struct archive_read *),
int (*format_capabilities)(struct archive_read *),
int (*has_encrypted_entries)(struct archive_read *))
{
int i, number_slots;
@ -1117,6 +1172,8 @@ __archive_read_register_format(struct archive_read *a,
a->formats[i].cleanup = cleanup;
a->formats[i].data = format_data;
a->formats[i].name = name;
a->formats[i].format_capabilties = format_capabilities;
a->formats[i].has_encrypted_entries = has_encrypted_entries;
return (ARCHIVE_OK);
}
}
@ -1557,10 +1614,9 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
client->dataset[++cursor].begin_position = r;
}
offset -= client->dataset[cursor].begin_position;
if (offset < 0)
offset = 0;
else if (offset > client->dataset[cursor].total_size - 1)
offset = client->dataset[cursor].total_size - 1;
if (offset < 0
|| offset > client->dataset[cursor].total_size)
return ARCHIVE_FATAL;
if ((r = client_seek_proxy(filter, offset, SEEK_SET)) < 0)
return r;
break;

View File

@ -399,7 +399,7 @@ setup_mac_metadata(struct archive_read_disk *a,
#endif
#if defined(HAVE_POSIX_ACL) && defined(ACL_TYPE_NFS4)
#ifdef HAVE_POSIX_ACL
static int translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
@ -419,6 +419,7 @@ setup_acls(struct archive_read_disk *a,
archive_entry_acl_clear(entry);
#ifdef ACL_TYPE_NFS4
/* Try NFS4 ACL first. */
if (*fd >= 0)
acl = acl_get_fd(*fd);
@ -447,6 +448,7 @@ setup_acls(struct archive_read_disk *a,
acl_free(acl);
return (ARCHIVE_OK);
}
#endif
/* Retrieve access ACL from file. */
if (*fd >= 0)
@ -492,6 +494,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
#ifdef ACL_TYPE_NFS4
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@ -508,8 +511,10 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
};
#ifdef ACL_TYPE_NFS4
static struct {
int archive_inherit;
int platform_inherit;
@ -519,21 +524,25 @@ static struct {
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
};
#endif
static int
translate_acl(struct archive_read_disk *a,
struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
{
acl_tag_t acl_tag;
#ifdef ACL_TYPE_NFS4
acl_entry_type_t acl_type;
acl_flagset_t acl_flagset;
int brand, r;
#endif
acl_entry_t acl_entry;
acl_permset_t acl_permset;
int brand, i, r, entry_acl_type;
int i, entry_acl_type;
int s, ae_id, ae_tag, ae_perm;
const char *ae_name;
#ifdef ACL_TYPE_NFS4
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
// Make sure the "brand" on this ACL is consistent
// with the default_entry_acl_type bits provided.
@ -560,6 +569,7 @@ translate_acl(struct archive_read_disk *a,
return ARCHIVE_FAILED;
break;
}
#endif
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
@ -592,9 +602,11 @@ translate_acl(struct archive_read_disk *a,
case ACL_OTHER:
ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
break;
#ifdef ACL_TYPE_NFS4
case ACL_EVERYONE:
ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
break;
#endif
default:
/* Skip types that libarchive can't support. */
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
@ -605,6 +617,7 @@ translate_acl(struct archive_read_disk *a,
// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
// non-NFSv4 ACLs
entry_acl_type = default_entry_acl_type;
#ifdef ACL_TYPE_NFS4
r = acl_get_entry_type_np(acl_entry, &acl_type);
if (r == 0) {
switch (acl_type) {
@ -634,9 +647,10 @@ translate_acl(struct archive_read_disk *a,
ae_perm |= acl_inherit_map[i].archive_inherit;
}
#endif
acl_get_permset(acl_entry, &acl_permset);
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
/*
* acl_get_perm() is spelled differently on different
* platforms; see above.

View File

@ -1973,7 +1973,7 @@ tree_dup(int fd)
static volatile int can_dupfd_cloexec = 1;
if (can_dupfd_cloexec) {
new_fd = fcntl(fd, F_DUPFD_CLOEXEC);
new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
if (new_fd != -1)
return (new_fd);
/* Linux 2.6.18 - 2.6.23 declare F_DUPFD_CLOEXEC,

View File

@ -929,7 +929,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
else
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
t->entry_fh = CreateFileW(tree_current_access_path(t),
GENERIC_READ, 0, NULL, OPEN_EXISTING, flags, NULL);
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
if (t->entry_fh == INVALID_HANDLE_VALUE) {
archive_set_error(&a->archive, errno,
"Couldn't open %ls", tree_current_path(a->tree));
@ -1886,7 +1886,7 @@ tree_current_file_information(struct tree *t, BY_HANDLE_FILE_INFORMATION *st,
if (sim_lstat && tree_current_is_physical_link(t))
flag |= FILE_FLAG_OPEN_REPARSE_POINT;
h = CreateFileW(tree_current_access_path(t), 0, 0, NULL,
h = CreateFileW(tree_current_access_path(t), 0, FILE_SHARE_READ, NULL,
OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
@ -2115,7 +2115,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
} else
desiredAccess = GENERIC_READ;
h = CreateFileW(path, desiredAccess, 0, NULL,
h = CreateFileW(path, desiredAccess, FILE_SHARE_READ, NULL,
OPEN_EXISTING, flag, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());
@ -2162,7 +2162,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
if (fd >= 0) {
h = (HANDLE)_get_osfhandle(fd);
} else {
h = CreateFileW(path, GENERIC_READ, 0, NULL,
h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
la_dosmaperr(GetLastError());

View File

@ -207,6 +207,8 @@ struct archive_read {
int (*read_data_skip)(struct archive_read *);
int64_t (*seek_data)(struct archive_read *, int64_t, int);
int (*cleanup)(struct archive_read *);
int (*format_capabilties)(struct archive_read *);
int (*has_encrypted_entries)(struct archive_read *);
} formats[16];
struct archive_format_descriptor *format; /* Active format. */
@ -218,15 +220,17 @@ struct archive_read {
};
int __archive_read_register_format(struct archive_read *a,
void *format_data,
const char *name,
int (*bid)(struct archive_read *, int),
int (*options)(struct archive_read *, const char *, const char *),
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *));
void *format_data,
const char *name,
int (*bid)(struct archive_read *, int),
int (*options)(struct archive_read *, const char *, const char *),
int (*read_header)(struct archive_read *, struct archive_entry *),
int (*read_data)(struct archive_read *, const void **, size_t *, int64_t *),
int (*read_data_skip)(struct archive_read *),
int64_t (*seek_data)(struct archive_read *, int64_t, int),
int (*cleanup)(struct archive_read *),
int (*format_capabilities)(struct archive_read *),
int (*has_encrypted_entries)(struct archive_read *));
int __archive_read_get_bidder(struct archive_read *a,
struct archive_read_filter_bidder **bidder);

View File

@ -193,6 +193,28 @@ Defaults to enabled, use
.Cm !rockridge
to disable.
.El
.It Format tar
.Bl -tag -compact -width indent
.It Cm compat-2x
Libarchive 2.x incorrectly encoded Unicode filenames on
some platforms.
This option mimics the libarchive 2.x filename handling
so that such archives can be read correctly.
.It Cm hdrcharset
The value is used as a character set name that will be
used when translating filenames.
.It Cm mac-ext
Support Mac OS metadata extension that records data in special
files beginning with a period and underscore.
Defaults to enabled on Mac OS, disabled on other platforms.
Use
.Cm !mac-ext
to disable.
.It Cm read_concatenated_archives
Ignore zeroed blocks in the archive, which occurs when multiple tar archives
have been concatenated together. Without this option, only the contents of
the first concatenated archive would be read.
.El
.El
.\"
.Sh ERRORS

View File

@ -78,7 +78,7 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
struct archive_read *a = (struct archive_read *)_a;
struct archive_format_descriptor *format;
size_t i;
int r, rv = ARCHIVE_WARN;
int r, rv = ARCHIVE_WARN, matched_modules = 0;
for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
format = &a->formats[i];
@ -86,8 +86,11 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
format->name == NULL)
/* This format does not support option. */
continue;
if (m != NULL && strcmp(format->name, m) != 0)
continue;
if (m != NULL) {
if (strcmp(format->name, m) != 0)
continue;
++matched_modules;
}
a->format = format;
r = format->options(a, o, v);
@ -96,16 +99,13 @@ archive_set_format_option(struct archive *_a, const char *m, const char *o,
if (r == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
if (m != NULL)
return (r);
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
/* If the format name didn't match, return a special code for
* _archive_set_option[s]. */
if (rv == ARCHIVE_WARN && m != NULL)
rv = ARCHIVE_WARN - 1;
if (m != NULL && matched_modules == 0)
return ARCHIVE_WARN - 1;
return (rv);
}
@ -116,7 +116,7 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
struct archive_read *a = (struct archive_read *)_a;
struct archive_read_filter *filter;
struct archive_read_filter_bidder *bidder;
int r, rv = ARCHIVE_WARN;
int r, rv = ARCHIVE_WARN, matched_modules = 0;
for (filter = a->filter; filter != NULL; filter = filter->upstream) {
bidder = filter->bidder;
@ -125,24 +125,24 @@ archive_set_filter_option(struct archive *_a, const char *m, const char *o,
if (bidder->options == NULL)
/* This bidder does not support option */
continue;
if (m != NULL && strcmp(filter->name, m) != 0)
continue;
if (m != NULL) {
if (strcmp(filter->name, m) != 0)
continue;
++matched_modules;
}
r = bidder->options(bidder, o, v);
if (r == ARCHIVE_FATAL)
return (ARCHIVE_FATAL);
if (m != NULL)
return (r);
if (r == ARCHIVE_OK)
rv = ARCHIVE_OK;
}
/* If the filter name didn't match, return a special code for
* _archive_set_option[s]. */
if (rv == ARCHIVE_WARN && m != NULL)
rv = ARCHIVE_WARN - 1;
if (m != NULL && matched_modules == 0)
return ARCHIVE_WARN - 1;
return (rv);
}

View File

@ -242,10 +242,11 @@ consume_header(struct archive_read_filter *self)
if (version >= 0x940) {
unsigned level = *p++;
if (method == 1 && level == 0) level = 3;
if (method == 2 && level == 0) level = 1;
if (method == 3 && level == 0) level = 9;
if (level < 1 && level > 9) {
unsigned default_level[] = {0, 3, 1, 9};
if (level == 0)
/* Method is 1..3 here due to check above. */
level = default_level[method];
else if (level > 9) {
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_MISC, "Invalid level");
return (ARCHIVE_FAILED);

View File

@ -601,7 +601,7 @@ lzip_init(struct archive_read_filter *self)
return (ARCHIVE_FATAL);
}
ret = lzma_raw_decoder(&(state->stream), filters);
#if LZMA_VERSION < 50000030
#if LZMA_VERSION < 50010000
free(filters[0].options);
#endif
if (ret != LZMA_OK) {

View File

@ -69,7 +69,11 @@ __FBSDID("$FreeBSD$");
#define _7Z_BZ2 0x040202
#define _7Z_PPMD 0x030401
#define _7Z_DELTA 0x03
#define _7Z_CRYPTO 0x06F10701
#define _7Z_CRYPTO_MAIN_ZIP 0x06F10101 /* Main Zip crypto algo */
#define _7Z_CRYPTO_RAR_29 0x06F10303 /* Rar29 AES-128 + (modified SHA-1) */
#define _7Z_CRYPTO_AES_256_SHA_256 0x06F10701 /* AES-256 + SHA-256 */
#define _7Z_X86 0x03030103
#define _7Z_X86_BCJ2 0x0303011B
#define _7Z_POWERPC 0x03030205
@ -322,8 +326,13 @@ struct _7zip {
struct archive_string_conv *sconv;
char format_name[64];
/* Custom value that is non-zero if this archive contains encrypted entries. */
int has_encrypted_entries;
};
static int archive_read_format_7zip_has_encrypted_entries(struct archive_read *);
static int archive_read_support_format_7zip_capabilities(struct archive_read *a);
static int archive_read_format_7zip_bid(struct archive_read *, int);
static int archive_read_format_7zip_cleanup(struct archive_read *);
static int archive_read_format_7zip_read_data(struct archive_read *,
@ -401,6 +410,13 @@ archive_read_support_format_7zip(struct archive *_a)
return (ARCHIVE_FATAL);
}
/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
r = __archive_read_register_format(a,
zip,
"7zip",
@ -410,13 +426,36 @@ archive_read_support_format_7zip(struct archive *_a)
archive_read_format_7zip_read_data,
archive_read_format_7zip_read_data_skip,
NULL,
archive_read_format_7zip_cleanup);
archive_read_format_7zip_cleanup,
archive_read_support_format_7zip_capabilities,
archive_read_format_7zip_has_encrypted_entries);
if (r != ARCHIVE_OK)
free(zip);
return (ARCHIVE_OK);
}
static int
archive_read_support_format_7zip_capabilities(struct archive_read * a)
{
(void)a; /* UNUSED */
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
}
static int
archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a)
{
if (_a && _a->format) {
struct _7zip * zip = (struct _7zip *)_a->format->data;
if (zip) {
return zip->has_encrypted_entries;
}
}
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
static int
archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
{
@ -476,7 +515,7 @@ check_7zip_header_in_sfx(const char *p)
switch ((unsigned char)p[5]) {
case 0x1C:
if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0)
return (6);
return (6);
/*
* Test the CRC because its extraction code has 7-Zip
* Magic Code, so we should do this in order not to
@ -484,15 +523,15 @@ check_7zip_header_in_sfx(const char *p)
*/
if (crc32(0, (const unsigned char *)p + 12, 20)
!= archive_le32dec(p + 8))
return (6);
return (6);
/* Hit the header! */
return (0);
case 0x37: return (5);
case 0x7A: return (4);
case 0xBC: return (3);
case 0xAF: return (2);
case 0x27: return (1);
default: return (6);
case 0x37: return (5);
case 0x7A: return (4);
case 0xBC: return (3);
case 0xAF: return (2);
case 0x27: return (1);
default: return (6);
}
}
@ -568,6 +607,19 @@ archive_read_format_7zip_read_header(struct archive_read *a,
struct _7zip *zip = (struct _7zip *)a->format->data;
struct _7zip_entry *zip_entry;
int r, ret = ARCHIVE_OK;
struct _7z_folder *folder = 0;
uint64_t fidx = 0;
/*
* It should be sufficient to call archive_read_next_header() for
* a reader to determine if an entry is encrypted or not. If the
* encryption of an entry is only detectable when calling
* archive_read_data(), so be it. We'll do the same check there
* as well.
*/
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
if (a->archive.archive_format_name == NULL)
@ -604,6 +656,32 @@ archive_read_format_7zip_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
/* Figure out if the entry is encrypted by looking at the folder
that is associated to the current 7zip entry. If the folder
has a coder with a _7Z_CRYPTO codec then the folder is encrypted.
Hence the entry must also be encrypted. */
if (zip_entry && zip_entry->folderIndex < zip->si.ci.numFolders) {
folder = &(zip->si.ci.folders[zip_entry->folderIndex]);
for (fidx=0; folder && fidx<folder->numCoders; fidx++) {
switch(folder->coders[fidx].codec) {
case _7Z_CRYPTO_MAIN_ZIP:
case _7Z_CRYPTO_RAR_29:
case _7Z_CRYPTO_AES_256_SHA_256: {
archive_entry_set_is_data_encrypted(entry, 1);
zip->has_encrypted_entries = 1;
break;
}
}
}
}
/* Now that we've checked for encryption, if there were still no
* encrypted entries found we can say for sure that there are none.
*/
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
if (archive_entry_copy_pathname_l(entry,
(const char *)zip_entry->utf16name,
zip_entry->name_len, zip->sconv) != 0) {
@ -707,6 +785,10 @@ archive_read_format_7zip_read_data(struct archive_read *a,
zip = (struct _7zip *)(a->format->data);
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
if (zip->pack_stream_bytes_unconsumed)
read_consume(a);
@ -969,7 +1051,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
{
lzma_options_delta delta_opt;
lzma_filter filters[LZMA_FILTERS_MAX];
#if LZMA_VERSION < 50000030
#if LZMA_VERSION < 50010000
lzma_filter *ff;
#endif
int fi = 0;
@ -994,7 +1076,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
* for BCJ+LZMA. If we were able to tell the uncompressed
* size to liblzma when using lzma_raw_decoder() liblzma
* could correctly deal with BCJ+LZMA. But unfortunately
* there is no way to do that.
* there is no way to do that.
* Discussion about this can be found at XZ Utils forum.
*/
if (coder2 != NULL) {
@ -1056,7 +1138,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
else
filters[fi].id = LZMA_FILTER_LZMA1;
filters[fi].options = NULL;
#if LZMA_VERSION < 50000030
#if LZMA_VERSION < 50010000
ff = &filters[fi];
#endif
r = lzma_properties_decode(&filters[fi], NULL,
@ -1070,7 +1152,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
filters[fi].id = LZMA_VLI_UNKNOWN;
filters[fi].options = NULL;
r = lzma_raw_decoder(&(zip->lzstream), filters);
#if LZMA_VERSION < 50000030
#if LZMA_VERSION < 50010000
free(ff->options);
#endif
if (r != LZMA_OK) {
@ -1203,6 +1285,17 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unexpected codec ID: %lX", zip->codec);
return (ARCHIVE_FAILED);
case _7Z_CRYPTO_MAIN_ZIP:
case _7Z_CRYPTO_RAR_29:
case _7Z_CRYPTO_AES_256_SHA_256:
if (a->entry) {
archive_entry_set_is_metadata_encrypted(a->entry, 1);
archive_entry_set_is_data_encrypted(a->entry, 1);
zip->has_encrypted_entries = 1;
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Crypto codec not supported yet (ID: 0x%lX)", zip->codec);
return (ARCHIVE_FAILED);
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Unknown codec ID: %lX", zip->codec);
@ -1426,7 +1519,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
do {
int sym;
sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
&(zip->ppmd7_context), &(zip->range_dec.p));
if (sym < 0) {
@ -2755,6 +2848,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
zip->header_crc32 = 0;
zip->header_is_encoded = 0;
zip->header_is_being_read = 1;
zip->has_encrypted_entries = 0;
check_header_crc = 1;
if ((p = header_bytes(a, 1)) == NULL) {
@ -3170,7 +3264,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size,
return (r);
/*
* Skip the bytes we alrady has skipped in skip_stream().
* Skip the bytes we alrady has skipped in skip_stream().
*/
while (skip_bytes) {
ssize_t skipped;
@ -3235,16 +3329,36 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
* Check coder types.
*/
for (i = 0; i < folder->numCoders; i++) {
if (folder->coders[i].codec == _7Z_CRYPTO) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"The %s is encrypted, "
"but currently not supported", cname);
return (ARCHIVE_FATAL);
switch(folder->coders[i].codec) {
case _7Z_CRYPTO_MAIN_ZIP:
case _7Z_CRYPTO_RAR_29:
case _7Z_CRYPTO_AES_256_SHA_256: {
/* For entry that is associated with this folder, mark
it as encrypted (data+metadata). */
zip->has_encrypted_entries = 1;
if (a->entry) {
archive_entry_set_is_data_encrypted(a->entry, 1);
archive_entry_set_is_metadata_encrypted(a->entry, 1);
}
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"The %s is encrypted, "
"but currently not supported", cname);
return (ARCHIVE_FATAL);
}
case _7Z_X86_BCJ2: {
found_bcj2++;
break;
}
}
if (folder->coders[i].codec == _7Z_X86_BCJ2)
found_bcj2++;
}
/* Now that we've checked for encryption, if there were still no
* encrypted entries found we can say for sure that there are none.
*/
if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
zip->has_encrypted_entries = 0;
}
if ((folder->numCoders > 2 && !found_bcj2) || found_bcj2 > 1) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,

View File

@ -122,7 +122,9 @@ archive_read_support_format_ar(struct archive *_a)
archive_read_format_ar_read_data,
archive_read_format_ar_skip,
NULL,
archive_read_format_ar_cleanup);
archive_read_format_ar_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) {
free(ar);

View File

@ -383,7 +383,9 @@ archive_read_support_format_cab(struct archive *_a)
archive_read_format_cab_read_data,
archive_read_format_cab_read_data_skip,
NULL,
archive_read_format_cab_cleanup);
archive_read_format_cab_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK)
free(cab);

View File

@ -243,7 +243,9 @@ archive_read_support_format_cpio(struct archive *_a)
archive_read_format_cpio_read_data,
archive_read_format_cpio_skip,
NULL,
archive_read_format_cpio_cleanup);
archive_read_format_cpio_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK)
free(cpio);

View File

@ -54,6 +54,8 @@ archive_read_support_format_empty(struct archive *_a)
archive_read_format_empty_read_data,
NULL,
NULL,
NULL,
NULL,
NULL);
return (r);

View File

@ -478,7 +478,9 @@ archive_read_support_format_iso9660(struct archive *_a)
archive_read_format_iso9660_read_data,
archive_read_format_iso9660_read_data_skip,
NULL,
archive_read_format_iso9660_cleanup);
archive_read_format_iso9660_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK) {
free(iso9660);

View File

@ -320,7 +320,9 @@ archive_read_support_format_lha(struct archive *_a)
archive_read_format_lha_read_data,
archive_read_format_lha_read_data_skip,
NULL,
archive_read_format_lha_cleanup);
archive_read_format_lha_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK)
free(lha);

View File

@ -51,6 +51,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
#include "archive_private.h"
#include "archive_read_private.h"
#include "archive_string.h"
#include "archive_pack_dev.h"
#ifndef O_BINARY
#define O_BINARY 0
@ -103,6 +104,7 @@ struct mtree {
struct archive_entry_linkresolver *resolver;
int64_t cur_size;
char checkfs;
};
static int bid_keycmp(const char *, const char *, ssize_t);
@ -173,6 +175,29 @@ get_time_t_min(void)
#endif
}
static int
archive_read_format_mtree_options(struct archive_read *a,
const char *key, const char *val)
{
struct mtree *mtree;
mtree = (struct mtree *)(a->format->data);
if (strcmp(key, "checkfs") == 0) {
/* Allows to read information missing from the mtree from the file system */
if (val == NULL || val[0] == 0) {
mtree->checkfs = 0;
} else {
mtree->checkfs = 1;
}
return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
* supervisor that we didn't handle it. It will generate
* a suitable error if no one used this option. */
return (ARCHIVE_WARN);
}
static void
free_options(struct mtree_option *head)
{
@ -205,7 +230,7 @@ archive_read_support_format_mtree(struct archive *_a)
mtree->fd = -1;
r = __archive_read_register_format(a, mtree, "mtree",
mtree_bid, NULL, read_header, read_data, skip, NULL, cleanup);
mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
if (r != ARCHIVE_OK)
free(mtree);
@ -367,7 +392,7 @@ bid_keyword(const char *p, ssize_t len)
"gid", "gname", NULL
};
static const char *keys_il[] = {
"ignore", "link", NULL
"ignore", "inode", "link", NULL
};
static const char *keys_m[] = {
"md5", "md5digest", "mode", NULL
@ -376,7 +401,7 @@ bid_keyword(const char *p, ssize_t len)
"nlink", "nochange", "optional", NULL
};
static const char *keys_r[] = {
"rmd160", "rmd160digest", NULL
"resdevice", "rmd160", "rmd160digest", NULL
};
static const char *keys_s[] = {
"sha1", "sha1digest",
@ -1103,162 +1128,164 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
mtree->current_dir.length = n;
}
/*
* Try to open and stat the file to get the real size
* and other file info. It would be nice to avoid
* this here so that getting a listing of an mtree
* wouldn't require opening every referenced contents
* file. But then we wouldn't know the actual
* contents size, so I don't see a really viable way
* around this. (Also, we may want to someday pull
* other unspecified info from the contents file on
* disk.)
*/
mtree->fd = -1;
if (archive_strlen(&mtree->contents_name) > 0)
path = mtree->contents_name.s;
else
path = archive_entry_pathname(entry);
if (mtree->checkfs) {
/*
* Try to open and stat the file to get the real size
* and other file info. It would be nice to avoid
* this here so that getting a listing of an mtree
* wouldn't require opening every referenced contents
* file. But then we wouldn't know the actual
* contents size, so I don't see a really viable way
* around this. (Also, we may want to someday pull
* other unspecified info from the contents file on
* disk.)
*/
mtree->fd = -1;
if (archive_strlen(&mtree->contents_name) > 0)
path = mtree->contents_name.s;
else
path = archive_entry_pathname(entry);
if (archive_entry_filetype(entry) == AE_IFREG ||
archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd == -1 &&
(errno != ENOENT ||
archive_strlen(&mtree->contents_name) > 0)) {
archive_set_error(&a->archive, errno,
"Can't open %s", path);
r = ARCHIVE_WARN;
}
}
st = &st_storage;
if (mtree->fd >= 0) {
if (fstat(mtree->fd, st) == -1) {
archive_set_error(&a->archive, errno,
"Could not fstat %s", path);
r = ARCHIVE_WARN;
/* If we can't stat it, don't keep it open. */
close(mtree->fd);
mtree->fd = -1;
st = NULL;
}
} else if (lstat(path, st) == -1) {
st = NULL;
}
/*
* Check for a mismatch between the type in the specification and
* the type of the contents object on disk.
*/
if (st != NULL) {
if (
((st->st_mode & S_IFMT) == S_IFREG &&
archive_entry_filetype(entry) == AE_IFREG)
#ifdef S_IFLNK
|| ((st->st_mode & S_IFMT) == S_IFLNK &&
archive_entry_filetype(entry) == AE_IFLNK)
#endif
#ifdef S_IFSOCK
|| ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
archive_entry_filetype(entry) == AE_IFSOCK)
#endif
#ifdef S_IFCHR
|| ((st->st_mode & S_IFMT) == S_IFCHR &&
archive_entry_filetype(entry) == AE_IFCHR)
#endif
#ifdef S_IFBLK
|| ((st->st_mode & S_IFMT) == S_IFBLK &&
archive_entry_filetype(entry) == AE_IFBLK)
#endif
|| ((st->st_mode & S_IFMT) == S_IFDIR &&
archive_entry_filetype(entry) == AE_IFDIR)
#ifdef S_IFIFO
|| ((st->st_mode & S_IFMT) == S_IFIFO &&
archive_entry_filetype(entry) == AE_IFIFO)
#endif
) {
/* Types match. */
} else {
/* Types don't match; bail out gracefully. */
if (mtree->fd >= 0)
close(mtree->fd);
mtree->fd = -1;
if (parsed_kws & MTREE_HAS_OPTIONAL) {
/* It's not an error for an optional entry
to not match disk. */
*use_next = 1;
} else if (r == ARCHIVE_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"mtree specification has different type for %s",
archive_entry_pathname(entry));
if (archive_entry_filetype(entry) == AE_IFREG ||
archive_entry_filetype(entry) == AE_IFDIR) {
mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
__archive_ensure_cloexec_flag(mtree->fd);
if (mtree->fd == -1 &&
(errno != ENOENT ||
archive_strlen(&mtree->contents_name) > 0)) {
archive_set_error(&a->archive, errno,
"Can't open %s", path);
r = ARCHIVE_WARN;
}
return r;
}
}
/*
* If there is a contents file on disk, pick some of the metadata
* from that file. For most of these, we only set it from the contents
* if it wasn't already parsed from the specification.
*/
if (st != NULL) {
if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
(archive_entry_filetype(entry) == AE_IFCHR ||
archive_entry_filetype(entry) == AE_IFBLK))
archive_entry_set_rdev(entry, st->st_rdev);
if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_gid(entry, st->st_gid);
if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_uid(entry, st->st_uid);
if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_n);
#elif HAVE_STRUCT_STAT_ST_UMTIME
archive_entry_set_mtime(entry, st->st_mtime,
st->st_umtime*1000);
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_usec*1000);
#else
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
st = &st_storage;
if (mtree->fd >= 0) {
if (fstat(mtree->fd, st) == -1) {
archive_set_error(&a->archive, errno,
"Could not fstat %s", path);
r = ARCHIVE_WARN;
/* If we can't stat it, don't keep it open. */
close(mtree->fd);
mtree->fd = -1;
st = NULL;
}
} else if (lstat(path, st) == -1) {
st = NULL;
}
if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_nlink(entry, st->st_nlink);
if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_perm(entry, st->st_mode);
if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_size(entry, st->st_size);
archive_entry_set_ino(entry, st->st_ino);
archive_entry_set_dev(entry, st->st_dev);
archive_entry_linkify(mtree->resolver, &entry, &sparse_entry);
} else if (parsed_kws & MTREE_HAS_OPTIONAL) {
/*
* Couldn't open the entry, stat it or the on-disk type
* didn't match. If this entry is optional, just ignore it
* and read the next header entry.
* Check for a mismatch between the type in the specification and
* the type of the contents object on disk.
*/
*use_next = 1;
return ARCHIVE_OK;
if (st != NULL) {
if (
((st->st_mode & S_IFMT) == S_IFREG &&
archive_entry_filetype(entry) == AE_IFREG)
#ifdef S_IFLNK
|| ((st->st_mode & S_IFMT) == S_IFLNK &&
archive_entry_filetype(entry) == AE_IFLNK)
#endif
#ifdef S_IFSOCK
|| ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
archive_entry_filetype(entry) == AE_IFSOCK)
#endif
#ifdef S_IFCHR
|| ((st->st_mode & S_IFMT) == S_IFCHR &&
archive_entry_filetype(entry) == AE_IFCHR)
#endif
#ifdef S_IFBLK
|| ((st->st_mode & S_IFMT) == S_IFBLK &&
archive_entry_filetype(entry) == AE_IFBLK)
#endif
|| ((st->st_mode & S_IFMT) == S_IFDIR &&
archive_entry_filetype(entry) == AE_IFDIR)
#ifdef S_IFIFO
|| ((st->st_mode & S_IFMT) == S_IFIFO &&
archive_entry_filetype(entry) == AE_IFIFO)
#endif
) {
/* Types match. */
} else {
/* Types don't match; bail out gracefully. */
if (mtree->fd >= 0)
close(mtree->fd);
mtree->fd = -1;
if (parsed_kws & MTREE_HAS_OPTIONAL) {
/* It's not an error for an optional entry
to not match disk. */
*use_next = 1;
} else if (r == ARCHIVE_OK) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"mtree specification has different type for %s",
archive_entry_pathname(entry));
r = ARCHIVE_WARN;
}
return r;
}
}
/*
* If there is a contents file on disk, pick some of the metadata
* from that file. For most of these, we only set it from the contents
* if it wasn't already parsed from the specification.
*/
if (st != NULL) {
if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
(archive_entry_filetype(entry) == AE_IFCHR ||
archive_entry_filetype(entry) == AE_IFBLK))
archive_entry_set_rdev(entry, st->st_rdev);
if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_gid(entry, st->st_gid);
if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_uid(entry, st->st_uid);
if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtimespec.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtim.tv_nsec);
#elif HAVE_STRUCT_STAT_ST_MTIME_N
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_n);
#elif HAVE_STRUCT_STAT_ST_UMTIME
archive_entry_set_mtime(entry, st->st_mtime,
st->st_umtime*1000);
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
archive_entry_set_mtime(entry, st->st_mtime,
st->st_mtime_usec*1000);
#else
archive_entry_set_mtime(entry, st->st_mtime, 0);
#endif
}
if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_nlink(entry, st->st_nlink);
if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_perm(entry, st->st_mode);
if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
(parsed_kws & MTREE_HAS_NOCHANGE) != 0)
archive_entry_set_size(entry, st->st_size);
archive_entry_set_ino(entry, st->st_ino);
archive_entry_set_dev(entry, st->st_dev);
archive_entry_linkify(mtree->resolver, &entry, &sparse_entry);
} else if (parsed_kws & MTREE_HAS_OPTIONAL) {
/*
* Couldn't open the entry, stat it or the on-disk type
* didn't match. If this entry is optional, just ignore it
* and read the next header entry.
*/
*use_next = 1;
return ARCHIVE_OK;
}
}
mtree->cur_size = archive_entry_size(entry);
@ -1292,33 +1319,82 @@ parse_line(struct archive_read *a, struct archive_entry *entry,
/*
* Device entries have one of the following forms:
* raw dev_t
* format,major,minor[,subdevice]
*
* Just use major and minor, no translation etc is done
* between formats.
* - raw dev_t
* - format,major,minor[,subdevice]
* When parsing succeeded, `pdev' will contain the appropriate dev_t value.
*/
static int
parse_device(struct archive *a, struct archive_entry *entry, char *val)
{
char *comma1, *comma2;
comma1 = strchr(val, ',');
if (comma1 == NULL) {
archive_entry_set_dev(entry, (dev_t)mtree_atol10(&val));
return (ARCHIVE_OK);
/* strsep() is not in C90, but strcspn() is. */
/* Taken from http://unixpapa.com/incnote/string.html */
static char *
la_strsep(char **sp, char *sep)
{
char *p, *s;
if (sp == NULL || *sp == NULL || **sp == '\0')
return(NULL);
s = *sp;
p = s + strcspn(s, sep);
if (*p != '\0')
*p++ = '\0';
*sp = p;
return(s);
}
static int
parse_device(dev_t *pdev, struct archive *a, char *val)
{
#define MAX_PACK_ARGS 3
unsigned long numbers[MAX_PACK_ARGS];
char *p, *dev;
int argc;
pack_t *pack;
dev_t result;
const char *error = NULL;
memset(pdev, 0, sizeof(*pdev));
if ((dev = strchr(val, ',')) != NULL) {
/*
* Device's major/minor are given in a specified format.
* Decode and pack it accordingly.
*/
*dev++ = '\0';
if ((pack = pack_find(val)) == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Unknown format `%s'", val);
return ARCHIVE_WARN;
}
argc = 0;
while ((p = la_strsep(&dev, ",")) != NULL) {
if (*p == '\0') {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Missing number");
return ARCHIVE_WARN;
}
numbers[argc++] = mtree_atol(&p);
if (argc > MAX_PACK_ARGS) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Too many arguments");
return ARCHIVE_WARN;
}
}
if (argc < 2) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Not enough arguments");
return ARCHIVE_WARN;
}
result = (*pack)(argc, numbers, &error);
if (error != NULL) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"%s", error);
return ARCHIVE_WARN;
}
} else {
/* file system raw value. */
result = (dev_t)mtree_atol(&val);
}
++comma1;
comma2 = strchr(comma1, ',');
if (comma2 == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
"Malformed device attribute");
return (ARCHIVE_WARN);
}
++comma2;
archive_entry_set_rdevmajor(entry, (dev_t)mtree_atol(&comma1));
archive_entry_set_rdevminor(entry, (dev_t)mtree_atol(&comma2));
return (ARCHIVE_OK);
*pdev = result;
return ARCHIVE_OK;
#undef MAX_PACK_ARGS
}
/*
@ -1374,8 +1450,16 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
break;
case 'd':
if (strcmp(key, "device") == 0) {
/* stat(2) st_rdev field, e.g. the major/minor IDs
* of a char/block special file */
int r;
dev_t dev;
*parsed_kws |= MTREE_HAS_DEVICE;
return parse_device(&a->archive, entry, val);
r = parse_device(&dev, &a->archive, val);
if (r == ARCHIVE_OK)
archive_entry_set_rdev(entry, dev);
return r;
}
case 'f':
if (strcmp(key, "flags") == 0) {
@ -1394,6 +1478,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
archive_entry_copy_gname(entry, val);
break;
}
case 'i':
if (strcmp(key, "inode") == 0) {
archive_entry_set_ino(entry, mtree_atol10(&val));
break;
}
case 'l':
if (strcmp(key, "link") == 0) {
archive_entry_copy_symlink(entry, val);
@ -1423,6 +1512,17 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
break;
}
case 'r':
if (strcmp(key, "resdevice") == 0) {
/* stat(2) st_dev field, e.g. the device ID where the
* inode resides */
int r;
dev_t dev;
r = parse_device(&dev, &a->archive, val);
if (r == ARCHIVE_OK)
archive_entry_set_dev(entry, dev);
return r;
}
if (strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0)
break;

View File

@ -304,8 +304,15 @@ struct rar
ssize_t avail_in;
const unsigned char *next_in;
} br;
/*
* Custom field to denote that this archive contains encrypted entries
*/
int has_encrypted_entries;
};
static int archive_read_support_format_rar_capabilities(struct archive_read *);
static int archive_read_format_rar_has_encrypted_entries(struct archive_read *);
static int archive_read_format_rar_bid(struct archive_read *, int);
static int archive_read_format_rar_options(struct archive_read *,
const char *, const char *);
@ -646,6 +653,12 @@ archive_read_support_format_rar(struct archive *_a)
}
memset(rar, 0, sizeof(*rar));
/*
* Until enough data has been read, we cannot tell about
* any encrypted entries yet.
*/
rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
r = __archive_read_register_format(a,
rar,
"rar",
@ -655,13 +668,36 @@ archive_read_support_format_rar(struct archive *_a)
archive_read_format_rar_read_data,
archive_read_format_rar_read_data_skip,
archive_read_format_rar_seek_data,
archive_read_format_rar_cleanup);
archive_read_format_rar_cleanup,
archive_read_support_format_rar_capabilities,
archive_read_format_rar_has_encrypted_entries);
if (r != ARCHIVE_OK)
free(rar);
return (r);
}
static int
archive_read_support_format_rar_capabilities(struct archive_read * a)
{
(void)a; /* UNUSED */
return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
}
static int
archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
{
if (_a && _a->format) {
struct rar * rar = (struct rar *)_a->format->data;
if (rar) {
return rar->has_encrypted_entries;
}
}
return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
}
static int
archive_read_format_rar_bid(struct archive_read *a, int best_bid)
{
@ -755,7 +791,7 @@ archive_read_format_rar_options(struct archive_read *a,
{
struct rar *rar;
int ret = ARCHIVE_FAILED;
rar = (struct rar *)(a->format->data);
if (strcmp(key, "hdrcharset") == 0) {
if (val == NULL || val[0] == 0)
@ -797,6 +833,17 @@ archive_read_format_rar_read_header(struct archive_read *a,
rar = (struct rar *)(a->format->data);
/*
* It should be sufficient to call archive_read_next_header() for
* a reader to determine if an entry is encrypted or not. If the
* encryption of an entry is only detectable when calling
* archive_read_data(), so be it. We'll do the same check there
* as well.
*/
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
}
/* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
* this fails.
*/
@ -857,9 +904,14 @@ archive_read_format_rar_read_header(struct archive_read *a,
sizeof(rar->reserved2));
}
/* Main header is password encrytped, so we cannot read any
file names or any other info about files from the header. */
if (rar->main_flags & MHD_PASSWORD)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
archive_entry_set_is_metadata_encrypted(entry, 1);
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable.");
return (ARCHIVE_FATAL);
}
@ -938,6 +990,10 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
struct rar *rar = (struct rar *)(a->format->data);
int ret;
if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
rar->has_encrypted_entries = 0;
}
if (rar->bytes_unconsumed > 0) {
/* Consume as much as the decompressor actually used. */
__archive_read_consume(a, rar->bytes_unconsumed);
@ -957,7 +1013,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
{
case COMPRESS_METHOD_STORE:
ret = read_data_stored(a, buff, size, offset);
break;
break;
case COMPRESS_METHOD_FASTEST:
case COMPRESS_METHOD_FAST:
@ -967,13 +1023,13 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
ret = read_data_compressed(a, buff, size, offset);
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
break;
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unsupported compression method for RAR file.");
ret = ARCHIVE_FATAL;
break;
break;
}
return (ret);
}
@ -1290,9 +1346,14 @@ read_header(struct archive_read *a, struct archive_entry *entry,
if (rar->file_flags & FHD_PASSWORD)
{
archive_entry_set_is_data_encrypted(entry, 1);
rar->has_encrypted_entries = 1;
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"RAR encryption support unavailable.");
return (ARCHIVE_FATAL);
/* Since it is only the data part itself that is encrypted we can at least
extract information about the currently processed entry and don't need
to return ARCHIVE_FATAL here. */
/*return (ARCHIVE_FATAL);*/
}
if (rar->file_flags & FHD_LARGE)
@ -1377,7 +1438,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
flagbyte = *(p + offset++);
flagbits = 8;
}
flagbits -= 2;
switch((flagbyte >> flagbits) & 3)
{
@ -2611,7 +2672,7 @@ expand(struct archive_read *a, int64_t end)
if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
return (ARCHIVE_FATAL);
rar->output_last_match = 0;
if (symbol < 256)
{
lzss_emit_literal(rar, symbol);

View File

@ -78,7 +78,9 @@ archive_read_support_format_raw(struct archive *_a)
archive_read_format_raw_read_data,
archive_read_format_raw_read_data_skip,
NULL,
archive_read_format_raw_cleanup);
archive_read_format_raw_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK)
free(info);
return (r);

View File

@ -151,6 +151,8 @@ struct tar {
struct archive_string_conv *sconv_default;
int init_default_conversion;
int compat_2x;
int process_mac_extensions;
int read_concatenated_archives;
};
static int archive_block_is_null(const char *p);
@ -241,6 +243,10 @@ archive_read_support_format_tar(struct archive *_a)
ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
tar = (struct tar *)calloc(1, sizeof(*tar));
#ifdef HAVE_COPYFILE_H
/* Set this by default on Mac OS. */
tar->process_mac_extensions = 1;
#endif
if (tar == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate tar data");
@ -254,7 +260,9 @@ archive_read_support_format_tar(struct archive *_a)
archive_read_format_tar_read_data,
archive_read_format_tar_skip,
NULL,
archive_read_format_tar_cleanup);
archive_read_format_tar_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK)
free(tar);
@ -368,7 +376,7 @@ archive_read_format_tar_options(struct archive_read *a,
tar = (struct tar *)(a->format->data);
if (strcmp(key, "compat-2x") == 0) {
/* Handle UTF-8 filnames as libarchive 2.x */
tar->compat_2x = (val != NULL)?1:0;
tar->compat_2x = (val != NULL && val[0] != 0);
tar->init_default_conversion = tar->compat_2x;
return (ARCHIVE_OK);
} else if (strcmp(key, "hdrcharset") == 0) {
@ -385,6 +393,12 @@ archive_read_format_tar_options(struct archive_read *a,
ret = ARCHIVE_FATAL;
}
return (ret);
} else if (strcmp(key, "mac-ext") == 0) {
tar->process_mac_extensions = (val != NULL && val[0] != 0);
return (ARCHIVE_OK);
} else if (strcmp(key, "read_concatenated_archives") == 0) {
tar->read_concatenated_archives = (val != NULL && val[0] != 0);
return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
@ -397,7 +411,7 @@ archive_read_format_tar_options(struct archive_read *a,
* how much unconsumed data we have floating around, and to consume
* anything outstanding since we're going to do read_aheads
*/
static void
static void
tar_flush_unconsumed(struct archive_read *a, size_t *unconsumed)
{
if (*unconsumed) {
@ -590,7 +604,7 @@ archive_read_format_tar_skip(struct archive_read *a)
tar = (struct tar *)(a->format->data);
bytes_skipped = __archive_read_consume(a,
tar->entry_bytes_remaining + tar->entry_padding +
tar->entry_bytes_remaining + tar->entry_padding +
tar->entry_bytes_unconsumed);
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
@ -619,36 +633,50 @@ tar_read_header(struct archive_read *a, struct tar *tar,
const struct archive_entry_header_ustar *header;
const struct archive_entry_header_gnutar *gnuheader;
tar_flush_unconsumed(a, unconsumed);
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
}
if (bytes < 512) { /* Short block at EOF; this is bad. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated tar archive");
return (ARCHIVE_FATAL);
}
*unconsumed = 512;
/* Check for end-of-archive mark. */
if (h[0] == 0 && archive_block_is_null(h)) {
/* Try to consume a second all-null record, as well. */
/* Loop until we find a workable header record. */
for (;;) {
tar_flush_unconsumed(a, unconsumed);
h = __archive_read_ahead(a, 512, NULL);
if (h != NULL)
__archive_read_consume(a, 512);
archive_clear_error(&a->archive);
/* Read 512-byte header record */
h = __archive_read_ahead(a, 512, &bytes);
if (bytes < 0)
return ((int)bytes);
if (bytes == 0) { /* EOF at a block boundary. */
/* Some writers do omit the block of nulls. <sigh> */
return (ARCHIVE_EOF);
}
if (bytes < 512) { /* Short block at EOF; this is bad. */
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated tar archive");
return (ARCHIVE_FATAL);
}
*unconsumed = 512;
/* Header is workable if it's not an end-of-archive mark. */
if (h[0] != 0 || !archive_block_is_null(h))
break;
/* Ensure format is set for archives with only null blocks. */
if (a->archive.archive_format_name == NULL) {
a->archive.archive_format = ARCHIVE_FORMAT_TAR;
a->archive.archive_format_name = "tar";
}
return (ARCHIVE_EOF);
if (!tar->read_concatenated_archives) {
/* Try to consume a second all-null record, as well. */
tar_flush_unconsumed(a, unconsumed);
h = __archive_read_ahead(a, 512, NULL);
if (h != NULL && h[0] == 0 && archive_block_is_null(h))
__archive_read_consume(a, 512);
archive_clear_error(&a->archive);
return (ARCHIVE_EOF);
}
/*
* We're reading concatenated archives, ignore this block and
* loop to get the next.
*/
}
/*
@ -683,6 +711,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
a->archive.archive_format_name = "POSIX pax interchange format";
err = header_pax_global(a, tar, entry, h, unconsumed);
if (err == ARCHIVE_EOF)
return (err);
break;
case 'K': /* Long link name (GNU tar, others) */
err = header_longlink(a, tar, entry, h, unconsumed);
@ -735,9 +765,9 @@ tar_read_header(struct archive_read *a, struct tar *tar,
* extensions for both the AppleDouble extension entry and the
* regular entry.
*/
/* TODO: Should this be disabled on non-Mac platforms? */
if ((err == ARCHIVE_WARN || err == ARCHIVE_OK) &&
tar->header_recursion_depth == 0) {
tar->header_recursion_depth == 0 &&
tar->process_mac_extensions) {
int err2 = read_mac_metadata_blob(a, tar, entry, h, unconsumed);
if (err2 < err)
err = err2;
@ -780,12 +810,20 @@ checksum(struct archive_read *a, const void *h)
{
const unsigned char *bytes;
const struct archive_entry_header_ustar *header;
int check, i, sum;
int check, sum;
size_t i;
(void)a; /* UNUSED */
bytes = (const unsigned char *)h;
header = (const struct archive_entry_header_ustar *)h;
/* Checksum field must hold an octal number */
for (i = 0; i < sizeof(header->checksum); ++i) {
char c = header->checksum[i];
if (c != ' ' && c != '\0' && (c < '0' || c > '7'))
return 0;
}
/*
* Test the checksum. Note that POSIX specifies _unsigned_
* bytes for this calculation.
@ -1277,7 +1315,7 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
if (wp[0] == '/' && wp[1] != L'\0')
wname = wp + 1;
}
/*
/*
* If last path element starts with "._", then
* this is a Mac extension.
*/
@ -1292,7 +1330,7 @@ read_mac_metadata_blob(struct archive_read *a, struct tar *tar,
if (p[0] == '/' && p[1] != '\0')
name = p + 1;
}
/*
/*
* If last path element starts with "._", then
* this is a Mac extension.
*/

View File

@ -468,7 +468,9 @@ archive_read_support_format_xar(struct archive *_a)
xar_read_data,
xar_read_data_skip,
NULL,
xar_cleanup);
xar_cleanup,
NULL,
NULL);
if (r != ARCHIVE_OK)
free(xar);
return (r);
@ -967,10 +969,14 @@ move_reading_point(struct archive_read *a, uint64_t offset)
return ((int)step);
xar->offset += step;
} else {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"Cannot seek.");
return (ARCHIVE_FAILED);
int64_t pos = __archive_read_seek(a, offset, SEEK_SET);
if (pos == ARCHIVE_FAILED) {
archive_set_error(&(a->archive),
ARCHIVE_ERRNO_MISC,
"Cannot seek.");
return (ARCHIVE_FAILED);
}
xar->offset = pos;
}
}
return (ARCHIVE_OK);

View File

@ -45,6 +45,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
#include <wincrypt.h>
#endif
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
#ifdef HAVE_LZMA_H
#include <lzma.h>
#endif
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
#endif
#include "archive.h"
#include "archive_private.h"
@ -54,6 +63,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
#define O_CLOEXEC 0
#endif
static int archive_utility_string_sort_helper(char **, unsigned int);
/* Generic initialization of 'struct archive' objects. */
int
__archive_clean(struct archive *a)
@ -74,6 +85,38 @@ archive_version_string(void)
return (ARCHIVE_VERSION_STRING);
}
const char *
archive_version_details(void)
{
static struct archive_string str;
static int init = 0;
if (!init) {
archive_string_init(&str);
archive_strcat(&str, ARCHIVE_VERSION_STRING);
#ifdef HAVE_ZLIB_H
archive_strcat(&str, " zlib/");
archive_strcat(&str, ZLIB_VERSION);
#endif
#ifdef HAVE_LZMA_H
archive_strcat(&str, " liblzma/");
archive_strcat(&str, LZMA_VERSION_STRING);
#endif
#ifdef HAVE_BZLIB_H
{
const char *p = BZ2_bzlibVersion();
const char *sep = strchr(p, ',');
if (sep == NULL)
sep = p + strlen(p);
archive_strcat(&str, " bz2lib/");
archive_strncat(&str, p, sep - p);
}
#endif
}
return str.s;
}
int
archive_errno(struct archive *a)
{
@ -499,3 +542,69 @@ __archive_ensure_cloexec_flag(int fd)
}
#endif
}
/*
* Utility function to sort a group of strings using quicksort.
*/
static int
archive_utility_string_sort_helper(char **strings, unsigned int n)
{
unsigned int i, lesser_count, greater_count;
char **lesser, **greater, **tmp, *pivot;
int retval1, retval2;
/* A list of 0 or 1 elements is already sorted */
if (n <= 1)
return (ARCHIVE_OK);
lesser_count = greater_count = 0;
lesser = greater = NULL;
pivot = strings[0];
for (i = 1; i < n; i++)
{
if (strcmp(strings[i], pivot) < 0)
{
lesser_count++;
tmp = (char **)realloc(lesser, lesser_count * sizeof(char *));
if (!tmp)
return (ARCHIVE_FATAL);
lesser = tmp;
lesser[lesser_count - 1] = strings[i];
}
else
{
greater_count++;
tmp = (char **)realloc(greater, greater_count * sizeof(char *));
if (!tmp)
return (ARCHIVE_FATAL);
greater = tmp;
greater[greater_count - 1] = strings[i];
}
}
/* quicksort(lesser) */
retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
for (i = 0; i < lesser_count; i++)
strings[i] = lesser[i];
free(lesser);
/* pivot */
strings[lesser_count] = pivot;
/* quicksort(greater) */
retval2 = archive_utility_string_sort_helper(greater, greater_count);
for (i = 0; i < greater_count; i++)
strings[lesser_count + 1 + i] = greater[i];
free(greater);
return (retval1 < retval2) ? retval1 : retval2;
}
int
archive_utility_string_sort(char **strings)
{
unsigned int size = 0;
while (strings[size] != NULL)
size++;
return archive_utility_string_sort_helper(strings, size);
}

View File

@ -54,6 +54,14 @@ archive_filter_bytes(struct archive *a, int n)
return ((a->vtable->archive_filter_bytes)(a, n));
}
int
archive_free(struct archive *a)
{
if (a == NULL)
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
}
int
archive_write_close(struct archive *a)
{
@ -76,9 +84,7 @@ archive_write_fail(struct archive *a)
int
archive_write_free(struct archive *a)
{
if (a == NULL)
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
return archive_free(a);
}
#if ARCHIVE_VERSION_NUMBER < 4000000
@ -93,9 +99,7 @@ archive_write_finish(struct archive *a)
int
archive_read_free(struct archive *a)
{
if (a == NULL)
return (ARCHIVE_OK);
return ((a->vtable->archive_free)(a));
return archive_free(a);
}
#if ARCHIVE_VERSION_NUMBER < 4000000

View File

@ -301,7 +301,7 @@ __la_open(const char *path, int flags, ...)
ws = NULL;
if ((flags & ~O_BINARY) == O_RDONLY) {
/*
* When we open a directory, _open function returns
* When we open a directory, _open function returns
* "Permission denied" error.
*/
attr = GetFileAttributesA(path);
@ -515,9 +515,9 @@ __hstat(HANDLE handle, struct ustat *st)
else
mode |= S_IFREG;
st->st_mode = mode;
fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
st->st_atime = t;
st->st_atime = t;
st->st_atime_nsec = ns;
fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
st->st_mtime = t;
@ -525,7 +525,7 @@ __hstat(HANDLE handle, struct ustat *st)
fileTimeToUTC(&info.ftCreationTime, &t, &ns);
st->st_ctime = t;
st->st_ctime_nsec = ns;
st->st_size =
st->st_size =
((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
+ (int64_t)(info.nFileSizeLow);
#ifdef SIMULATE_WIN_STAT
@ -599,7 +599,7 @@ __la_stat(const char *path, struct stat *st)
struct ustat u;
int ret;
handle = la_CreateFile(path, 0, 0, NULL, OPEN_EXISTING,
handle = la_CreateFile(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle == INVALID_HANDLE_VALUE) {

View File

@ -93,7 +93,7 @@
/* Alias the Windows _function to the POSIX equivalent. */
#define close _close
#define fcntl(fd, cmd, flg) /* No operation. */
#define fcntl(fd, cmd, flg) /* No operation. */
#ifndef fileno
#define fileno _fileno
#endif
@ -113,13 +113,14 @@
#define lstat __la_stat
#define open __la_open
#define read __la_read
#if !defined(__BORLANDC__)
#if !defined(__BORLANDC__) && !defined(__WATCOMC__)
#define setmode _setmode
#endif
#ifdef stat
#undef stat
#endif
#define stat(path,stref) __la_stat(path,stref)
#if !defined(__WATCOMC__)
#if !defined(__BORLANDC__)
#define strdup _strdup
#endif
@ -127,9 +128,12 @@
#if !defined(__BORLANDC__)
#define umask _umask
#endif
#endif
#define waitpid __la_waitpid
#define write __la_write
#if !defined(__WATCOMC__)
#ifndef O_RDONLY
#define O_RDONLY _O_RDONLY
#define O_WRONLY _O_WRONLY
@ -189,8 +193,6 @@
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* regular file */
#endif
#if !defined(__WATCOMC__)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* Symbolic link */
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* Socket */
@ -210,7 +212,7 @@
#define _S_IXGRP (_S_IXUSR >> 3) /* read permission, group */
#define _S_IWGRP (_S_IWUSR >> 3) /* write permission, group */
#define _S_IRGRP (_S_IRUSR >> 3) /* execute/search permission, group */
#define _S_IRWXO (_S_IRWXG >> 3)
#define _S_IRWXO (_S_IRWXG >> 3)
#define _S_IXOTH (_S_IXGRP >> 3) /* read permission, other */
#define _S_IWOTH (_S_IWGRP >> 3) /* write permission, other */
#define _S_IROTH (_S_IRGRP >> 3) /* execute/search permission, other */

View File

@ -503,8 +503,9 @@ _archive_write_close(struct archive *_a)
archive_clear_error(&a->archive);
/* Finish the last entry. */
if (a->archive.state == ARCHIVE_STATE_DATA)
/* Finish the last entry if a finish callback is specified */
if (a->archive.state == ARCHIVE_STATE_DATA
&& a->format_finish_entry != NULL)
r = ((a->format_finish_entry)(a));
/* Finish off the archive. */
@ -638,6 +639,9 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
/* Format and write header. */
r2 = ((a->format_write_header)(a, entry));
if (r2 == ARCHIVE_FAILED) {
return (ARCHIVE_FAILED);
}
if (r2 == ARCHIVE_FATAL) {
a->archive.state = ARCHIVE_STATE_FATAL;
return (ARCHIVE_FATAL);
@ -658,7 +662,8 @@ _archive_write_finish_entry(struct archive *_a)
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
"archive_write_finish_entry");
if (a->archive.state & ARCHIVE_STATE_DATA)
if (a->archive.state & ARCHIVE_STATE_DATA
&& a->format_finish_entry != NULL)
ret = (a->format_finish_entry)(a);
a->archive.state = ARCHIVE_STATE_HEADER;
return (ret);
@ -671,8 +676,13 @@ static ssize_t
_archive_write_data(struct archive *_a, const void *buff, size_t s)
{
struct archive_write *a = (struct archive_write *)_a;
const size_t max_write = INT_MAX;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_data");
/* In particular, this catches attempts to pass negative values. */
if (s > max_write)
s = max_write;
archive_clear_error(&a->archive);
return ((a->format_write_data)(a, buff, s));
}

View File

@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
struct write_lrzip {
struct archive_write_program_data *pdata;
int compression_level;
enum { lzma = 0, bzip2, gzip, lzo, zpaq } compression;
enum { lzma = 0, bzip2, gzip, lzo, none, zpaq } compression;
};
static int archive_write_lrzip_open(struct archive_write_filter *);
@ -107,6 +107,8 @@ archive_write_lrzip_options(struct archive_write_filter *f, const char *key,
data->compression = gzip;
else if (strcmp(value, "lzo") == 0)
data->compression = lzo;
else if (strcmp(value, "none") == 0)
data->compression = none;
else if (strcmp(value, "zpaq") == 0)
data->compression = zpaq;
else
@ -148,6 +150,9 @@ archive_write_lrzip_open(struct archive_write_filter *f)
case lzo:
archive_strcat(&as, " -l");
break;
case none:
archive_strcat(&as, " -n");
break;
case zpaq:
archive_strcat(&as, " -z");
break;

View File

@ -43,7 +43,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0
#include "archive_acl_private.h"
#include "archive_write_disk_private.h"
#if !defined(HAVE_POSIX_ACL) || !defined(ACL_TYPE_NFS4)
#ifndef HAVE_POSIX_ACL
/* Default empty function body to satisfy mainline code. */
int
archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
@ -79,10 +79,12 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
return (ret);
#ifdef ACL_TYPE_NFS4
} else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) {
ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4,
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
return (ret);
#endif
} else
return ARCHIVE_OK;
}
@ -94,6 +96,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
#ifdef ACL_TYPE_NFS4
{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
@ -110,8 +113,10 @@ static struct {
{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
#endif
};
#ifdef ACL_TYPE_NFS4
static struct {
int archive_inherit;
int platform_inherit;
@ -121,6 +126,7 @@ static struct {
{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
};
#endif
static int
set_acl(struct archive *a, int fd, const char *name,
@ -130,7 +136,9 @@ set_acl(struct archive *a, int fd, const char *name,
acl_t acl;
acl_entry_t acl_entry;
acl_permset_t acl_permset;
#ifdef ACL_TYPE_NFS4
acl_flagset_t acl_flagset;
#endif
int ret;
int ae_type, ae_permset, ae_tag, ae_id;
uid_t ae_uid;
@ -171,14 +179,17 @@ set_acl(struct archive *a, int fd, const char *name,
case ARCHIVE_ENTRY_ACL_OTHER:
acl_set_tag_type(acl_entry, ACL_OTHER);
break;
#ifdef ACL_TYPE_NFS4
case ARCHIVE_ENTRY_ACL_EVERYONE:
acl_set_tag_type(acl_entry, ACL_EVERYONE);
break;
#endif
default:
/* XXX */
break;
}
#ifdef ACL_TYPE_NFS4
switch (ae_type) {
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
@ -200,6 +211,7 @@ set_acl(struct archive *a, int fd, const char *name,
// XXX error handling here.
break;
}
#endif
acl_get_permset(acl_entry, &acl_permset);
acl_clear_perms(acl_permset);
@ -210,6 +222,7 @@ set_acl(struct archive *a, int fd, const char *name,
acl_perm_map[i].platform_perm);
}
#ifdef ACL_TYPE_NFS4
acl_get_flagset_np(acl_entry, &acl_flagset);
acl_clear_flags_np(acl_flagset);
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
@ -217,6 +230,7 @@ set_acl(struct archive *a, int fd, const char *name,
acl_add_flag_np(acl_flagset,
acl_inherit_map[i].platform_inherit);
}
#endif
}
/* Try restoring the ACL through 'fd' if we can. */

View File

@ -525,7 +525,7 @@ la_GetFunctionKernel32(const char *name)
static int set;
if (!set) {
set = 1;
lib = LoadLibrary("kernel32.dll");
lib = LoadLibrary(TEXT("kernel32.dll"));
}
if (lib == NULL) {
fprintf(stderr, "Can't load kernel32.dll?!\n");

View File

@ -24,13 +24,14 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 2, 2012
.Dd February 14, 2013
.Dt ARCHIVE_WRITE_FORMAT 3
.Os
.Sh NAME
.Nm archive_write_set_format_cpio ,
.Nm archive_write_set_format_pax ,
.Nm archive_write_set_format_pax_restricted ,
.Nm archive_write_set_format_raw ,
.Nm archive_write_set_format_shar ,
.Nm archive_write_set_format_shar_dump ,
.Nm archive_write_set_format_ustar
@ -46,6 +47,8 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_write_set_format_pax_restricted "struct archive *"
.Ft int
.Fn archive_write_set_format_raw "struct archive *"
.Ft int
.Fn archive_write_set_format_shar "struct archive *"
.Ft int
.Fn archive_write_set_format_shar_dump "struct archive *"

View File

@ -47,6 +47,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
{ ARCHIVE_FORMAT_RAW, archive_write_set_format_raw },
{ ARCHIVE_FORMAT_SHAR, archive_write_set_format_shar },
{ ARCHIVE_FORMAT_SHAR_BASE, archive_write_set_format_shar },
{ ARCHIVE_FORMAT_SHAR_DUMP, archive_write_set_format_shar_dump },
@ -57,7 +58,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
archive_write_set_format_pax_restricted },
{ ARCHIVE_FORMAT_TAR_USTAR, archive_write_set_format_ustar },
{ ARCHIVE_FORMAT_XAR, archive_write_set_format_xar },
{ ARCHIVE_FORMAT_ZIP, archive_write_set_format_zip },
{ ARCHIVE_FORMAT_ZIP, archive_write_set_format_zip },
{ 0, NULL }
};

View File

@ -63,6 +63,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "pax", archive_write_set_format_pax },
{ "paxr", archive_write_set_format_pax_restricted },
{ "posix", archive_write_set_format_pax },
{ "raw", archive_write_set_format_raw },
{ "rpax", archive_write_set_format_pax_restricted },
{ "shar", archive_write_set_format_shar },
{ "shardump", archive_write_set_format_shar_dump },

View File

@ -128,6 +128,9 @@ struct mtree_entry {
unsigned long fflags_clear;
dev_t rdevmajor;
dev_t rdevminor;
dev_t devmajor;
dev_t devminor;
int64_t ino;
};
struct mtree_writer {
@ -210,6 +213,9 @@ struct mtree_writer {
#define F_SHA256 0x00800000 /* SHA-256 digest */
#define F_SHA384 0x01000000 /* SHA-384 digest */
#define F_SHA512 0x02000000 /* SHA-512 digest */
#define F_INO 0x04000000 /* inode number */
#define F_RESDEV 0x08000000 /* device ID on which the
* entry resides */
/* Options */
int dironly; /* If it is set, ignore all files except
@ -823,8 +829,11 @@ mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
me->mtime = archive_entry_mtime(entry);
me->mtime_nsec = archive_entry_mtime_nsec(entry);
me->rdevmajor = archive_entry_rdevmajor(entry);
me->rdevmajor = archive_entry_rdevmajor(entry);
me->rdevminor = archive_entry_rdevminor(entry);
me->devmajor = archive_entry_devmajor(entry);
me->devminor = archive_entry_devminor(entry);
me->ino = archive_entry_ino(entry);
me->size = archive_entry_size(entry);
if (me->filetype == AE_IFDIR) {
me->dir_info = calloc(1, sizeof(*me->dir_info));
@ -882,7 +891,7 @@ archive_write_mtree_header(struct archive_write *a,
mtree->first = 0;
archive_strcat(&mtree->buf, "#mtree\n");
if ((mtree->keys & SET_KEYS) == 0)
mtree->output_global_set = 0;/* Disalbed. */
mtree->output_global_set = 0;/* Disabled. */
}
mtree->entry_bytes_remaining = archive_entry_size(entry);
@ -983,6 +992,15 @@ write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
if ((keys & F_UID) != 0)
archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
if ((keys & F_INO) != 0)
archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino);
if ((keys & F_RESDEV) != 0) {
archive_string_sprintf(str,
" resdevice=native,%ju,%ju",
(uintmax_t)me->devmajor,
(uintmax_t)me->devminor);
}
switch (me->filetype) {
case AE_IFLNK:
if ((keys & F_TYPE) != 0)
@ -1117,7 +1135,7 @@ write_mtree_entry_tree(struct archive_write *a)
} else {
/* Whenever output_global_set is enabled
* output global value(/set keywords)
* even if the directory entry is not allowd
* even if the directory entry is not allowed
* to be written because the global values
* can be used for the children. */
if (mtree->output_global_set)
@ -1296,6 +1314,8 @@ archive_write_mtree_options(struct archive_write *a, const char *key,
if (strcmp(key, "indent") == 0) {
mtree->indent = (value != NULL)? 1: 0;
return (ARCHIVE_OK);
} else if (strcmp(key, "inode") == 0) {
keybit = F_INO;
}
break;
case 'l':
@ -1314,7 +1334,9 @@ archive_write_mtree_options(struct archive_write *a, const char *key,
keybit = F_NLINK;
break;
case 'r':
if (strcmp(key, "ripemd160digest") == 0 ||
if (strcmp(key, "resdevice") == 0) {
keybit = F_RESDEV;
} else if (strcmp(key, "ripemd160digest") == 0 ||
strcmp(key, "rmd160") == 0 ||
strcmp(key, "rmd160digest") == 0)
keybit = F_RMD160;
@ -1855,9 +1877,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
return (ret);
}
/* Make a basename from dirname and slash */
/* Make a basename from file->parentdir.s and slash */
*slash = '\0';
file->parentdir.length = slash - dirname;
file->parentdir.length = slash - file->parentdir.s;
archive_strcpy(&(file->basename), slash + 1);
return (ret);
}
@ -2198,6 +2220,9 @@ mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
np->mtime_nsec = file->mtime_nsec;
np->rdevmajor = file->rdevmajor;
np->rdevminor = file->rdevminor;
np->devmajor = file->devmajor;
np->devminor = file->devminor;
np->ino = file->ino;
return (ARCHIVE_WARN);
}

View File

@ -0,0 +1,125 @@
/*-
* Copyright (c) 2013 Marek Kubica
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "archive_platform.h"
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "archive_entry.h"
#include "archive_write_private.h"
static ssize_t archive_write_raw_data(struct archive_write *,
const void *buff, size_t s);
static int archive_write_raw_free(struct archive_write *);
static int archive_write_raw_header(struct archive_write *,
struct archive_entry *);
struct raw {
int entries_written;
};
/*
* Set output format to 'raw' format.
*/
int
archive_write_set_format_raw(struct archive *_a)
{
struct archive_write *a = (struct archive_write *)_a;
struct raw *raw;
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_set_format_raw");
/* If someone else was already registered, unregister them. */
if (a->format_free != NULL)
(a->format_free)(a);
raw = (struct raw *)calloc(1, sizeof(*raw));
if (raw == NULL) {
archive_set_error(&a->archive, ENOMEM, "Can't allocate raw data");
return (ARCHIVE_FATAL);
}
raw->entries_written = 0;
a->format_data = raw;
a->format_name = "raw";
/* no options exist for this format */
a->format_options = NULL;
a->format_write_header = archive_write_raw_header;
a->format_write_data = archive_write_raw_data;
a->format_finish_entry = NULL;
/* nothing needs to be done on closing */
a->format_close = NULL;
a->format_free = archive_write_raw_free;
a->archive.archive_format = ARCHIVE_FORMAT_RAW;
a->archive.archive_format_name = "RAW";
return (ARCHIVE_OK);
}
static int
archive_write_raw_header(struct archive_write *a, struct archive_entry *entry)
{
struct raw *raw = (struct raw *)a->format_data;
if (archive_entry_filetype(entry) != AE_IFREG) {
archive_set_error(&a->archive, ERANGE,
"Raw format only supports filetype AE_IFREG");
return (ARCHIVE_FATAL);
}
if (raw->entries_written > 0) {
archive_set_error(&a->archive, ERANGE,
"Raw format only supports one entry per archive");
return (ARCHIVE_FATAL);
}
raw->entries_written++;
return (ARCHIVE_OK);
}
static ssize_t
archive_write_raw_data(struct archive_write *a, const void *buff, size_t s)
{
int ret;
ret = __archive_write_output(a, buff, s);
if (ret >= 0)
return (s);
else
return (ret);
}
static int
archive_write_raw_free(struct archive_write *a)
{
struct raw *raw;
raw = (struct raw *)a->format_data;
free(raw);
a->format_data = NULL;
return (ARCHIVE_OK);
}

View File

@ -548,6 +548,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
archive_strcat(&shar->work, ":");
shar_quote(&shar->work, g, 1);
}
archive_strcat(&shar->work, " ");
shar_quote(&shar->work,
archive_entry_pathname(shar->entry), 1);
archive_strcat(&shar->work, "\n");

View File

@ -36,7 +36,7 @@ __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout)
{
HANDLE childStdout[2], childStdin[2],childStderr;
SECURITY_ATTRIBUTES secAtts;
STARTUPINFO staInfo;
STARTUPINFOA staInfo;
PROCESS_INFORMATION childInfo;
struct archive_string cmdline;
struct archive_string fullpath;

View File

@ -28,7 +28,7 @@
.\" From: @(#)mtree.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
.Dd May 6, 2008
.Dd September 4, 2013
.Dt MTREE 5
.Os
.Sh NAME
@ -134,6 +134,52 @@ The checksum of the file using the default algorithm specified by
the
.Xr cksum 1
utility.
.It Cm device
The device number for
.Sy block
or
.Sy char
file types.
The value must be one of the following forms:
.Pp
.Bl -tag -width 4n
.It Ar format , Ns Ar major , Ns Ar minor Ns Bo , Ns Ar subunit Bc
A device with
.Ar major , minor
and optional
.Ar subunit
fields.
Their meaning is specified by the operating's system
.Ar format .
See below for valid formats.
.It Ar number
Opaque number (as stored on the file system).
.El
.Pp
The following values for
.Ar format
are recognized:
.Sy native ,
.Sy 386bsd ,
.Sy 4bsd ,
.Sy bsdos ,
.Sy freebsd ,
.Sy hpux ,
.Sy isc ,
.Sy linux ,
.Sy netbsd ,
.Sy osf1 ,
.Sy sco ,
.Sy solaris ,
.Sy sunos ,
.Sy svr3 ,
.Sy svr4 ,
and
.Sy ultrix .
.Pp
See
.Xr mknod 8
for more details.
.It Cm contents
The full pathname of a file that holds the contents of this file.
.It Cm flags
@ -150,6 +196,8 @@ The file group as a numeric value.
The file group as a symbolic name.
.It Cm ignore
Ignore any file hierarchy below this file.
.It Cm inode
The inode number.
.It Cm link
The target of the symbolic link when type=link.
.It Cm md5
@ -164,6 +212,16 @@ value.
The number of hard links the file is expected to have.
.It Cm nochange
Make sure this file or directory exists but otherwise ignore all attributes.
.It Cm optional
The file is optional; do not complain about the file if it is not in
the file hierarchy.
.It Cm resdevice
The
.Dq resident
device number of the file, e.g. the ID of the device that
contains the file.
Its format is the same as the one for
.Cm device .
.It Cm ripemd160digest
The
.Tn RIPEMD160
@ -192,6 +250,24 @@ message digest of the file.
.It Cm sha256digest
A synonym for
.Cm sha256 .
.It Cm sha384
The
.Tn FIPS
180-2
.Pq Dq Tn SHA-384
message digest of the file.
.It Cm sha384digest
A synonym for
.Cm sha384 .
.It Cm sha512
The
.Tn FIPS
180-2
.Pq Dq Tn SHA-512
message digest of the file.
.It Cm sha512digest
A synonym for
.Cm sha512 .
.It Cm size
The size, in bytes, of the file.
.It Cm time