Merge topic 'update-libarchive'
5a58efaa
libarchive: Avoid using name 'u_long'e2b02823
Update libarchive configuration within CMake80883321
libarchive: Do not require includers to have windows.hdfb0458e
libarchive: Convert literal LL suffix to ARCHIVE_LITERAL_LLb0a9807f
libarchive: Update archive_util.c to use CMake zlib and bzip2 headersdebe4dec
libarchive: Drop options not present in reduced version66b0c4fa
libarchive: Do not generate a pkg-config file8092e759
libarchive: Update README-CMake.txt for new snapshot2f197863
Merge branch 'libarchive-upstream' into update-libarchive23e4666c
libarchive: Disable more whitespace checks in third-party code64713ae3
libarchive 3.1.2-218-g00f4bd83 (reduced)
This commit is contained in:
commit
11a6b3d59a
|
@ -321,6 +321,12 @@ macro (CMAKE_BUILD_UTILITIES)
|
|||
add_definitions(-DLIBARCHIVE_STATIC)
|
||||
set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle")
|
||||
set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL")
|
||||
set(ENABLE_LZMA OFF CACHE INTERNAL "Enable the use of the system found LZMA library if found")
|
||||
set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found")
|
||||
set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found")
|
||||
set(ENABLE_EXPAT OFF CACHE INTERNAL "Enable the use of the system found EXPAT library if found")
|
||||
set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found")
|
||||
set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found")
|
||||
set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support")
|
||||
set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support")
|
||||
set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support")
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
*.h whitespace=indent-with-non-tab,-blank-at-eol
|
||||
*.c whitespace=indent-with-non-tab,-blank-at-eol
|
||||
* whitespace=-indent-with-non-tab,-tab-in-indent,-blank-at-eol,-blank-at-eof
|
||||
|
|
|
@ -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,6 +69,13 @@ 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_XATTR "Enable extended attribute support" ON)
|
||||
OPTION(ENABLE_ACL "Enable ACL support" ON)
|
||||
OPTION(ENABLE_ICONV "Enable iconv support" ON)
|
||||
|
@ -190,7 +197,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 +211,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 +250,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 +278,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 +304,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 +533,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 +621,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 +1041,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)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ branch, but it is merged into our history.
|
|||
Update libarchive from upstream as follows. Create a local branch to
|
||||
explicitly reference the upstream snapshot branch head:
|
||||
|
||||
git branch libarchive-upstream 35df7c8b
|
||||
git branch libarchive-upstream 64713ae3
|
||||
|
||||
Use a temporary directory to checkout the branch:
|
||||
|
||||
|
@ -24,7 +24,7 @@ Use a temporary directory to checkout the branch:
|
|||
Now place the (reduced) libarchive content in this directory. See
|
||||
instructions shown by
|
||||
|
||||
git log 35df7c8b
|
||||
git log 64713ae3
|
||||
|
||||
for help extracting the content from the upstream svn repo. Then run
|
||||
the following commands to commit the new version. Substitute the
|
||||
|
@ -34,8 +34,8 @@ appropriate date and version number:
|
|||
|
||||
GIT_AUTHOR_NAME='LibArchive Upstream' \
|
||||
GIT_AUTHOR_EMAIL='libarchive-discuss@googlegroups.com' \
|
||||
GIT_AUTHOR_DATE='2013-02-09 12:17:57 -0500' \
|
||||
git commit -m 'libarchive 3.1.2 (reduced)' &&
|
||||
GIT_AUTHOR_DATE='Mon Mar 17 20:43:07 2014 -0700' \
|
||||
git commit -m 'libarchive 3.1.2-218-g00f4bd83 (reduced)' &&
|
||||
git commit --amend
|
||||
|
||||
Edit the commit message to describe the procedure used to obtain the
|
||||
|
|
|
@ -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")
|
|
@ -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)")
|
||||
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
@ -248,7 +247,7 @@ __LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
|
|||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
|
||||
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *);
|
||||
#endif
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_birthtime(struct 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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = apd_makedev(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
else if ((unsigned long)minor(dev) != numbers[1])
|
||||
*error = iMinorError;
|
||||
} else
|
||||
*error = tooManyFields;
|
||||
return (dev);
|
||||
}
|
||||
|
||||
|
||||
static dev_t
|
||||
pack_netbsd(int n, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_netbsd(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_netbsd(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
else if ((unsigned 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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_freebsd(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_freebsd(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned 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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_8_8(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_8_8(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned 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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_12_20(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_12_20(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned 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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_14_18(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_14_18(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned 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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_8_24(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_8_24(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned 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, unsigned long numbers[], const char **error)
|
||||
{
|
||||
dev_t dev = 0;
|
||||
|
||||
if (n == 2) {
|
||||
dev = makedev_12_20(numbers[0], numbers[1]);
|
||||
if ((unsigned long)major_12_20(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned 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 ((unsigned long)major_12_12_8(dev) != numbers[0])
|
||||
*error = iMajorError;
|
||||
if ((unsigned long)unit_12_12_8(dev) != numbers[1])
|
||||
*error = "invalid unit number";
|
||||
if ((unsigned 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);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* $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, unsigned long [], const char **);
|
||||
|
||||
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 */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 <cm_zlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_LZMA_H
|
||||
#include <lzma.h>
|
||||
#endif
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#include <cm_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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 *"
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue