Merge branch 'libarchive-upstream' into update-libarchive
Add Utilities/cmlibarchive using upstream libarchive 3.0.0-r3950 snapshot.
This commit is contained in:
commit
3e5a80f063
1106
Utilities/cmlibarchive/CMakeLists.txt
Normal file
1106
Utilities/cmlibarchive/CMakeLists.txt
Normal file
File diff suppressed because it is too large
Load Diff
60
Utilities/cmlibarchive/COPYING
Normal file
60
Utilities/cmlibarchive/COPYING
Normal file
@ -0,0 +1,60 @@
|
||||
The libarchive distribution as a whole is Copyright by Tim Kientzle
|
||||
and is subject to the copyright notice reproduced at the bottom of
|
||||
this file.
|
||||
|
||||
Each individual file in this distribution should have a clear
|
||||
copyright/licensing statement at the beginning of the file. If any do
|
||||
not, please let me know and I will rectify it. The following is
|
||||
intended to summarize the copyright status of the individual files;
|
||||
the actual statements in the files are controlling.
|
||||
|
||||
* Except as listed below, all C sources (including .c and .h files)
|
||||
and documentation files are subject to the copyright notice reproduced
|
||||
at the bottom of this file.
|
||||
|
||||
* The following source files are also subject in whole or in part to
|
||||
a 3-clause UC Regents copyright; please read the individual source
|
||||
files for details:
|
||||
libarchive/archive_entry.c
|
||||
libarchive/archive_read_support_filter_compress.c
|
||||
libarchive/archive_write_set_filter_compress.c
|
||||
libarchive/mtree.5
|
||||
tar/matching.c
|
||||
|
||||
* The following source files are in the public domain:
|
||||
tar/getdate.c
|
||||
|
||||
* The build files---including Makefiles, configure scripts,
|
||||
and auxiliary scripts used as part of the compile process---have
|
||||
widely varying licensing terms. Please check individual files before
|
||||
distributing them to see if those restrictions apply to you.
|
||||
|
||||
I intend for all new source code to use the license below and hope over
|
||||
time to replace code with other licenses with new implementations that
|
||||
do use the license below. The varying licensing of the build scripts
|
||||
seems to be an unavoidable mess.
|
||||
|
||||
|
||||
Copyright (c) 2003-2009 <author(s)>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in this position and unchanged.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
11
Utilities/cmlibarchive/CTestConfig.cmake
Normal file
11
Utilities/cmlibarchive/CTestConfig.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
# TODO: This file should be moved into the build/cmake directory...
|
||||
|
||||
# The libarchive CDash page appears at
|
||||
# http://my.cdash.org/index.php?project=libarchive
|
||||
set(CTEST_PROJECT_NAME "libarchive")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=libarchive")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
107
Utilities/cmlibarchive/build/cmake/AddTest28.cmake
Normal file
107
Utilities/cmlibarchive/build/cmake/AddTest28.cmake
Normal file
@ -0,0 +1,107 @@
|
||||
# - Macro approximating the CMake 2.8 ADD_TEST(NAME) signature.
|
||||
# ADD_TEST_28(NAME <name> COMMAND <command> [arg1 [arg2 ...]])
|
||||
# <name> - The name of the test
|
||||
# <command> - The test executable
|
||||
# [argN...] - Arguments to the test executable
|
||||
# This macro approximates the ADD_TEST(NAME) signature provided in
|
||||
# CMake 2.8 but works with CMake 2.6 too. See CMake 2.8 documentation
|
||||
# of ADD_TEST()for details.
|
||||
#
|
||||
# This macro automatically replaces a <command> that names an
|
||||
# executable target with the target location. A generator expression
|
||||
# of the form "$<TARGET_FILE:tgt>" is supported in both the command
|
||||
# and arguments of the test. Howerver, this macro only works for
|
||||
# targets without per-config output name properties set.
|
||||
#
|
||||
# Example usage:
|
||||
# add_test(NAME mytest COMMAND testDriver --exe $<TARGET_FILE:myexe>)
|
||||
# This creates a test "mytest" whose command runs a testDriver tool
|
||||
# passing the full path to the executable file produced by target
|
||||
# "myexe".
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2009 Kitware, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer
|
||||
# in this position and unchanged.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3)
|
||||
|
||||
# CMake 2.8 supports ADD_TEST(NAME) natively.
|
||||
IF(NOT "${CMAKE_VERSION}" VERSION_LESS "2.8")
|
||||
MACRO(ADD_TEST_28)
|
||||
ADD_TEST(${ARGV})
|
||||
ENDMACRO()
|
||||
RETURN()
|
||||
ENDIF()
|
||||
|
||||
# Simulate ADD_TEST(NAME) signature from CMake 2.8.
|
||||
MACRO(ADD_TEST_28 NAME name COMMAND command)
|
||||
# Enforce the signature.
|
||||
IF(NOT "x${NAME}" STREQUAL "xNAME")
|
||||
MESSAGE(FATAL_ERROR "First ADD_TEST_28 argument must be \"NAME\"")
|
||||
ENDIF()
|
||||
IF(NOT "x${COMMAND}" STREQUAL "xCOMMAND")
|
||||
MESSAGE(FATAL_ERROR "Third ADD_TEST_28 argument must be \"COMMAND\"")
|
||||
ENDIF()
|
||||
|
||||
# Perform "COMMAND myexe ..." substitution.
|
||||
SET(cmd "${command}")
|
||||
IF(TARGET "${cmd}")
|
||||
_ADD_TEST_28_GET_EXE(${cmd} cmd)
|
||||
ENDIF()
|
||||
|
||||
# Perform "COMMAND ... $<TARGET_FILE:myexe> ..." substitution.
|
||||
SET(target_file "\\$<TARGET_FILE:(.+)>")
|
||||
SET(args)
|
||||
FOREACH(ARG ${cmd} ${ARGN})
|
||||
SET(arg "${ARG}")
|
||||
IF("${arg}" MATCHES "${target_file}")
|
||||
STRING(REGEX REPLACE "${target_file}" "\\1" tgt "${arg}")
|
||||
IF(TARGET "${tgt}")
|
||||
_ADD_TEST_28_GET_EXE(${tgt} exe)
|
||||
STRING(REGEX REPLACE "${target_file}" "${exe}" arg "${arg}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
LIST(APPEND args "${arg}")
|
||||
ENDFOREACH()
|
||||
|
||||
# Invoke old ADD_TEST() signature with transformed arguments.
|
||||
ADD_TEST(${name} ${args})
|
||||
ENDMACRO()
|
||||
|
||||
# Get the test-time location of an executable target.
|
||||
MACRO(_ADD_TEST_28_GET_EXE tgt exe_var)
|
||||
# The LOCATION property gives a build-time location.
|
||||
GET_TARGET_PROPERTY(${exe_var} ${tgt} LOCATION)
|
||||
|
||||
# In single-configuration generatrs the build-time and test-time
|
||||
# locations are the same because there is no per-config variable
|
||||
# reference. In multi-configuration generators the following
|
||||
# substitution converts the build-time configuration variable
|
||||
# reference to a test-time configuration variable reference.
|
||||
IF(CMAKE_CONFIGURATION_TYPES)
|
||||
STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CTEST_CONFIGURATION_TYPE}"
|
||||
${exe_var} "${${exe_var}}")
|
||||
ENDIF(CMAKE_CONFIGURATION_TYPES)
|
||||
ENDMACRO()
|
14
Utilities/cmlibarchive/build/cmake/CheckFileOffsetBits.c
Normal file
14
Utilities/cmlibarchive/build/cmake/CheckFileOffsetBits.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#define KB ((off_t)1024)
|
||||
#define MB ((off_t)1024 * KB)
|
||||
#define GB ((off_t)1024 * MB)
|
||||
#define TB ((off_t)1024 * GB)
|
||||
int t2[(((64 * GB -1) % 671088649) == 268434537)
|
||||
&& (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1];
|
||||
|
||||
int main()
|
||||
{
|
||||
;
|
||||
return 0;
|
||||
}
|
44
Utilities/cmlibarchive/build/cmake/CheckFileOffsetBits.cmake
Normal file
44
Utilities/cmlibarchive/build/cmake/CheckFileOffsetBits.cmake
Normal file
@ -0,0 +1,44 @@
|
||||
# - Check if _FILE_OFFSET_BITS macro needed for large files
|
||||
# CHECK_FILE_OFFSET_BITS ()
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
# Copyright (c) 2009, Michihiro NAKAJIMA
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
#INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
GET_FILENAME_COMPONENT(_selfdir_CheckFileOffsetBits
|
||||
"${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
MACRO (CHECK_FILE_OFFSET_BITS)
|
||||
IF(NOT DEFINED _FILE_OFFSET_BITS)
|
||||
MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files")
|
||||
TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
|
||||
IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
|
||||
TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
|
||||
ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
|
||||
|
||||
IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
|
||||
SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
|
||||
MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files - needed")
|
||||
ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
|
||||
SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
|
||||
MESSAGE(STATUS "Cheking _FILE_OFFSET_BITS for large files - not needed")
|
||||
ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
|
||||
ENDIF(NOT DEFINED _FILE_OFFSET_BITS)
|
||||
|
||||
ENDMACRO (CHECK_FILE_OFFSET_BITS)
|
||||
|
49
Utilities/cmlibarchive/build/cmake/CheckFuncs.cmake
Normal file
49
Utilities/cmlibarchive/build/cmake/CheckFuncs.cmake
Normal file
@ -0,0 +1,49 @@
|
||||
# Check if the system has the specified function; treat glibc "stub"
|
||||
# functions as nonexistent:
|
||||
# CHECK_FUNCTION_EXISTS_GLIBC (FUNCTION FUNCVAR)
|
||||
#
|
||||
# FUNCTION - the function(s) where the prototype should be declared
|
||||
# FUNCVAR - variable to define if the function does exist
|
||||
#
|
||||
# In particular, this understands the glibc convention of
|
||||
# defining macros __stub_XXXX or __stub___XXXX if the function
|
||||
# does appear in the library but is merely a stub that does nothing.
|
||||
# By detecting this case, we can select alternate behavior on
|
||||
# platforms that don't support this functionality.
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
# Copyright (c) 2009, Michihiro NAKAJIMA
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
INCLUDE(CheckFunctionExists)
|
||||
GET_FILENAME_COMPONENT(_selfdir_CheckFunctionExistsGlibc
|
||||
"${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
MACRO (CHECK_FUNCTION_EXISTS_GLIBC _FUNC _FUNCVAR)
|
||||
IF(NOT DEFINED ${_FUNCVAR})
|
||||
SET(CHECK_STUB_FUNC_1 "__stub_${_FUNC}")
|
||||
SET(CHECK_STUB_FUNC_2 "__stub___${_FUNC}")
|
||||
CONFIGURE_FILE( ${_selfdir_CheckFunctionExistsGlibc}/CheckFuncs_stub.c.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake.tmp/CheckFuncs_stub.c IMMEDIATE)
|
||||
TRY_COMPILE(__stub
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake.tmp/CheckFuncs_stub.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
|
||||
CMAKE_FLAGS
|
||||
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_INCLUDE_FILE_FLAGS}
|
||||
"${CHECK_INCLUDE_FILE_C_INCLUDE_DIRS}")
|
||||
IF (__stub)
|
||||
SET("${_FUNCVAR}" "" CACHE INTERNAL "Have function ${_FUNC}")
|
||||
ELSE (__stub)
|
||||
CHECK_FUNCTION_EXISTS("${_FUNC}" "${_FUNCVAR}")
|
||||
ENDIF (__stub)
|
||||
ENDIF(NOT DEFINED ${_FUNCVAR})
|
||||
ENDMACRO (CHECK_FUNCTION_EXISTS_GLIBC)
|
||||
|
16
Utilities/cmlibarchive/build/cmake/CheckFuncs_stub.c.in
Normal file
16
Utilities/cmlibarchive/build/cmake/CheckFuncs_stub.c.in
Normal file
@ -0,0 +1,16 @@
|
||||
#ifdef __STDC__
|
||||
#include <limits.h>
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
#if defined ${CHECK_STUB_FUNC_1} || defined ${CHECK_STUB_FUNC_2}
|
||||
return 0;
|
||||
#else
|
||||
this system have stub
|
||||
return 0;
|
||||
#endif
|
||||
}
|
32
Utilities/cmlibarchive/build/cmake/CheckHeaderDirent.cmake
Normal file
32
Utilities/cmlibarchive/build/cmake/CheckHeaderDirent.cmake
Normal file
@ -0,0 +1,32 @@
|
||||
# - Check if the system has the specified type
|
||||
# CHECK_HEADER_DIRENT (HEADER1 HEARDER2 ...)
|
||||
#
|
||||
# HEADER - the header(s) where the prototype should be declared
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
# Copyright (c) 2009, Michihiro NAKAJIMA
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE(CheckTypeExists)
|
||||
|
||||
MACRO (CHECK_HEADER_DIRENT)
|
||||
CHECK_TYPE_EXISTS("DIR *" dirent.h HAVE_DIRENT_H)
|
||||
IF(NOT HAVE_DIRENT_H)
|
||||
CHECK_TYPE_EXISTS("DIR *" sys/ndir.h HAVE_SYS_NDIR_H)
|
||||
IF(NOT HAVE_SYS_NDIR_H)
|
||||
CHECK_TYPE_EXISTS("DIR *" ndir.h HAVE_NDIR_H)
|
||||
IF(NOT HAVE_NDIR_H)
|
||||
CHECK_TYPE_EXISTS("DIR *" sys/dir.h HAVE_SYS_DIR_H)
|
||||
ENDIF(NOT HAVE_NDIR_H)
|
||||
ENDIF(NOT HAVE_SYS_NDIR_H)
|
||||
ENDIF(NOT HAVE_DIRENT_H)
|
||||
ENDMACRO (CHECK_HEADER_DIRENT)
|
||||
|
43
Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake
Normal file
43
Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake
Normal file
@ -0,0 +1,43 @@
|
||||
# - Check if the given struct or class has the specified member variable
|
||||
# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE)
|
||||
#
|
||||
# STRUCT - the name of the struct or class you are interested in
|
||||
# MEMBER - the member which existence you want to check
|
||||
# HEADER - the header(s) where the prototype should be declared
|
||||
# VARIABLE - variable to store the result
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
|
||||
MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
|
||||
SET(_INCLUDE_FILES)
|
||||
FOREACH (it ${_HEADER})
|
||||
SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
|
||||
ENDFOREACH (it)
|
||||
|
||||
SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
|
||||
${_INCLUDE_FILES}
|
||||
int main()
|
||||
{
|
||||
static ${_STRUCT} tmp;
|
||||
if (sizeof(tmp.${_MEMBER}))
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
|
||||
|
||||
ENDMACRO (CHECK_STRUCT_MEMBER)
|
||||
|
42
Utilities/cmlibarchive/build/cmake/CheckTypeExists.cmake
Normal file
42
Utilities/cmlibarchive/build/cmake/CheckTypeExists.cmake
Normal file
@ -0,0 +1,42 @@
|
||||
# - Check if the system has the specified type
|
||||
# CHECK_TYPE_EXISTS (TYPE HEADER VARIABLE)
|
||||
#
|
||||
# TYPE - the name of the type or struct or class you are interested in
|
||||
# HEADER - the header(s) where the prototype should be declared
|
||||
# VARIABLE - variable to store the result
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
# Copyright (c) 2009, Michihiro NAKAJIMA
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
|
||||
MACRO (CHECK_TYPE_EXISTS _TYPE _HEADER _RESULT)
|
||||
SET(_INCLUDE_FILES)
|
||||
FOREACH (it ${_HEADER})
|
||||
SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
|
||||
ENDFOREACH (it)
|
||||
|
||||
SET(_CHECK_TYPE_EXISTS_SOURCE_CODE "
|
||||
${_INCLUDE_FILES}
|
||||
int main()
|
||||
{
|
||||
static ${_TYPE} tmp;
|
||||
if (sizeof(tmp))
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
CHECK_C_SOURCE_COMPILES("${_CHECK_TYPE_EXISTS_SOURCE_CODE}" ${_RESULT})
|
||||
|
||||
ENDMACRO (CHECK_TYPE_EXISTS)
|
||||
|
48
Utilities/cmlibarchive/build/cmake/FindLZMA.cmake
Normal file
48
Utilities/cmlibarchive/build/cmake/FindLZMA.cmake
Normal file
@ -0,0 +1,48 @@
|
||||
# - Find lzma and lzmadec
|
||||
# Find the native LZMA includes and library
|
||||
#
|
||||
# LZMA_INCLUDE_DIR - where to find lzma.h, etc.
|
||||
# LZMA_LIBRARIES - List of libraries when using liblzma.
|
||||
# LZMA_FOUND - True if liblzma found.
|
||||
# LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc.
|
||||
# LZMADEC_LIBRARIES - List of libraries when using liblzmadec.
|
||||
# LZMADEC_FOUND - True if liblzmadec found.
|
||||
|
||||
IF (LZMA_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
SET(LZMA_FIND_QUIETLY TRUE)
|
||||
ENDIF (LZMA_INCLUDE_DIR)
|
||||
|
||||
FIND_PATH(LZMA_INCLUDE_DIR lzma.h)
|
||||
FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR)
|
||||
|
||||
IF(LZMA_FOUND)
|
||||
SET( LZMA_LIBRARIES ${LZMA_LIBRARY} )
|
||||
ELSE(LZMA_FOUND)
|
||||
SET( LZMA_LIBRARIES )
|
||||
|
||||
IF (LZMADEC_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
SET(LZMADEC_FIND_QUIETLY TRUE)
|
||||
ENDIF (LZMADEC_INCLUDE_DIR)
|
||||
|
||||
FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h)
|
||||
FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec )
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY
|
||||
LZMADEC_INCLUDE_DIR)
|
||||
|
||||
IF(LZMADEC_FOUND)
|
||||
SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} )
|
||||
ELSE(LZMADEC_FOUND)
|
||||
SET( LZMADEC_LIBRARIES )
|
||||
ENDIF(LZMADEC_FOUND)
|
||||
ENDIF(LZMA_FOUND)
|
1101
Utilities/cmlibarchive/build/cmake/config.h.in
Normal file
1101
Utilities/cmlibarchive/build/cmake/config.h.in
Normal file
File diff suppressed because it is too large
Load Diff
11
Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in
Normal file
11
Utilities/cmlibarchive/build/pkgconfig/libarchive.pc.in
Normal file
@ -0,0 +1,11 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libarchive
|
||||
Description: library that can create and read several streaming archive formats
|
||||
Version: @VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -larchive
|
||||
Libs.private: @LIBS@
|
@ -0,0 +1,418 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This needs http://unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
#
|
||||
inputfile="$1" # Expect UnicodeData.txt
|
||||
outfile=archive_string_composition.h
|
||||
pickout=/tmp/mk_unicode_composition_tbl$$.awk
|
||||
#################################################################################
|
||||
#
|
||||
# Append the file header of "archive_string_composition.h"
|
||||
#
|
||||
#################################################################################
|
||||
append_copyright()
|
||||
{
|
||||
cat > ${outfile} <<CR_END
|
||||
/*-
|
||||
* Copyright (c) 2011 libarchive Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \$FreeBSD\$
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* ATTENTION!
|
||||
* This file is generated by build/utils/gen_archive_string_composition_h.sh
|
||||
* from http://unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
*
|
||||
* See also http://unicode.org/report/tr15/
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_STRING_COMPOSITION_H_INCLUDED
|
||||
#define ARCHIVE_STRING_COMPOSITION_H_INCLUDED
|
||||
|
||||
struct unicode_composition_table {
|
||||
uint32_t cp1;
|
||||
uint32_t cp2;
|
||||
uint32_t nfc;
|
||||
};
|
||||
|
||||
CR_END
|
||||
}
|
||||
#################################################################################
|
||||
#
|
||||
# awk script
|
||||
#
|
||||
#################################################################################
|
||||
cat > ${pickout} <<AWK_END
|
||||
#
|
||||
BEGIN {
|
||||
FS = ";"
|
||||
min = "";
|
||||
max = "";
|
||||
cmd="sort | awk -F ' ' '{printf \"\\\\t{ 0x%s , 0x%s , 0x%s },\\\\n\",\$1,\$2,\$3}'"
|
||||
print "static const struct unicode_composition_table u_composition_table[] = {"
|
||||
}
|
||||
END {
|
||||
close(cmd)
|
||||
print "};"
|
||||
print ""
|
||||
#
|
||||
# Output Canonical Combining Class tables used for translating NFD to NFC.
|
||||
#
|
||||
printf "#define CANONICAL_CLASS_MIN\\t0x%s\\n", min
|
||||
printf "#define CANONICAL_CLASS_MAX\\t0x%s\\n", max
|
||||
print ""
|
||||
printf "#define IS_DECOMPOSABLE_BLOCK(uc)\\t\\\\\n"
|
||||
printf "\\t(((uc)>>8) <= 0x%X && u_decomposable_blocks[(uc)>>8])\\n", highnum
|
||||
printf "static const char u_decomposable_blocks[0x%X+1] = {\\n\\t", highnum
|
||||
#
|
||||
# Output blockmap
|
||||
for (i = 0; i <= highnum; i++) {
|
||||
if (i != 0 && i % 32 == 0)
|
||||
printf "\\n\\t"
|
||||
# Additionally Hangul[11XX(17), AC00(172) - D7FF(215)] is decomposable.
|
||||
if (blockmap[i] || i == 17 || (i >= 172 && i <= 215))
|
||||
printf "1,"
|
||||
else
|
||||
printf "0,"
|
||||
}
|
||||
printf "\\n};\\n\\n"
|
||||
#
|
||||
# Output a macro to get a canonical combining class.
|
||||
#
|
||||
print "/* Get Canonical Combining Class(CCC). */"
|
||||
printf "#define CCC(uc)\\t\\\\\n"
|
||||
printf "\\t(((uc) > 0x%s)?0:\\\\\\n", max
|
||||
printf "\\tccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F])\\n"
|
||||
print ""
|
||||
#
|
||||
# Output a canonical combining class value table.
|
||||
#
|
||||
midcnt = 0
|
||||
printf "/* The table of the value of Canonical Cimbining Class */\\n"
|
||||
print "static const unsigned char ccc_val[][16] = {"
|
||||
print " /* idx=0: XXXX0 - XXXXF */"
|
||||
print " { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },"
|
||||
for (h = 0; h <= highnum; h++) {
|
||||
if (!blockmap[h])
|
||||
continue;
|
||||
for (m = 0; m < 16; m++) {
|
||||
if (!xx_blockmap[h, m])
|
||||
continue;
|
||||
midcnt++
|
||||
printf " /* idx=%d: %03X%1X0 - %03X%1XF */\\n {", midcnt, h, m, h, m
|
||||
for (l = 0; l < 15; l++) {
|
||||
printf "%d, ", xxx_blockmap[h, m, l]
|
||||
}
|
||||
printf "%d },\n", xxx_blockmap[h, m, 15]
|
||||
}
|
||||
}
|
||||
printf "};\n"
|
||||
#
|
||||
# Output the index table of the canonical combining class value table.
|
||||
#
|
||||
cnt = 0
|
||||
midcnt = 0
|
||||
printf "\\n/* The index table to ccc_val[*][16] */\\n"
|
||||
print "static const unsigned char ccc_val_index[][16] = {"
|
||||
print " /* idx=0: XXX00 - XXXFF */"
|
||||
print " { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },"
|
||||
for (h = 0; h <= highnum; h++) {
|
||||
if (!blockmap[h])
|
||||
continue;
|
||||
cnt++
|
||||
printf " /* idx=%d: %03X00 - %03XFF */\\n {", cnt, h, h
|
||||
for (m = 0; m < 16; m++) {
|
||||
if (m != 0)
|
||||
printf ","
|
||||
if (xx_blockmap[h, m]) {
|
||||
midcnt++
|
||||
printf "%2d", midcnt
|
||||
} else
|
||||
printf " 0"
|
||||
}
|
||||
printf " },\\n"
|
||||
}
|
||||
printf "};\\n"
|
||||
#
|
||||
# Output the index table to the index table of the canonical combining
|
||||
# class value table.
|
||||
#
|
||||
printf "\\n/* The index table to ccc_val_index[*][16] */\\n"
|
||||
printf "static const unsigned char ccc_index[] = {\\n ", h
|
||||
cnt = 0
|
||||
for (h = 0; h <= highnum; h++) {
|
||||
if (h != 0 && h % 24 == 0)
|
||||
printf "\\n "
|
||||
if (blockmap[h]) {
|
||||
cnt++;
|
||||
printf "%2d,", cnt
|
||||
} else
|
||||
printf " 0,"
|
||||
}
|
||||
print "};"
|
||||
print ""
|
||||
print "#endif /* ARCHIVE_STRING_COMPOSITION_H_INCLUDED */"
|
||||
}
|
||||
#
|
||||
#
|
||||
function hextoi(hex)
|
||||
{
|
||||
dec = 0
|
||||
for (i=0; i < length(hex); i++) {
|
||||
x = substr(hex, i+1, 1)
|
||||
if (x ~/[0-9]/)
|
||||
dec = dec * 16 + x;
|
||||
else if (x == "A")
|
||||
dec = dec * 16 + 10;
|
||||
else if (x == "B")
|
||||
dec = dec * 16 + 11;
|
||||
else if (x == "C")
|
||||
dec = dec * 16 + 12;
|
||||
else if (x == "D")
|
||||
dec = dec * 16 + 13;
|
||||
else if (x == "E")
|
||||
dec = dec * 16 + 14;
|
||||
else if (x == "F")
|
||||
dec = dec * 16 + 15;
|
||||
}
|
||||
return dec
|
||||
}
|
||||
#
|
||||
# Collect Canonical Combining Class values.
|
||||
#
|
||||
\$4 ~/^[0-9A-F]+$/ {
|
||||
if (\$4 !~/^0$/) {
|
||||
if (min == "") {
|
||||
min = \$1
|
||||
}
|
||||
max = \$1
|
||||
high = substr(\$1, 1, length(\$1) -2)
|
||||
highnum = hextoi(high)
|
||||
mid = substr(\$1, length(\$1) -1, 1)
|
||||
midnum = hextoi(mid)
|
||||
low = substr(\$1, length(\$1), 1)
|
||||
lownum = hextoi(low)
|
||||
blockmap[highnum] = 1
|
||||
xx_blockmap[highnum, midnum] = 1
|
||||
xxx_blockmap[highnum, midnum, lownum] = \$4
|
||||
}
|
||||
}
|
||||
#
|
||||
# Following code points are not decomposed in MAC OS.
|
||||
# U+2000 - U+2FFF
|
||||
# U+F900 - U+FAFF
|
||||
# U+2F800 - U+2FAFF
|
||||
#
|
||||
#\$1 ~/^2[0-9A-F][0-9A-F][0-9A-F]\$/ {
|
||||
# next
|
||||
#}
|
||||
#\$1 ~/^F[9A][0-9A-F][0-9A-F]\$/ {
|
||||
# next
|
||||
#}
|
||||
#\$1 ~/^2F[89A][0-9A-F][0-9A-F]\$/ {
|
||||
# next
|
||||
#}
|
||||
#
|
||||
# Exclusion code points specified by
|
||||
# http://unicode.org/Public/UNIDATA/CompositionExclusions.txt
|
||||
##
|
||||
# 1. Script Specifices
|
||||
##
|
||||
\$1 ~/^095[89ABCDEF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^09D[CDF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0A3[36]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0A5[9ABE]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0B5[CD]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F4[3D]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F5[27C]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F69\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F7[68]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F9[3D]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0FA[27C]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0FB9\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FB1[DF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FB2[ABCDEF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FB3[012345689ABCE]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FB4[01346789ABCDE]\$/ {
|
||||
next
|
||||
}
|
||||
##
|
||||
# 2. Post Composition Version precomposed characters
|
||||
##
|
||||
\$1 ~/^2ADC\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1D15[EF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1D16[01234]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1D1B[BCDEF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1D1C0\$/ {
|
||||
next
|
||||
}
|
||||
##
|
||||
# 3. Singleton Decompositions
|
||||
##
|
||||
\$1 ~/^034[01]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^037[4E]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0387\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1F7[13579BD]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1FB[BE]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1FC[9B]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1FD[3B]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1FE[3BEF]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^1FF[9BD]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^200[01]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^212[6AB]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^232[9A]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^F9[0-9A-F][0-9A-F]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FA0[0-9A-D]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FA1[025-9A-E]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FA2[0256A-D]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FA[3-5][0-9A-F]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FA6[0-9A-D]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FA[7-9A-C][0-9A-F]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^FAD[0-9]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^2F[89][0-9A-F][0-9A-F]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^2FA0[0-9A-F]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^2FA1[0-9A-D]\$/ {
|
||||
next
|
||||
}
|
||||
##
|
||||
# 4. Non-Starter Decompositions
|
||||
##
|
||||
\$1 ~/^0344\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F7[35]\$/ {
|
||||
next
|
||||
}
|
||||
\$1 ~/^0F81\$/ {
|
||||
next
|
||||
}
|
||||
#
|
||||
# Output combinations for NFD ==> NFC.
|
||||
#
|
||||
\$6 ~/^[0-9A-F]+ [0-9A-F]+\$/ {
|
||||
split(\$6, cp, " ")
|
||||
if (length(\$1) == 4)
|
||||
print "0"cp[1], "0"cp[2], "0"\$1 | cmd
|
||||
else
|
||||
print cp[1], cp[2], \$1 | cmd
|
||||
}
|
||||
AWK_END
|
||||
#################################################################################
|
||||
#
|
||||
# Run awk a script.
|
||||
#
|
||||
#################################################################################
|
||||
append_copyright
|
||||
awk -f ${pickout} ${inputfile} >> ${outfile}
|
||||
#
|
||||
# Remove awk the script.
|
||||
rm ${pickout}
|
1
Utilities/cmlibarchive/build/version
Normal file
1
Utilities/cmlibarchive/build/version
Normal file
@ -0,0 +1 @@
|
||||
3000001b
|
172
Utilities/cmlibarchive/libarchive/CMakeLists.txt
Normal file
172
Utilities/cmlibarchive/libarchive/CMakeLists.txt
Normal file
@ -0,0 +1,172 @@
|
||||
|
||||
############################################
|
||||
#
|
||||
# How to build libarchive
|
||||
#
|
||||
############################################
|
||||
|
||||
# Public headers
|
||||
SET(include_HEADERS
|
||||
archive.h
|
||||
archive_entry.h
|
||||
)
|
||||
|
||||
# Sources and private headers
|
||||
SET(libarchive_SOURCES
|
||||
archive_acl.c
|
||||
archive_check_magic.c
|
||||
archive_crypto.c
|
||||
archive_crypto_private.h
|
||||
archive_endian.h
|
||||
archive_entry.c
|
||||
archive_entry.h
|
||||
archive_entry_copy_stat.c
|
||||
archive_entry_link_resolver.c
|
||||
archive_entry_locale.h
|
||||
archive_entry_private.h
|
||||
archive_entry_sparse.c
|
||||
archive_entry_stat.c
|
||||
archive_entry_strmode.c
|
||||
archive_entry_xattr.c
|
||||
archive_options.c
|
||||
archive_options_private.h
|
||||
archive_platform.h
|
||||
archive_ppmd_private.h
|
||||
archive_ppmd7.c
|
||||
archive_ppmd7_private.h
|
||||
archive_private.h
|
||||
archive_rb.c
|
||||
archive_rb.h
|
||||
archive_read.c
|
||||
archive_read_data_into_fd.c
|
||||
archive_read_disk_entry_from_file.c
|
||||
archive_read_disk_posix.c
|
||||
archive_read_disk_private.h
|
||||
archive_read_disk_set_standard_lookup.c
|
||||
archive_read_extract.c
|
||||
archive_read_open_fd.c
|
||||
archive_read_open_file.c
|
||||
archive_read_open_filename.c
|
||||
archive_read_open_memory.c
|
||||
archive_read_private.h
|
||||
archive_read_set_options.c
|
||||
archive_read_support_filter_all.c
|
||||
archive_read_support_filter_bzip2.c
|
||||
archive_read_support_filter_compress.c
|
||||
archive_read_support_filter_gzip.c
|
||||
archive_read_support_filter_none.c
|
||||
archive_read_support_filter_program.c
|
||||
archive_read_support_filter_rpm.c
|
||||
archive_read_support_filter_uu.c
|
||||
archive_read_support_filter_xz.c
|
||||
archive_read_support_format_7zip.c
|
||||
archive_read_support_format_all.c
|
||||
archive_read_support_format_ar.c
|
||||
archive_read_support_format_by_code.c
|
||||
archive_read_support_format_cab.c
|
||||
archive_read_support_format_cpio.c
|
||||
archive_read_support_format_empty.c
|
||||
archive_read_support_format_iso9660.c
|
||||
archive_read_support_format_lha.c
|
||||
archive_read_support_format_mtree.c
|
||||
archive_read_support_format_rar.c
|
||||
archive_read_support_format_raw.c
|
||||
archive_read_support_format_tar.c
|
||||
archive_read_support_format_xar.c
|
||||
archive_read_support_format_zip.c
|
||||
archive_string.c
|
||||
archive_string.h
|
||||
archive_string_composition.h
|
||||
archive_string_sprintf.c
|
||||
archive_util.c
|
||||
archive_virtual.c
|
||||
archive_write.c
|
||||
archive_write_disk_posix.c
|
||||
archive_write_disk_private.h
|
||||
archive_write_disk_set_standard_lookup.c
|
||||
archive_write_private.h
|
||||
archive_write_open_fd.c
|
||||
archive_write_open_file.c
|
||||
archive_write_open_filename.c
|
||||
archive_write_open_memory.c
|
||||
archive_write_add_filter_bzip2.c
|
||||
archive_write_add_filter_compress.c
|
||||
archive_write_add_filter_gzip.c
|
||||
archive_write_add_filter_none.c
|
||||
archive_write_add_filter_program.c
|
||||
archive_write_add_filter_xz.c
|
||||
archive_write_set_format.c
|
||||
archive_write_set_format_7zip.c
|
||||
archive_write_set_format_ar.c
|
||||
archive_write_set_format_by_name.c
|
||||
archive_write_set_format_cpio.c
|
||||
archive_write_set_format_cpio_newc.c
|
||||
archive_write_set_format_gnutar.c
|
||||
archive_write_set_format_iso9660.c
|
||||
archive_write_set_format_mtree.c
|
||||
archive_write_set_format_pax.c
|
||||
archive_write_set_format_shar.c
|
||||
archive_write_set_format_ustar.c
|
||||
archive_write_set_format_xar.c
|
||||
archive_write_set_format_zip.c
|
||||
archive_write_set_options.c
|
||||
filter_fork.c
|
||||
filter_fork.h
|
||||
)
|
||||
|
||||
# Man pages
|
||||
SET(libarchive_MANS
|
||||
archive_entry.3
|
||||
archive_entry_acl.3
|
||||
archive_entry_linkify.3
|
||||
archive_entry_paths.3
|
||||
archive_entry_perms.3
|
||||
archive_entry_stat.3
|
||||
archive_entry_time.3
|
||||
archive_read.3
|
||||
archive_read_disk.3
|
||||
archive_read_set_options.3
|
||||
archive_util.3
|
||||
archive_write.3
|
||||
archive_write_disk.3
|
||||
archive_write_set_options.3
|
||||
cpio.5
|
||||
libarchive.3
|
||||
libarchive_internals.3
|
||||
libarchive-formats.5
|
||||
mtree.5
|
||||
tar.5
|
||||
)
|
||||
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LIST(APPEND libarchive_SOURCES archive_entry_copy_bhfi.c)
|
||||
LIST(APPEND libarchive_SOURCES archive_read_disk_windows.c)
|
||||
LIST(APPEND libarchive_SOURCES archive_windows.c)
|
||||
LIST(APPEND libarchive_SOURCES archive_windows.h)
|
||||
LIST(APPEND libarchive_SOURCES archive_write_disk_windows.c)
|
||||
LIST(APPEND libarchive_SOURCES filter_fork_windows.c)
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
|
||||
# Libarchive is a shared library
|
||||
ADD_LIBRARY(archive SHARED ${libarchive_SOURCES} ${include_HEADERS})
|
||||
TARGET_LINK_LIBRARIES(archive ${ADDITIONAL_LIBS})
|
||||
SET_TARGET_PROPERTIES(archive PROPERTIES SOVERSION ${SOVERSION})
|
||||
|
||||
# archive_static is a static library
|
||||
ADD_LIBRARY(archive_static STATIC ${libarchive_SOURCES} ${include_HEADERS})
|
||||
SET_TARGET_PROPERTIES(archive_static PROPERTIES COMPILE_DEFINITIONS
|
||||
LIBARCHIVE_STATIC)
|
||||
# On Posix systems, libarchive.so and libarchive.a can co-exist.
|
||||
IF(NOT WIN32 OR CYGWIN)
|
||||
SET_TARGET_PROPERTIES(archive_static PROPERTIES OUTPUT_NAME archive)
|
||||
ENDIF(NOT WIN32 OR CYGWIN)
|
||||
|
||||
# How to install the libraries
|
||||
INSTALL(TARGETS archive archive_static
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
INSTALL_MAN(${libarchive_MANS})
|
||||
INSTALL(FILES ${include_HEADERS} DESTINATION include)
|
||||
|
||||
add_subdirectory(test)
|
832
Utilities/cmlibarchive/libarchive/archive.h
Normal file
832
Utilities/cmlibarchive/libarchive/archive.h
Normal file
@ -0,0 +1,832 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2010 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_H_INCLUDED
|
||||
#define ARCHIVE_H_INCLUDED
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stdio.h> /* For FILE * */
|
||||
|
||||
/*
|
||||
* Note: archive.h is for use outside of libarchive; the configuration
|
||||
* headers (config.h, archive_platform.h, etc.) are purely internal.
|
||||
* Do NOT use HAVE_XXX configuration macros to control the behavior of
|
||||
* this header! If you must conditionalize, use predefined compiler and/or
|
||||
* platform macros.
|
||||
*/
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560
|
||||
# include <stdint.h>
|
||||
#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS)
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* Get appropriate definitions of standard POSIX-style types. */
|
||||
/* These should match the types used in 'struct stat' */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
# define __LA_INT64_T __int64
|
||||
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
|
||||
# define __LA_SSIZE_T ssize_t
|
||||
# elif defined(_WIN64)
|
||||
# define __LA_SSIZE_T __int64
|
||||
# else
|
||||
# define __LA_SSIZE_T long
|
||||
# endif
|
||||
# if defined(__BORLANDC__)
|
||||
# define __LA_UID_T uid_t
|
||||
# define __LA_GID_T gid_t
|
||||
# else
|
||||
# define __LA_UID_T short
|
||||
# define __LA_GID_T short
|
||||
# endif
|
||||
#else
|
||||
# include <unistd.h> /* ssize_t, uid_t, and gid_t */
|
||||
# if defined(_SCO_DS)
|
||||
# define __LA_INT64_T long long
|
||||
# else
|
||||
# define __LA_INT64_T int64_t
|
||||
# endif
|
||||
# define __LA_SSIZE_T ssize_t
|
||||
# define __LA_UID_T uid_t
|
||||
# define __LA_GID_T gid_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
|
||||
* .lib. The default here assumes you're building a DLL. Only
|
||||
* libarchive source should ever define __LIBARCHIVE_BUILD.
|
||||
*/
|
||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
|
||||
# ifdef __LIBARCHIVE_BUILD
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL __attribute__((dllexport)) extern
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Static libraries or non-Windows needs no special declaration. */
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__)
|
||||
#define __LA_PRINTF(fmtarg, firstvararg) \
|
||||
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
|
||||
#else
|
||||
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The version number is provided as both a macro and a function.
|
||||
* The macro identifies the installed header; the function identifies
|
||||
* the library version (which may not be the same if you're using a
|
||||
* dynamically-linked version of the library). Of course, if the
|
||||
* header and library are very different, you should expect some
|
||||
* strangeness. Don't do that.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The version number is expressed as a single integer that makes it
|
||||
* easy to compare versions at build time: for version a.b.c, the
|
||||
* version number is printf("%d%03d%03d",a,b,c). For example, if you
|
||||
* know your application requires version 2.12.108 or later, you can
|
||||
* assert that ARCHIVE_VERSION >= 2012108.
|
||||
*
|
||||
* This single-number format was introduced with libarchive 1.9.0 in
|
||||
* the libarchive 1.x family and libarchive 2.2.4 in the libarchive
|
||||
* 2.x family. The following may be useful if you really want to do
|
||||
* feature detection for earlier libarchive versions (which defined
|
||||
* ARCHIVE_API_VERSION and ARCHIVE_API_FEATURE instead):
|
||||
*
|
||||
* #ifndef ARCHIVE_VERSION_NUMBER
|
||||
* #define ARCHIVE_VERSION_NUMBER \
|
||||
* (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
|
||||
* #endif
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3000001
|
||||
__LA_DECL int archive_version_number(void);
|
||||
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_STRING "libarchive 3.0.1b"
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
/* Declare our basic types. */
|
||||
struct archive;
|
||||
struct archive_entry;
|
||||
|
||||
/*
|
||||
* Error codes: Use archive_errno() and archive_error_string()
|
||||
* to retrieve details. Unless specified otherwise, all functions
|
||||
* that return 'int' use these codes.
|
||||
*/
|
||||
#define ARCHIVE_EOF 1 /* Found end of archive. */
|
||||
#define ARCHIVE_OK 0 /* Operation was successful. */
|
||||
#define ARCHIVE_RETRY (-10) /* Retry might succeed. */
|
||||
#define ARCHIVE_WARN (-20) /* Partial success. */
|
||||
/* For example, if write_header "fails", then you can't push data. */
|
||||
#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */
|
||||
/* But if write_header is "fatal," then this archive is dead and useless. */
|
||||
#define ARCHIVE_FATAL (-30) /* No more operations are possible. */
|
||||
|
||||
/*
|
||||
* As far as possible, archive_errno returns standard platform errno codes.
|
||||
* Of course, the details vary by platform, so the actual definitions
|
||||
* here are stored in "archive_platform.h". The symbols are listed here
|
||||
* for reference; as a rule, clients should not need to know the exact
|
||||
* platform-dependent error code.
|
||||
*/
|
||||
/* Unrecognized or invalid file format. */
|
||||
/* #define ARCHIVE_ERRNO_FILE_FORMAT */
|
||||
/* Illegal usage of the library. */
|
||||
/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */
|
||||
/* Unknown or unclassified error. */
|
||||
/* #define ARCHIVE_ERRNO_MISC */
|
||||
|
||||
/*
|
||||
* Callbacks are invoked to automatically read/skip/write/open/close the
|
||||
* archive. You can provide your own for complex tasks (like breaking
|
||||
* archives across multiple tapes) or use standard ones built into the
|
||||
* library.
|
||||
*/
|
||||
|
||||
/* Returns pointer and size of next block of data from archive. */
|
||||
typedef __LA_SSIZE_T archive_read_callback(struct archive *,
|
||||
void *_client_data, const void **_buffer);
|
||||
|
||||
/* Skips at most request bytes from archive and returns the skipped amount.
|
||||
* This may skip fewer bytes than requested; it may even skip zero bytes.
|
||||
* If you do skip fewer bytes than requested, libarchive will invoke your
|
||||
* read callback and discard data as necessary to make up the full skip.
|
||||
*/
|
||||
typedef __LA_INT64_T archive_skip_callback(struct archive *,
|
||||
void *_client_data, __LA_INT64_T request);
|
||||
|
||||
/* Seeks to specified location in the file and returns the position.
|
||||
* Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h.
|
||||
* Return ARCHIVE_FATAL if the seek fails for any reason.
|
||||
*/
|
||||
typedef __LA_INT64_T archive_seek_callback(struct archive *,
|
||||
void *_client_data, __LA_INT64_T offset, int whence);
|
||||
|
||||
/* Returns size actually written, zero on EOF, -1 on error. */
|
||||
typedef __LA_SSIZE_T archive_write_callback(struct archive *,
|
||||
void *_client_data,
|
||||
const void *_buffer, size_t _length);
|
||||
|
||||
typedef int archive_open_callback(struct archive *, void *_client_data);
|
||||
|
||||
typedef int archive_close_callback(struct archive *, void *_client_data);
|
||||
|
||||
/*
|
||||
* Codes to identify various stream filters.
|
||||
*/
|
||||
#define ARCHIVE_FILTER_NONE 0
|
||||
#define ARCHIVE_FILTER_GZIP 1
|
||||
#define ARCHIVE_FILTER_BZIP2 2
|
||||
#define ARCHIVE_FILTER_COMPRESS 3
|
||||
#define ARCHIVE_FILTER_PROGRAM 4
|
||||
#define ARCHIVE_FILTER_LZMA 5
|
||||
#define ARCHIVE_FILTER_XZ 6
|
||||
#define ARCHIVE_FILTER_UU 7
|
||||
#define ARCHIVE_FILTER_RPM 8
|
||||
#define ARCHIVE_FILTER_LZIP 9
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
|
||||
#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP
|
||||
#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2
|
||||
#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS
|
||||
#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM
|
||||
#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA
|
||||
#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ
|
||||
#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU
|
||||
#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM
|
||||
#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Codes returned by archive_format.
|
||||
*
|
||||
* Top 16 bits identifies the format family (e.g., "tar"); lower
|
||||
* 16 bits indicate the variant. This is updated by read_next_header.
|
||||
* Note that the lower 16 bits will often vary from entry to entry.
|
||||
* In some cases, this variation occurs as libarchive learns more about
|
||||
* the archive (for example, later entries might utilize extensions that
|
||||
* weren't necessary earlier in the archive; in this case, libarchive
|
||||
* will change the format code to indicate the extended format that
|
||||
* was used). In other cases, it's because different tools have
|
||||
* modified the archive and so different parts of the archive
|
||||
* actually have slightly different formats. (Both tar and cpio store
|
||||
* format codes in each entry, so it is quite possible for each
|
||||
* entry to be in a different format.)
|
||||
*/
|
||||
#define ARCHIVE_FORMAT_BASE_MASK 0xff0000
|
||||
#define ARCHIVE_FORMAT_CPIO 0x10000
|
||||
#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1)
|
||||
#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2)
|
||||
#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3)
|
||||
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
|
||||
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
||||
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
|
||||
#define ARCHIVE_FORMAT_SHAR 0x20000
|
||||
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
||||
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
|
||||
#define ARCHIVE_FORMAT_TAR 0x30000
|
||||
#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1)
|
||||
#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2)
|
||||
#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3)
|
||||
#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4)
|
||||
#define ARCHIVE_FORMAT_ISO9660 0x40000
|
||||
#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1)
|
||||
#define ARCHIVE_FORMAT_ZIP 0x50000
|
||||
#define ARCHIVE_FORMAT_EMPTY 0x60000
|
||||
#define ARCHIVE_FORMAT_AR 0x70000
|
||||
#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1)
|
||||
#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2)
|
||||
#define ARCHIVE_FORMAT_MTREE 0x80000
|
||||
#define ARCHIVE_FORMAT_RAW 0x90000
|
||||
#define ARCHIVE_FORMAT_XAR 0xA0000
|
||||
#define ARCHIVE_FORMAT_LHA 0xB0000
|
||||
#define ARCHIVE_FORMAT_CAB 0xC0000
|
||||
#define ARCHIVE_FORMAT_RAR 0xD0000
|
||||
#define ARCHIVE_FORMAT_7ZIP 0xE0000
|
||||
|
||||
/*-
|
||||
* Basic outline for reading an archive:
|
||||
* 1) Ask archive_read_new for an archive reader object.
|
||||
* 2) Update any global properties as appropriate.
|
||||
* In particular, you'll certainly want to call appropriate
|
||||
* archive_read_support_XXX functions.
|
||||
* 3) Call archive_read_open_XXX to open the archive
|
||||
* 4) Repeatedly call archive_read_next_header to get information about
|
||||
* successive archive entries. Call archive_read_data to extract
|
||||
* data for entries of interest.
|
||||
* 5) Call archive_read_finish to end processing.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_read_new(void);
|
||||
|
||||
/*
|
||||
* The archive_read_support_XXX calls enable auto-detect for this
|
||||
* archive handle. They also link in the necessary support code.
|
||||
* For example, if you don't want bzlib linked in, don't invoke
|
||||
* support_compression_bzip2(). The "all" functions provide the
|
||||
* obvious shorthand.
|
||||
*/
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
__LA_DECL int archive_read_support_compression_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_compress(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_gzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_lzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_none(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_program(struct archive *,
|
||||
const char *command);
|
||||
__LA_DECL int archive_read_support_compression_program_signature
|
||||
(struct archive *, const char *,
|
||||
const void * /* match */, size_t);
|
||||
|
||||
__LA_DECL int archive_read_support_compression_rpm(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_uu(struct archive *);
|
||||
__LA_DECL int archive_read_support_compression_xz(struct archive *);
|
||||
#endif
|
||||
|
||||
__LA_DECL int archive_read_support_filter_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_bzip2(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_compress(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_gzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_lzip(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_lzma(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_none(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_program(struct archive *,
|
||||
const char *command);
|
||||
__LA_DECL int archive_read_support_filter_program_signature
|
||||
(struct archive *, const char *,
|
||||
const void * /* match */, size_t);
|
||||
|
||||
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_uu(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_xz(struct archive *);
|
||||
|
||||
__LA_DECL int archive_read_support_format_7zip(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_all(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_ar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_by_code(struct archive *, int);
|
||||
__LA_DECL int archive_read_support_format_cab(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_cpio(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_empty(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_gnutar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_iso9660(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_lha(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_mtree(struct archive *);
|
||||
__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 *);
|
||||
__LA_DECL int archive_read_support_format_zip(struct archive *);
|
||||
|
||||
/* Set various callbacks. */
|
||||
__LA_DECL int archive_read_set_open_callback(struct archive *,
|
||||
archive_open_callback *);
|
||||
__LA_DECL int archive_read_set_read_callback(struct archive *,
|
||||
archive_read_callback *);
|
||||
__LA_DECL int archive_read_set_seek_callback(struct archive *,
|
||||
archive_seek_callback *);
|
||||
__LA_DECL int archive_read_set_skip_callback(struct archive *,
|
||||
archive_skip_callback *);
|
||||
__LA_DECL int archive_read_set_close_callback(struct archive *,
|
||||
archive_close_callback *);
|
||||
/* The callback data is provided to all of the callbacks above. */
|
||||
__LA_DECL int archive_read_set_callback_data(struct archive *, void *);
|
||||
/* Opening freezes the callbacks. */
|
||||
__LA_DECL int archive_read_open1(struct archive *);
|
||||
|
||||
/* Convenience wrappers around the above. */
|
||||
__LA_DECL int archive_read_open(struct archive *, void *_client_data,
|
||||
archive_open_callback *, archive_read_callback *,
|
||||
archive_close_callback *);
|
||||
__LA_DECL int archive_read_open2(struct archive *, void *_client_data,
|
||||
archive_open_callback *, archive_read_callback *,
|
||||
archive_skip_callback *, archive_close_callback *);
|
||||
|
||||
/*
|
||||
* A variety of shortcuts that invoke archive_read_open() with
|
||||
* canned callbacks suitable for common situations. The ones that
|
||||
* accept a block size handle tape blocking correctly.
|
||||
*/
|
||||
/* Use this if you know the filename. Note: NULL indicates stdin. */
|
||||
__LA_DECL int archive_read_open_filename(struct archive *,
|
||||
const char *_filename, size_t _block_size);
|
||||
__LA_DECL int archive_read_open_filename_w(struct archive *,
|
||||
const wchar_t *_filename, size_t _block_size);
|
||||
/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */
|
||||
__LA_DECL int archive_read_open_file(struct archive *,
|
||||
const char *_filename, size_t _block_size);
|
||||
/* Read an archive that's stored in memory. */
|
||||
__LA_DECL int archive_read_open_memory(struct archive *,
|
||||
void * buff, size_t size);
|
||||
/* A more involved version that is only used for internal testing. */
|
||||
__LA_DECL int archive_read_open_memory2(struct archive *a, void *buff,
|
||||
size_t size, size_t read_size);
|
||||
/* Read an archive that's already open, using the file descriptor. */
|
||||
__LA_DECL int archive_read_open_fd(struct archive *, int _fd,
|
||||
size_t _block_size);
|
||||
/* Read an archive that's already open, using a FILE *. */
|
||||
/* Note: DO NOT use this with tape drives. */
|
||||
__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file);
|
||||
|
||||
/* Parses and returns next entry header. */
|
||||
__LA_DECL int archive_read_next_header(struct archive *,
|
||||
struct archive_entry **);
|
||||
|
||||
/* Parses and returns next entry header using the archive_entry passed in */
|
||||
__LA_DECL int archive_read_next_header2(struct archive *,
|
||||
struct archive_entry *);
|
||||
|
||||
/*
|
||||
* Retrieve the byte offset in UNCOMPRESSED data where last-read
|
||||
* header started.
|
||||
*/
|
||||
__LA_DECL __LA_INT64_T archive_read_header_position(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);
|
||||
|
||||
/*
|
||||
* A zero-copy version of archive_read_data that also exposes the file offset
|
||||
* of each returned block. Note that the client has no way to specify
|
||||
* the desired size of the block. The API does guarantee that offsets will
|
||||
* be strictly increasing and that returned blocks will not overlap.
|
||||
*/
|
||||
__LA_DECL int archive_read_data_block(struct archive *a,
|
||||
const void **buff, size_t *size, __LA_INT64_T *offset);
|
||||
|
||||
/*-
|
||||
* Some convenience functions that are built on archive_read_data:
|
||||
* 'skip': skips entire entry
|
||||
* 'into_buffer': writes data into memory buffer that you provide
|
||||
* 'into_fd': writes data to specified filedes
|
||||
*/
|
||||
__LA_DECL int archive_read_data_skip(struct archive *);
|
||||
__LA_DECL int archive_read_data_into_buffer(struct archive *,
|
||||
void *buffer, __LA_SSIZE_T len);
|
||||
__LA_DECL int archive_read_data_into_fd(struct archive *, int fd);
|
||||
|
||||
/*
|
||||
* Set read options.
|
||||
*/
|
||||
/* Apply option to the format only. */
|
||||
__LA_DECL int archive_read_set_format_option(struct archive *_a,
|
||||
const char *m, const char *o,
|
||||
const char *v);
|
||||
/* Apply option to the filter only. */
|
||||
__LA_DECL int archive_read_set_filter_option(struct archive *_a,
|
||||
const char *m, const char *o,
|
||||
const char *v);
|
||||
/* Apply option to both the format and the filter. */
|
||||
__LA_DECL int archive_read_set_option(struct archive *_a,
|
||||
const char *m, const char *o,
|
||||
const char *v);
|
||||
/* Apply option string to both the format and the filter. */
|
||||
__LA_DECL int archive_read_set_options(struct archive *_a,
|
||||
const char *opts);
|
||||
|
||||
/*-
|
||||
* Convenience function to recreate the current entry (whose header
|
||||
* has just been read) on disk.
|
||||
*
|
||||
* This does quite a bit more than just copy data to disk. It also:
|
||||
* - Creates intermediate directories as required.
|
||||
* - Manages directory permissions: non-writable directories will
|
||||
* be initially created with write permission enabled; when the
|
||||
* archive is closed, dir permissions are edited to the values specified
|
||||
* in the archive.
|
||||
* - Checks hardlinks: hardlinks will not be extracted unless the
|
||||
* linked-to file was also extracted within the same session. (TODO)
|
||||
*/
|
||||
|
||||
/* The "flags" argument selects optional behavior, 'OR' the flags you want. */
|
||||
|
||||
/* Default: Do not try to set owner/group. */
|
||||
#define ARCHIVE_EXTRACT_OWNER (0x0001)
|
||||
/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */
|
||||
#define ARCHIVE_EXTRACT_PERM (0x0002)
|
||||
/* Default: Do not restore mtime/atime. */
|
||||
#define ARCHIVE_EXTRACT_TIME (0x0004)
|
||||
/* Default: Replace existing files. */
|
||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008)
|
||||
/* Default: Try create first, unlink only if create fails with EEXIST. */
|
||||
#define ARCHIVE_EXTRACT_UNLINK (0x0010)
|
||||
/* Default: Do not restore ACLs. */
|
||||
#define ARCHIVE_EXTRACT_ACL (0x0020)
|
||||
/* Default: Do not restore fflags. */
|
||||
#define ARCHIVE_EXTRACT_FFLAGS (0x0040)
|
||||
/* Default: Do not restore xattrs. */
|
||||
#define ARCHIVE_EXTRACT_XATTR (0x0080)
|
||||
/* Default: Do not try to guard against extracts redirected by symlinks. */
|
||||
/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */
|
||||
#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100)
|
||||
/* Default: Do not reject entries with '..' as path elements. */
|
||||
#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200)
|
||||
/* Default: Create parent directories as needed. */
|
||||
#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400)
|
||||
/* Default: Overwrite files, even if one on disk is newer. */
|
||||
#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800)
|
||||
/* Detect blocks of 0 and write holes instead. */
|
||||
#define ARCHIVE_EXTRACT_SPARSE (0x1000)
|
||||
/* Default: Do not restore Mac extended metadata. */
|
||||
/* This has no effect except on Mac OS. */
|
||||
#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000)
|
||||
|
||||
__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *,
|
||||
int flags);
|
||||
__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *,
|
||||
struct archive * /* dest */);
|
||||
__LA_DECL void archive_read_extract_set_progress_callback(struct archive *,
|
||||
void (*_progress_func)(void *), void *_user_data);
|
||||
|
||||
/* Record the dev/ino of a file that will not be written. This is
|
||||
* generally set to the dev/ino of the archive being read. */
|
||||
__LA_DECL void archive_read_extract_set_skip_file(struct archive *,
|
||||
__LA_INT64_T, __LA_INT64_T);
|
||||
|
||||
/* Close the file and release most resources. */
|
||||
__LA_DECL int archive_read_close(struct archive *);
|
||||
/* Release all resources and destroy the object. */
|
||||
/* Note that archive_read_free will call archive_read_close for you. */
|
||||
__LA_DECL int archive_read_free(struct archive *);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Synonym for archive_read_free() for backwards compatibility. */
|
||||
__LA_DECL int archive_read_finish(struct archive *);
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* To create an archive:
|
||||
* 1) Ask archive_write_new for an archive writer object.
|
||||
* 2) Set any global properties. In particular, you should set
|
||||
* the compression and format to use.
|
||||
* 3) Call archive_write_open to open the file (most people
|
||||
* will use archive_write_open_file or archive_write_open_fd,
|
||||
* which provide convenient canned I/O callbacks for you).
|
||||
* 4) For each entry:
|
||||
* - construct an appropriate struct archive_entry structure
|
||||
* - archive_write_header to write the header
|
||||
* - archive_write_data to write the entry data
|
||||
* 5) archive_write_close to close the output
|
||||
* 6) archive_write_free to cleanup the writer and release resources
|
||||
*/
|
||||
__LA_DECL struct archive *archive_write_new(void);
|
||||
__LA_DECL int archive_write_set_bytes_per_block(struct archive *,
|
||||
int bytes_per_block);
|
||||
__LA_DECL int archive_write_get_bytes_per_block(struct archive *);
|
||||
/* XXX This is badly misnamed; suggestions appreciated. XXX */
|
||||
__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *,
|
||||
int bytes_in_last_block);
|
||||
__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *);
|
||||
|
||||
/* The dev/ino of a file that won't be archived. This is used
|
||||
* to avoid recursively adding an archive to itself. */
|
||||
__LA_DECL int archive_write_set_skip_file(struct archive *,
|
||||
__LA_INT64_T, __LA_INT64_T);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
__LA_DECL int archive_write_set_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_compress(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_gzip(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_lzip(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_none(struct archive *);
|
||||
__LA_DECL int archive_write_set_compression_program(struct archive *,
|
||||
const char *cmd);
|
||||
__LA_DECL int archive_write_set_compression_xz(struct archive *);
|
||||
#endif
|
||||
|
||||
__LA_DECL int archive_write_add_filter_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_compress(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_gzip(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_lzip(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_none(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_program(struct archive *,
|
||||
const char *cmd);
|
||||
__LA_DECL int archive_write_add_filter_xz(struct archive *);
|
||||
|
||||
|
||||
/* A convenience function to set the format based on the code or name. */
|
||||
__LA_DECL int archive_write_set_format(struct archive *, int format_code);
|
||||
__LA_DECL int archive_write_set_format_by_name(struct archive *,
|
||||
const char *name);
|
||||
/* To minimize link pollution, use one or more of the following. */
|
||||
__LA_DECL int archive_write_set_format_7zip(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_cpio(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_mtree(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_shar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_shar_dump(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_ustar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_xar(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_zip(struct archive *);
|
||||
__LA_DECL int archive_write_open(struct archive *, void *,
|
||||
archive_open_callback *, archive_write_callback *,
|
||||
archive_close_callback *);
|
||||
__LA_DECL int archive_write_open_fd(struct archive *, int _fd);
|
||||
__LA_DECL int archive_write_open_filename(struct archive *, const char *_file);
|
||||
__LA_DECL int archive_write_open_filename_w(struct archive *,
|
||||
const wchar_t *_file);
|
||||
/* A deprecated synonym for archive_write_open_filename() */
|
||||
__LA_DECL int archive_write_open_file(struct archive *, const char *_file);
|
||||
__LA_DECL int archive_write_open_FILE(struct archive *, FILE *);
|
||||
/* _buffSize is the size of the buffer, _used refers to a variable that
|
||||
* will be updated after each write into the buffer. */
|
||||
__LA_DECL int archive_write_open_memory(struct archive *,
|
||||
void *_buffer, size_t _buffSize, size_t *_used);
|
||||
|
||||
/*
|
||||
* Note that the library will truncate writes beyond the size provided
|
||||
* to archive_write_header or pad if the provided data is short.
|
||||
*/
|
||||
__LA_DECL int archive_write_header(struct archive *,
|
||||
struct archive_entry *);
|
||||
__LA_DECL __LA_SSIZE_T archive_write_data(struct archive *,
|
||||
const void *, size_t);
|
||||
|
||||
/* This interface is currently only available for archive_write_disk handles. */
|
||||
__LA_DECL __LA_SSIZE_T archive_write_data_block(struct archive *,
|
||||
const void *, size_t, __LA_INT64_T);
|
||||
|
||||
__LA_DECL int archive_write_finish_entry(struct archive *);
|
||||
__LA_DECL int archive_write_close(struct archive *);
|
||||
/* This can fail if the archive wasn't already closed, in which case
|
||||
* archive_write_free() will implicitly call archive_write_close(). */
|
||||
__LA_DECL int archive_write_free(struct archive *);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Synonym for archive_write_free() for backwards compatibility. */
|
||||
__LA_DECL int archive_write_finish(struct archive *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set write options.
|
||||
*/
|
||||
/* Apply option to the format only. */
|
||||
__LA_DECL int archive_write_set_format_option(struct archive *_a,
|
||||
const char *m, const char *o,
|
||||
const char *v);
|
||||
/* Apply option to the filter only. */
|
||||
__LA_DECL int archive_write_set_filter_option(struct archive *_a,
|
||||
const char *m, const char *o,
|
||||
const char *v);
|
||||
/* Apply option to both the format and the filter. */
|
||||
__LA_DECL int archive_write_set_option(struct archive *_a,
|
||||
const char *m, const char *o,
|
||||
const char *v);
|
||||
/* Apply option string to both the format and the filter. */
|
||||
__LA_DECL int archive_write_set_options(struct archive *_a,
|
||||
const char *opts);
|
||||
|
||||
/*-
|
||||
* ARCHIVE_WRITE_DISK API
|
||||
*
|
||||
* To create objects on disk:
|
||||
* 1) Ask archive_write_disk_new for a new archive_write_disk object.
|
||||
* 2) Set any global properties. In particular, you probably
|
||||
* want to set the options.
|
||||
* 3) For each entry:
|
||||
* - construct an appropriate struct archive_entry structure
|
||||
* - archive_write_header to create the file/dir/etc on disk
|
||||
* - archive_write_data to write the entry data
|
||||
* 4) archive_write_free to cleanup the writer and release resources
|
||||
*
|
||||
* In particular, you can use this in conjunction with archive_read()
|
||||
* to pull entries out of an archive and create them on disk.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_write_disk_new(void);
|
||||
/* This file will not be overwritten. */
|
||||
__LA_DECL int archive_write_disk_set_skip_file(struct archive *,
|
||||
__LA_INT64_T, __LA_INT64_T);
|
||||
/* Set flags to control how the next item gets created.
|
||||
* This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */
|
||||
__LA_DECL int archive_write_disk_set_options(struct archive *,
|
||||
int flags);
|
||||
/*
|
||||
* The lookup functions are given uname/uid (or gname/gid) pairs and
|
||||
* return a uid (gid) suitable for this system. These are used for
|
||||
* restoring ownership and for setting ACLs. The default functions
|
||||
* are naive, they just return the uid/gid. These are small, so reasonable
|
||||
* for applications that don't need to preserve ownership; they
|
||||
* are probably also appropriate for applications that are doing
|
||||
* same-system backup and restore.
|
||||
*/
|
||||
/*
|
||||
* The "standard" lookup functions use common system calls to lookup
|
||||
* the uname/gname, falling back to the uid/gid if the names can't be
|
||||
* found. They cache lookups and are reasonably fast, but can be very
|
||||
* large, so they are not used unless you ask for them. In
|
||||
* particular, these match the specifications of POSIX "pax" and old
|
||||
* POSIX "tar".
|
||||
*/
|
||||
__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *);
|
||||
/*
|
||||
* If neither the default (naive) nor the standard (big) functions suit
|
||||
* your needs, you can write your own and register them. Be sure to
|
||||
* include a cleanup function if you have allocated private data.
|
||||
*/
|
||||
__LA_DECL int archive_write_disk_set_group_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
__LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
|
||||
void (* /* cleanup */)(void *));
|
||||
__LA_DECL int archive_write_disk_set_user_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
__LA_INT64_T (*)(void *, const char *, __LA_INT64_T),
|
||||
void (* /* cleanup */)(void *));
|
||||
__LA_DECL __LA_INT64_T archive_write_disk_gid(struct archive *, const char *, __LA_INT64_T);
|
||||
__LA_DECL __LA_INT64_T archive_write_disk_uid(struct archive *, const char *, __LA_INT64_T);
|
||||
|
||||
/*
|
||||
* ARCHIVE_READ_DISK API
|
||||
*
|
||||
* This is still evolving and somewhat experimental.
|
||||
*/
|
||||
__LA_DECL struct archive *archive_read_disk_new(void);
|
||||
/* The names for symlink modes here correspond to an old BSD
|
||||
* command-line argument convention: -L, -P, -H */
|
||||
/* Follow all symlinks. */
|
||||
__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *);
|
||||
/* Follow no symlinks. */
|
||||
__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *);
|
||||
/* Follow symlink initially, then not. */
|
||||
__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *);
|
||||
/* TODO: Handle Linux stat32/stat64 ugliness. <sigh> */
|
||||
__LA_DECL int archive_read_disk_entry_from_file(struct archive *,
|
||||
struct archive_entry *, int /* fd */, const struct stat *);
|
||||
/* Look up gname for gid or uname for uid. */
|
||||
/* Default implementations are very, very stupid. */
|
||||
__LA_DECL const char *archive_read_disk_gname(struct archive *, __LA_INT64_T);
|
||||
__LA_DECL const char *archive_read_disk_uname(struct archive *, __LA_INT64_T);
|
||||
/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the
|
||||
* results for performance. */
|
||||
__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *);
|
||||
/* You can install your own lookups if you like. */
|
||||
__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
|
||||
void (* /* cleanup_fn */)(void *));
|
||||
__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *,
|
||||
void * /* private_data */,
|
||||
const char *(* /* lookup_fn */)(void *, __LA_INT64_T),
|
||||
void (* /* cleanup_fn */)(void *));
|
||||
/* Start traversal. */
|
||||
__LA_DECL int archive_read_disk_open(struct archive *, const char *);
|
||||
__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *);
|
||||
/*
|
||||
* Request that current entry be visited. If you invoke it on every
|
||||
* directory, you'll get a physical traversal. This is ignored if the
|
||||
* current entry isn't a directory or a link to a directory. So, if
|
||||
* you invoke this on every returned path, you'll get a full logical
|
||||
* traversal.
|
||||
*/
|
||||
__LA_DECL int archive_read_disk_descend(struct archive *);
|
||||
__LA_DECL int archive_read_disk_current_filesystem(struct archive *);
|
||||
__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *);
|
||||
__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *);
|
||||
/* Request that the access time of the entry visited by travesal be restored. */
|
||||
__LA_DECL int archive_read_disk_set_atime_restored(struct archive *);
|
||||
|
||||
/*
|
||||
* Accessor functions to read/set various information in
|
||||
* the struct archive object:
|
||||
*/
|
||||
|
||||
/* Number of filters in the current filter pipeline. */
|
||||
/* Filter #0 is the one closest to the format, -1 is a synonym for the
|
||||
* last filter, which is always the pseudo-filter that wraps the
|
||||
* client callbacks. */
|
||||
__LA_DECL int archive_filter_count(struct archive *);
|
||||
__LA_DECL __LA_INT64_T archive_filter_bytes(struct archive *, int);
|
||||
__LA_DECL int archive_filter_code(struct archive *, int);
|
||||
__LA_DECL const char * archive_filter_name(struct archive *, int);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* These don't properly handle multiple filters, so are deprecated and
|
||||
* will eventually be removed. */
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */
|
||||
__LA_DECL __LA_INT64_T archive_position_compressed(struct archive *);
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */
|
||||
__LA_DECL __LA_INT64_T archive_position_uncompressed(struct archive *);
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */
|
||||
__LA_DECL const char *archive_compression_name(struct archive *);
|
||||
/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */
|
||||
__LA_DECL int archive_compression(struct archive *);
|
||||
#endif
|
||||
|
||||
__LA_DECL int archive_errno(struct archive *);
|
||||
__LA_DECL const char *archive_error_string(struct archive *);
|
||||
__LA_DECL const char *archive_format_name(struct archive *);
|
||||
__LA_DECL int archive_format(struct archive *);
|
||||
__LA_DECL void archive_clear_error(struct archive *);
|
||||
__LA_DECL void archive_set_error(struct archive *, int _err,
|
||||
const char *fmt, ...) __LA_PRINTF(3, 4);
|
||||
__LA_DECL void archive_copy_error(struct archive *dest,
|
||||
struct archive *src);
|
||||
__LA_DECL int archive_file_count(struct archive *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* These are meaningless outside of this header. */
|
||||
#undef __LA_DECL
|
||||
#undef __LA_GID_T
|
||||
#undef __LA_UID_T
|
||||
|
||||
/* These need to remain defined because they're used in the
|
||||
* callback type definitions. XXX Fix this. This is ugly. XXX */
|
||||
/* #undef __LA_INT64_T */
|
||||
/* #undef __LA_SSIZE_T */
|
||||
|
||||
#endif /* !ARCHIVE_H_INCLUDED */
|
1264
Utilities/cmlibarchive/libarchive/archive_acl.c
Normal file
1264
Utilities/cmlibarchive/libarchive/archive_acl.c
Normal file
File diff suppressed because it is too large
Load Diff
87
Utilities/cmlibarchive/libarchive/archive_acl_private.h
Normal file
87
Utilities/cmlibarchive/libarchive/archive_acl_private.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2010 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_ACL_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_ACL_PRIVATE_H_INCLUDED
|
||||
|
||||
#include "archive_string.h"
|
||||
|
||||
struct archive_acl_entry {
|
||||
struct archive_acl_entry *next;
|
||||
int type; /* E.g., access or default */
|
||||
int tag; /* E.g., user/group/other/mask */
|
||||
int permset; /* r/w/x bits */
|
||||
int id; /* uid/gid for user/group */
|
||||
struct archive_mstring name; /* uname/gname */
|
||||
};
|
||||
|
||||
struct archive_acl {
|
||||
mode_t mode;
|
||||
struct archive_acl_entry *acl_head;
|
||||
struct archive_acl_entry *acl_p;
|
||||
int acl_state; /* See acl_next for details. */
|
||||
wchar_t *acl_text_w;
|
||||
char *acl_text;
|
||||
int acl_types;
|
||||
};
|
||||
|
||||
void archive_acl_clear(struct archive_acl *);
|
||||
void archive_acl_copy(struct archive_acl *, struct archive_acl *);
|
||||
int archive_acl_count(struct archive_acl *, int);
|
||||
int archive_acl_reset(struct archive_acl *, int);
|
||||
int archive_acl_next(struct archive *, struct archive_acl *, int,
|
||||
int *, int *, int *, int *, const char **);
|
||||
|
||||
int archive_acl_add_entry(struct archive_acl *, int, int, int, int, const char *);
|
||||
int archive_acl_add_entry_w_len(struct archive_acl *,
|
||||
int, int, int, int, const wchar_t *, size_t);
|
||||
int archive_acl_add_entry_len(struct archive_acl *,
|
||||
int, int, int, int, const char *, size_t);
|
||||
|
||||
const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int);
|
||||
int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *,
|
||||
struct archive_string_conv *);
|
||||
|
||||
/*
|
||||
* Private ACL parser. This is private because it handles some
|
||||
* very weird formats that clients should not be messing with.
|
||||
* Clients should only deal with their platform-native formats.
|
||||
* Because of the need to support many formats cleanly, new arguments
|
||||
* are likely to get added on a regular basis. Clients who try to use
|
||||
* this interface are likely to be surprised when it changes.
|
||||
*/
|
||||
int archive_acl_parse_w(struct archive_acl *,
|
||||
const wchar_t *, int /* type */);
|
||||
int archive_acl_parse_l(struct archive_acl *,
|
||||
const char *, int /* type */,
|
||||
struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
174
Utilities/cmlibarchive/libarchive/archive_check_magic.c
Normal file
174
Utilities/cmlibarchive/libarchive/archive_check_magic.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2010 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_check_magic.c 201089 2009-12-28 02:20:23Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#include "archive_private.h"
|
||||
|
||||
static void
|
||||
errmsg(const char *m)
|
||||
{
|
||||
size_t s = strlen(m);
|
||||
ssize_t written;
|
||||
|
||||
while (s > 0) {
|
||||
written = write(2, m, strlen(m));
|
||||
if (written <= 0)
|
||||
return;
|
||||
m += written;
|
||||
s -= written;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
diediedie(void)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
|
||||
/* Cause a breakpoint exception */
|
||||
DebugBreak();
|
||||
#endif
|
||||
abort(); /* Terminate the program abnormally. */
|
||||
}
|
||||
|
||||
static const char *
|
||||
state_name(unsigned s)
|
||||
{
|
||||
switch (s) {
|
||||
case ARCHIVE_STATE_NEW: return ("new");
|
||||
case ARCHIVE_STATE_HEADER: return ("header");
|
||||
case ARCHIVE_STATE_DATA: return ("data");
|
||||
case ARCHIVE_STATE_EOF: return ("eof");
|
||||
case ARCHIVE_STATE_CLOSED: return ("closed");
|
||||
case ARCHIVE_STATE_FATAL: return ("fatal");
|
||||
default: return ("??");
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
archive_handle_type_name(unsigned m)
|
||||
{
|
||||
switch (m) {
|
||||
case ARCHIVE_WRITE_MAGIC: return ("archive_write");
|
||||
case ARCHIVE_READ_MAGIC: return ("archive_read");
|
||||
case ARCHIVE_WRITE_DISK_MAGIC: return ("archive_write_disk");
|
||||
case ARCHIVE_READ_DISK_MAGIC: return ("archive_read_disk");
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
write_all_states(char *buff, unsigned int states)
|
||||
{
|
||||
unsigned int lowbit;
|
||||
|
||||
buff[0] = '\0';
|
||||
|
||||
/* A trick for computing the lowest set bit. */
|
||||
while ((lowbit = states & (1 + ~states)) != 0) {
|
||||
states &= ~lowbit; /* Clear the low bit. */
|
||||
strcat(buff, state_name(lowbit));
|
||||
if (states != 0)
|
||||
strcat(buff, "/");
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check magic value and current state.
|
||||
* Magic value mismatches are fatal and result in calls to abort().
|
||||
* State mismatches return ARCHIVE_FATAL.
|
||||
* Otherwise, returns ARCHIVE_OK.
|
||||
*
|
||||
* This is designed to catch serious programming errors that violate
|
||||
* the libarchive API.
|
||||
*/
|
||||
int
|
||||
__archive_check_magic(struct archive *a, unsigned int magic,
|
||||
unsigned int state, const char *function)
|
||||
{
|
||||
char states1[64];
|
||||
char states2[64];
|
||||
const char *handle_type;
|
||||
|
||||
/*
|
||||
* If this isn't some form of archive handle,
|
||||
* then the library user has screwed up so bad that
|
||||
* we don't even have a reliable way to report an error.
|
||||
*/
|
||||
handle_type = archive_handle_type_name(a->magic);
|
||||
|
||||
if (!handle_type) {
|
||||
errmsg("PROGRAMMER ERROR: Function ");
|
||||
errmsg(function);
|
||||
errmsg(" invoked with invalid archive handle.\n");
|
||||
diediedie();
|
||||
}
|
||||
|
||||
if (a->magic != magic) {
|
||||
archive_set_error(a, -1,
|
||||
"PROGRAMMER ERROR: Function '%s' invoked"
|
||||
" on '%s' archive object, which is not supported.",
|
||||
function,
|
||||
handle_type);
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if ((a->state & state) == 0) {
|
||||
/* If we're already FATAL, don't overwrite the error. */
|
||||
if (a->state != ARCHIVE_STATE_FATAL)
|
||||
archive_set_error(a, -1,
|
||||
"INTERNAL ERROR: Function '%s' invoked with"
|
||||
" archive structure in state '%s',"
|
||||
" should be in state '%s'",
|
||||
function,
|
||||
write_all_states(states1, a->state),
|
||||
write_all_states(states2, state));
|
||||
a->state = ARCHIVE_STATE_FATAL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
return ARCHIVE_OK;
|
||||
}
|
78
Utilities/cmlibarchive/libarchive/archive_crc32.h
Normal file
78
Utilities/cmlibarchive/libarchive/archive_crc32.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Joerg Sonnenberger
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_crc32.h 201102 2009-12-28 03:11:36Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When zlib is unavailable, we should still be able to validate
|
||||
* uncompressed zip archives. That requires us to be able to compute
|
||||
* the CRC32 check value. This is a drop-in compatible replacement
|
||||
* for crc32() from zlib. It's slower than the zlib implementation,
|
||||
* but still pretty fast: This runs about 300MB/s on my 3GHz P4
|
||||
* compared to about 800MB/s for the zlib implementation.
|
||||
*/
|
||||
static unsigned long
|
||||
crc32(unsigned long crc, const void *_p, size_t len)
|
||||
{
|
||||
unsigned long crc2, b, i;
|
||||
const unsigned char *p = _p;
|
||||
static volatile int crc_tbl_inited = 0;
|
||||
static unsigned long crc_tbl[256];
|
||||
|
||||
if (!crc_tbl_inited) {
|
||||
for (b = 0; b < 256; ++b) {
|
||||
crc2 = b;
|
||||
for (i = 8; i > 0; --i) {
|
||||
if (crc2 & 1)
|
||||
crc2 = (crc2 >> 1) ^ 0xedb88320UL;
|
||||
else
|
||||
crc2 = (crc2 >> 1);
|
||||
}
|
||||
crc_tbl[b] = crc2;
|
||||
}
|
||||
crc_tbl_inited = 1;
|
||||
}
|
||||
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
/* A use of this loop is about 20% - 30% faster than
|
||||
* no use version in any optimization option of gcc. */
|
||||
for (;len >= 8; len -= 8) {
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
while (len--)
|
||||
crc = crc_tbl[(crc ^ *p++) & 0xff] ^ (crc >> 8);
|
||||
return (crc ^ 0xffffffffUL);
|
||||
}
|
1427
Utilities/cmlibarchive/libarchive/archive_crypto.c
Normal file
1427
Utilities/cmlibarchive/libarchive/archive_crypto.c
Normal file
File diff suppressed because it is too large
Load Diff
376
Utilities/cmlibarchive/libarchive/archive_crypto_private.h
Normal file
376
Utilities/cmlibarchive/libarchive/archive_crypto_private.h
Normal file
@ -0,0 +1,376 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2011 Andres Mejia
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_CRYPTO_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_CRYPTO_PRIVATE_H_INCLUDED
|
||||
|
||||
/*
|
||||
* Crypto support in various Operating Systems:
|
||||
*
|
||||
* NetBSD:
|
||||
* - MD5 and SHA1 in libc: without _ after algorithm name
|
||||
* - SHA2 in libc: with _ after algorithm name
|
||||
*
|
||||
* OpenBSD:
|
||||
* - MD5, SHA1 and SHA2 in libc: without _ after algorithm name
|
||||
* - OpenBSD 4.4 and earlier have SHA2 in libc with _ after algorithm name
|
||||
*
|
||||
* DragonFly and FreeBSD:
|
||||
* - MD5 libmd: without _ after algorithm name
|
||||
* - SHA1, SHA256 and SHA512 in libmd: with _ after algorithm name
|
||||
*
|
||||
* Mac OS X (10.4 and later):
|
||||
* - MD5, SHA1 and SHA2 in libSystem: with CC_ prefix and _ after algorithm name
|
||||
*
|
||||
* OpenSSL:
|
||||
* - MD5, SHA1 and SHA2 in libcrypto: with _ after algorithm name
|
||||
*
|
||||
* Windows:
|
||||
* - MD5, SHA1 and SHA2 in archive_crypto.c using Windows crypto API
|
||||
*/
|
||||
|
||||
/* libc crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
|
||||
#include <md5.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
|
||||
#include <rmd160.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
|
||||
#include <sha1.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
|
||||
#include <sha2.h>
|
||||
#endif
|
||||
|
||||
/* libmd crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBMD) ||\
|
||||
defined(ARCHIVE_CRYPTO_RMD160_LIBMD) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_LIBMD) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
|
||||
#define ARCHIVE_CRYPTO_LIBMD 1
|
||||
#endif
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBMD)
|
||||
#include <md5.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
|
||||
#include <ripemd.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
|
||||
#include <sha.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
|
||||
#include <sha256.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
|
||||
#include <sha512.h>
|
||||
#endif
|
||||
|
||||
/* libSystem crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#endif
|
||||
|
||||
/* Nettle crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_NETTLE)
|
||||
#include <nettle/md5.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
|
||||
#include <nettle/ripemd160.h>
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
|
||||
#include <nettle/sha.h>
|
||||
#endif
|
||||
|
||||
/* OpenSSL crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
|
||||
#define ARCHIVE_CRYPTO_OPENSSL 1
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
/* Windows crypto headers */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
#include <wincrypt.h>
|
||||
typedef struct {
|
||||
int valid;
|
||||
HCRYPTPROV cryptProv;
|
||||
HCRYPTHASH hash;
|
||||
} Digest_CTX;
|
||||
#endif
|
||||
|
||||
/* typedefs */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBC)
|
||||
typedef MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_LIBMD)
|
||||
typedef MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
|
||||
typedef CC_MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
|
||||
typedef struct md5_ctx archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
|
||||
typedef EVP_MD_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
typedef Digest_CTX archive_md5_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_md5_ctx;
|
||||
#endif
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_RMD160_LIBC)
|
||||
typedef RMD160_CTX archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
|
||||
typedef RIPEMD160_CTX archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
|
||||
typedef struct ripemd160_ctx archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
|
||||
typedef EVP_MD_CTX archive_rmd160_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_rmd160_ctx;
|
||||
#endif
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA1_LIBC)
|
||||
typedef SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBMD)
|
||||
typedef SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
|
||||
typedef CC_SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
|
||||
typedef struct sha1_ctx archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
|
||||
typedef EVP_MD_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
typedef Digest_CTX archive_sha1_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha1_ctx;
|
||||
#endif
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA256_LIBC)
|
||||
typedef SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC2)
|
||||
typedef SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBC3)
|
||||
typedef SHA2_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBMD)
|
||||
typedef SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
|
||||
typedef CC_SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
|
||||
typedef struct sha256_ctx archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
|
||||
typedef EVP_MD_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
typedef Digest_CTX archive_sha256_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha256_ctx;
|
||||
#endif
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA384_LIBC)
|
||||
typedef SHA384_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC2)
|
||||
typedef SHA384_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBC3)
|
||||
typedef SHA2_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
|
||||
typedef CC_SHA512_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
|
||||
typedef struct sha384_ctx archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
|
||||
typedef EVP_MD_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
typedef Digest_CTX archive_sha384_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha384_ctx;
|
||||
#endif
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA512_LIBC)
|
||||
typedef SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2)
|
||||
typedef SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3)
|
||||
typedef SHA2_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD)
|
||||
typedef SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
|
||||
typedef CC_SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
|
||||
typedef struct sha512_ctx archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
|
||||
typedef EVP_MD_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
typedef Digest_CTX archive_sha512_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha512_ctx;
|
||||
#endif
|
||||
|
||||
/* defines */
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_MD5_LIBMD) || \
|
||||
defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_MD5_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_MD5_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
#define ARCHIVE_HAS_MD5
|
||||
#endif
|
||||
#define archive_md5_init(ctx)\
|
||||
__archive_crypto.md5init(ctx)
|
||||
#define archive_md5_final(ctx, md)\
|
||||
__archive_crypto.md5final(ctx, md)
|
||||
#define archive_md5_update(ctx, buf, n)\
|
||||
__archive_crypto.md5update(ctx, buf, n)
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_RMD160_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_RMD160_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
|
||||
#define ARCHIVE_HAS_RMD160
|
||||
#endif
|
||||
#define archive_rmd160_init(ctx)\
|
||||
__archive_crypto.rmd160init(ctx)
|
||||
#define archive_rmd160_final(ctx, md)\
|
||||
__archive_crypto.rmd160final(ctx, md)
|
||||
#define archive_rmd160_update(ctx, buf, n)\
|
||||
__archive_crypto.rmd160update(ctx, buf, n)
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA1_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_LIBMD) || \
|
||||
defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
#define ARCHIVE_HAS_SHA1
|
||||
#endif
|
||||
#define archive_sha1_init(ctx)\
|
||||
__archive_crypto.sha1init(ctx)
|
||||
#define archive_sha1_final(ctx, md)\
|
||||
__archive_crypto.sha1final(ctx, md)
|
||||
#define archive_sha1_update(ctx, buf, n)\
|
||||
__archive_crypto.sha1update(ctx, buf, n)
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA256_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBC2) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBC3) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBMD) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
#define ARCHIVE_HAS_SHA256
|
||||
#endif
|
||||
#define archive_sha256_init(ctx)\
|
||||
__archive_crypto.sha256init(ctx)
|
||||
#define archive_sha256_final(ctx, md)\
|
||||
__archive_crypto.sha256final(ctx, md)
|
||||
#define archive_sha256_update(ctx, buf, n)\
|
||||
__archive_crypto.sha256update(ctx, buf, n)
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA384_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBC2) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBC3) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
#define ARCHIVE_HAS_SHA384
|
||||
#endif
|
||||
#define archive_sha384_init(ctx)\
|
||||
__archive_crypto.sha384init(ctx)
|
||||
#define archive_sha384_final(ctx, md)\
|
||||
__archive_crypto.sha384final(ctx, md)
|
||||
#define archive_sha384_update(ctx, buf, n)\
|
||||
__archive_crypto.sha384update(ctx, buf, n)
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_SHA512_LIBC) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBC2) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBC3) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBMD) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_NETTLE) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
#define ARCHIVE_HAS_SHA512
|
||||
#endif
|
||||
#define archive_sha512_init(ctx)\
|
||||
__archive_crypto.sha512init(ctx)
|
||||
#define archive_sha512_final(ctx, md)\
|
||||
__archive_crypto.sha512final(ctx, md)
|
||||
#define archive_sha512_update(ctx, buf, n)\
|
||||
__archive_crypto.sha512update(ctx, buf, n)
|
||||
|
||||
/* Minimal interface to crypto functionality for internal use in libarchive */
|
||||
struct archive_crypto
|
||||
{
|
||||
/* Message Digest */
|
||||
int (*md5init)(archive_md5_ctx *ctx);
|
||||
int (*md5update)(archive_md5_ctx *, const void *, size_t);
|
||||
int (*md5final)(archive_md5_ctx *, void *);
|
||||
int (*rmd160init)(archive_rmd160_ctx *);
|
||||
int (*rmd160update)(archive_rmd160_ctx *, const void *, size_t);
|
||||
int (*rmd160final)(archive_rmd160_ctx *, void *);
|
||||
int (*sha1init)(archive_sha1_ctx *);
|
||||
int (*sha1update)(archive_sha1_ctx *, const void *, size_t);
|
||||
int (*sha1final)(archive_sha1_ctx *, void *);
|
||||
int (*sha256init)(archive_sha256_ctx *);
|
||||
int (*sha256update)(archive_sha256_ctx *, const void *, size_t);
|
||||
int (*sha256final)(archive_sha256_ctx *, void *);
|
||||
int (*sha384init)(archive_sha384_ctx *);
|
||||
int (*sha384update)(archive_sha384_ctx *, const void *, size_t);
|
||||
int (*sha384final)(archive_sha384_ctx *, void *);
|
||||
int (*sha512init)(archive_sha512_ctx *);
|
||||
int (*sha512update)(archive_sha512_ctx *, const void *, size_t);
|
||||
int (*sha512final)(archive_sha512_ctx *, void *);
|
||||
};
|
||||
|
||||
extern const struct archive_crypto __archive_crypto;
|
||||
|
||||
#endif
|
162
Utilities/cmlibarchive/libarchive/archive_endian.h
Normal file
162
Utilities/cmlibarchive/libarchive/archive_endian.h
Normal file
@ -0,0 +1,162 @@
|
||||
/*-
|
||||
* Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
|
||||
* 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 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_endian.h 201085 2009-12-28 02:17:15Z kientzle $
|
||||
*
|
||||
* Borrowed from FreeBSD's <sys/endian.h>
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
/* Note: This is a purely internal header! */
|
||||
/* Do not use this outside of libarchive internal code! */
|
||||
|
||||
#ifndef ARCHIVE_ENDIAN_H_INCLUDED
|
||||
#define ARCHIVE_ENDIAN_H_INCLUDED
|
||||
|
||||
|
||||
/*
|
||||
* Disabling inline keyword for compilers known to choke on it:
|
||||
* - Watcom C++ in C code. (For any version?)
|
||||
* - SGI MIPSpro
|
||||
* - Microsoft Visual C++ 6.0 (supposedly newer versions too)
|
||||
*/
|
||||
#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__)
|
||||
#define inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
|
||||
|
||||
static inline uint16_t
|
||||
archive_be16dec(const void *pp)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
return ((p[0] << 8) | p[1]);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
archive_be32dec(const void *pp)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
archive_be64dec(const void *pp)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
return (((uint64_t)archive_be32dec(p) << 32) | archive_be32dec(p + 4));
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
archive_le16dec(const void *pp)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
return ((p[1] << 8) | p[0]);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
archive_le32dec(const void *pp)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
archive_le64dec(const void *pp)
|
||||
{
|
||||
unsigned char const *p = (unsigned char const *)pp;
|
||||
|
||||
return (((uint64_t)archive_le32dec(p + 4) << 32) | archive_le32dec(p));
|
||||
}
|
||||
|
||||
static inline void
|
||||
archive_be16enc(void *pp, uint16_t u)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)pp;
|
||||
|
||||
p[0] = (u >> 8) & 0xff;
|
||||
p[1] = u & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
archive_be32enc(void *pp, uint32_t u)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)pp;
|
||||
|
||||
p[0] = (u >> 24) & 0xff;
|
||||
p[1] = (u >> 16) & 0xff;
|
||||
p[2] = (u >> 8) & 0xff;
|
||||
p[3] = u & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
archive_be64enc(void *pp, uint64_t u)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)pp;
|
||||
|
||||
archive_be32enc(p, u >> 32);
|
||||
archive_be32enc(p + 4, u & 0xffffffff);
|
||||
}
|
||||
|
||||
static inline void
|
||||
archive_le16enc(void *pp, uint16_t u)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)pp;
|
||||
|
||||
p[0] = u & 0xff;
|
||||
p[1] = (u >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
archive_le32enc(void *pp, uint32_t u)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)pp;
|
||||
|
||||
p[0] = u & 0xff;
|
||||
p[1] = (u >> 8) & 0xff;
|
||||
p[2] = (u >> 16) & 0xff;
|
||||
p[3] = (u >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
archive_le64enc(void *pp, uint64_t u)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)pp;
|
||||
|
||||
archive_le32enc(p, u & 0xffffffff);
|
||||
archive_le32enc(p + 4, u >> 32);
|
||||
}
|
||||
|
||||
#endif
|
148
Utilities/cmlibarchive/libarchive/archive_entry.3
Normal file
148
Utilities/cmlibarchive/libarchive/archive_entry.3
Normal file
@ -0,0 +1,148 @@
|
||||
.\" Copyright (c) 2003-2007 Tim Kientzle
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
|
||||
.\"
|
||||
.Dd Feburary 22, 2010
|
||||
.Dt archive_entry 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_clear ,
|
||||
.Nm archive_entry_clone ,
|
||||
.Nm archive_entry_free ,
|
||||
.Nm archive_entry_new ,
|
||||
.Nd functions for managing archive entry descriptions
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft "struct archive_entry *"
|
||||
.Fn archive_entry_clear "struct archive_entry *"
|
||||
.Ft struct archive_entry *
|
||||
.Fn archive_entry_clone "struct archive_entry *"
|
||||
.Ft void
|
||||
.Fn archive_entry_free "struct archive_entry *"
|
||||
.Ft struct archive_entry *
|
||||
.Fn archive_entry_new "void"
|
||||
.Sh DESCRIPTION
|
||||
These functions create and manipulate data objects that
|
||||
represent entries within an archive.
|
||||
You can think of a
|
||||
.Tn struct archive_entry
|
||||
as a heavy-duty version of
|
||||
.Tn struct stat :
|
||||
it includes everything from
|
||||
.Tn struct stat
|
||||
plus associated pathname, textual group and user names, etc.
|
||||
These objects are used by
|
||||
.Xr libarchive 3
|
||||
to represent the metadata associated with a particular
|
||||
entry in an archive.
|
||||
.Ss Create and Destroy
|
||||
There are functions to allocate, destroy, clear, and copy
|
||||
.Va archive_entry
|
||||
objects:
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_entry_clear
|
||||
Erases the object, resetting all internal fields to the
|
||||
same state as a newly-created object.
|
||||
This is provided to allow you to quickly recycle objects
|
||||
without thrashing the heap.
|
||||
.It Fn archive_entry_clone
|
||||
A deep copy operation; all text fields are duplicated.
|
||||
.It Fn archive_entry_free
|
||||
Releases the
|
||||
.Tn struct archive_entry
|
||||
object.
|
||||
.It Fn archive_entry_new
|
||||
Allocate and return a blank
|
||||
.Tn struct archive_entry
|
||||
object.
|
||||
.El
|
||||
.Ss Function groups
|
||||
Due to high number of functions, the accessor functions can be found in
|
||||
man pages grouped by the purpose.
|
||||
.Bl -tag -width ".Xr archive_entry_perms 3"
|
||||
.It Xr archive_entry_acl 3
|
||||
Access Control List manipulation
|
||||
.It Xr archive_entry_paths 3
|
||||
Path name manipulation
|
||||
.It Xr archive_entry_perms 3
|
||||
User, group and mode manipulation
|
||||
.It Xr archive_entry_stat 3
|
||||
Functions not in the other groups and copying to/from
|
||||
.Vt struct stat .
|
||||
.It Xr archive_entry_time 3
|
||||
Time field manipulation
|
||||
.El
|
||||
.Pp
|
||||
Most of the functions set or read entries in an object.
|
||||
Such functions have one of the following forms:
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_entry_set_XXXX
|
||||
Stores the provided data in the object.
|
||||
In particular, for strings, the pointer is stored,
|
||||
not the referenced string.
|
||||
.It Fn archive_entry_copy_XXXX
|
||||
As above, except that the referenced data is copied
|
||||
into the object.
|
||||
.It Fn archive_entry_XXXX
|
||||
Returns the specified data.
|
||||
In the case of strings, a const-qualified pointer to
|
||||
the string is returned.
|
||||
.El
|
||||
String data can be set or accessed as wide character strings
|
||||
or normal
|
||||
.Va char
|
||||
strings.
|
||||
The functions that use wide character strings are suffixed with
|
||||
.Cm _w .
|
||||
Note that these are different representations of the same data:
|
||||
For example, if you store a narrow string and read the corresponding
|
||||
wide string, the object will transparently convert formats
|
||||
using the current locale.
|
||||
Similarly, if you store a wide string and then store a
|
||||
narrow string for the same data, the previously-set wide string will
|
||||
be discarded in favor of the new data.
|
||||
.Pp
|
||||
.\" .Sh EXAMPLE
|
||||
.\" .Sh RETURN VALUES
|
||||
.\" .Sh ERRORS
|
||||
.Sh SEE ALSO
|
||||
.Xr archive 3 ,
|
||||
.Xr archive_entry_acl 3 ,
|
||||
.Xr archive_entry_paths 3 ,
|
||||
.Xr archive_entry_perms 3 ,
|
||||
.Xr archive_entry_time 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm libarchive
|
||||
library first appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm libarchive
|
||||
library was written by
|
||||
.An Tim Kientzle Aq kientzle@acm.org .
|
||||
.\" .Sh BUGS
|
1651
Utilities/cmlibarchive/libarchive/archive_entry.c
Normal file
1651
Utilities/cmlibarchive/libarchive/archive_entry.c
Normal file
File diff suppressed because it is too large
Load Diff
620
Utilities/cmlibarchive/libarchive/archive_entry.h
Normal file
620
Utilities/cmlibarchive/libarchive/archive_entry.h
Normal file
@ -0,0 +1,620 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2008 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_ENTRY_H_INCLUDED
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3000001
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
* configuration headers (config.h, archive_platform.h, etc.) are
|
||||
* purely internal. Do NOT use HAVE_XXX configuration macros to
|
||||
* control the behavior of this header! If you must conditionalize,
|
||||
* use predefined compiler and/or platform macros.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <time.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Get appropriate definitions of standard POSIX-style types. */
|
||||
/* These should match the types used in 'struct stat' */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define __LA_INT64_T __int64
|
||||
# if defined(__BORLANDC__)
|
||||
# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
|
||||
# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
|
||||
# define __LA_DEV_T dev_t
|
||||
# define __LA_MODE_T mode_t
|
||||
# else
|
||||
# define __LA_UID_T short /* Remove in libarchive 3.2 */
|
||||
# define __LA_GID_T short /* Remove in libarchive 3.2 */
|
||||
# define __LA_DEV_T unsigned int
|
||||
# define __LA_MODE_T unsigned short
|
||||
# endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
# if defined(_SCO_DS)
|
||||
# define __LA_INT64_T long long
|
||||
# else
|
||||
# define __LA_INT64_T int64_t
|
||||
# endif
|
||||
# define __LA_UID_T uid_t /* Remove in libarchive 3.2 */
|
||||
# define __LA_GID_T gid_t /* Remove in libarchive 3.2 */
|
||||
# define __LA_DEV_T dev_t
|
||||
# define __LA_MODE_T mode_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Remove this for libarchive 3.2, since ino_t is no longer used.
|
||||
*/
|
||||
#define __LA_INO_T ino_t
|
||||
|
||||
|
||||
/*
|
||||
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
|
||||
* .lib. The default here assumes you're building a DLL. Only
|
||||
* libarchive source should ever define __LIBARCHIVE_BUILD.
|
||||
*/
|
||||
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
|
||||
# ifdef __LIBARCHIVE_BUILD
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL __attribute__((dllexport)) extern
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllexport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define __LA_DECL
|
||||
# else
|
||||
# define __LA_DECL __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Static libraries on all platforms and shared libraries on non-Windows. */
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Description of an archive entry.
|
||||
*
|
||||
* You can think of this as "struct stat" with some text fields added in.
|
||||
*
|
||||
* TODO: Add "comment", "charset", and possibly other entries that are
|
||||
* supported by "pax interchange" format. However, GNU, ustar, cpio,
|
||||
* and other variants don't support these features, so they're not an
|
||||
* excruciatingly high priority right now.
|
||||
*
|
||||
* TODO: "pax interchange" format allows essentially arbitrary
|
||||
* key/value attributes to be attached to any entry. Supporting
|
||||
* such extensions may make this library useful for special
|
||||
* applications (e.g., a package manager could attach special
|
||||
* package-management attributes to each entry).
|
||||
*/
|
||||
struct archive;
|
||||
struct archive_entry;
|
||||
|
||||
/*
|
||||
* File-type constants. These are returned from archive_entry_filetype()
|
||||
* and passed to archive_entry_set_filetype().
|
||||
*
|
||||
* These values match S_XXX defines on every platform I've checked,
|
||||
* including Windows, AIX, Linux, Solaris, and BSD. They're
|
||||
* (re)defined here because platforms generally don't define the ones
|
||||
* they don't support. For example, Windows doesn't define S_IFLNK or
|
||||
* S_IFBLK. Instead of having a mass of conditional logic and system
|
||||
* checks to define any S_XXX values that aren't supported locally,
|
||||
* I've just defined a new set of such constants so that
|
||||
* libarchive-based applications can manipulate and identify archive
|
||||
* entries properly even if the hosting platform can't store them on
|
||||
* disk.
|
||||
*
|
||||
* These values are also used directly within some portable formats,
|
||||
* such as cpio. If you find a platform that varies from these, the
|
||||
* correct solution is to leave these alone and translate from these
|
||||
* portable values to platform-native values when entries are read from
|
||||
* or written to disk.
|
||||
*/
|
||||
#define AE_IFMT 0170000
|
||||
#define AE_IFREG 0100000
|
||||
#define AE_IFLNK 0120000
|
||||
#define AE_IFSOCK 0140000
|
||||
#define AE_IFCHR 0020000
|
||||
#define AE_IFBLK 0060000
|
||||
#define AE_IFDIR 0040000
|
||||
#define AE_IFIFO 0010000
|
||||
|
||||
/*
|
||||
* Basic object manipulation
|
||||
*/
|
||||
|
||||
__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *);
|
||||
/* The 'clone' function does a deep copy; all of the strings are copied too. */
|
||||
__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_free(struct archive_entry *);
|
||||
__LA_DECL struct archive_entry *archive_entry_new(void);
|
||||
|
||||
/*
|
||||
* This form of archive_entry_new2() will pull character-set
|
||||
* conversion information from the specified archive handle. The
|
||||
* older archive_entry_new(void) form is equivalent to calling
|
||||
* archive_entry_new2(NULL) and will result in the use of an internal
|
||||
* default character-set conversion.
|
||||
*/
|
||||
__LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
|
||||
|
||||
/*
|
||||
* Retrieve fields from an archive_entry.
|
||||
*
|
||||
* There are a number of implicit conversions among these fields. For
|
||||
* example, if a regular string field is set and you read the _w wide
|
||||
* character field, the entry will implicitly convert narrow-to-wide
|
||||
* using the current locale. Similarly, dev values are automatically
|
||||
* updated when you write devmajor or devminor and vice versa.
|
||||
*
|
||||
* In addition, fields can be "set" or "unset." Unset string fields
|
||||
* return NULL, non-string fields have _is_set() functions to test
|
||||
* whether they've been set. You can "unset" a string field by
|
||||
* assigning NULL; non-string fields have _unset() functions to
|
||||
* unset them.
|
||||
*
|
||||
* Note: There is one ambiguity in the above; string fields will
|
||||
* also return NULL when implicit character set conversions fail.
|
||||
* This is usually what you want.
|
||||
*/
|
||||
__LA_DECL time_t archive_entry_atime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_ctime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_fflags(struct archive_entry *,
|
||||
unsigned long * /* set */,
|
||||
unsigned long * /* clear */);
|
||||
__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
|
||||
__LA_DECL __LA_INT64_T archive_entry_gid(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_gname(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
|
||||
__LA_DECL __LA_INT64_T archive_entry_ino(struct archive_entry *);
|
||||
__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *);
|
||||
__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
|
||||
__LA_DECL __LA_INT64_T archive_entry_size(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_size_is_set(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
|
||||
__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 *);
|
||||
|
||||
/*
|
||||
* Set fields in an archive_entry.
|
||||
*
|
||||
* Note: Before libarchive 2.4, there were 'set' and 'copy' versions
|
||||
* of the string setters. 'copy' copied the actual string, 'set' just
|
||||
* stored the pointer. In libarchive 2.4 and later, strings are
|
||||
* always copied.
|
||||
*/
|
||||
|
||||
__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 *);
|
||||
#endif
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
|
||||
unsigned long /* set */, unsigned long /* clear */);
|
||||
/* Returns pointer to start of first invalid token, or NULL if none. */
|
||||
/* Note that all recognized tokens are processed, regardless. */
|
||||
__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
|
||||
const char *);
|
||||
__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
|
||||
const wchar_t *);
|
||||
__LA_DECL void archive_entry_set_gid(struct archive_entry *, __LA_INT64_T);
|
||||
__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T);
|
||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T);
|
||||
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_size(struct archive_entry *, __LA_INT64_T);
|
||||
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_INT64_T);
|
||||
__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 *);
|
||||
/*
|
||||
* Routines to bulk copy fields to/from a platform-native "struct
|
||||
* stat." Libarchive used to just store a struct stat inside of each
|
||||
* archive_entry object, but this created issues when trying to
|
||||
* manipulate archives on systems different than the ones they were
|
||||
* created on.
|
||||
*
|
||||
* TODO: On Linux, provide both stat32 and stat64 versions of these functions.
|
||||
*/
|
||||
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
|
||||
|
||||
/*
|
||||
* Storage for Mac OS-specific AppleDouble metadata information.
|
||||
* Apple-format tar files store a separate binary blob containing
|
||||
* encoded metadata with ACL, extended attributes, etc.
|
||||
* This provides a place to store that blob.
|
||||
*/
|
||||
|
||||
__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *);
|
||||
__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t);
|
||||
|
||||
/*
|
||||
* ACL routines. This used to simply store and return text-format ACL
|
||||
* strings, but that proved insufficient for a number of reasons:
|
||||
* = clients need control over uname/uid and gname/gid mappings
|
||||
* = there are many different ACL text formats
|
||||
* = would like to be able to read/convert archives containing ACLs
|
||||
* on platforms that lack ACL libraries
|
||||
*
|
||||
* This last point, in particular, forces me to implement a reasonably
|
||||
* complete set of ACL support routines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Permission bits.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002
|
||||
#define ARCHIVE_ENTRY_ACL_READ 0x00000004
|
||||
#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008
|
||||
#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010
|
||||
#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010
|
||||
#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020
|
||||
#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020
|
||||
#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080
|
||||
#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100
|
||||
#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400
|
||||
#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800
|
||||
#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000
|
||||
#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000
|
||||
#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000
|
||||
|
||||
#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \
|
||||
(ARCHIVE_ENTRY_ACL_EXECUTE \
|
||||
| ARCHIVE_ENTRY_ACL_WRITE \
|
||||
| ARCHIVE_ENTRY_ACL_READ)
|
||||
|
||||
#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \
|
||||
(ARCHIVE_ENTRY_ACL_EXECUTE \
|
||||
| ARCHIVE_ENTRY_ACL_READ_DATA \
|
||||
| ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \
|
||||
| ARCHIVE_ENTRY_ACL_WRITE_DATA \
|
||||
| ARCHIVE_ENTRY_ACL_ADD_FILE \
|
||||
| ARCHIVE_ENTRY_ACL_APPEND_DATA \
|
||||
| ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \
|
||||
| ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \
|
||||
| ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \
|
||||
| ARCHIVE_ENTRY_ACL_DELETE_CHILD \
|
||||
| ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \
|
||||
| ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \
|
||||
| ARCHIVE_ENTRY_ACL_DELETE \
|
||||
| ARCHIVE_ENTRY_ACL_READ_ACL \
|
||||
| ARCHIVE_ENTRY_ACL_WRITE_ACL \
|
||||
| ARCHIVE_ENTRY_ACL_WRITE_OWNER \
|
||||
| ARCHIVE_ENTRY_ACL_SYNCHRONIZE)
|
||||
|
||||
/*
|
||||
* Inheritance values (NFS4 ACLs only); included in permset.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000
|
||||
#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000
|
||||
|
||||
#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \
|
||||
(ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
|
||||
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS)
|
||||
|
||||
/* We need to be able to specify combinations of these. */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
|
||||
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
|
||||
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
|
||||
| ARCHIVE_ENTRY_ACL_TYPE_DENY \
|
||||
| ARCHIVE_ENTRY_ACL_TYPE_AUDIT \
|
||||
| ARCHIVE_ENTRY_ACL_TYPE_ALARM)
|
||||
|
||||
/* Tag values mimic POSIX.1e */
|
||||
#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */
|
||||
#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */
|
||||
#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */
|
||||
#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */
|
||||
#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */
|
||||
#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */
|
||||
#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */
|
||||
|
||||
/*
|
||||
* Set the ACL by clearing it and adding entries one at a time.
|
||||
* Unlike the POSIX.1e ACL routines, you must specify the type
|
||||
* (access/default) for each entry. Internally, the ACL data is just
|
||||
* a soup of entries. API calls here allow you to retrieve just the
|
||||
* entries of interest. This design (which goes against the spirit of
|
||||
* POSIX.1e) is useful for handling archive formats that combine
|
||||
* default and access information in a single ACL list.
|
||||
*/
|
||||
__LA_DECL void archive_entry_acl_clear(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *,
|
||||
int /* type */, int /* permset */, int /* tag */,
|
||||
int /* qual */, const char * /* name */);
|
||||
__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *,
|
||||
int /* type */, int /* permset */, int /* tag */,
|
||||
int /* qual */, const wchar_t * /* name */);
|
||||
|
||||
/*
|
||||
* To retrieve the ACL, first "reset", then repeatedly ask for the
|
||||
* "next" entry. The want_type parameter allows you to request only
|
||||
* certain types of entries.
|
||||
*/
|
||||
__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */);
|
||||
__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */,
|
||||
int * /* type */, int * /* permset */, int * /* tag */,
|
||||
int * /* qual */, const char ** /* name */);
|
||||
__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */,
|
||||
int * /* type */, int * /* permset */, int * /* tag */,
|
||||
int * /* qual */, const wchar_t ** /* name */);
|
||||
|
||||
/*
|
||||
* Construct a text-format ACL. The flags argument is a bitmask that
|
||||
* can include any of the following:
|
||||
*
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
|
||||
* ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries.
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
|
||||
* each ACL entry. ('star' introduced this for POSIX.1e, this flag
|
||||
* also applies to NFS4.)
|
||||
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
|
||||
* default ACL entry, as used in old Solaris ACLs.
|
||||
*/
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
|
||||
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
|
||||
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
|
||||
int /* flags */);
|
||||
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
|
||||
int /* flags */);
|
||||
|
||||
/* Return a count of entries matching 'want_type' */
|
||||
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
|
||||
|
||||
/* Return an opaque ACL object. */
|
||||
/* There's not yet anything clients can actually do with this... */
|
||||
struct archive_acl;
|
||||
__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *);
|
||||
|
||||
/*
|
||||
* extended attributes
|
||||
*/
|
||||
|
||||
__LA_DECL void archive_entry_xattr_clear(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *,
|
||||
const char * /* name */, const void * /* value */,
|
||||
size_t /* size */);
|
||||
|
||||
/*
|
||||
* To retrieve the xattr list, first "reset", then repeatedly ask for the
|
||||
* "next" entry.
|
||||
*/
|
||||
|
||||
__LA_DECL int archive_entry_xattr_count(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_xattr_reset(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_xattr_next(struct archive_entry *,
|
||||
const char ** /* name */, const void ** /* value */, size_t *);
|
||||
|
||||
/*
|
||||
* sparse
|
||||
*/
|
||||
|
||||
__LA_DECL void archive_entry_sparse_clear(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *,
|
||||
__LA_INT64_T /* offset */, __LA_INT64_T /* length */);
|
||||
|
||||
/*
|
||||
* To retrieve the xattr list, first "reset", then repeatedly ask for the
|
||||
* "next" entry.
|
||||
*/
|
||||
|
||||
__LA_DECL int archive_entry_sparse_count(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_sparse_reset(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_sparse_next(struct archive_entry *,
|
||||
__LA_INT64_T * /* offset */, __LA_INT64_T * /* length */);
|
||||
|
||||
/*
|
||||
* Utility to match up hardlinks.
|
||||
*
|
||||
* The 'struct archive_entry_linkresolver' is a cache of archive entries
|
||||
* for files with multiple links. Here's how to use it:
|
||||
* 1. Create a lookup object with archive_entry_linkresolver_new()
|
||||
* 2. Tell it the archive format you're using.
|
||||
* 3. Hand each archive_entry to archive_entry_linkify().
|
||||
* That function will return 0, 1, or 2 entries that should
|
||||
* be written.
|
||||
* 4. Call archive_entry_linkify(resolver, NULL) until
|
||||
* no more entries are returned.
|
||||
* 5. Call archive_entry_linkresolver_free(resolver) to free resources.
|
||||
*
|
||||
* The entries returned have their hardlink and size fields updated
|
||||
* appropriately. If an entry is passed in that does not refer to
|
||||
* a file with multiple links, it is returned unchanged. The intention
|
||||
* is that you should be able to simply filter all entries through
|
||||
* this machine.
|
||||
*
|
||||
* To make things more efficient, be sure that each entry has a valid
|
||||
* nlinks value. The hardlink cache uses this to track when all links
|
||||
* have been found. If the nlinks value is zero, it will keep every
|
||||
* name in the cache indefinitely, which can use a lot of memory.
|
||||
*
|
||||
* Note that archive_entry_size() is reset to zero if the file
|
||||
* body should not be written to the archive. Pay attention!
|
||||
*/
|
||||
struct archive_entry_linkresolver;
|
||||
|
||||
/*
|
||||
* There are three different strategies for marking hardlinks.
|
||||
* The descriptions below name them after the best-known
|
||||
* formats that rely on each strategy:
|
||||
*
|
||||
* "Old cpio" is the simplest, it always returns any entry unmodified.
|
||||
* As far as I know, only cpio formats use this. Old cpio archives
|
||||
* store every link with the full body; the onus is on the dearchiver
|
||||
* to detect and properly link the files as they are restored.
|
||||
* "tar" is also pretty simple; it caches a copy the first time it sees
|
||||
* any link. Subsequent appearances are modified to be hardlink
|
||||
* references to the first one without any body. Used by all tar
|
||||
* formats, although the newest tar formats permit the "old cpio" strategy
|
||||
* as well. This strategy is very simple for the dearchiver,
|
||||
* and reasonably straightforward for the archiver.
|
||||
* "new cpio" is trickier. It stores the body only with the last
|
||||
* occurrence. The complication is that we might not
|
||||
* see every link to a particular file in a single session, so
|
||||
* there's no easy way to know when we've seen the last occurrence.
|
||||
* The solution here is to queue one link until we see the next.
|
||||
* At the end of the session, you can enumerate any remaining
|
||||
* entries by calling archive_entry_linkify(NULL) and store those
|
||||
* bodies. If you have a file with three links l1, l2, and l3,
|
||||
* you'll get the following behavior if you see all three links:
|
||||
* linkify(l1) => NULL (the resolver stores l1 internally)
|
||||
* linkify(l2) => l1 (resolver stores l2, you write l1)
|
||||
* linkify(l3) => l2, l3 (all links seen, you can write both).
|
||||
* If you only see l1 and l2, you'll get this behavior:
|
||||
* linkify(l1) => NULL
|
||||
* linkify(l2) => l1
|
||||
* linkify(NULL) => l2 (at end, you retrieve remaining links)
|
||||
* As the name suggests, this strategy is used by newer cpio variants.
|
||||
* It's noticeably more complex for the archiver, slightly more complex
|
||||
* for the dearchiver than the tar strategy, but makes it straightforward
|
||||
* to restore a file using any link by simply continuing to scan until
|
||||
* you see a link that is stored with a body. In contrast, the tar
|
||||
* strategy requires you to rescan the archive from the beginning to
|
||||
* correctly extract an arbitrary link.
|
||||
*/
|
||||
|
||||
__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void);
|
||||
__LA_DECL void archive_entry_linkresolver_set_strategy(
|
||||
struct archive_entry_linkresolver *, int /* format_code */);
|
||||
__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
|
||||
__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
|
||||
struct archive_entry **, struct archive_entry **);
|
||||
__LA_DECL struct archive_entry *archive_entry_partial_links(
|
||||
struct archive_entry_linkresolver *res, unsigned int *links);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is meaningless outside of this header. */
|
||||
#undef __LA_DECL
|
||||
|
||||
#endif /* !ARCHIVE_ENTRY_H_INCLUDED */
|
233
Utilities/cmlibarchive/libarchive/archive_entry_acl.3
Normal file
233
Utilities/cmlibarchive/libarchive/archive_entry_acl.3
Normal file
@ -0,0 +1,233 @@
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.Dd February 21, 2010
|
||||
.Dt archive_entry_acl 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_acl_add_entry ,
|
||||
.Nm archive_entry_acl_add_entry_w ,
|
||||
.Nm archive_entry_acl_clear ,
|
||||
.Nm archive_entry_acl_count ,
|
||||
.Nm archive_entry_acl_next ,
|
||||
.Nm archive_entry_acl_next_w ,
|
||||
.Nm archive_entry_acl_reset ,
|
||||
.Nm archive_entry_acl_text_w
|
||||
.Nd functions for manipulating Access Control Lists in archive entry descriptions
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft void
|
||||
.Fo archive_entry_acl_add_entry
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "int type"
|
||||
.Fa "int permset"
|
||||
.Fa "int tag"
|
||||
.Fa "int qualifier"
|
||||
.Fa "const char *name"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo archive_entry_acl_add_entry_w
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "int type"
|
||||
.Fa "int permset"
|
||||
.Fa "int tag"
|
||||
.Fa "int qualifier"
|
||||
.Fa "const wchar_t *name"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fn archive_entry_acl_clear "struct archive_entry *a"
|
||||
.Ft int
|
||||
.Fn archive_entry_acl_count "struct archive_entry *a" "int type"
|
||||
.Ft int
|
||||
.Fo archive_entry_acl_next
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "int type"
|
||||
.Fa "int *ret_type"
|
||||
.Fa "int *ret_permset"
|
||||
.Fa "int *ret_tag"
|
||||
.Fa "int *ret_qual"
|
||||
.Fa "const char **ret_name"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_entry_acl_next_w
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "int type"
|
||||
.Fa "int *ret_type"
|
||||
.Fa "int *ret_permset"
|
||||
.Fa "int *ret_tag"
|
||||
.Fa "int *ret_qual"
|
||||
.Fa "const wchar_t **ret_name"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_entry_acl_reset "struct archive_entry *a" "int type"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags"
|
||||
.\" enum?
|
||||
.Sh DESCRIPTION
|
||||
An
|
||||
.Dq Access Control List
|
||||
is a generalisation of the classic Unix permission system.
|
||||
The ACL interface of
|
||||
.Nm libarchive
|
||||
is derived from the POSIX.1e draft, but restricted to simplify dealing
|
||||
with practical implementations in various Operating Systems and archive formats.
|
||||
.Pp
|
||||
An ACL consists of a number of independent entries.
|
||||
Each entry specifies the permission set as bitmask of basic permissions.
|
||||
Valid permissions are:
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_EXECUTE
|
||||
.It Dv ARCHIVE_ENTRY_ACL_WRITE
|
||||
.It Dv ARCHIVE_ENTRY_ACL_READ
|
||||
.El
|
||||
The permissions correspond to the normal Unix permissions.
|
||||
.Pp
|
||||
The tag specifies the principal to which the permission applies.
|
||||
Valid values are:
|
||||
.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ"
|
||||
.It Dv ARCHIVE_ENTRY_ACL_USER
|
||||
The user specified by the name field.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ
|
||||
The owner of the file.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_GROUP
|
||||
The group specied by the name field.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
||||
The group who owns the file.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_MASK
|
||||
The maximum permissions to be obtained via group permissions.
|
||||
.It Dv ARCHIVE_ENTRY_ACL_OTHER
|
||||
Any principal who doesn't have a user or group entry.
|
||||
.El
|
||||
The principals
|
||||
.Dv ARCHIVE_ENTRY_ACL_USER_OBJ ,
|
||||
.Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_OTHER
|
||||
are equivalent to user, group and other in the classic Unix permission
|
||||
model and specify non-extended ACL entries.
|
||||
.Pp
|
||||
All files have an access ACL
|
||||
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS .
|
||||
This specifies the permissions required for access to the file itself.
|
||||
Directories have an additional ACL
|
||||
.Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT ,
|
||||
which controlls the initial access ACL for newly created directory entries.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_add_entry
|
||||
and
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
add a single ACL entry.
|
||||
For the access ACL and non-extended principals, the classic Unix permissions
|
||||
are updated.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_clear
|
||||
removes all ACL entries and resets the enumeration pointer.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_count
|
||||
counts the ACL entries that have the given type mask.
|
||||
.Fa type
|
||||
can be the bitwise-or of
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT .
|
||||
If
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
is included and at least one extended ACL entry is found,
|
||||
the three non-extened ACLs are added.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_next
|
||||
and
|
||||
.Fn archive_entry_acl_next_w
|
||||
return the next entry of the ACL list.
|
||||
This functions may only be called after
|
||||
.Fn archive_entry_acl_reset
|
||||
has indicated the presence of extended ACL entries.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_reset
|
||||
prepare reading the list of ACL entries with
|
||||
.Fn archive_entry_acl_next
|
||||
or
|
||||
.Fn archive_entry_acl_next_w .
|
||||
The function returns either 0, if no non-extended ACLs are found.
|
||||
In this case, the access permissions should be obtained by
|
||||
.Xr archive_entry_mode 3
|
||||
or set using
|
||||
.Xr chmod 2 .
|
||||
Otherwise, the function returns the same value as
|
||||
.Fn archive_entry_acl_count .
|
||||
.Pp
|
||||
.Fn archive_entry_acl_text_w
|
||||
converts the ACL entries for the given type mask into a wide string.
|
||||
In addition to the normal type flags,
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
|
||||
can be specified to further customize the result.
|
||||
The returned long string is valid until the next call to
|
||||
.Fn archive_entry_acl_clear ,
|
||||
.Fn archive_entry_acl_add_entry ,
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
or
|
||||
.Fn archive_entry_acl_text_w .
|
||||
.Sh RETURN VALUES
|
||||
.Fn archive_entry_acl_count
|
||||
and
|
||||
.Fn archive_entry_acl_reset
|
||||
returns the number of ACL entries that match the given type mask.
|
||||
If the type mask includes
|
||||
.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS
|
||||
and at least one extended ACL entry exists, the three classic Unix
|
||||
permissions are counted.
|
||||
.Pp
|
||||
.Fn archive_entry_acl_next
|
||||
and
|
||||
.Fn archive_entry_acl_next_w
|
||||
return
|
||||
.Dv ARCHIVE_OK
|
||||
on success,
|
||||
.Dv ARCHIVE_EOF
|
||||
if no more ACL entries exist
|
||||
and
|
||||
.Dv ARCHIVE_WARN
|
||||
if
|
||||
.Fn archive_entry_acl_reset
|
||||
has not been called first.
|
||||
.Pp
|
||||
.Fn archive_entry_text_w
|
||||
returns a wide string representation of the ACL entrise matching the
|
||||
given type mask.
|
||||
The returned long string is valid until the next call to
|
||||
.Fn archive_entry_acl_clear ,
|
||||
.Fn archive_entry_acl_add_entry ,
|
||||
.Fn archive_entry_acl_add_entry_w
|
||||
or
|
||||
.Fn archive_entry_acl_text_w .
|
||||
.Sh SEE ALSO
|
||||
.Xr archive 3 ,
|
||||
.Xr archive_entry 3
|
||||
.Sh BUGS
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID
|
||||
and
|
||||
.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT
|
||||
are not documented.
|
75
Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c
Normal file
75
Utilities/cmlibarchive/libarchive/archive_entry_copy_bhfi.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive_private.h"
|
||||
#include "archive_entry.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
|
||||
__inline static void
|
||||
fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
|
||||
{
|
||||
ULARGE_INTEGER utc;
|
||||
|
||||
utc.HighPart = filetime->dwHighDateTime;
|
||||
utc.LowPart = filetime->dwLowDateTime;
|
||||
if (utc.QuadPart >= EPOC_TIME) {
|
||||
utc.QuadPart -= EPOC_TIME;
|
||||
*time = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
|
||||
*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
|
||||
} else {
|
||||
*time = 0;
|
||||
*ns = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_copy_bhfi(struct archive_entry *entry,
|
||||
BY_HANDLE_FILE_INFORMATION *bhfi)
|
||||
{
|
||||
time_t secs;
|
||||
long nsecs;
|
||||
|
||||
fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
|
||||
archive_entry_set_atime(entry, secs, nsecs);
|
||||
fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
|
||||
archive_entry_set_mtime(entry, secs, nsecs);
|
||||
fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
|
||||
archive_entry_set_birthtime(entry, secs, nsecs);
|
||||
archive_entry_set_ctime(entry, secs, nsecs);
|
||||
archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
|
||||
archive_entry_set_ino64(entry, (((int64_t)bhfi->nFileIndexHigh) << 32)
|
||||
+ bhfi->nFileIndexLow);
|
||||
archive_entry_set_nlink(entry, bhfi->nNumberOfLinks);
|
||||
archive_entry_set_size(entry, (((int64_t)bhfi->nFileSizeHigh) << 32)
|
||||
+ bhfi->nFileSizeLow);
|
||||
/* archive_entry_set_mode(entry, st->st_mode); */
|
||||
}
|
||||
#endif
|
79
Utilities/cmlibarchive/libarchive/archive_entry_copy_stat.c
Normal file
79
Utilities/cmlibarchive/libarchive/archive_entry_copy_stat.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_copy_stat.c 189466 2009-03-07 00:52:02Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
|
||||
void
|
||||
archive_entry_copy_stat(struct archive_entry *entry, const struct stat *st)
|
||||
{
|
||||
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
||||
archive_entry_set_atime(entry, st->st_atime, st->st_atimespec.tv_nsec);
|
||||
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctimespec.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_atime(entry, st->st_atime, st->st_atim.tv_nsec);
|
||||
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctim.tv_nsec);
|
||||
archive_entry_set_mtime(entry, st->st_mtime, st->st_mtim.tv_nsec);
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIME_N
|
||||
archive_entry_set_atime(entry, st->st_atime, st->st_atime_n);
|
||||
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_n);
|
||||
archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_n);
|
||||
#elif HAVE_STRUCT_STAT_ST_UMTIME
|
||||
archive_entry_set_atime(entry, st->st_atime, st->st_uatime * 1000);
|
||||
archive_entry_set_ctime(entry, st->st_ctime, st->st_uctime * 1000);
|
||||
archive_entry_set_mtime(entry, st->st_mtime, st->st_umtime * 1000);
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
|
||||
archive_entry_set_atime(entry, st->st_atime, st->st_atime_usec * 1000);
|
||||
archive_entry_set_ctime(entry, st->st_ctime, st->st_ctime_usec * 1000);
|
||||
archive_entry_set_mtime(entry, st->st_mtime, st->st_mtime_usec * 1000);
|
||||
#else
|
||||
archive_entry_set_atime(entry, st->st_atime, 0);
|
||||
archive_entry_set_ctime(entry, st->st_ctime, 0);
|
||||
archive_entry_set_mtime(entry, st->st_mtime, 0);
|
||||
#endif
|
||||
#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
|
||||
archive_entry_set_birthtime(entry, st->st_birthtime, st->st_birthtimespec.tv_nsec);
|
||||
#elif HAVE_STRUCT_STAT_ST_BIRTHTIME
|
||||
archive_entry_set_birthtime(entry, st->st_birthtime, 0);
|
||||
#else
|
||||
archive_entry_unset_birthtime(entry);
|
||||
#endif
|
||||
archive_entry_set_dev(entry, st->st_dev);
|
||||
archive_entry_set_gid(entry, st->st_gid);
|
||||
archive_entry_set_uid(entry, st->st_uid);
|
||||
archive_entry_set_ino(entry, st->st_ino);
|
||||
archive_entry_set_nlink(entry, st->st_nlink);
|
||||
archive_entry_set_rdev(entry, st->st_rdev);
|
||||
archive_entry_set_size(entry, st->st_size);
|
||||
archive_entry_set_mode(entry, st->st_mode);
|
||||
}
|
444
Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c
Normal file
444
Utilities/cmlibarchive/libarchive/archive_entry_link_resolver.c
Normal file
@ -0,0 +1,444 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_link_resolver.c 201100 2009-12-28 03:05:31Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
|
||||
/*
|
||||
* This is mostly a pretty straightforward hash table implementation.
|
||||
* The only interesting bit is the different strategies used to
|
||||
* match up links. These strategies match those used by various
|
||||
* archiving formats:
|
||||
* tar - content stored with first link, remainder refer back to it.
|
||||
* This requires us to match each subsequent link up with the
|
||||
* first appearance.
|
||||
* cpio - Old cpio just stored body with each link, match-ups were
|
||||
* implicit. This is trivial.
|
||||
* new cpio - New cpio only stores body with last link, match-ups
|
||||
* are implicit. This is actually quite tricky; see the notes
|
||||
* below.
|
||||
*/
|
||||
|
||||
/* Users pass us a format code, we translate that into a strategy here. */
|
||||
#define ARCHIVE_ENTRY_LINKIFY_LIKE_TAR 0
|
||||
#define ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE 1
|
||||
#define ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO 2
|
||||
#define ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO 3
|
||||
|
||||
/* Initial size of link cache. */
|
||||
#define links_cache_initial_size 1024
|
||||
|
||||
struct links_entry {
|
||||
struct links_entry *next;
|
||||
struct links_entry *previous;
|
||||
struct archive_entry *canonical;
|
||||
struct archive_entry *entry;
|
||||
size_t hash;
|
||||
unsigned int links; /* # links not yet seen */
|
||||
};
|
||||
|
||||
struct archive_entry_linkresolver {
|
||||
struct links_entry **buckets;
|
||||
struct links_entry *spare;
|
||||
unsigned long number_entries;
|
||||
size_t number_buckets;
|
||||
int strategy;
|
||||
};
|
||||
|
||||
#define NEXT_ENTRY_DEFERRED 1
|
||||
#define NEXT_ENTRY_PARTIAL 2
|
||||
#define NEXT_ENTRY_ALL (NEXT_ENTRY_DEFERRED | NEXT_ENTRY_PARTIAL)
|
||||
|
||||
static struct links_entry *find_entry(struct archive_entry_linkresolver *,
|
||||
struct archive_entry *);
|
||||
static void grow_hash(struct archive_entry_linkresolver *);
|
||||
static struct links_entry *insert_entry(struct archive_entry_linkresolver *,
|
||||
struct archive_entry *);
|
||||
static struct links_entry *next_entry(struct archive_entry_linkresolver *,
|
||||
int);
|
||||
|
||||
struct archive_entry_linkresolver *
|
||||
archive_entry_linkresolver_new(void)
|
||||
{
|
||||
struct archive_entry_linkresolver *res;
|
||||
|
||||
/* Check for positive power-of-two */
|
||||
if (links_cache_initial_size == 0 ||
|
||||
(links_cache_initial_size & (links_cache_initial_size - 1)) != 0)
|
||||
return (NULL);
|
||||
|
||||
res = calloc(1, sizeof(struct archive_entry_linkresolver));
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
res->number_buckets = links_cache_initial_size;
|
||||
res->buckets = calloc(res->number_buckets, sizeof(res->buckets[0]));
|
||||
if (res->buckets == NULL) {
|
||||
free(res);
|
||||
return (NULL);
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res,
|
||||
int fmt)
|
||||
{
|
||||
int fmtbase = fmt & ARCHIVE_FORMAT_BASE_MASK;
|
||||
|
||||
switch (fmtbase) {
|
||||
case ARCHIVE_FORMAT_7ZIP:
|
||||
case ARCHIVE_FORMAT_AR:
|
||||
case ARCHIVE_FORMAT_ZIP:
|
||||
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CPIO:
|
||||
switch (fmt) {
|
||||
case ARCHIVE_FORMAT_CPIO_SVR4_NOCRC:
|
||||
case ARCHIVE_FORMAT_CPIO_SVR4_CRC:
|
||||
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO;
|
||||
break;
|
||||
default:
|
||||
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ARCHIVE_FORMAT_MTREE:
|
||||
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE;
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ISO9660:
|
||||
case ARCHIVE_FORMAT_SHAR:
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
case ARCHIVE_FORMAT_XAR:
|
||||
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_TAR;
|
||||
break;
|
||||
default:
|
||||
res->strategy = ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_linkresolver_free(struct archive_entry_linkresolver *res)
|
||||
{
|
||||
struct links_entry *le;
|
||||
|
||||
if (res == NULL)
|
||||
return;
|
||||
|
||||
while ((le = next_entry(res, NEXT_ENTRY_ALL)) != NULL)
|
||||
archive_entry_free(le->entry);
|
||||
free(res->buckets);
|
||||
free(res);
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_linkify(struct archive_entry_linkresolver *res,
|
||||
struct archive_entry **e, struct archive_entry **f)
|
||||
{
|
||||
struct links_entry *le;
|
||||
struct archive_entry *t;
|
||||
|
||||
*f = NULL; /* Default: Don't return a second entry. */
|
||||
|
||||
if (*e == NULL) {
|
||||
le = next_entry(res, NEXT_ENTRY_DEFERRED);
|
||||
if (le != NULL) {
|
||||
*e = le->entry;
|
||||
le->entry = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If it has only one link, then we're done. */
|
||||
if (archive_entry_nlink(*e) == 1)
|
||||
return;
|
||||
/* Directories, devices never have hardlinks. */
|
||||
if (archive_entry_filetype(*e) == AE_IFDIR
|
||||
|| archive_entry_filetype(*e) == AE_IFBLK
|
||||
|| archive_entry_filetype(*e) == AE_IFCHR)
|
||||
return;
|
||||
|
||||
switch (res->strategy) {
|
||||
case ARCHIVE_ENTRY_LINKIFY_LIKE_TAR:
|
||||
le = find_entry(res, *e);
|
||||
if (le != NULL) {
|
||||
archive_entry_unset_size(*e);
|
||||
archive_entry_copy_hardlink(*e,
|
||||
archive_entry_pathname(le->canonical));
|
||||
} else
|
||||
insert_entry(res, *e);
|
||||
return;
|
||||
case ARCHIVE_ENTRY_LINKIFY_LIKE_MTREE:
|
||||
le = find_entry(res, *e);
|
||||
if (le != NULL) {
|
||||
archive_entry_copy_hardlink(*e,
|
||||
archive_entry_pathname(le->canonical));
|
||||
} else
|
||||
insert_entry(res, *e);
|
||||
return;
|
||||
case ARCHIVE_ENTRY_LINKIFY_LIKE_OLD_CPIO:
|
||||
/* This one is trivial. */
|
||||
return;
|
||||
case ARCHIVE_ENTRY_LINKIFY_LIKE_NEW_CPIO:
|
||||
le = find_entry(res, *e);
|
||||
if (le != NULL) {
|
||||
/*
|
||||
* Put the new entry in le, return the
|
||||
* old entry from le.
|
||||
*/
|
||||
t = *e;
|
||||
*e = le->entry;
|
||||
le->entry = t;
|
||||
/* Make the old entry into a hardlink. */
|
||||
archive_entry_unset_size(*e);
|
||||
archive_entry_copy_hardlink(*e,
|
||||
archive_entry_pathname(le->canonical));
|
||||
/* If we ran out of links, return the
|
||||
* final entry as well. */
|
||||
if (le->links == 0) {
|
||||
*f = le->entry;
|
||||
le->entry = NULL;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If we haven't seen it, tuck it away
|
||||
* for future use.
|
||||
*/
|
||||
le = insert_entry(res, *e);
|
||||
le->entry = *e;
|
||||
*e = NULL;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static struct links_entry *
|
||||
find_entry(struct archive_entry_linkresolver *res,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct links_entry *le;
|
||||
size_t hash, bucket;
|
||||
dev_t dev;
|
||||
int64_t ino;
|
||||
|
||||
/* Free a held entry. */
|
||||
if (res->spare != NULL) {
|
||||
archive_entry_free(res->spare->canonical);
|
||||
archive_entry_free(res->spare->entry);
|
||||
free(res->spare);
|
||||
res->spare = NULL;
|
||||
}
|
||||
|
||||
dev = archive_entry_dev(entry);
|
||||
ino = archive_entry_ino64(entry);
|
||||
hash = (size_t)(dev ^ ino);
|
||||
|
||||
/* Try to locate this entry in the links cache. */
|
||||
bucket = hash & (res->number_buckets - 1);
|
||||
for (le = res->buckets[bucket]; le != NULL; le = le->next) {
|
||||
if (le->hash == hash
|
||||
&& dev == archive_entry_dev(le->canonical)
|
||||
&& ino == archive_entry_ino64(le->canonical)) {
|
||||
/*
|
||||
* Decrement link count each time and release
|
||||
* the entry if it hits zero. This saves
|
||||
* memory and is necessary for detecting
|
||||
* missed links.
|
||||
*/
|
||||
--le->links;
|
||||
if (le->links > 0)
|
||||
return (le);
|
||||
/* Remove it from this hash bucket. */
|
||||
if (le->previous != NULL)
|
||||
le->previous->next = le->next;
|
||||
if (le->next != NULL)
|
||||
le->next->previous = le->previous;
|
||||
if (res->buckets[bucket] == le)
|
||||
res->buckets[bucket] = le->next;
|
||||
res->number_entries--;
|
||||
/* Defer freeing this entry. */
|
||||
res->spare = le;
|
||||
return (le);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct links_entry *
|
||||
next_entry(struct archive_entry_linkresolver *res, int mode)
|
||||
{
|
||||
struct links_entry *le;
|
||||
size_t bucket;
|
||||
|
||||
/* Free a held entry. */
|
||||
if (res->spare != NULL) {
|
||||
archive_entry_free(res->spare->canonical);
|
||||
archive_entry_free(res->spare->entry);
|
||||
free(res->spare);
|
||||
res->spare = NULL;
|
||||
}
|
||||
|
||||
/* Look for next non-empty bucket in the links cache. */
|
||||
for (bucket = 0; bucket < res->number_buckets; bucket++) {
|
||||
for (le = res->buckets[bucket]; le != NULL; le = le->next) {
|
||||
if (le->entry != NULL &&
|
||||
(mode & NEXT_ENTRY_DEFERRED) == 0)
|
||||
continue;
|
||||
if (le->entry == NULL &&
|
||||
(mode & NEXT_ENTRY_PARTIAL) == 0)
|
||||
continue;
|
||||
/* Remove it from this hash bucket. */
|
||||
if (le->next != NULL)
|
||||
le->next->previous = le->previous;
|
||||
if (le->previous != NULL)
|
||||
le->previous->next = le->next;
|
||||
else
|
||||
res->buckets[bucket] = le->next;
|
||||
res->number_entries--;
|
||||
/* Defer freeing this entry. */
|
||||
res->spare = le;
|
||||
return (le);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct links_entry *
|
||||
insert_entry(struct archive_entry_linkresolver *res,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct links_entry *le;
|
||||
size_t hash, bucket;
|
||||
|
||||
/* Add this entry to the links cache. */
|
||||
le = calloc(1, sizeof(struct links_entry));
|
||||
if (le == NULL)
|
||||
return (NULL);
|
||||
le->canonical = archive_entry_clone(entry);
|
||||
|
||||
/* If the links cache is getting too full, enlarge the hash table. */
|
||||
if (res->number_entries > res->number_buckets * 2)
|
||||
grow_hash(res);
|
||||
|
||||
hash = archive_entry_dev(entry) ^ archive_entry_ino64(entry);
|
||||
bucket = hash & (res->number_buckets - 1);
|
||||
|
||||
/* If we could allocate the entry, record it. */
|
||||
if (res->buckets[bucket] != NULL)
|
||||
res->buckets[bucket]->previous = le;
|
||||
res->number_entries++;
|
||||
le->next = res->buckets[bucket];
|
||||
le->previous = NULL;
|
||||
res->buckets[bucket] = le;
|
||||
le->hash = hash;
|
||||
le->links = archive_entry_nlink(entry) - 1;
|
||||
return (le);
|
||||
}
|
||||
|
||||
static void
|
||||
grow_hash(struct archive_entry_linkresolver *res)
|
||||
{
|
||||
struct links_entry *le, **new_buckets;
|
||||
size_t new_size;
|
||||
size_t i, bucket;
|
||||
|
||||
/* Try to enlarge the bucket list. */
|
||||
new_size = res->number_buckets * 2;
|
||||
if (new_size < res->number_buckets)
|
||||
return;
|
||||
new_buckets = calloc(new_size, sizeof(struct links_entry *));
|
||||
|
||||
if (new_buckets == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < res->number_buckets; i++) {
|
||||
while (res->buckets[i] != NULL) {
|
||||
/* Remove entry from old bucket. */
|
||||
le = res->buckets[i];
|
||||
res->buckets[i] = le->next;
|
||||
|
||||
/* Add entry to new bucket. */
|
||||
bucket = le->hash & (new_size - 1);
|
||||
|
||||
if (new_buckets[bucket] != NULL)
|
||||
new_buckets[bucket]->previous = le;
|
||||
le->next = new_buckets[bucket];
|
||||
le->previous = NULL;
|
||||
new_buckets[bucket] = le;
|
||||
}
|
||||
}
|
||||
free(res->buckets);
|
||||
res->buckets = new_buckets;
|
||||
res->number_buckets = new_size;
|
||||
}
|
||||
|
||||
struct archive_entry *
|
||||
archive_entry_partial_links(struct archive_entry_linkresolver *res,
|
||||
unsigned int *links)
|
||||
{
|
||||
struct archive_entry *e;
|
||||
struct links_entry *le;
|
||||
|
||||
/* Free a held entry. */
|
||||
if (res->spare != NULL) {
|
||||
archive_entry_free(res->spare->canonical);
|
||||
archive_entry_free(res->spare->entry);
|
||||
free(res->spare);
|
||||
res->spare = NULL;
|
||||
}
|
||||
|
||||
le = next_entry(res, NEXT_ENTRY_PARTIAL);
|
||||
if (le != NULL) {
|
||||
e = le->canonical;
|
||||
if (links != NULL)
|
||||
*links = le->links;
|
||||
le->canonical = NULL;
|
||||
} else {
|
||||
e = NULL;
|
||||
if (links != NULL)
|
||||
*links = 0;
|
||||
}
|
||||
return (e);
|
||||
}
|
224
Utilities/cmlibarchive/libarchive/archive_entry_linkify.3
Normal file
224
Utilities/cmlibarchive/libarchive/archive_entry_linkify.3
Normal file
@ -0,0 +1,224 @@
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.Dd February 20, 2010
|
||||
.Dt archive_entry_linkify 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_linkresolver ,
|
||||
.Nm archive_entry_linkresolver_new ,
|
||||
.Nm archive_entry_linkresolver_set_strategy ,
|
||||
.Nm archive_entry_linkresolver_free ,
|
||||
.Nm archive_entry_linkify
|
||||
.Nd hardlink resolver functions
|
||||
.Sh LIBRARY
|
||||
.Lb libarchive
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft struct archive_entry_linkresolver *
|
||||
.Fn archive_entry_linkresolver_new void
|
||||
.Ft void
|
||||
.Fo archive_entry_linkresolver_set_strategy
|
||||
.Fa "struct archive_entry_linkresolver *resolver"
|
||||
.Fa "int format"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo archive_entry_linkresolver_free
|
||||
.Fa "struct archive_entry_linkresolver *resolver"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo archive_entry_linkify
|
||||
.Fa "struct archive_entry_linkresolver *resolver"
|
||||
.Fa "struct archive_entry **entry"
|
||||
.Fa "struct archive_entry **sparse"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
Programs that want to create archives have to deal with hardlinks.
|
||||
Hardlinks are handled in different ways by the archive formats.
|
||||
The basic strategies are:
|
||||
.Bl -enum
|
||||
.It
|
||||
Ignore hardlinks and store the body for each reference (old cpio, zip).
|
||||
.It
|
||||
Store the body the first time an inode is seen (ustar, pax).
|
||||
.It
|
||||
Store the body the last time an inode is seen (new cpio).
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
functions help by providing a unified interface and handling the complexity
|
||||
behind the scene.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
functions assume that
|
||||
.Vt archive_entry
|
||||
instances have valid nlinks, inode and device values.
|
||||
The inode and device value is used to match entries.
|
||||
The nlinks value is used to determined if all references have been found and
|
||||
if the internal references can be recycled.
|
||||
.Pp
|
||||
The
|
||||
.Fn archive_entry_linkresolver_new
|
||||
function allocates a new link resolver.
|
||||
The instance can be freed using
|
||||
.Fn archive_entry_linkresolver_free .
|
||||
All deferred entries are flushed and the internal storage is freed.
|
||||
.Pp
|
||||
The
|
||||
.Fn archive_entry_linkresolver_set_strategy
|
||||
function selects the optimal hardlink strategy for the given format.
|
||||
The format code can be obtained from
|
||||
.Xr archive_format 3 .
|
||||
The function can be called more than once, but it is recommended to
|
||||
flush all deferred entries first.
|
||||
.Pp
|
||||
The
|
||||
.Fn archive_entry_linkify
|
||||
function is the core of
|
||||
.Nm .
|
||||
The
|
||||
.Fn entry
|
||||
argument points to the
|
||||
.Vt archive_entry
|
||||
that should be written.
|
||||
Depending on the strategy one of the following actions is taken:
|
||||
.Bl -enum
|
||||
.It
|
||||
For the simple archive formats
|
||||
.Va *entry
|
||||
is left unmodified and
|
||||
.Va *sparse
|
||||
is set to
|
||||
.Dv NULL .
|
||||
.It
|
||||
For tar like archive formats,
|
||||
.Va *sparse
|
||||
is set to
|
||||
.Dv NULL .
|
||||
If
|
||||
.Va *entry
|
||||
is
|
||||
.Dv NULL ,
|
||||
no action is taken.
|
||||
If the hardlink count of
|
||||
.Va *entry
|
||||
is larger than 1 and the file type is a regular file or symbolic link,
|
||||
the internal list is searched for a matching inode.
|
||||
If such an inode is found, the link count is decremented and the file size
|
||||
of
|
||||
.Va *entry
|
||||
is set to 0 to notify that no body should be written.
|
||||
If no such inode is found, a copy of the entry is added to the internal cache
|
||||
with a link count reduced by one.
|
||||
.It
|
||||
For new cpio like archive formats a value for
|
||||
.Va *entry
|
||||
of
|
||||
.Dv NULL
|
||||
is used to flush deferred entries.
|
||||
In that case
|
||||
.Va *entry
|
||||
is set to an arbitrary deferred entry and the entry itself is removed from the
|
||||
internal list.
|
||||
If the internal list is empty,
|
||||
.Va *entry
|
||||
is set to
|
||||
.Dv NULL .
|
||||
In either case,
|
||||
.Va *sparse
|
||||
is set to
|
||||
.Dv NULL
|
||||
and the function returns.
|
||||
If the hardlink count of
|
||||
.Va *entry
|
||||
is one or the file type is a directory or device,
|
||||
.Va *sparse
|
||||
is set to
|
||||
.Dv NULL
|
||||
and no further action is taken.
|
||||
Otherwise, the internal list is searched for a matching inode.
|
||||
If such an inode is not found, the entry is added to the internal list,
|
||||
both
|
||||
.Va *entry
|
||||
and
|
||||
.Va *sparse
|
||||
are set to
|
||||
.Dv NULL
|
||||
and the function returns.
|
||||
If such an inode is found, the link count is decremented.
|
||||
If it remains larger than one, the existing entry on the internal list
|
||||
is swapped with
|
||||
.Va *entry
|
||||
after retaining the link count.
|
||||
The existing entry is returned in
|
||||
.Va *entry .
|
||||
If the link count reached one, the new entry is also removed from the
|
||||
internal list and returned in
|
||||
.Va *sparse .
|
||||
Otherwise
|
||||
.Va *sparse
|
||||
is set to
|
||||
.Dv NULL .
|
||||
.El
|
||||
.Pp
|
||||
The general usage is therefore:
|
||||
.Bl -enum
|
||||
.It
|
||||
For each new archive entry, call
|
||||
.Fn archive_entry_linkify .
|
||||
.It
|
||||
Keep in mind that the entries returned may have a size of 0 now.
|
||||
.It
|
||||
If
|
||||
.Va *entry
|
||||
is not
|
||||
.Dv NULL ,
|
||||
archive it.
|
||||
.It
|
||||
If
|
||||
.Va *sparse
|
||||
is not
|
||||
.Dv NULL ,
|
||||
archive it.
|
||||
.It
|
||||
After all entries have been written to disk, call
|
||||
.Fn archive_entry_linkify
|
||||
with
|
||||
.Va *entry
|
||||
set to
|
||||
.Dv NULL
|
||||
and archive the returned entry as long as it is not
|
||||
.Dv NULL .
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
.Fn archive_entry_linkresolver_new
|
||||
returns
|
||||
.Dv NULL
|
||||
on
|
||||
.Xr malloc 3
|
||||
failures.
|
||||
.Sh SEE ALSO
|
||||
.Xr archive_entry 3
|
88
Utilities/cmlibarchive/libarchive/archive_entry_locale.h
Normal file
88
Utilities/cmlibarchive/libarchive/archive_entry_locale.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Michihiro NAKAJIMA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_ENTRY_LOCALE_H_INCLUDED
|
||||
#define ARCHIVE_ENTRY_LOCALE_H_INCLUDED
|
||||
|
||||
struct archive_entry;
|
||||
struct archive_string_conv;
|
||||
|
||||
/*
|
||||
* Utility functions to set and get entry attributes by translating
|
||||
* character-set. These are designed for use in format readers and writers.
|
||||
*
|
||||
* The return code and interface of these are quite different from other
|
||||
* functions for archive_entry defined in archive_entry.h.
|
||||
* Common return code are:
|
||||
* Return 0 if the string conversion succeeded.
|
||||
* Return -1 if the string conversion failed.
|
||||
*/
|
||||
|
||||
#define archive_entry_gname_l _archive_entry_gname_l
|
||||
int _archive_entry_gname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_hardlink_l _archive_entry_hardlink_l
|
||||
int _archive_entry_hardlink_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_pathname_l _archive_entry_pathname_l
|
||||
int _archive_entry_pathname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_symlink_l _archive_entry_symlink_l
|
||||
int _archive_entry_symlink_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_uname_l _archive_entry_uname_l
|
||||
int _archive_entry_uname_l(struct archive_entry *,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
#define archive_entry_acl_text_l _archive_entry_acl_text_l
|
||||
int _archive_entry_acl_text_l(struct archive_entry *, int,
|
||||
const char **, size_t *, struct archive_string_conv *);
|
||||
|
||||
|
||||
#define archive_entry_copy_gname_l _archive_entry_copy_gname_l
|
||||
int _archive_entry_copy_gname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_hardlink_l _archive_entry_copy_hardlink_l
|
||||
int _archive_entry_copy_hardlink_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_link_l _archive_entry_copy_link_l
|
||||
int _archive_entry_copy_link_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_pathname_l _archive_entry_copy_pathname_l
|
||||
int _archive_entry_copy_pathname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_symlink_l _archive_entry_copy_symlink_l
|
||||
int _archive_entry_copy_symlink_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
#define archive_entry_copy_uname_l _archive_entry_copy_uname_l
|
||||
int _archive_entry_copy_uname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
|
151
Utilities/cmlibarchive/libarchive/archive_entry_paths.3
Normal file
151
Utilities/cmlibarchive/libarchive/archive_entry_paths.3
Normal file
@ -0,0 +1,151 @@
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.Dd February 22, 2010
|
||||
.Dt archive_entry_paths 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_hardlink ,
|
||||
.Nm archive_entry_hardlink_w ,
|
||||
.Nm archive_entry_set_hardlink ,
|
||||
.Nm archive_entry_copy_hardlink ,
|
||||
.Nm archive_entry_copy_hardlink_w ,
|
||||
.Nm archve_entry_update_hardlink_utf8 ,
|
||||
.Nm archive_entry_set_link ,
|
||||
.Nm archive_entry_copy_link ,
|
||||
.Nm archive_entry_copy_link_w ,
|
||||
.Nm archve_entry_update_link_utf8 ,
|
||||
.Nm archive_entry_pathname ,
|
||||
.Nm archive_entry_pathname_w ,
|
||||
.Nm archive_entry_set_pathname ,
|
||||
.Nm archive_entry_copy_pathname ,
|
||||
.Nm archive_entry_copy_pathname_w ,
|
||||
.Nm archve_entry_update_pathname_utf8 ,
|
||||
.Nm archive_entry_sourcepath ,
|
||||
.Nm archive_entry_copy_sourcepath ,
|
||||
.Nm archive_entry_symlink,
|
||||
.Nm archive_entry_symlink_w,
|
||||
.Nm archive_entry_set_symlink ,
|
||||
.Nm archive_entry_copy_symlink ,
|
||||
.Nm archive_entry_copy_symlink_w ,
|
||||
.Nm archve_entry_update_symlink_utf8
|
||||
.Nd functions for manipulating path names in archive entry descriptions
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft const char *
|
||||
.Fn archive_entry_hardlink "struct archive_entry *a"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_hardlink_w "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_hardlink "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_hardlink "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_hardlink_w "struct archive_entry *a "const wchar_t *path"
|
||||
.Ft int
|
||||
.Fn archive_entry_update_hardlink_utf8 "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_link "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_link "struct archive_entry *a" " const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_link_w "struct archive_entry *a" " const wchar_t *path"
|
||||
.Ft int
|
||||
.Fn archive_entry_update_link_utf8 "struct archive_entry *a" " const char *path"
|
||||
.Ft const char *
|
||||
.Fn archive_entry_pathname "struct archive_entry *a"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_pathname_w "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_pathname "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_pathname "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_pathname_w "struct archive_entry *a" "const wchar_t *path"
|
||||
.Ft int
|
||||
.Fn archive_entry_update_pathname_utf8 "struct archive_entry *a" "const char *path"
|
||||
.Ft const char *
|
||||
.Fn archive_entry_sourcepath "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_sourcepath "struct archive_entry *a" "const char *path"
|
||||
.Ft const char *
|
||||
.Fn archive_entry_symlink "struct archive_entry *a"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_symlink_w "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_symlink "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_symlink "struct archive_entry *a" "const char *path"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_symlink_w "struct archive_entry *a" "const wchar_t *path"
|
||||
.Ft int
|
||||
.Fn archive_entry_update_symlink_utf8 "struct archive_entry *a" "const char *path"
|
||||
.Sh DESCRIPTION
|
||||
Path names supported by
|
||||
.Xr archive_entry 3 :
|
||||
.Bl -tag -width "sourcepath" -compact
|
||||
.It hardlink
|
||||
Destination of the hardlink.
|
||||
.It link
|
||||
Update only.
|
||||
For a symlink, update the destination.
|
||||
Otherwise, make the entry a hardlink and alter
|
||||
the destination for that.
|
||||
.It pathname
|
||||
Path in the archive
|
||||
.It sourcepath
|
||||
Path on the disk for use by
|
||||
.Xr archive_read_disk 3 .
|
||||
.It symlink
|
||||
Destination of the symbolic link.
|
||||
.El
|
||||
.Pp
|
||||
Path names can be provided in one of three different ways:
|
||||
.Bl -tag -width "wchar_t *"
|
||||
.It char *
|
||||
Multibyte strings in the current locale.
|
||||
.It wchar_t *
|
||||
Wide character strings in the current locale.
|
||||
The accessor functions are named
|
||||
.Fn XXX_w .
|
||||
.It UTF-8
|
||||
Unicode strings encoded as UTF-8.
|
||||
This are convience functions to update both the multibyte and wide
|
||||
character strings at the same time.
|
||||
.El
|
||||
.Pp
|
||||
The sourcepath is a pure filesystem concept and never stored in an
|
||||
archive directly.
|
||||
.Pp
|
||||
For that reason, it is only available as multibyte string.
|
||||
The link path is a convience function for conditionally setting
|
||||
hardlink or symlink destination.
|
||||
It doesn't have a corresponding get accessor function.
|
||||
.Pp
|
||||
.Fn archive_entry_set_XXX
|
||||
is an alias for
|
||||
.Fn archive_entry_copy_XXX .
|
||||
.Sh SEE ALSO
|
||||
.Xr archive 3 ,
|
||||
.Xr archive_entry 3
|
207
Utilities/cmlibarchive/libarchive/archive_entry_perms.3
Normal file
207
Utilities/cmlibarchive/libarchive/archive_entry_perms.3
Normal file
@ -0,0 +1,207 @@
|
||||
.\" Copyright (c) 2003-2007 Tim Kientzle
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.Dd February 22, 2010
|
||||
.Dt archive_entry_perms 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_gid ,
|
||||
.Nm archive_entry_set_gid ,
|
||||
.Nm archive_entry_uid ,
|
||||
.Nm archive_entry_set_uid ,
|
||||
.Nm archive_entry_perm ,
|
||||
.Nm archive_entry_set_perm ,
|
||||
.Nm archive_entry_strmode ,
|
||||
.Nm archive_entry_uname
|
||||
.Nm archive_entry_uname_w
|
||||
.Nm archive_entry_set_uname ,
|
||||
.Nm archive_entry_copy_uname ,
|
||||
.Nm archive_entry_copy_uname_w ,
|
||||
.Nm archive_entry_update_uname_utf8 ,
|
||||
.Nm archive_entry_gname ,
|
||||
.Nm archive_entry_gname_w ,
|
||||
.Nm archive_entry_set_gname ,
|
||||
.Nm archive_entry_copy_gname ,
|
||||
.Nm archive_entry_copy_gname_w ,
|
||||
.Nm archive_entry_update_gname_utf8 ,
|
||||
.Nm archive_entry_fflags ,
|
||||
.Nm archive_entry_fflags_text ,
|
||||
.Nm archive_entry_set_fflags ,
|
||||
.Nm archive_entry_copy_fflags_text ,
|
||||
.Nm archive_entry_copy_fflags_text_w
|
||||
.Nd functions for manipulating ownership and permissions in archive entry descriptions
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft gid_t
|
||||
.Fn archive_entry_gid "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_gid "struct archive_entry *a" "gid_t gid"
|
||||
.Ft uid_t
|
||||
.Fn archive_entry_uid "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_uid "struct archive_entry *a" "uid_t uid"
|
||||
.Ft mode_t
|
||||
.Fn archive_entry_perm "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_perm "struct archive_entry *a" "mode_t mode"
|
||||
.Ft const char *
|
||||
.Fn archive_entry_strmode "struct archive_entry *a"
|
||||
.Ft const char *
|
||||
.Fn archive_entry_gname "struct archive_entry *a"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_gname_w "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_gname "struct archive_entry *a" "const char *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_gname "struct archive_entry *a" "const char *name"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_gname_w "struct archive_entry *a" "const wchar_t *name"
|
||||
.Ft int
|
||||
.Fn archive_entry_update_gname_utf8 "struct archive_entry *a" "const char *name"
|
||||
.Ft const char *
|
||||
.Fn archive_entry_uname "struct archive_entry *a"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_uname_w "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_uname "struct archive_entry *a" "const char *name"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_uname "struct archive_entry *a" "const char *name"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_uname_w "struct archive_entry *a" "const wchar_t *name"
|
||||
.Ft int
|
||||
.Fn archive_entry_update_uname_utf8 "struct archive_entry *a" "const char *name"
|
||||
.Ft void
|
||||
.Fo archive_entry_fflags
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "unsigned long *set_bits"
|
||||
.Fa "unsigned long *clear_bits"
|
||||
.Fc
|
||||
.Ft const char *
|
||||
.Fn archive_entry_fflags_text "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fo archive_entry_set_fflags
|
||||
.Fa "struct archive_entry *a"
|
||||
.Fa "unsigned long set_bits"
|
||||
.Fa "unsigned long clear_bits"
|
||||
.Fc
|
||||
.Ft const char *
|
||||
.Fn archive_entry_copy_fflags_text "struct archive_entry *a" "const char *text"
|
||||
.Ft const wchar_t *
|
||||
.Fn archive_entry_copy_fflags_text_w "struct archive_entry *a" "const wchar_t *text"
|
||||
.Sh DESCRIPTION
|
||||
.Ss User id, group id and mode
|
||||
The functions
|
||||
.Fn archive_entry_uid ,
|
||||
.Fn archive_entry_gid ,
|
||||
and
|
||||
.Fn archive_entry_perm
|
||||
can be used to extract the user id, group id and permission from the given entry.
|
||||
The corresponding functions
|
||||
.Fn archive_entry_set_uid ,
|
||||
.Fn archive_entry_set_gid ,
|
||||
and
|
||||
.Fn archive_entry_set_perm
|
||||
store the given user id, group id and permission in the entry.
|
||||
The permission is also set as side effect of calling
|
||||
.Fn archive_entry_set_mode .
|
||||
.Pp
|
||||
.Fn archive_entry_strmode
|
||||
returns a string representation of the permission as used by the long mode of
|
||||
.Xr ls 1 .
|
||||
.Ss User and group name
|
||||
User and group names can be provided in one of three different ways:
|
||||
.Bl -tag -width "wchar_t *"
|
||||
.It char *
|
||||
Multibyte strings in the current locale.
|
||||
.It wchar_t *
|
||||
Wide character strings in the current locale.
|
||||
The accessor functions are named
|
||||
.Fn XXX_w .
|
||||
.It UTF-8
|
||||
Unicode strings encoded as UTF-8.
|
||||
This are convience functions to update both the multibyte and wide
|
||||
character strings at the same time.
|
||||
.El
|
||||
.Pp
|
||||
.Fn archive_entry_set_XXX
|
||||
is an alias for
|
||||
.Fn archive_entry_copy_XXX .
|
||||
.Ss File Flags
|
||||
File flags are transparently converted between a bitmap
|
||||
representation and a textual format.
|
||||
For example, if you set the bitmap and ask for text, the library
|
||||
will build a canonical text format.
|
||||
However, if you set a text format and request a text format,
|
||||
you will get back the same text, even if it is ill-formed.
|
||||
If you need to canonicalize a textual flags string, you should first set the
|
||||
text form, then request the bitmap form, then use that to set the bitmap form.
|
||||
Setting the bitmap format will clear the internal text representation
|
||||
and force it to be reconstructed when you next request the text form.
|
||||
.Pp
|
||||
The bitmap format consists of two integers, one containing bits
|
||||
that should be set, the other specifying bits that should be
|
||||
cleared.
|
||||
Bits not mentioned in either bitmap will be ignored.
|
||||
Usually, the bitmap of bits to be cleared will be set to zero.
|
||||
In unusual circumstances, you can force a fully-specified set
|
||||
of file flags by setting the bitmap of flags to clear to the complement
|
||||
of the bitmap of flags to set.
|
||||
(This differs from
|
||||
.Xr fflagstostr 3 ,
|
||||
which only includes names for set bits.)
|
||||
Converting a bitmap to a textual string is a platform-specific
|
||||
operation; bits that are not meaningful on the current platform
|
||||
will be ignored.
|
||||
.Pp
|
||||
The canonical text format is a comma-separated list of flag names.
|
||||
The
|
||||
.Fn archive_entry_copy_fflags_text
|
||||
and
|
||||
.Fn archive_entry_copy_fflags_text_w
|
||||
functions parse the provided text and sets the internal bitmap values.
|
||||
This is a platform-specific operation; names that are not meaningful
|
||||
on the current platform will be ignored.
|
||||
The function returns a pointer to the start of the first name that was not
|
||||
recognized, or NULL if every name was recognized.
|
||||
Note that every name \(em including names that follow an unrecognized
|
||||
name \(em will be evaluated, and the bitmaps will be set to reflect
|
||||
every name that is recognized.
|
||||
(In particular, this differs from
|
||||
.Xr strtofflags 3 ,
|
||||
which stops parsing at the first unrecognized name.)
|
||||
.Sh SEE ALSO
|
||||
.Xr archive 3 ,
|
||||
.Xr archive_entry 3 ,
|
||||
.Xr archive_entry_acl 3 ,
|
||||
.Xr archive_read_disk 3 ,
|
||||
.Xr archive_write_disk 3
|
||||
.Sh BUGS
|
||||
The platform types
|
||||
.Vt uid_t
|
||||
and
|
||||
.Vt gid_t
|
||||
are often 16 or 32 bit wide.
|
||||
In this case it is possible that the ids can not be correctly restored
|
||||
from archives and get truncated.
|
176
Utilities/cmlibarchive/libarchive/archive_entry_private.h
Normal file
176
Utilities/cmlibarchive/libarchive/archive_entry_private.h
Normal file
@ -0,0 +1,176 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_entry_private.h 201096 2009-12-28 02:41:27Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED
|
||||
|
||||
#include "archive_acl_private.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
struct ae_xattr {
|
||||
struct ae_xattr *next;
|
||||
|
||||
char *name;
|
||||
void *value;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct ae_sparse {
|
||||
struct ae_sparse *next;
|
||||
|
||||
int64_t offset;
|
||||
int64_t length;
|
||||
};
|
||||
|
||||
/*
|
||||
* Description of an archive entry.
|
||||
*
|
||||
* Basically, this is a "struct stat" with a few text fields added in.
|
||||
*
|
||||
* TODO: Add "comment", "charset", and possibly other entries
|
||||
* that are supported by "pax interchange" format. However, GNU, ustar,
|
||||
* cpio, and other variants don't support these features, so they're not an
|
||||
* excruciatingly high priority right now.
|
||||
*
|
||||
* TODO: "pax interchange" format allows essentially arbitrary
|
||||
* key/value attributes to be attached to any entry. Supporting
|
||||
* such extensions may make this library useful for special
|
||||
* applications (e.g., a package manager could attach special
|
||||
* package-management attributes to each entry). There are tricky
|
||||
* API issues involved, so this is not going to happen until
|
||||
* there's a real demand for it.
|
||||
*
|
||||
* TODO: Design a good API for handling sparse files.
|
||||
*/
|
||||
struct archive_entry {
|
||||
struct archive *archive;
|
||||
|
||||
/*
|
||||
* Note that ae_stat.st_mode & AE_IFMT can be 0!
|
||||
*
|
||||
* This occurs when the actual file type of the object is not
|
||||
* in the archive. For example, 'tar' archives store
|
||||
* hardlinks without marking the type of the underlying
|
||||
* object.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We have a "struct aest" for holding file metadata rather than just
|
||||
* a "struct stat" because on some platforms the "struct stat" has
|
||||
* fields which are too narrow to hold the range of possible values;
|
||||
* we don't want to lose information if we read an archive and write
|
||||
* out another (e.g., in "tar -cf new.tar @old.tar").
|
||||
*
|
||||
* The "stat" pointer points to some form of platform-specific struct
|
||||
* stat; it is declared as a void * rather than a struct stat * as
|
||||
* some platforms have multiple varieties of stat structures.
|
||||
*/
|
||||
void *stat;
|
||||
int stat_valid; /* Set to 0 whenever a field in aest changes. */
|
||||
|
||||
struct aest {
|
||||
int64_t aest_atime;
|
||||
uint32_t aest_atime_nsec;
|
||||
int64_t aest_ctime;
|
||||
uint32_t aest_ctime_nsec;
|
||||
int64_t aest_mtime;
|
||||
uint32_t aest_mtime_nsec;
|
||||
int64_t aest_birthtime;
|
||||
uint32_t aest_birthtime_nsec;
|
||||
int64_t aest_gid;
|
||||
int64_t aest_ino;
|
||||
uint32_t aest_nlink;
|
||||
uint64_t aest_size;
|
||||
int64_t aest_uid;
|
||||
/*
|
||||
* Because converting between device codes and
|
||||
* major/minor values is platform-specific and
|
||||
* inherently a bit risky, we only do that conversion
|
||||
* lazily. That way, we will do a better job of
|
||||
* preserving information in those cases where no
|
||||
* conversion is actually required.
|
||||
*/
|
||||
int aest_dev_is_broken_down;
|
||||
dev_t aest_dev;
|
||||
dev_t aest_devmajor;
|
||||
dev_t aest_devminor;
|
||||
int aest_rdev_is_broken_down;
|
||||
dev_t aest_rdev;
|
||||
dev_t aest_rdevmajor;
|
||||
dev_t aest_rdevminor;
|
||||
} ae_stat;
|
||||
|
||||
int ae_set; /* bitmap of fields that are currently set */
|
||||
#define AE_SET_HARDLINK 1
|
||||
#define AE_SET_SYMLINK 2
|
||||
#define AE_SET_ATIME 4
|
||||
#define AE_SET_CTIME 8
|
||||
#define AE_SET_MTIME 16
|
||||
#define AE_SET_BIRTHTIME 32
|
||||
#define AE_SET_SIZE 64
|
||||
#define AE_SET_INO 128
|
||||
#define AE_SET_DEV 256
|
||||
|
||||
/*
|
||||
* Use aes here so that we get transparent mbs<->wcs conversions.
|
||||
*/
|
||||
struct archive_mstring ae_fflags_text; /* Text fflags per fflagstostr(3) */
|
||||
unsigned long ae_fflags_set; /* Bitmap fflags */
|
||||
unsigned long ae_fflags_clear;
|
||||
struct archive_mstring ae_gname; /* Name of owning group */
|
||||
struct archive_mstring ae_hardlink; /* Name of target for hardlink */
|
||||
struct archive_mstring ae_pathname; /* Name of entry */
|
||||
struct archive_mstring ae_symlink; /* symlink contents */
|
||||
struct archive_mstring ae_uname; /* Name of owner */
|
||||
|
||||
/* Not used within libarchive; useful for some clients. */
|
||||
struct archive_mstring ae_sourcepath; /* Path this entry is sourced from. */
|
||||
|
||||
void *mac_metadata;
|
||||
size_t mac_metadata_size;
|
||||
|
||||
/* ACL support. */
|
||||
struct archive_acl acl;
|
||||
|
||||
/* extattr support. */
|
||||
struct ae_xattr *xattr_head;
|
||||
struct ae_xattr *xattr_p;
|
||||
|
||||
/* sparse support. */
|
||||
struct ae_sparse *sparse_head;
|
||||
struct ae_sparse *sparse_tail;
|
||||
struct ae_sparse *sparse_p;
|
||||
|
||||
/* Miscellaneous. */
|
||||
char strmode[12];
|
||||
};
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
156
Utilities/cmlibarchive/libarchive/archive_entry_sparse.c
Normal file
156
Utilities/cmlibarchive/libarchive/archive_entry_sparse.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* Copyright (c) 2010-2011 Michihiro NAKAJIMA
|
||||
* 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"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_entry_private.h"
|
||||
|
||||
/*
|
||||
* sparse handling
|
||||
*/
|
||||
|
||||
void
|
||||
archive_entry_sparse_clear(struct archive_entry *entry)
|
||||
{
|
||||
struct ae_sparse *sp;
|
||||
|
||||
while (entry->sparse_head != NULL) {
|
||||
sp = entry->sparse_head->next;
|
||||
free(entry->sparse_head);
|
||||
entry->sparse_head = sp;
|
||||
}
|
||||
entry->sparse_tail = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_sparse_add_entry(struct archive_entry *entry,
|
||||
int64_t offset, int64_t length)
|
||||
{
|
||||
struct ae_sparse *sp;
|
||||
|
||||
if (offset < 0 || length < 0)
|
||||
/* Invalid value */
|
||||
return;
|
||||
if (offset + length < 0 ||
|
||||
offset + length > archive_entry_size(entry))
|
||||
/* A value of "length" parameter is too large. */
|
||||
return;
|
||||
if ((sp = entry->sparse_tail) != NULL) {
|
||||
if (sp->offset + sp->length > offset)
|
||||
/* Invalid value. */
|
||||
return;
|
||||
if (sp->offset + sp->length == offset) {
|
||||
if (sp->offset + sp->length + length < 0)
|
||||
/* A value of "length" parameter is
|
||||
* too large. */
|
||||
return;
|
||||
/* Expand existing sparse block size. */
|
||||
sp->length += length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL)
|
||||
/* XXX Error XXX */
|
||||
return;
|
||||
|
||||
sp->offset = offset;
|
||||
sp->length = length;
|
||||
sp->next = NULL;
|
||||
|
||||
if (entry->sparse_head == NULL)
|
||||
entry->sparse_head = entry->sparse_tail = sp;
|
||||
else {
|
||||
/* Add a new sparse block to the tail of list. */
|
||||
if (entry->sparse_tail != NULL)
|
||||
entry->sparse_tail->next = sp;
|
||||
entry->sparse_tail = sp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* returns number of the sparse entries
|
||||
*/
|
||||
int
|
||||
archive_entry_sparse_count(struct archive_entry *entry)
|
||||
{
|
||||
struct ae_sparse *sp;
|
||||
int count = 0;
|
||||
|
||||
for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
|
||||
count++;
|
||||
|
||||
/*
|
||||
* Sanity check if this entry is exactly sparse.
|
||||
* If amount of sparse blocks is just one and it indicates the whole
|
||||
* file data, we should remove it and return zero.
|
||||
*/
|
||||
if (count == 1) {
|
||||
sp = entry->sparse_head;
|
||||
if (sp->offset == 0 &&
|
||||
sp->length >= archive_entry_size(entry)) {
|
||||
count = 0;
|
||||
archive_entry_sparse_clear(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
int
|
||||
archive_entry_sparse_reset(struct archive_entry * entry)
|
||||
{
|
||||
entry->sparse_p = entry->sparse_head;
|
||||
|
||||
return archive_entry_sparse_count(entry);
|
||||
}
|
||||
|
||||
int
|
||||
archive_entry_sparse_next(struct archive_entry * entry,
|
||||
int64_t *offset, int64_t *length)
|
||||
{
|
||||
if (entry->sparse_p) {
|
||||
*offset = entry->sparse_p->offset;
|
||||
*length = entry->sparse_p->length;
|
||||
|
||||
entry->sparse_p = entry->sparse_p->next;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
*offset = 0;
|
||||
*length = 0;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* end of sparse handling
|
||||
*/
|
272
Utilities/cmlibarchive/libarchive/archive_entry_stat.3
Normal file
272
Utilities/cmlibarchive/libarchive/archive_entry_stat.3
Normal file
@ -0,0 +1,272 @@
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.Dd May 12, 2008
|
||||
.Dt archive_entry 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_stat ,
|
||||
.Nm archive_entry_copy_stat ,
|
||||
.Nm archive_entry_filetype ,
|
||||
.Nm archive_entry_set_filetype ,
|
||||
.Nm archive_entry_mode ,
|
||||
.Nm archive_entry_set_mode ,
|
||||
.Nm archive_entry_size ,
|
||||
.Nm archive_entry_size_is_set ,
|
||||
.Nm archive_entry_set_size ,
|
||||
.Nm archive_entry_unset_size ,
|
||||
.Nm archive_entry_dev ,
|
||||
.Nm archive_entry_set_dev ,
|
||||
.Nm archive_entry_dev_is_set ,
|
||||
.Nm archive_entry_devmajor ,
|
||||
.Nm archive_entry_set_devmajor ,
|
||||
.Nm archive_entry_devminor ,
|
||||
.Nm archive_entry_set_devminor ,
|
||||
.Nm archive_entry_ino ,
|
||||
.Nm archive_entry_set_ino ,
|
||||
.Nm archive_entry_ino_is_set ,
|
||||
.Nm archive_entry_ino64 ,
|
||||
.Nm archive_entry_set_ino64 ,
|
||||
.Nm archive_entry_nlink ,
|
||||
.Nm archive_entry_rdev ,
|
||||
.Nm archive_entry_set_rdev ,
|
||||
.Nm archive_entry_rdevmajor ,
|
||||
.Nm archive_entry_set_rdevmajor ,
|
||||
.Nm archive_entry_rdevminor ,
|
||||
.Nm archive_entry_set_rdevminor ,
|
||||
.Nd accessor functions for manipulating archive entry descriptions
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft const struct stat *
|
||||
.Fn archive_entry_stat "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_copy_stat "struct archive_entry *a" "const struct stat *sb"
|
||||
.Ft mode_t
|
||||
.Fn archive_entry_filetype "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_filetype "struct archive_entry *a" "unsigned int type"
|
||||
.Ft mode_t
|
||||
.Fn archive_entry_mode "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_mode "struct archive_entry *a" "mode_t mode"
|
||||
.Ft int64_t
|
||||
.Fn archive_entry_size "struct archive_entry *a"
|
||||
.Ft int
|
||||
.Fn archive_entry_size_is_set "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_size "struct archive_entry *a" "int64_t size"
|
||||
.Ft void
|
||||
.Fn archive_entry_unset_size "struct archive_entry *a"
|
||||
.Ft dev_t
|
||||
.Fn archive_entry_dev "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_dev "struct archive_entry *a" "dev_t dev"
|
||||
.Ft int
|
||||
.Fn archive_entry_dev_is_set "struct archive_entry *a"
|
||||
.Ft dev_t
|
||||
.Fn archive_entry_devmajor "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_devmajor "struct archive_entry *a" "dev_t major"
|
||||
.Ft dev_t
|
||||
.Fn archive_entry_devminor "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_devminor "struct archive_entry *a" "dev_t minor"
|
||||
.Ft ino_t
|
||||
.Fn archive_entry_ino "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_ino "struct archive_entry *a" "unsigned long ino"
|
||||
.Ft int
|
||||
.Fn archive_entry_ino_is_set "struct archive_entry *a"
|
||||
.Ft int64_t
|
||||
.Fn archive_entry_ino64 "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_ino64 "struct archive_entry *a" "int64_t ino"
|
||||
.Ft unsigned int
|
||||
.Fn archive_entry_nlink "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_nlink "struct archive_entry *a" "unsigned int count"
|
||||
.Ft dev_t
|
||||
.Fn archive_entry_rdev "struct archive_entry *a"
|
||||
.Ft dev_t
|
||||
.Fn archive_entry_rdevmajor "struct archive_entry *a"
|
||||
.Ft dev_t
|
||||
.Fn archive_entry_rdevminor "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_rdev "struct archive_entry *a" "dev_t dev"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_rdevmajor "struct archive_entry *a" "dev_t major"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_rdevminor "struct archive_entry *a" "dev_t minor"
|
||||
.Sh DESCRIPTION
|
||||
.Ss Copying to and from Vt struct stat
|
||||
The function
|
||||
.Fn archive_entry_stat
|
||||
converts the various fields stored in the archive entry to the format
|
||||
used by
|
||||
.Xr stat 2 .
|
||||
The return value remains valid until either
|
||||
.Fn archive_entry_clear
|
||||
or
|
||||
.Fn archive_entry_free
|
||||
is called.
|
||||
It is not affected by calls to the set accessor functions.
|
||||
It currently sets the following values in
|
||||
.Vt struct stat :
|
||||
.Vt st_atime ,
|
||||
.Vt st_ctime ,
|
||||
.Vt st_dev ,
|
||||
.Vt st_gid ,
|
||||
.Vt st_ino ,
|
||||
.Vt st_mode ,
|
||||
.Vt st_mtime ,
|
||||
.Vt st_nlink ,
|
||||
.Vt st_rdev ,
|
||||
.Vt st_size ,
|
||||
.Vt st_uid .
|
||||
In addition,
|
||||
.Vt st_birthtime
|
||||
and high-precision information for time-related fields
|
||||
will be included on platforms that support it.
|
||||
.Pp
|
||||
The function
|
||||
.Fn archive_entry_copy_stat
|
||||
copies fields from the platform's
|
||||
.Vt struct stat .
|
||||
Fields not provided by
|
||||
.Vt struct stat
|
||||
are unchanged.
|
||||
.Ss General accessor functions
|
||||
The functions
|
||||
.Fn archive_entry_filetype
|
||||
and
|
||||
.Fn archive_entry_set_filetype
|
||||
get respectively set the filetype.
|
||||
The file type is one of the following constants:
|
||||
.Bl -tag -width "AE_IFSOCK" -compact -offset indent
|
||||
.It AE_IFREG
|
||||
Regular file
|
||||
.It AE_IFLNK
|
||||
Symbolic link
|
||||
.It AE_IFSOCK
|
||||
Socket
|
||||
.It AE_IFCHR
|
||||
Character device
|
||||
.It AE_IFBLK
|
||||
Block device
|
||||
.It AE_IFDIR
|
||||
Directory
|
||||
.It AE_IFIFO
|
||||
Named pipe (fifo)
|
||||
.El
|
||||
Not all file types are supported by all platforms.
|
||||
The constants used by
|
||||
.Xr stat 2
|
||||
may have different numeric values from the
|
||||
corresponding constants above.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn archive_entry_mode
|
||||
and
|
||||
.Fn archive_entry_set_mode
|
||||
get/set a combination of file type and permissions and provide the
|
||||
equivalent of
|
||||
.Va st_mode .
|
||||
Use of
|
||||
.Fn archive_entry_filetype
|
||||
and
|
||||
.Fn archive_entry_perm
|
||||
for getting and
|
||||
.Fn archive_entry_set_filetype
|
||||
and
|
||||
.Fn archive_entry_set_perm
|
||||
for setting is recommended.
|
||||
.Pp
|
||||
The function
|
||||
.Fn archive_entry_size
|
||||
returns the file size, if it has been set, and 0 otherwise.
|
||||
.Fn archive_entry_size
|
||||
can be used to query that status.
|
||||
.Fn archive_entry_set_size
|
||||
and
|
||||
.Fn archive_entry_unset_size
|
||||
set and unset the size, respectively.
|
||||
.Pp
|
||||
The number of references (hardlinks) can be obtained by calling
|
||||
.Fn archive_entry_nlinks
|
||||
and set with
|
||||
.Fn archive_entry_set_nlinks .
|
||||
.Ss Identifying unique files
|
||||
The functions
|
||||
.Fn archive_entry_dev
|
||||
and
|
||||
.Fn archive_entry_ino64
|
||||
are used by
|
||||
.Xr archive_entry_linkify 3
|
||||
to find hardlinks.
|
||||
The pair of device and inode is suppossed to identify hardlinked files.
|
||||
.Pp
|
||||
The device major and minor number can be obtained independently using
|
||||
.Fn archive_entry_devmajor
|
||||
and
|
||||
.Fn archive_entry_devminor .
|
||||
The device can be set either via
|
||||
.Fn archive_entry_set_dev
|
||||
or by the combination of major and minor number using
|
||||
.Fn archive_entry_set_devmajor
|
||||
and
|
||||
.Fn archive_entry_set_devminor .
|
||||
.Pp
|
||||
The inode number can be obtained using
|
||||
.Fn archive_entry_ino .
|
||||
This is a legacy interface that uses the platform
|
||||
.Vt ino_t ,
|
||||
which may be very small.
|
||||
To set the inode number,
|
||||
.Fn archive_entry_set_ino64
|
||||
is the preferred interface.
|
||||
.Ss Accessor functions for block and character devices
|
||||
Block and character devices are characterised either using a device number
|
||||
or a pair of major and minor number.
|
||||
The combined device number can be obtained with
|
||||
.Fn archive_device_rdev
|
||||
and set with
|
||||
.Fn archive_device_set_rdev .
|
||||
The major and minor numbers are accessed by
|
||||
.Fn archive_device_rdevmajor ,
|
||||
.Fn archive_device_rdevminor
|
||||
.Fn archive_device_set_rdevmajor
|
||||
and
|
||||
.Fn archive_device_set_rdevminor .
|
||||
.Pp
|
||||
The process of splitting the combined device number into major and
|
||||
minor number and the reverse process of combing them differs between
|
||||
platforms.
|
||||
Some archive formats use the combined form, while other formats use
|
||||
the split form.
|
||||
.Sh SEE ALSO
|
||||
.Xr archive 3 ,
|
||||
.Xr archive_entry_acl 3 ,
|
||||
.Xr archive_entry_perms 3 ,
|
||||
.Xr archive_entry_time 3 ,
|
||||
.Xr stat 2
|
118
Utilities/cmlibarchive/libarchive/archive_entry_stat.c
Normal file
118
Utilities/cmlibarchive/libarchive/archive_entry_stat.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_stat.c 201100 2009-12-28 03:05:31Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_private.h"
|
||||
|
||||
const struct stat *
|
||||
archive_entry_stat(struct archive_entry *entry)
|
||||
{
|
||||
struct stat *st;
|
||||
if (entry->stat == NULL) {
|
||||
entry->stat = calloc(1, sizeof(*st));
|
||||
if (entry->stat == NULL)
|
||||
return (NULL);
|
||||
entry->stat_valid = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If none of the underlying fields have been changed, we
|
||||
* don't need to regenerate. In theory, we could use a bitmap
|
||||
* here to flag only those items that have changed, but the
|
||||
* extra complexity probably isn't worth it. It will be very
|
||||
* rare for anyone to change just one field then request a new
|
||||
* stat structure.
|
||||
*/
|
||||
if (entry->stat_valid)
|
||||
return (entry->stat);
|
||||
|
||||
st = entry->stat;
|
||||
/*
|
||||
* Use the public interfaces to extract items, so that
|
||||
* the appropriate conversions get invoked.
|
||||
*/
|
||||
st->st_atime = archive_entry_atime(entry);
|
||||
#if HAVE_STRUCT_STAT_ST_BIRTHTIME
|
||||
st->st_birthtime = archive_entry_birthtime(entry);
|
||||
#endif
|
||||
st->st_ctime = archive_entry_ctime(entry);
|
||||
st->st_mtime = archive_entry_mtime(entry);
|
||||
st->st_dev = archive_entry_dev(entry);
|
||||
st->st_gid = archive_entry_gid(entry);
|
||||
st->st_uid = archive_entry_uid(entry);
|
||||
st->st_ino = archive_entry_ino64(entry);
|
||||
st->st_nlink = archive_entry_nlink(entry);
|
||||
st->st_rdev = archive_entry_rdev(entry);
|
||||
st->st_size = archive_entry_size(entry);
|
||||
st->st_mode = archive_entry_mode(entry);
|
||||
|
||||
/*
|
||||
* On systems that support high-res timestamps, copy that
|
||||
* information into struct stat.
|
||||
*/
|
||||
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
||||
st->st_atimespec.tv_nsec = archive_entry_atime_nsec(entry);
|
||||
st->st_ctimespec.tv_nsec = archive_entry_ctime_nsec(entry);
|
||||
st->st_mtimespec.tv_nsec = archive_entry_mtime_nsec(entry);
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
st->st_atim.tv_nsec = archive_entry_atime_nsec(entry);
|
||||
st->st_ctim.tv_nsec = archive_entry_ctime_nsec(entry);
|
||||
st->st_mtim.tv_nsec = archive_entry_mtime_nsec(entry);
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIME_N
|
||||
st->st_atime_n = archive_entry_atime_nsec(entry);
|
||||
st->st_ctime_n = archive_entry_ctime_nsec(entry);
|
||||
st->st_mtime_n = archive_entry_mtime_nsec(entry);
|
||||
#elif HAVE_STRUCT_STAT_ST_UMTIME
|
||||
st->st_uatime = archive_entry_atime_nsec(entry) / 1000;
|
||||
st->st_uctime = archive_entry_ctime_nsec(entry) / 1000;
|
||||
st->st_umtime = archive_entry_mtime_nsec(entry) / 1000;
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
|
||||
st->st_atime_usec = archive_entry_atime_nsec(entry) / 1000;
|
||||
st->st_ctime_usec = archive_entry_ctime_nsec(entry) / 1000;
|
||||
st->st_mtime_usec = archive_entry_mtime_nsec(entry) / 1000;
|
||||
#endif
|
||||
#if HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
|
||||
st->st_birthtimespec.tv_nsec = archive_entry_birthtime_nsec(entry);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO: On Linux, store 32 or 64 here depending on whether
|
||||
* the cached stat structure is a stat32 or a stat64. This
|
||||
* will allow us to support both variants interchangably.
|
||||
*/
|
||||
entry->stat_valid = 1;
|
||||
|
||||
return (st);
|
||||
}
|
87
Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
Normal file
87
Utilities/cmlibarchive/libarchive/archive_entry_strmode.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: src/lib/libarchive/archive_entry_strmode.c,v 1.4 2008/06/15 05:14:01 kientzle Exp $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive_entry.h"
|
||||
#include "archive_entry_private.h"
|
||||
|
||||
const char *
|
||||
archive_entry_strmode(struct archive_entry *entry)
|
||||
{
|
||||
static const mode_t permbits[] =
|
||||
{ 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 };
|
||||
char *bp = entry->strmode;
|
||||
mode_t mode;
|
||||
int i;
|
||||
|
||||
/* Fill in a default string, then selectively override. */
|
||||
strcpy(bp, "?rwxrwxrwx ");
|
||||
|
||||
mode = archive_entry_mode(entry);
|
||||
switch (archive_entry_filetype(entry)) {
|
||||
case AE_IFREG: bp[0] = '-'; break;
|
||||
case AE_IFBLK: bp[0] = 'b'; break;
|
||||
case AE_IFCHR: bp[0] = 'c'; break;
|
||||
case AE_IFDIR: bp[0] = 'd'; break;
|
||||
case AE_IFLNK: bp[0] = 'l'; break;
|
||||
case AE_IFSOCK: bp[0] = 's'; break;
|
||||
case AE_IFIFO: bp[0] = 'p'; break;
|
||||
default:
|
||||
if (archive_entry_hardlink(entry) != NULL) {
|
||||
bp[0] = 'h';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
if (!(mode & permbits[i]))
|
||||
bp[i+1] = '-';
|
||||
|
||||
if (mode & S_ISUID) {
|
||||
if (mode & 0100) bp[3] = 's';
|
||||
else bp[3] = 'S';
|
||||
}
|
||||
if (mode & S_ISGID) {
|
||||
if (mode & 0010) bp[6] = 's';
|
||||
else bp[6] = 'S';
|
||||
}
|
||||
if (mode & S_ISVTX) {
|
||||
if (mode & 0001) bp[9] = 't';
|
||||
else bp[9] = 'T';
|
||||
}
|
||||
if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS))
|
||||
bp[10] = '+';
|
||||
|
||||
return (bp);
|
||||
}
|
127
Utilities/cmlibarchive/libarchive/archive_entry_time.3
Normal file
127
Utilities/cmlibarchive/libarchive/archive_entry_time.3
Normal file
@ -0,0 +1,127 @@
|
||||
.\" Copyright (c) 2003-2007 Tim Kientzle
|
||||
.\" Copyright (c) 2010 Joerg Sonnenberger
|
||||
.\" 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 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: src/lib/libarchive/archive_entry.3,v 1.18 2008/05/26 17:00:22 kientzle Exp $
|
||||
.\"
|
||||
.Dd February 21, 2010
|
||||
.Dt archive_entry_time 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_atime ,
|
||||
.Nm archive_entry_atime_nsec ,
|
||||
.Nm archive_entry_atime_is_set ,
|
||||
.Nm archive_entry_set_atime ,
|
||||
.Nm archive_entry_unset_atime ,
|
||||
.Nm archive_entry_birthtime ,
|
||||
.Nm archive_entry_birthtime_nsec ,
|
||||
.Nm archive_entry_birthtime_is_set ,
|
||||
.Nm archive_entry_set_birthtime ,
|
||||
.Nm archive_entry_unset_birthtime ,
|
||||
.Nm archive_entry_ctime ,
|
||||
.Nm archive_entry_ctime_nsec ,
|
||||
.Nm archive_entry_ctime_is_set ,
|
||||
.Nm archive_entry_set_ctime ,
|
||||
.Nm archive_entry_unset_ctime ,
|
||||
.Nm archive_entry_mtime ,
|
||||
.Nm archive_entry_mtime_nsec ,
|
||||
.Nm archive_entry_mtime_is_set ,
|
||||
.Nm archive_entry_set_mtime ,
|
||||
.Nm archive_entry_unset_mtime ,
|
||||
.Nd functions for manipulating times in archive entry descriptions
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft time_t
|
||||
.Fn archive_entry_atime "struct archive_entry *a"
|
||||
.Ft long
|
||||
.Fn archive_entry_atime_nsec "struct archive_entry *a"
|
||||
.Ft int
|
||||
.Fn archive_entry_atime_is_set "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_atime "struct archive_entry *a" "time_t sec" "long nanosec"
|
||||
.Ft void
|
||||
.Fn archive_entry_unset_atime "struct archive_entry *a"
|
||||
.Ft time_t
|
||||
.Fn archive_entry_birthtime "struct archive_entry *a"
|
||||
.Ft long
|
||||
.Fn archive_entry_birthtime_nsec "struct archive_entry *a"
|
||||
.Ft int
|
||||
.Fn archive_entry_birthtime_is_set "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_birthtime "struct archive_entry *a" "time_t sec" "long nanosec"
|
||||
.Ft void
|
||||
.Fn archive_entry_unset_birthtime "struct archive_entry *a"
|
||||
.Ft time_t
|
||||
.Fn archive_entry_ctime "struct archive_entry *a"
|
||||
.Ft long
|
||||
.Fn archive_entry_ctime_nsec "struct archive_entry *a"
|
||||
.Ft int
|
||||
.Fn archive_entry_ctime_is_set "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_ctime "struct archive_entry *a" "time_t sec" "long nanosec"
|
||||
.Ft void
|
||||
.Fn archive_entry_unset_ctime "struct archive_entry *a"
|
||||
.Ft time_t
|
||||
.Fn archive_entry_mtime "struct archive_entry *a"
|
||||
.Ft long
|
||||
.Fn archive_entry_mtime_nsec "struct archive_entry *a"
|
||||
.Ft int
|
||||
.Fn archive_entry_mtime_is_set "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_mtime "struct archive_entry *a" "time_t sec" "long nanosec"
|
||||
.Ft void
|
||||
.Fn archive_entry_unset_mtime "struct archive_entry *a"
|
||||
.Sh DESCRIPTION
|
||||
These functions create and manipulate the time fields in an
|
||||
.Vt archive_entry .
|
||||
Supported time fields are atime (access time), birthtime (creation time),
|
||||
ctime (last time an inode property was changed) and mtime (modification time).
|
||||
.Pp
|
||||
.Xr libarchive 3
|
||||
provides a high-resolution interface.
|
||||
The timestamps are truncated automatically depending on the archive format
|
||||
(for archiving) or the filesystem capabilities (for restoring).
|
||||
.Pp
|
||||
All timestamp fields are optional.
|
||||
The
|
||||
.Fn XXX_unset
|
||||
functions can be used to mark the corresponding field as missing.
|
||||
The current state can be queried using
|
||||
.Fn XXX_is_set .
|
||||
Unset time fields have a second and nanosecond field of 0.
|
||||
.Sh SEE ALSO
|
||||
.Xr archive 3 ,
|
||||
.Xr archive_entry 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm libarchive
|
||||
library first appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm libarchive
|
||||
library was written by
|
||||
.An Tim Kientzle Aq kientzle@acm.org .
|
||||
.\" .Sh BUGS
|
158
Utilities/cmlibarchive/libarchive/archive_entry_xattr.c
Normal file
158
Utilities/cmlibarchive/libarchive/archive_entry_xattr.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_entry_xattr.c 201096 2009-12-28 02:41:27Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_FS_H
|
||||
#include <linux/fs.h> /* for Linux file flags */
|
||||
#endif
|
||||
/*
|
||||
* Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
|
||||
* As the include guards don't agree, the order of include is important.
|
||||
*/
|
||||
#ifdef HAVE_LINUX_EXT2_FS_H
|
||||
#include <linux/ext2_fs.h> /* for Linux file flags */
|
||||
#endif
|
||||
#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
|
||||
#include <ext2fs/ext2_fs.h> /* for Linux file flags */
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_WCHAR_H
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_entry_private.h"
|
||||
|
||||
/*
|
||||
* extended attribute handling
|
||||
*/
|
||||
|
||||
void
|
||||
archive_entry_xattr_clear(struct archive_entry *entry)
|
||||
{
|
||||
struct ae_xattr *xp;
|
||||
|
||||
while (entry->xattr_head != NULL) {
|
||||
xp = entry->xattr_head->next;
|
||||
free(entry->xattr_head->name);
|
||||
free(entry->xattr_head->value);
|
||||
free(entry->xattr_head);
|
||||
entry->xattr_head = xp;
|
||||
}
|
||||
|
||||
entry->xattr_head = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_xattr_add_entry(struct archive_entry *entry,
|
||||
const char *name, const void *value, size_t size)
|
||||
{
|
||||
struct ae_xattr *xp;
|
||||
|
||||
for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
|
||||
;
|
||||
|
||||
if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL)
|
||||
/* XXX Error XXX */
|
||||
return;
|
||||
|
||||
xp->name = strdup(name);
|
||||
if ((xp->value = malloc(size)) != NULL) {
|
||||
memcpy(xp->value, value, size);
|
||||
xp->size = size;
|
||||
} else
|
||||
xp->size = 0;
|
||||
|
||||
xp->next = entry->xattr_head;
|
||||
entry->xattr_head = xp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* returns number of the extended attribute entries
|
||||
*/
|
||||
int
|
||||
archive_entry_xattr_count(struct archive_entry *entry)
|
||||
{
|
||||
struct ae_xattr *xp;
|
||||
int count = 0;
|
||||
|
||||
for (xp = entry->xattr_head; xp != NULL; xp = xp->next)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
archive_entry_xattr_reset(struct archive_entry * entry)
|
||||
{
|
||||
entry->xattr_p = entry->xattr_head;
|
||||
|
||||
return archive_entry_xattr_count(entry);
|
||||
}
|
||||
|
||||
int
|
||||
archive_entry_xattr_next(struct archive_entry * entry,
|
||||
const char **name, const void **value, size_t *size)
|
||||
{
|
||||
if (entry->xattr_p) {
|
||||
*name = entry->xattr_p->name;
|
||||
*value = entry->xattr_p->value;
|
||||
*size = entry->xattr_p->size;
|
||||
|
||||
entry->xattr_p = entry->xattr_p->next;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
*name = NULL;
|
||||
*value = NULL;
|
||||
*size = (size_t)0;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* end of xattr handling
|
||||
*/
|
164
Utilities/cmlibarchive/libarchive/archive_options.c
Normal file
164
Utilities/cmlibarchive/libarchive/archive_options.c
Normal file
@ -0,0 +1,164 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive_options_private.h"
|
||||
|
||||
static const char *
|
||||
parse_option(const char **str,
|
||||
const char **mod, const char **opt, const char **val);
|
||||
|
||||
int
|
||||
_archive_set_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
const char *mp, *op, *vp;
|
||||
|
||||
archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
|
||||
|
||||
mp = m != NULL && m[0] == '\0' ? NULL : m;
|
||||
op = o != NULL && o[0] == '\0' ? NULL : o;
|
||||
vp = v != NULL && v[0] == '\0' ? NULL : v;
|
||||
|
||||
if (op == NULL && vp == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
if (op == NULL)
|
||||
return (ARCHIVE_FAILED);
|
||||
|
||||
return use_option(a, mp, op, vp);
|
||||
}
|
||||
|
||||
int
|
||||
_archive_set_either_option(struct archive *a, const char *m, const char *o, const char *v,
|
||||
option_handler use_format_option, option_handler use_filter_option)
|
||||
{
|
||||
int r1, r2;
|
||||
|
||||
if (o == NULL && v == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
if (o == NULL)
|
||||
return (ARCHIVE_FAILED);
|
||||
|
||||
r1 = use_format_option(a, m, o, v);
|
||||
if (r1 == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
r2 = use_filter_option(a, m, o, v);
|
||||
if (r2 == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
return r1 > r2 ? r1 : r2;
|
||||
}
|
||||
|
||||
int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
int allok = 1, anyok = 0, r;
|
||||
char *data;
|
||||
const char *s, *mod, *opt, *val;
|
||||
|
||||
archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn);
|
||||
|
||||
if (options == NULL || options[0] == '\0')
|
||||
return ARCHIVE_OK;
|
||||
|
||||
data = (char *)malloc(strlen(options) + 1);
|
||||
strcpy(data, options);
|
||||
s = (const char *)data;
|
||||
|
||||
do {
|
||||
mod = opt = val = NULL;
|
||||
|
||||
parse_option(&s, &mod, &opt, &val);
|
||||
|
||||
r = use_option(a, mod, opt, val);
|
||||
if (r == ARCHIVE_FATAL) {
|
||||
free(data);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (r == ARCHIVE_OK)
|
||||
anyok = 1;
|
||||
else
|
||||
allok = 0;
|
||||
} while (s != NULL);
|
||||
|
||||
free(data);
|
||||
return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED;
|
||||
}
|
||||
|
||||
static const char *
|
||||
parse_option(const char **s, const char **m, const char **o, const char **v)
|
||||
{
|
||||
const char *end, *mod, *opt, *val;
|
||||
char *p;
|
||||
|
||||
end = NULL;
|
||||
mod = NULL;
|
||||
opt = *s;
|
||||
val = "1";
|
||||
|
||||
p = strchr(opt, ',');
|
||||
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
end = ((const char *)p) + 1;
|
||||
}
|
||||
|
||||
if (0 == strlen(opt)) {
|
||||
*s = end;
|
||||
*m = NULL;
|
||||
*o = NULL;
|
||||
*v = NULL;
|
||||
return end;
|
||||
}
|
||||
|
||||
p = strchr(opt, ':');
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
mod = opt;
|
||||
opt = ++p;
|
||||
}
|
||||
|
||||
p = strchr(opt, '=');
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
val = ++p;
|
||||
} else if (opt[0] == '!') {
|
||||
++opt;
|
||||
val = NULL;
|
||||
}
|
||||
|
||||
*s = end;
|
||||
*m = mod;
|
||||
*o = opt;
|
||||
*v = val;
|
||||
|
||||
return end;
|
||||
}
|
||||
|
47
Utilities/cmlibarchive/libarchive/archive_options_private.h
Normal file
47
Utilities/cmlibarchive/libarchive/archive_options_private.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive_private.h"
|
||||
|
||||
typedef int (*option_handler)(struct archive *a,
|
||||
const char *mod, const char *opt, const char *val);
|
||||
|
||||
int
|
||||
_archive_set_option(struct archive *a,
|
||||
const char *mod, const char *opt, const char *val,
|
||||
int magic, const char *fn, option_handler use_option);
|
||||
|
||||
int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option);
|
||||
|
||||
int
|
||||
_archive_set_either_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v,
|
||||
option_handler use_format_option, option_handler use_filter_option);
|
||||
|
165
Utilities/cmlibarchive/libarchive/archive_platform.h
Normal file
165
Utilities/cmlibarchive/libarchive/archive_platform.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_platform.h 201090 2009-12-28 02:22:04Z kientzle $
|
||||
*/
|
||||
|
||||
/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */
|
||||
|
||||
/*
|
||||
* This header is the first thing included in any of the libarchive
|
||||
* source files. As far as possible, platform-specific issues should
|
||||
* be dealt with here and not within individual source files. I'm
|
||||
* actively trying to minimize #if blocks within the main source,
|
||||
* since they obfuscate the code.
|
||||
*/
|
||||
|
||||
#ifndef ARCHIVE_PLATFORM_H_INCLUDED
|
||||
#define ARCHIVE_PLATFORM_H_INCLUDED
|
||||
|
||||
/* archive.h and archive_entry.h require this. */
|
||||
#define __LIBARCHIVE_BUILD 1
|
||||
|
||||
#if defined(PLATFORM_CONFIG_H)
|
||||
/* Use hand-built config.h in environments that need it. */
|
||||
#include PLATFORM_CONFIG_H
|
||||
#elif defined(HAVE_CONFIG_H)
|
||||
/* Most POSIX platforms use the 'configure' script to build config.h */
|
||||
#include "config.h"
|
||||
#else
|
||||
/* Warn if the library hasn't been (automatically or manually) configured. */
|
||||
#error Oops: No config.h and no pre-built configuration in archive_platform.h.
|
||||
#endif
|
||||
|
||||
/* It should be possible to get rid of this by extending the feature-test
|
||||
* macros to cover Windows API functions, probably along with non-trivial
|
||||
* refactoring of code to find structures that sit more cleanly on top of
|
||||
* either Windows or Posix APIs. */
|
||||
#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
|
||||
#include "archive_windows.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The config files define a lot of feature macros. The following
|
||||
* uses those macros to select/define replacements and include key
|
||||
* headers as required.
|
||||
*/
|
||||
|
||||
/* Get a real definition for __FBSDID if we can */
|
||||
#if HAVE_SYS_CDEFS_H
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
|
||||
/* If not, define it so as to avoid dangling semicolons. */
|
||||
#ifndef __FBSDID
|
||||
#define __FBSDID(a) struct _undefined_hack
|
||||
#endif
|
||||
|
||||
/* Try to get standard C99-style integer type definitions. */
|
||||
#if HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Borland warns about its own constants! */
|
||||
#if defined(__BORLANDC__)
|
||||
# if HAVE_DECL_UINT64_MAX
|
||||
# undef UINT64_MAX
|
||||
# undef HAVE_DECL_UINT64_MAX
|
||||
# endif
|
||||
# if HAVE_DECL_UINT64_MIN
|
||||
# undef UINT64_MIN
|
||||
# undef HAVE_DECL_UINT64_MIN
|
||||
# endif
|
||||
# if HAVE_DECL_INT64_MAX
|
||||
# undef INT64_MAX
|
||||
# undef HAVE_DECL_INT64_MAX
|
||||
# endif
|
||||
# if HAVE_DECL_INT64_MIN
|
||||
# undef INT64_MIN
|
||||
# undef HAVE_DECL_INT64_MIN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Some platforms lack the standard *_MAX definitions. */
|
||||
#if !HAVE_DECL_SIZE_MAX
|
||||
#define SIZE_MAX (~(size_t)0)
|
||||
#endif
|
||||
#if !HAVE_DECL_SSIZE_MAX
|
||||
#define SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1))
|
||||
#endif
|
||||
#if !HAVE_DECL_UINT32_MAX
|
||||
#define UINT32_MAX (~(uint32_t)0)
|
||||
#endif
|
||||
#if !HAVE_DECL_UINT64_MAX
|
||||
#define UINT64_MAX (~(uint64_t)0)
|
||||
#endif
|
||||
#if !HAVE_DECL_INT64_MAX
|
||||
#define INT64_MAX ((int64_t)(UINT64_MAX >> 1))
|
||||
#endif
|
||||
#if !HAVE_DECL_INT64_MIN
|
||||
#define INT64_MIN ((int64_t)(~INT64_MAX))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this platform has <sys/acl.h>, acl_create(), acl_init(),
|
||||
* acl_set_file(), and ACL_USER, we assume it has the rest of the
|
||||
* POSIX.1e draft functions used in archive_read_extract.c.
|
||||
*/
|
||||
#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER
|
||||
#define HAVE_POSIX_ACL 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we can't restore metadata using a file descriptor, then
|
||||
* for compatibility's sake, close files before trying to restore metadata.
|
||||
*/
|
||||
#if defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(HAVE_ACL_SET_FD) || defined(HAVE_ACL_SET_FD_NP) || defined(HAVE_FCHOWN)
|
||||
#define CAN_RESTORE_METADATA_FD
|
||||
#endif
|
||||
|
||||
/* Set up defaults for internal error codes. */
|
||||
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
|
||||
#if HAVE_EFTYPE
|
||||
#define ARCHIVE_ERRNO_FILE_FORMAT EFTYPE
|
||||
#else
|
||||
#if HAVE_EILSEQ
|
||||
#define ARCHIVE_ERRNO_FILE_FORMAT EILSEQ
|
||||
#else
|
||||
#define ARCHIVE_ERRNO_FILE_FORMAT EINVAL
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_ERRNO_PROGRAMMER
|
||||
#define ARCHIVE_ERRNO_PROGRAMMER EINVAL
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_ERRNO_MISC
|
||||
#define ARCHIVE_ERRNO_MISC (-1)
|
||||
#endif
|
||||
|
||||
#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
|
1164
Utilities/cmlibarchive/libarchive/archive_ppmd7.c
Normal file
1164
Utilities/cmlibarchive/libarchive/archive_ppmd7.c
Normal file
File diff suppressed because it is too large
Load Diff
119
Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
Normal file
119
Utilities/cmlibarchive/libarchive/archive_ppmd7_private.h
Normal file
@ -0,0 +1,119 @@
|
||||
/* Ppmd7.h -- PPMdH compression codec
|
||||
2010-03-12 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
/* This code supports virtual RangeDecoder and includes the implementation
|
||||
of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H.
|
||||
If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_PPMD7_PRIVATE_H_INCLUDED
|
||||
|
||||
#include "archive_ppmd_private.h"
|
||||
|
||||
#define PPMD7_MIN_ORDER 2
|
||||
#define PPMD7_MAX_ORDER 64
|
||||
|
||||
#define PPMD7_MIN_MEM_SIZE (1 << 11)
|
||||
#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)
|
||||
|
||||
struct CPpmd7_Context_;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
struct CPpmd7_Context_ *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd7_Context_Ref;
|
||||
|
||||
typedef struct CPpmd7_Context_
|
||||
{
|
||||
UInt16 NumStats;
|
||||
UInt16 SummFreq;
|
||||
CPpmd_State_Ref Stats;
|
||||
CPpmd7_Context_Ref Suffix;
|
||||
} CPpmd7_Context;
|
||||
|
||||
#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CPpmd7_Context *MinContext, *MaxContext;
|
||||
CPpmd_State *FoundState;
|
||||
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;
|
||||
Int32 RunLength, InitRL; /* must be 32-bit at least */
|
||||
|
||||
UInt32 Size;
|
||||
UInt32 GlueCount;
|
||||
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||
UInt32 AlignOffset;
|
||||
|
||||
Byte Indx2Units[PPMD_NUM_INDEXES];
|
||||
Byte Units2Indx[128];
|
||||
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||
Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
|
||||
CPpmd_See DummySee, See[25][16];
|
||||
UInt16 BinSumm[128][64];
|
||||
} CPpmd7;
|
||||
|
||||
/* ---------- Decode ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 (*GetThreshold)(void *p, UInt32 total);
|
||||
void (*Decode)(void *p, UInt32 start, UInt32 size);
|
||||
UInt32 (*DecodeBit)(void *p, UInt32 size0);
|
||||
} IPpmd7_RangeDec;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IPpmd7_RangeDec p;
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
UInt32 Low;
|
||||
UInt32 Bottom;
|
||||
IByteIn *Stream;
|
||||
} CPpmd7z_RangeDec;
|
||||
|
||||
/* ---------- Encode ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 Low;
|
||||
UInt32 Range;
|
||||
Byte Cache;
|
||||
UInt64 CacheSize;
|
||||
IByteOut *Stream;
|
||||
} CPpmd7z_RangeEnc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Base Functions */
|
||||
void (*Ppmd7_Construct)(CPpmd7 *p);
|
||||
Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
|
||||
void (*Ppmd7_Free)(CPpmd7 *p, ISzAlloc *alloc);
|
||||
void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
|
||||
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
||||
|
||||
/* Decode Functions */
|
||||
void (*Ppmd7z_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p);
|
||||
void (*PpmdRAR_RangeDec_CreateVTable)(CPpmd7z_RangeDec *p);
|
||||
Bool (*Ppmd7z_RangeDec_Init)(CPpmd7z_RangeDec *p);
|
||||
Bool (*PpmdRAR_RangeDec_Init)(CPpmd7z_RangeDec *p);
|
||||
#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||
int (*Ppmd7_DecodeSymbol)(CPpmd7 *p, IPpmd7_RangeDec *rc);
|
||||
|
||||
/* Encode Functions */
|
||||
void (*Ppmd7z_RangeEnc_Init)(CPpmd7z_RangeEnc *p);
|
||||
void (*Ppmd7z_RangeEnc_FlushData)(CPpmd7z_RangeEnc *p);
|
||||
|
||||
void (*Ppmd7_EncodeSymbol)(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol);
|
||||
} IPpmd7;
|
||||
|
||||
extern const IPpmd7 __archive_ppmd7_functions;
|
||||
#endif
|
158
Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
Normal file
158
Utilities/cmlibarchive/libarchive/archive_ppmd_private.h
Normal file
@ -0,0 +1,158 @@
|
||||
/* Ppmd.h -- PPMD codec common code
|
||||
2010-03-12 : Igor Pavlov : Public domain
|
||||
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_PPMD_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_PPMD_PRIVATE_H_INCLUDED
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "archive_read_private.h"
|
||||
|
||||
/*** Begin defined in Types.h ***/
|
||||
|
||||
#if !defined(ZCONF_H)
|
||||
typedef unsigned char Byte;
|
||||
#endif
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#ifdef _LZMA_UINT32_IS_ULONG
|
||||
typedef long Int32;
|
||||
typedef unsigned long UInt32;
|
||||
#else
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
NOTES: Some code will work incorrectly in that case! */
|
||||
|
||||
typedef long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#define UINT64_CONST(n) n
|
||||
#else
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#define UINT64_CONST(n) n ## ULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef int Bool;
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct archive_read *a;
|
||||
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
} IByteIn;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct archive_write *a;
|
||||
void (*Write)(void *p, Byte b);
|
||||
} IByteOut;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
|
||||
/*** End defined in Types.h ***/
|
||||
/*** Begin defined in CpuArch.h ***/
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#ifdef MY_CPU_32BIT
|
||||
#define PPMD_32BIT
|
||||
#endif
|
||||
|
||||
/*** End defined in CpuArch.h ***/
|
||||
|
||||
#define PPMD_INT_BITS 7
|
||||
#define PPMD_PERIOD_BITS 7
|
||||
#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
|
||||
|
||||
#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
|
||||
#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
|
||||
#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
|
||||
#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
|
||||
|
||||
#define PPMD_N1 4
|
||||
#define PPMD_N2 4
|
||||
#define PPMD_N3 4
|
||||
#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
|
||||
#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
|
||||
|
||||
/* SEE-contexts for PPM-contexts with masked symbols */
|
||||
typedef struct
|
||||
{
|
||||
UInt16 Summ; /* Freq */
|
||||
Byte Shift; /* Speed of Freq change; low Shift is for fast change */
|
||||
Byte Count; /* Count to next change of Shift */
|
||||
} CPpmd_See;
|
||||
|
||||
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte Symbol;
|
||||
Byte Freq;
|
||||
UInt16 SuccessorLow;
|
||||
UInt16 SuccessorHigh;
|
||||
} CPpmd_State;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
CPpmd_State *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_State_Ref;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
void *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Void_Ref;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
Byte *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd_Byte_Ref;
|
||||
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||
{ unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \
|
||||
p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }}
|
||||
|
||||
#endif
|
150
Utilities/cmlibarchive/libarchive/archive_private.h
Normal file
150
Utilities/cmlibarchive/libarchive/archive_private.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_private.h 201098 2009-12-28 02:58:14Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_PRIVATE_H_INCLUDED
|
||||
|
||||
#if HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2 || \
|
||||
(__GNUC__ == 2 && __GNUC_MINOR__ >= 5))
|
||||
#define __LA_DEAD __attribute__((__noreturn__))
|
||||
#else
|
||||
#define __LA_DEAD
|
||||
#endif
|
||||
|
||||
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
|
||||
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
|
||||
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
||||
#define ARCHIVE_READ_DISK_MAGIC (0xbadb0c5U)
|
||||
|
||||
#define ARCHIVE_STATE_NEW 1U
|
||||
#define ARCHIVE_STATE_HEADER 2U
|
||||
#define ARCHIVE_STATE_DATA 4U
|
||||
#define ARCHIVE_STATE_EOF 0x10U
|
||||
#define ARCHIVE_STATE_CLOSED 0x20U
|
||||
#define ARCHIVE_STATE_FATAL 0x8000U
|
||||
#define ARCHIVE_STATE_ANY (0xFFFFU & ~ARCHIVE_STATE_FATAL)
|
||||
|
||||
struct archive_vtable {
|
||||
int (*archive_close)(struct archive *);
|
||||
int (*archive_free)(struct archive *);
|
||||
int (*archive_write_header)(struct archive *,
|
||||
struct archive_entry *);
|
||||
int (*archive_write_finish_entry)(struct archive *);
|
||||
ssize_t (*archive_write_data)(struct archive *,
|
||||
const void *, size_t);
|
||||
ssize_t (*archive_write_data_block)(struct archive *,
|
||||
const void *, size_t, int64_t);
|
||||
|
||||
int (*archive_read_next_header)(struct archive *,
|
||||
struct archive_entry **);
|
||||
int (*archive_read_next_header2)(struct archive *,
|
||||
struct archive_entry *);
|
||||
int (*archive_read_data_block)(struct archive *,
|
||||
const void **, size_t *, int64_t *);
|
||||
|
||||
int (*archive_filter_count)(struct archive *);
|
||||
int64_t (*archive_filter_bytes)(struct archive *, int);
|
||||
int (*archive_filter_code)(struct archive *, int);
|
||||
const char * (*archive_filter_name)(struct archive *, int);
|
||||
};
|
||||
|
||||
struct archive_string_conv;
|
||||
|
||||
struct archive {
|
||||
/*
|
||||
* The magic/state values are used to sanity-check the
|
||||
* client's usage. If an API function is called at a
|
||||
* ridiculous time, or the client passes us an invalid
|
||||
* pointer, these values allow me to catch that.
|
||||
*/
|
||||
unsigned int magic;
|
||||
unsigned int state;
|
||||
|
||||
/*
|
||||
* Some public API functions depend on the "real" type of the
|
||||
* archive object.
|
||||
*/
|
||||
struct archive_vtable *vtable;
|
||||
|
||||
int archive_format;
|
||||
const char *archive_format_name;
|
||||
|
||||
int compression_code; /* Currently active compression. */
|
||||
const char *compression_name;
|
||||
|
||||
/* Number of file entries processed. */
|
||||
int file_count;
|
||||
|
||||
int archive_error_number;
|
||||
const char *error;
|
||||
struct archive_string error_string;
|
||||
|
||||
char *current_code;
|
||||
unsigned current_codepage; /* Current ACP(ANSI CodePage). */
|
||||
unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */
|
||||
struct archive_string_conv *sconv;
|
||||
};
|
||||
|
||||
/* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */
|
||||
int __archive_check_magic(struct archive *, unsigned int magic,
|
||||
unsigned int state, const char *func);
|
||||
#define archive_check_magic(a, expected_magic, allowed_states, function_name) \
|
||||
do { \
|
||||
int magic_test = __archive_check_magic((a), (expected_magic), \
|
||||
(allowed_states), (function_name)); \
|
||||
if (magic_test == ARCHIVE_FATAL) \
|
||||
return ARCHIVE_FATAL; \
|
||||
} while (0)
|
||||
|
||||
void __archive_errx(int retvalue, const char *msg) __LA_DEAD;
|
||||
|
||||
int __archive_mktemp(const char *tmpdir);
|
||||
|
||||
int __archive_clean(struct archive *);
|
||||
|
||||
#define err_combine(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER <= 1300)
|
||||
# define ARCHIVE_LITERAL_LL(x) x##i64
|
||||
# define ARCHIVE_LITERAL_ULL(x) x##ui64
|
||||
#else
|
||||
# define ARCHIVE_LITERAL_LL(x) x##ll
|
||||
# define ARCHIVE_LITERAL_ULL(x) x##ull
|
||||
#endif
|
||||
|
||||
#endif
|
701
Utilities/cmlibarchive/libarchive/archive_rb.c
Normal file
701
Utilities/cmlibarchive/libarchive/archive_rb.c
Normal file
@ -0,0 +1,701 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas <matt@3am-software.com>.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Based on: NetBSD: rb.c,v 1.6 2010/04/30 13:58:09 joerg Exp
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "archive_rb.h"
|
||||
|
||||
/* Keep in sync with archive_rb.h */
|
||||
#define RB_DIR_LEFT 0
|
||||
#define RB_DIR_RIGHT 1
|
||||
#define RB_DIR_OTHER 1
|
||||
#define rb_left rb_nodes[RB_DIR_LEFT]
|
||||
#define rb_right rb_nodes[RB_DIR_RIGHT]
|
||||
|
||||
#define RB_FLAG_POSITION 0x2
|
||||
#define RB_FLAG_RED 0x1
|
||||
#define RB_FLAG_MASK (RB_FLAG_POSITION|RB_FLAG_RED)
|
||||
#define RB_FATHER(rb) \
|
||||
((struct archive_rb_node *)((rb)->rb_info & ~RB_FLAG_MASK))
|
||||
#define RB_SET_FATHER(rb, father) \
|
||||
((void)((rb)->rb_info = (uintptr_t)(father)|((rb)->rb_info & RB_FLAG_MASK)))
|
||||
|
||||
#define RB_SENTINEL_P(rb) ((rb) == NULL)
|
||||
#define RB_LEFT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_left)
|
||||
#define RB_RIGHT_SENTINEL_P(rb) RB_SENTINEL_P((rb)->rb_right)
|
||||
#define RB_FATHER_SENTINEL_P(rb) RB_SENTINEL_P(RB_FATHER((rb)))
|
||||
#define RB_CHILDLESS_P(rb) \
|
||||
(RB_SENTINEL_P(rb) || (RB_LEFT_SENTINEL_P(rb) && RB_RIGHT_SENTINEL_P(rb)))
|
||||
#define RB_TWOCHILDREN_P(rb) \
|
||||
(!RB_SENTINEL_P(rb) && !RB_LEFT_SENTINEL_P(rb) && !RB_RIGHT_SENTINEL_P(rb))
|
||||
|
||||
#define RB_POSITION(rb) \
|
||||
(((rb)->rb_info & RB_FLAG_POSITION) ? RB_DIR_RIGHT : RB_DIR_LEFT)
|
||||
#define RB_RIGHT_P(rb) (RB_POSITION(rb) == RB_DIR_RIGHT)
|
||||
#define RB_LEFT_P(rb) (RB_POSITION(rb) == RB_DIR_LEFT)
|
||||
#define RB_RED_P(rb) (!RB_SENTINEL_P(rb) && ((rb)->rb_info & RB_FLAG_RED) != 0)
|
||||
#define RB_BLACK_P(rb) (RB_SENTINEL_P(rb) || ((rb)->rb_info & RB_FLAG_RED) == 0)
|
||||
#define RB_MARK_RED(rb) ((void)((rb)->rb_info |= RB_FLAG_RED))
|
||||
#define RB_MARK_BLACK(rb) ((void)((rb)->rb_info &= ~RB_FLAG_RED))
|
||||
#define RB_INVERT_COLOR(rb) ((void)((rb)->rb_info ^= RB_FLAG_RED))
|
||||
#define RB_ROOT_P(rbt, rb) ((rbt)->rbt_root == (rb))
|
||||
#define RB_SET_POSITION(rb, position) \
|
||||
((void)((position) ? ((rb)->rb_info |= RB_FLAG_POSITION) : \
|
||||
((rb)->rb_info &= ~RB_FLAG_POSITION)))
|
||||
#define RB_ZERO_PROPERTIES(rb) ((void)((rb)->rb_info &= ~RB_FLAG_MASK))
|
||||
#define RB_COPY_PROPERTIES(dst, src) \
|
||||
((void)((dst)->rb_info ^= ((dst)->rb_info ^ (src)->rb_info) & RB_FLAG_MASK))
|
||||
#define RB_SWAP_PROPERTIES(a, b) do { \
|
||||
uintptr_t xorinfo = ((a)->rb_info ^ (b)->rb_info) & RB_FLAG_MASK; \
|
||||
(a)->rb_info ^= xorinfo; \
|
||||
(b)->rb_info ^= xorinfo; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
static void __archive_rb_tree_insert_rebalance(struct archive_rb_tree *,
|
||||
struct archive_rb_node *);
|
||||
static void __archive_rb_tree_removal_rebalance(struct archive_rb_tree *,
|
||||
struct archive_rb_node *, unsigned int);
|
||||
|
||||
#define RB_SENTINEL_NODE NULL
|
||||
|
||||
#define T 1
|
||||
#define F 0
|
||||
|
||||
void
|
||||
__archive_rb_tree_init(struct archive_rb_tree *rbt,
|
||||
const struct archive_rb_tree_ops *ops)
|
||||
{
|
||||
rbt->rbt_ops = ops;
|
||||
*((const struct archive_rb_node **)&rbt->rbt_root) = RB_SENTINEL_NODE;
|
||||
}
|
||||
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_find_node(struct archive_rb_tree *rbt, const void *key)
|
||||
{
|
||||
archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
|
||||
struct archive_rb_node *parent = rbt->rbt_root;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const signed int diff = (*compare_key)(parent, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
parent = parent->rb_nodes[diff > 0];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_find_node_geq(struct archive_rb_tree *rbt, const void *key)
|
||||
{
|
||||
archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
|
||||
struct archive_rb_node *parent = rbt->rbt_root;
|
||||
struct archive_rb_node *last = NULL;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const signed int diff = (*compare_key)(parent, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
if (diff < 0)
|
||||
last = parent;
|
||||
parent = parent->rb_nodes[diff > 0];
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_find_node_leq(struct archive_rb_tree *rbt, const void *key)
|
||||
{
|
||||
archive_rbto_compare_key_fn compare_key = rbt->rbt_ops->rbto_compare_key;
|
||||
struct archive_rb_node *parent = rbt->rbt_root;
|
||||
struct archive_rb_node *last = NULL;
|
||||
|
||||
while (!RB_SENTINEL_P(parent)) {
|
||||
const signed int diff = (*compare_key)(parent, key);
|
||||
if (diff == 0)
|
||||
return parent;
|
||||
if (diff > 0)
|
||||
last = parent;
|
||||
parent = parent->rb_nodes[diff > 0];
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
int
|
||||
__archive_rb_tree_insert_node(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self)
|
||||
{
|
||||
archive_rbto_compare_nodes_fn compare_nodes = rbt->rbt_ops->rbto_compare_nodes;
|
||||
struct archive_rb_node *parent, *tmp;
|
||||
unsigned int position;
|
||||
int rebalance;
|
||||
|
||||
tmp = rbt->rbt_root;
|
||||
/*
|
||||
* This is a hack. Because rbt->rbt_root is just a
|
||||
* struct archive_rb_node *, just like rb_node->rb_nodes[RB_DIR_LEFT],
|
||||
* we can use this fact to avoid a lot of tests for root and know
|
||||
* that even at root, updating
|
||||
* RB_FATHER(rb_node)->rb_nodes[RB_POSITION(rb_node)] will
|
||||
* update rbt->rbt_root.
|
||||
*/
|
||||
parent = (struct archive_rb_node *)(void *)&rbt->rbt_root;
|
||||
position = RB_DIR_LEFT;
|
||||
|
||||
/*
|
||||
* Find out where to place this new leaf.
|
||||
*/
|
||||
while (!RB_SENTINEL_P(tmp)) {
|
||||
const signed int diff = (*compare_nodes)(tmp, self);
|
||||
if (diff == 0) {
|
||||
/*
|
||||
* Node already exists; don't insert.
|
||||
*/
|
||||
return F;
|
||||
}
|
||||
parent = tmp;
|
||||
position = (diff > 0);
|
||||
tmp = parent->rb_nodes[position];
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the node and insert as a leaf into the tree.
|
||||
*/
|
||||
RB_SET_FATHER(self, parent);
|
||||
RB_SET_POSITION(self, position);
|
||||
if (parent == (struct archive_rb_node *)(void *)&rbt->rbt_root) {
|
||||
RB_MARK_BLACK(self); /* root is always black */
|
||||
rebalance = F;
|
||||
} else {
|
||||
/*
|
||||
* All new nodes are colored red. We only need to rebalance
|
||||
* if our parent is also red.
|
||||
*/
|
||||
RB_MARK_RED(self);
|
||||
rebalance = RB_RED_P(parent);
|
||||
}
|
||||
self->rb_left = parent->rb_nodes[position];
|
||||
self->rb_right = parent->rb_nodes[position];
|
||||
parent->rb_nodes[position] = self;
|
||||
|
||||
/*
|
||||
* Rebalance tree after insertion
|
||||
*/
|
||||
if (rebalance)
|
||||
__archive_rb_tree_insert_rebalance(rbt, self);
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap the location and colors of 'self' and its child @ which. The child
|
||||
* can not be a sentinel node. This is our rotation function. However,
|
||||
* since it preserves coloring, it great simplifies both insertion and
|
||||
* removal since rotation almost always involves the exchanging of colors
|
||||
* as a separate step.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
__archive_rb_tree_reparent_nodes(
|
||||
struct archive_rb_node *old_father, const unsigned int which)
|
||||
{
|
||||
const unsigned int other = which ^ RB_DIR_OTHER;
|
||||
struct archive_rb_node * const grandpa = RB_FATHER(old_father);
|
||||
struct archive_rb_node * const old_child = old_father->rb_nodes[which];
|
||||
struct archive_rb_node * const new_father = old_child;
|
||||
struct archive_rb_node * const new_child = old_father;
|
||||
|
||||
/*
|
||||
* Exchange descendant linkages.
|
||||
*/
|
||||
grandpa->rb_nodes[RB_POSITION(old_father)] = new_father;
|
||||
new_child->rb_nodes[which] = old_child->rb_nodes[other];
|
||||
new_father->rb_nodes[other] = new_child;
|
||||
|
||||
/*
|
||||
* Update ancestor linkages
|
||||
*/
|
||||
RB_SET_FATHER(new_father, grandpa);
|
||||
RB_SET_FATHER(new_child, new_father);
|
||||
|
||||
/*
|
||||
* Exchange properties between new_father and new_child. The only
|
||||
* change is that new_child's position is now on the other side.
|
||||
*/
|
||||
RB_SWAP_PROPERTIES(new_father, new_child);
|
||||
RB_SET_POSITION(new_child, other);
|
||||
|
||||
/*
|
||||
* Make sure to reparent the new child to ourself.
|
||||
*/
|
||||
if (!RB_SENTINEL_P(new_child->rb_nodes[which])) {
|
||||
RB_SET_FATHER(new_child->rb_nodes[which], new_child);
|
||||
RB_SET_POSITION(new_child->rb_nodes[which], which);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
__archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self)
|
||||
{
|
||||
struct archive_rb_node * father = RB_FATHER(self);
|
||||
struct archive_rb_node * grandpa;
|
||||
struct archive_rb_node * uncle;
|
||||
unsigned int which;
|
||||
unsigned int other;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* We are red and our parent is red, therefore we must have a
|
||||
* grandfather and he must be black.
|
||||
*/
|
||||
grandpa = RB_FATHER(father);
|
||||
which = (father == grandpa->rb_right);
|
||||
other = which ^ RB_DIR_OTHER;
|
||||
uncle = grandpa->rb_nodes[other];
|
||||
|
||||
if (RB_BLACK_P(uncle))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Case 1: our uncle is red
|
||||
* Simply invert the colors of our parent and
|
||||
* uncle and make our grandparent red. And
|
||||
* then solve the problem up at his level.
|
||||
*/
|
||||
RB_MARK_BLACK(uncle);
|
||||
RB_MARK_BLACK(father);
|
||||
if (RB_ROOT_P(rbt, grandpa)) {
|
||||
/*
|
||||
* If our grandpa is root, don't bother
|
||||
* setting him to red, just return.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
RB_MARK_RED(grandpa);
|
||||
self = grandpa;
|
||||
father = RB_FATHER(self);
|
||||
if (RB_BLACK_P(father)) {
|
||||
/*
|
||||
* If our greatgrandpa is black, we're done.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Case 2&3: our uncle is black.
|
||||
*/
|
||||
if (self == father->rb_nodes[other]) {
|
||||
/*
|
||||
* Case 2: we are on the same side as our uncle
|
||||
* Swap ourselves with our parent so this case
|
||||
* becomes case 3. Basically our parent becomes our
|
||||
* child.
|
||||
*/
|
||||
__archive_rb_tree_reparent_nodes(father, other);
|
||||
}
|
||||
/*
|
||||
* Case 3: we are opposite a child of a black uncle.
|
||||
* Swap our parent and grandparent. Since our grandfather
|
||||
* is black, our father will become black and our new sibling
|
||||
* (former grandparent) will become red.
|
||||
*/
|
||||
__archive_rb_tree_reparent_nodes(grandpa, which);
|
||||
|
||||
/*
|
||||
* Final step: Set the root to black.
|
||||
*/
|
||||
RB_MARK_BLACK(rbt->rbt_root);
|
||||
}
|
||||
|
||||
static void
|
||||
__archive_rb_tree_prune_node(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self, int rebalance)
|
||||
{
|
||||
const unsigned int which = RB_POSITION(self);
|
||||
struct archive_rb_node *father = RB_FATHER(self);
|
||||
|
||||
/*
|
||||
* Since we are childless, we know that self->rb_left is pointing
|
||||
* to the sentinel node.
|
||||
*/
|
||||
father->rb_nodes[which] = self->rb_left;
|
||||
|
||||
/*
|
||||
* Rebalance if requested.
|
||||
*/
|
||||
if (rebalance)
|
||||
__archive_rb_tree_removal_rebalance(rbt, father, which);
|
||||
}
|
||||
|
||||
/*
|
||||
* When deleting an interior node
|
||||
*/
|
||||
static void
|
||||
__archive_rb_tree_swap_prune_and_rebalance(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self, struct archive_rb_node *standin)
|
||||
{
|
||||
const unsigned int standin_which = RB_POSITION(standin);
|
||||
unsigned int standin_other = standin_which ^ RB_DIR_OTHER;
|
||||
struct archive_rb_node *standin_son;
|
||||
struct archive_rb_node *standin_father = RB_FATHER(standin);
|
||||
int rebalance = RB_BLACK_P(standin);
|
||||
|
||||
if (standin_father == self) {
|
||||
/*
|
||||
* As a child of self, any childen would be opposite of
|
||||
* our parent.
|
||||
*/
|
||||
standin_son = standin->rb_nodes[standin_which];
|
||||
} else {
|
||||
/*
|
||||
* Since we aren't a child of self, any childen would be
|
||||
* on the same side as our parent.
|
||||
*/
|
||||
standin_son = standin->rb_nodes[standin_other];
|
||||
}
|
||||
|
||||
if (RB_RED_P(standin_son)) {
|
||||
/*
|
||||
* We know we have a red child so if we flip it to black
|
||||
* we don't have to rebalance.
|
||||
*/
|
||||
RB_MARK_BLACK(standin_son);
|
||||
rebalance = F;
|
||||
|
||||
if (standin_father != self) {
|
||||
/*
|
||||
* Change the son's parentage to point to his grandpa.
|
||||
*/
|
||||
RB_SET_FATHER(standin_son, standin_father);
|
||||
RB_SET_POSITION(standin_son, standin_which);
|
||||
}
|
||||
}
|
||||
|
||||
if (standin_father == self) {
|
||||
/*
|
||||
* If we are about to delete the standin's father, then when
|
||||
* we call rebalance, we need to use ourselves as our father.
|
||||
* Otherwise remember our original father. Also, sincef we are
|
||||
* our standin's father we only need to reparent the standin's
|
||||
* brother.
|
||||
*
|
||||
* | R --> S |
|
||||
* | Q S --> Q T |
|
||||
* | t --> |
|
||||
*
|
||||
* Have our son/standin adopt his brother as his new son.
|
||||
*/
|
||||
standin_father = standin;
|
||||
} else {
|
||||
/*
|
||||
* | R --> S . |
|
||||
* | / \ | T --> / \ | / |
|
||||
* | ..... | S --> ..... | T |
|
||||
*
|
||||
* Sever standin's connection to his father.
|
||||
*/
|
||||
standin_father->rb_nodes[standin_which] = standin_son;
|
||||
/*
|
||||
* Adopt the far son.
|
||||
*/
|
||||
standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
|
||||
RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
|
||||
/*
|
||||
* Use standin_other because we need to preserve standin_which
|
||||
* for the removal_rebalance.
|
||||
*/
|
||||
standin_other = standin_which;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the only remaining son to our standin. If our standin is our
|
||||
* son, this will be the only son needed to be moved.
|
||||
*/
|
||||
standin->rb_nodes[standin_other] = self->rb_nodes[standin_other];
|
||||
RB_SET_FATHER(standin->rb_nodes[standin_other], standin);
|
||||
|
||||
/*
|
||||
* Now copy the result of self to standin and then replace
|
||||
* self with standin in the tree.
|
||||
*/
|
||||
RB_COPY_PROPERTIES(standin, self);
|
||||
RB_SET_FATHER(standin, RB_FATHER(self));
|
||||
RB_FATHER(standin)->rb_nodes[RB_POSITION(standin)] = standin;
|
||||
|
||||
if (rebalance)
|
||||
__archive_rb_tree_removal_rebalance(rbt, standin_father, standin_which);
|
||||
}
|
||||
|
||||
/*
|
||||
* We could do this by doing
|
||||
* __archive_rb_tree_node_swap(rbt, self, which);
|
||||
* __archive_rb_tree_prune_node(rbt, self, F);
|
||||
*
|
||||
* But it's more efficient to just evalate and recolor the child.
|
||||
*/
|
||||
static void
|
||||
__archive_rb_tree_prune_blackred_branch(
|
||||
struct archive_rb_node *self, unsigned int which)
|
||||
{
|
||||
struct archive_rb_node *father = RB_FATHER(self);
|
||||
struct archive_rb_node *son = self->rb_nodes[which];
|
||||
|
||||
/*
|
||||
* Remove ourselves from the tree and give our former child our
|
||||
* properties (position, color, root).
|
||||
*/
|
||||
RB_COPY_PROPERTIES(son, self);
|
||||
father->rb_nodes[RB_POSITION(son)] = son;
|
||||
RB_SET_FATHER(son, father);
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
__archive_rb_tree_remove_node(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self)
|
||||
{
|
||||
struct archive_rb_node *standin;
|
||||
unsigned int which;
|
||||
|
||||
/*
|
||||
* In the following diagrams, we (the node to be removed) are S. Red
|
||||
* nodes are lowercase. T could be either red or black.
|
||||
*
|
||||
* Remember the major axiom of the red-black tree: the number of
|
||||
* black nodes from the root to each leaf is constant across all
|
||||
* leaves, only the number of red nodes varies.
|
||||
*
|
||||
* Thus removing a red leaf doesn't require any other changes to a
|
||||
* red-black tree. So if we must remove a node, attempt to rearrange
|
||||
* the tree so we can remove a red node.
|
||||
*
|
||||
* The simpliest case is a childless red node or a childless root node:
|
||||
*
|
||||
* | T --> T | or | R --> * |
|
||||
* | s --> * |
|
||||
*/
|
||||
if (RB_CHILDLESS_P(self)) {
|
||||
const int rebalance = RB_BLACK_P(self) && !RB_ROOT_P(rbt, self);
|
||||
__archive_rb_tree_prune_node(rbt, self, rebalance);
|
||||
return;
|
||||
}
|
||||
if (!RB_TWOCHILDREN_P(self)) {
|
||||
/*
|
||||
* The next simpliest case is the node we are deleting is
|
||||
* black and has one red child.
|
||||
*
|
||||
* | T --> T --> T |
|
||||
* | S --> R --> R |
|
||||
* | r --> s --> * |
|
||||
*/
|
||||
which = RB_LEFT_SENTINEL_P(self) ? RB_DIR_RIGHT : RB_DIR_LEFT;
|
||||
__archive_rb_tree_prune_blackred_branch(self, which);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We invert these because we prefer to remove from the inside of
|
||||
* the tree.
|
||||
*/
|
||||
which = RB_POSITION(self) ^ RB_DIR_OTHER;
|
||||
|
||||
/*
|
||||
* Let's find the node closes to us opposite of our parent
|
||||
* Now swap it with ourself, "prune" it, and rebalance, if needed.
|
||||
*/
|
||||
standin = __archive_rb_tree_iterate(rbt, self, which);
|
||||
__archive_rb_tree_swap_prune_and_rebalance(rbt, self, standin);
|
||||
}
|
||||
|
||||
static void
|
||||
__archive_rb_tree_removal_rebalance(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *parent, unsigned int which)
|
||||
{
|
||||
|
||||
while (RB_BLACK_P(parent->rb_nodes[which])) {
|
||||
unsigned int other = which ^ RB_DIR_OTHER;
|
||||
struct archive_rb_node *brother = parent->rb_nodes[other];
|
||||
|
||||
/*
|
||||
* For cases 1, 2a, and 2b, our brother's children must
|
||||
* be black and our father must be black
|
||||
*/
|
||||
if (RB_BLACK_P(parent)
|
||||
&& RB_BLACK_P(brother->rb_left)
|
||||
&& RB_BLACK_P(brother->rb_right)) {
|
||||
if (RB_RED_P(brother)) {
|
||||
/*
|
||||
* Case 1: Our brother is red, swap its
|
||||
* position (and colors) with our parent.
|
||||
* This should now be case 2b (unless C or E
|
||||
* has a red child which is case 3; thus no
|
||||
* explicit branch to case 2b).
|
||||
*
|
||||
* B -> D
|
||||
* A d -> b E
|
||||
* C E -> A C
|
||||
*/
|
||||
__archive_rb_tree_reparent_nodes(parent, other);
|
||||
brother = parent->rb_nodes[other];
|
||||
} else {
|
||||
/*
|
||||
* Both our parent and brother are black.
|
||||
* Change our brother to red, advance up rank
|
||||
* and go through the loop again.
|
||||
*
|
||||
* B -> *B
|
||||
* *A D -> A d
|
||||
* C E -> C E
|
||||
*/
|
||||
RB_MARK_RED(brother);
|
||||
if (RB_ROOT_P(rbt, parent))
|
||||
return; /* root == parent == black */
|
||||
which = RB_POSITION(parent);
|
||||
parent = RB_FATHER(parent);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Avoid an else here so that case 2a above can hit either
|
||||
* case 2b, 3, or 4.
|
||||
*/
|
||||
if (RB_RED_P(parent)
|
||||
&& RB_BLACK_P(brother)
|
||||
&& RB_BLACK_P(brother->rb_left)
|
||||
&& RB_BLACK_P(brother->rb_right)) {
|
||||
/*
|
||||
* We are black, our father is red, our brother and
|
||||
* both nephews are black. Simply invert/exchange the
|
||||
* colors of our father and brother (to black and red
|
||||
* respectively).
|
||||
*
|
||||
* | f --> F |
|
||||
* | * B --> * b |
|
||||
* | N N --> N N |
|
||||
*/
|
||||
RB_MARK_BLACK(parent);
|
||||
RB_MARK_RED(brother);
|
||||
break; /* We're done! */
|
||||
} else {
|
||||
/*
|
||||
* Our brother must be black and have at least one
|
||||
* red child (it may have two).
|
||||
*/
|
||||
if (RB_BLACK_P(brother->rb_nodes[other])) {
|
||||
/*
|
||||
* Case 3: our brother is black, our near
|
||||
* nephew is red, and our far nephew is black.
|
||||
* Swap our brother with our near nephew.
|
||||
* This result in a tree that matches case 4.
|
||||
* (Our father could be red or black).
|
||||
*
|
||||
* | F --> F |
|
||||
* | x B --> x B |
|
||||
* | n --> n |
|
||||
*/
|
||||
__archive_rb_tree_reparent_nodes(brother, which);
|
||||
brother = parent->rb_nodes[other];
|
||||
}
|
||||
/*
|
||||
* Case 4: our brother is black and our far nephew
|
||||
* is red. Swap our father and brother locations and
|
||||
* change our far nephew to black. (these can be
|
||||
* done in either order so we change the color first).
|
||||
* The result is a valid red-black tree and is a
|
||||
* terminal case. (again we don't care about the
|
||||
* father's color)
|
||||
*
|
||||
* If the father is red, we will get a red-black-black
|
||||
* tree:
|
||||
* | f -> f --> b |
|
||||
* | B -> B --> F N |
|
||||
* | n -> N --> |
|
||||
*
|
||||
* If the father is black, we will get an all black
|
||||
* tree:
|
||||
* | F -> F --> B |
|
||||
* | B -> B --> F N |
|
||||
* | n -> N --> |
|
||||
*
|
||||
* If we had two red nephews, then after the swap,
|
||||
* our former father would have a red grandson.
|
||||
*/
|
||||
RB_MARK_BLACK(brother->rb_nodes[other]);
|
||||
__archive_rb_tree_reparent_nodes(parent, other);
|
||||
break; /* We're done! */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_iterate(struct archive_rb_tree *rbt,
|
||||
struct archive_rb_node *self, const unsigned int direction)
|
||||
{
|
||||
const unsigned int other = direction ^ RB_DIR_OTHER;
|
||||
|
||||
if (self == NULL) {
|
||||
self = rbt->rbt_root;
|
||||
if (RB_SENTINEL_P(self))
|
||||
return NULL;
|
||||
while (!RB_SENTINEL_P(self->rb_nodes[direction]))
|
||||
self = self->rb_nodes[direction];
|
||||
return self;
|
||||
}
|
||||
/*
|
||||
* We can't go any further in this direction. We proceed up in the
|
||||
* opposite direction until our parent is in direction we want to go.
|
||||
*/
|
||||
if (RB_SENTINEL_P(self->rb_nodes[direction])) {
|
||||
while (!RB_ROOT_P(rbt, self)) {
|
||||
if (other == RB_POSITION(self))
|
||||
return RB_FATHER(self);
|
||||
self = RB_FATHER(self);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance down one in current direction and go down as far as possible
|
||||
* in the opposite direction.
|
||||
*/
|
||||
self = self->rb_nodes[direction];
|
||||
while (!RB_SENTINEL_P(self->rb_nodes[other]))
|
||||
self = self->rb_nodes[other];
|
||||
return self;
|
||||
}
|
100
Utilities/cmlibarchive/libarchive/archive_rb.h
Normal file
100
Utilities/cmlibarchive/libarchive/archive_rb.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas <matt@3am-software.com>.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Based on NetBSD: rb.h,v 1.13 2009/08/16 10:57:01 yamt Exp
|
||||
*/
|
||||
#ifndef ARCHIVE_RB_H_
|
||||
#define ARCHIVE_RB_H_
|
||||
|
||||
struct archive_rb_node {
|
||||
struct archive_rb_node *rb_nodes[2];
|
||||
/*
|
||||
* rb_info contains the two flags and the parent back pointer.
|
||||
* We put the two flags in the low two bits since we know that
|
||||
* rb_node will have an alignment of 4 or 8 bytes.
|
||||
*/
|
||||
uintptr_t rb_info;
|
||||
};
|
||||
|
||||
#define ARCHIVE_RB_DIR_LEFT 0
|
||||
#define ARCHIVE_RB_DIR_RIGHT 1
|
||||
|
||||
#define ARCHIVE_RB_TREE_MIN(T) \
|
||||
__archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_LEFT)
|
||||
#define ARCHIVE_RB_TREE_MAX(T) \
|
||||
__archive_rb_tree_iterate((T), NULL, ARCHIVE_RB_DIR_RIGHT)
|
||||
#define ARCHIVE_RB_TREE_FOREACH(N, T) \
|
||||
for ((N) = ARCHIVE_RB_TREE_MIN(T); (N); \
|
||||
(N) = __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_RIGHT))
|
||||
#define ARCHIVE_RB_TREE_FOREACH_REVERSE(N, T) \
|
||||
for ((N) = ARCHIVE_RB_TREE_MAX(T); (N); \
|
||||
(N) = __archive_rb_tree_iterate((T), (N), ARCHIVE_RB_DIR_LEFT))
|
||||
|
||||
/*
|
||||
* archive_rbto_compare_nodes_fn:
|
||||
* return a positive value if the first node < the second node.
|
||||
* return a negative value if the first node > the second node.
|
||||
* return 0 if they are considered same.
|
||||
*
|
||||
* archive_rbto_compare_key_fn:
|
||||
* return a positive value if the node < the key.
|
||||
* return a negative value if the node > the key.
|
||||
* return 0 if they are considered same.
|
||||
*/
|
||||
|
||||
typedef signed int (*const archive_rbto_compare_nodes_fn)(const struct archive_rb_node *,
|
||||
const struct archive_rb_node *);
|
||||
typedef signed int (*const archive_rbto_compare_key_fn)(const struct archive_rb_node *,
|
||||
const void *);
|
||||
|
||||
struct archive_rb_tree_ops {
|
||||
archive_rbto_compare_nodes_fn rbto_compare_nodes;
|
||||
archive_rbto_compare_key_fn rbto_compare_key;
|
||||
};
|
||||
|
||||
struct archive_rb_tree {
|
||||
struct archive_rb_node *rbt_root;
|
||||
const struct archive_rb_tree_ops *rbt_ops;
|
||||
};
|
||||
|
||||
void __archive_rb_tree_init(struct archive_rb_tree *,
|
||||
const struct archive_rb_tree_ops *);
|
||||
int __archive_rb_tree_insert_node(struct archive_rb_tree *,
|
||||
struct archive_rb_node *);
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_find_node(struct archive_rb_tree *, const void *);
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_find_node_geq(struct archive_rb_tree *, const void *);
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_find_node_leq(struct archive_rb_tree *, const void *);
|
||||
void __archive_rb_tree_remove_node(struct archive_rb_tree *, struct archive_rb_node *);
|
||||
struct archive_rb_node *
|
||||
__archive_rb_tree_iterate(struct archive_rb_tree *,
|
||||
struct archive_rb_node *, const unsigned int);
|
||||
|
||||
#endif /* ARCHIVE_RB_H_*/
|
250
Utilities/cmlibarchive/libarchive/archive_read.3
Normal file
250
Utilities/cmlibarchive/libarchive/archive_read.3
Normal file
@ -0,0 +1,250 @@
|
||||
.\" Copyright (c) 2003-2007 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
|
||||
.\"
|
||||
.Dd March 23, 2011
|
||||
.Dt archive_read 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Sh DESCRIPTION
|
||||
These functions provide a complete API for reading streaming archives.
|
||||
The general process is to first create the
|
||||
.Tn struct archive
|
||||
object, set options, initialize the reader, iterate over the archive
|
||||
headers and associated data, then close the archive and release all
|
||||
resources.
|
||||
.\"
|
||||
.Ss Create archive object
|
||||
See
|
||||
.Xr archive_read_new 3 .
|
||||
.Pp
|
||||
To read an archive, you must first obtain an initialized
|
||||
.Tn struct archive
|
||||
object from
|
||||
.Fn archive_read_new .
|
||||
.\"
|
||||
.Ss Enable filters and formats
|
||||
See
|
||||
.Xr archive_read_filter 3
|
||||
and
|
||||
.Xr archive_read_format 3 .
|
||||
.Pp
|
||||
You can then modify this object for the desired operations with the
|
||||
various
|
||||
.Fn archive_read_set_XXX
|
||||
and
|
||||
.Fn archive_read_support_XXX
|
||||
functions.
|
||||
In particular, you will need to invoke appropriate
|
||||
.Fn archive_read_support_XXX
|
||||
functions to enable the corresponding compression and format
|
||||
support.
|
||||
Note that these latter functions perform two distinct operations:
|
||||
they cause the corresponding support code to be linked into your
|
||||
program, and they enable the corresponding auto-detect code.
|
||||
Unless you have specific constraints, you will generally want
|
||||
to invoke
|
||||
.Fn archive_read_support_filter_all
|
||||
and
|
||||
.Fn archive_read_support_format_all
|
||||
to enable auto-detect for all formats and compression types
|
||||
currently supported by the library.
|
||||
.\"
|
||||
.Ss Set options
|
||||
See
|
||||
.Xr archive_read_set_options 3 .
|
||||
.\"
|
||||
.Ss Open archive
|
||||
See
|
||||
.Xr archive_read_open 3 .
|
||||
.Pp
|
||||
Once you have prepared the
|
||||
.Tn struct archive
|
||||
object, you call
|
||||
.Fn archive_read_open
|
||||
to actually open the archive and prepare it for reading.
|
||||
There are several variants of this function;
|
||||
the most basic expects you to provide pointers to several
|
||||
functions that can provide blocks of bytes from the archive.
|
||||
There are convenience forms that allow you to
|
||||
specify a filename, file descriptor,
|
||||
.Ft "FILE *"
|
||||
object, or a block of memory from which to read the archive data.
|
||||
Note that the core library makes no assumptions about the
|
||||
size of the blocks read;
|
||||
callback functions are free to read whatever block size is
|
||||
most appropriate for the medium.
|
||||
.\"
|
||||
.Ss Consume archive
|
||||
See
|
||||
.Xr archive_read_header 3 ,
|
||||
.Xr archive_read_data 3
|
||||
and
|
||||
.Xr archive_read_extract 3 .
|
||||
.Pp
|
||||
Each archive entry consists of a header followed by a certain
|
||||
amount of data.
|
||||
You can obtain the next header with
|
||||
.Fn archive_read_next_header ,
|
||||
which returns a pointer to an
|
||||
.Tn struct archive_entry
|
||||
structure with information about the current archive element.
|
||||
If the entry is a regular file, then the header will be followed
|
||||
by the file data.
|
||||
You can use
|
||||
.Fn archive_read_data
|
||||
(which works much like the
|
||||
.Xr read 2
|
||||
system call)
|
||||
to read this data from the archive, or
|
||||
.Fn archive_read_data_block
|
||||
which provides a slightly more efficient interface.
|
||||
You may prefer to use the higher-level
|
||||
.Fn archive_read_data_skip ,
|
||||
which reads and discards the data for this entry,
|
||||
.Fn archive_read_data_to_file ,
|
||||
which copies the data to the provided file descriptor, or
|
||||
.Fn archive_read_extract ,
|
||||
which recreates the specified entry on disk and copies data
|
||||
from the archive.
|
||||
In particular, note that
|
||||
.Fn archive_read_extract
|
||||
uses the
|
||||
.Tn struct archive_entry
|
||||
structure that you provide it, which may differ from the
|
||||
entry just read from the archive.
|
||||
In particular, many applications will want to override the
|
||||
pathname, file permissions, or ownership.
|
||||
.\"
|
||||
.Ss Release resources
|
||||
See
|
||||
.Xr archive_read_free 3 .
|
||||
.Pp
|
||||
Once you have finished reading data from the archive, you
|
||||
should call
|
||||
.Fn archive_read_close
|
||||
to close the archive, then call
|
||||
.Fn archive_read_free
|
||||
to release all resources, including all memory allocated by the library.
|
||||
.\"
|
||||
.Sh EXAMPLE
|
||||
The following illustrates basic usage of the library.
|
||||
In this example,
|
||||
the callback functions are simply wrappers around the standard
|
||||
.Xr open 2 ,
|
||||
.Xr read 2 ,
|
||||
and
|
||||
.Xr close 2
|
||||
system calls.
|
||||
.Bd -literal -offset indent
|
||||
void
|
||||
list_archive(const char *name)
|
||||
{
|
||||
struct mydata *mydata;
|
||||
struct archive *a;
|
||||
struct archive_entry *entry;
|
||||
|
||||
mydata = malloc(sizeof(struct mydata));
|
||||
a = archive_read_new();
|
||||
mydata->name = name;
|
||||
archive_read_support_filter_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
archive_read_open(a, mydata, myopen, myread, myclose);
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
printf("%s\en",archive_entry_pathname(entry));
|
||||
archive_read_data_skip(a);
|
||||
}
|
||||
archive_read_free(a);
|
||||
free(mydata);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
myread(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct mydata *mydata = client_data;
|
||||
|
||||
*buff = mydata->buff;
|
||||
return (read(mydata->fd, mydata->buff, 10240));
|
||||
}
|
||||
|
||||
int
|
||||
myopen(struct archive *a, void *client_data)
|
||||
{
|
||||
struct mydata *mydata = client_data;
|
||||
|
||||
mydata->fd = open(mydata->name, O_RDONLY);
|
||||
return (mydata->fd >= 0 ? ARCHIVE_OK : ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
myclose(struct archive *a, void *client_data)
|
||||
{
|
||||
struct mydata *mydata = client_data;
|
||||
|
||||
if (mydata->fd > 0)
|
||||
close(mydata->fd);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
.Ed
|
||||
.\" .Sh ERRORS
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read_new 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_extract 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_header 3 ,
|
||||
.Xr archive_read_open 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm libarchive
|
||||
library first appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm libarchive
|
||||
library was written by
|
||||
.An Tim Kientzle Aq kientzle@acm.org .
|
||||
.Sh BUGS
|
||||
Many traditional archiver programs treat
|
||||
empty files as valid empty archives.
|
||||
For example, many implementations of
|
||||
.Xr tar 1
|
||||
allow you to append entries to an empty file.
|
||||
Of course, it is impossible to determine the format of an empty file
|
||||
by inspecting the contents, so this library treats empty files as
|
||||
having a special
|
||||
.Dq empty
|
||||
format.
|
1358
Utilities/cmlibarchive/libarchive/archive_read.c
Normal file
1358
Utilities/cmlibarchive/libarchive/archive_read.c
Normal file
File diff suppressed because it is too large
Load Diff
142
Utilities/cmlibarchive/libarchive/archive_read_data.3
Normal file
142
Utilities/cmlibarchive/libarchive/archive_read_data.3
Normal file
@ -0,0 +1,142 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 22, 2011
|
||||
.Dt archive_read_data 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_data
|
||||
.Nm archive_read_data_block ,
|
||||
.Nm archive_read_data_skip ,
|
||||
.\" #if ARCHIVE_API_VERSION < 3
|
||||
.Nm archive_read_data_into_buffer ,
|
||||
.\" #endif
|
||||
.Nm archive_read_data_into_fd
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft ssize_t
|
||||
.Fn archive_read_data "struct archive *" "void *buff" "size_t len"
|
||||
.Ft int
|
||||
.Fo archive_read_data_block
|
||||
.Fa "struct archive *"
|
||||
.Fa "const void **buff"
|
||||
.Fa "size_t *len"
|
||||
.Fa "off_t *offset"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_read_data_skip "struct archive *"
|
||||
.\" #if ARCHIVE_API_VERSION < 3
|
||||
.Ft int
|
||||
.Fn archive_read_data_into_buffer "struct archive *" "void *" "ssize_t len"
|
||||
.\" #endif
|
||||
.Ft int
|
||||
.Fn archive_read_data_into_fd "struct archive *" "int fd"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_read_data
|
||||
Read data associated with the header just read.
|
||||
Internally, this is a convenience function that calls
|
||||
.Fn archive_read_data_block
|
||||
and fills any gaps with nulls so that callers see a single
|
||||
continuous stream of data.
|
||||
.It Fn archive_read_data_block
|
||||
Return the next available block of data for this entry.
|
||||
Unlike
|
||||
.Fn archive_read_data ,
|
||||
the
|
||||
.Fn archive_read_data_block
|
||||
function avoids copying data and allows you to correctly handle
|
||||
sparse files, as supported by some archive formats.
|
||||
The library guarantees that offsets will increase and that blocks
|
||||
will not overlap.
|
||||
Note that the blocks returned from this function can be much larger
|
||||
than the block size read from disk, due to compression
|
||||
and internal buffer optimizations.
|
||||
.It Fn archive_read_data_skip
|
||||
A convenience function that repeatedly calls
|
||||
.Fn archive_read_data_block
|
||||
to skip all of the data for this archive entry.
|
||||
Note that this function is invoked automatically by
|
||||
.Fn archive_read_next_header2
|
||||
if the previous entry was not completely consumed.
|
||||
.\" #if ARCHIVE_API_VERSION < 3
|
||||
.It Fn archive_read_data_into_buffer
|
||||
This function is deprecated and will be removed.
|
||||
Use
|
||||
.Fn archive_read_data
|
||||
instead.
|
||||
.\" #endif
|
||||
.It Fn archive_read_data_into_fd
|
||||
A convenience function that repeatedly calls
|
||||
.Fn archive_read_data_block
|
||||
to copy the entire entry to the provided file descriptor.
|
||||
.El
|
||||
.\"
|
||||
.Sh RETURN VALUES
|
||||
Most functions return zero on success, non-zero on error.
|
||||
The possible return codes include:
|
||||
.Cm ARCHIVE_OK
|
||||
(the operation succeeded),
|
||||
.Cm ARCHIVE_WARN
|
||||
(the operation succeeded but a non-critical error was encountered),
|
||||
.Cm ARCHIVE_EOF
|
||||
(end-of-archive was encountered),
|
||||
.Cm ARCHIVE_RETRY
|
||||
(the operation failed but can be retried),
|
||||
and
|
||||
.Cm ARCHIVE_FATAL
|
||||
(there was a fatal error; the archive should be closed immediately).
|
||||
.Pp
|
||||
.Fn archive_read_data
|
||||
returns a count of bytes actually read or zero at the end of the entry.
|
||||
On error, a value of
|
||||
.Cm ARCHIVE_FATAL ,
|
||||
.Cm ARCHIVE_WARN ,
|
||||
or
|
||||
.Cm ARCHIVE_RETRY
|
||||
is returned.
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_read_extract 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_header 3 ,
|
||||
.Xr archive_read_open 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
139
Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c
Normal file
139
Utilities/cmlibarchive/libarchive/archive_read_data_into_fd.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_data_into_fd.c,v 1.16 2008/05/23 05:01:29 cperciva Exp $");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
/* Maximum amount of data to write at one time. */
|
||||
#define MAX_WRITE (1024 * 1024)
|
||||
|
||||
/*
|
||||
* This implementation minimizes copying of data and is sparse-file aware.
|
||||
*/
|
||||
int
|
||||
pad_to(struct archive *a, int fd, int can_lseek,
|
||||
size_t nulls_size, const char *nulls,
|
||||
int64_t target_offset, int64_t actual_offset)
|
||||
{
|
||||
size_t to_write;
|
||||
ssize_t bytes_written;
|
||||
|
||||
if (can_lseek) {
|
||||
actual_offset = lseek(fd,
|
||||
target_offset - actual_offset, SEEK_CUR);
|
||||
if (actual_offset != target_offset) {
|
||||
archive_set_error(a, errno, "Seek error");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
while (target_offset > actual_offset) {
|
||||
to_write = nulls_size;
|
||||
if (target_offset < actual_offset + nulls_size)
|
||||
to_write = (size_t)(target_offset - actual_offset);
|
||||
bytes_written = write(fd, nulls, to_write);
|
||||
if (bytes_written < 0) {
|
||||
archive_set_error(a, errno, "Write error");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
actual_offset += bytes_written;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
archive_read_data_into_fd(struct archive *a, int fd)
|
||||
{
|
||||
struct stat st;
|
||||
int r, r2;
|
||||
const void *buff;
|
||||
size_t size, bytes_to_write;
|
||||
ssize_t bytes_written;
|
||||
int64_t target_offset;
|
||||
int64_t actual_offset = 0;
|
||||
int can_lseek;
|
||||
char *nulls = NULL;
|
||||
size_t nulls_size = 16384;
|
||||
|
||||
archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA,
|
||||
"archive_read_data_into_fd");
|
||||
|
||||
can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode);
|
||||
if (!can_lseek)
|
||||
nulls = calloc(1, nulls_size);
|
||||
|
||||
while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) ==
|
||||
ARCHIVE_OK) {
|
||||
const char *p = buff;
|
||||
if (target_offset > actual_offset) {
|
||||
r = pad_to(a, fd, can_lseek, nulls_size, nulls,
|
||||
target_offset, actual_offset);
|
||||
if (r != ARCHIVE_OK)
|
||||
break;
|
||||
actual_offset = target_offset;
|
||||
}
|
||||
while (size > 0) {
|
||||
bytes_to_write = size;
|
||||
if (bytes_to_write > MAX_WRITE)
|
||||
bytes_to_write = MAX_WRITE;
|
||||
bytes_written = write(fd, p, bytes_to_write);
|
||||
if (bytes_written < 0) {
|
||||
archive_set_error(a, errno, "Write error");
|
||||
r = ARCHIVE_FATAL;
|
||||
goto cleanup;
|
||||
}
|
||||
actual_offset += bytes_written;
|
||||
p += bytes_written;
|
||||
size -= bytes_written;
|
||||
}
|
||||
}
|
||||
|
||||
if (r == ARCHIVE_EOF && target_offset > actual_offset) {
|
||||
r2 = pad_to(a, fd, can_lseek, nulls_size, nulls,
|
||||
target_offset, actual_offset);
|
||||
if (r2 != ARCHIVE_OK)
|
||||
r = r2;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(nulls);
|
||||
if (r != ARCHIVE_EOF)
|
||||
return (r);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
315
Utilities/cmlibarchive/libarchive/archive_read_disk.3
Normal file
315
Utilities/cmlibarchive/libarchive/archive_read_disk.3
Normal file
@ -0,0 +1,315 @@
|
||||
.\" Copyright (c) 2003-2009 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: head/lib/libarchive/archive_read_disk.3 190957 2009-04-12 05:04:02Z kientzle $
|
||||
.\"
|
||||
.Dd March 10, 2009
|
||||
.Dt archive_read_disk 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_disk_new ,
|
||||
.Nm archive_read_disk_set_symlink_logical ,
|
||||
.Nm archive_read_disk_set_symlink_physical ,
|
||||
.Nm archive_read_disk_set_symlink_hybrid ,
|
||||
.Nm archive_read_disk_entry_from_file ,
|
||||
.Nm archive_read_disk_gname ,
|
||||
.Nm archive_read_disk_uname ,
|
||||
.Nm archive_read_disk_set_uname_lookup ,
|
||||
.Nm archive_read_disk_set_gname_lookup ,
|
||||
.Nm archive_read_disk_set_standard_lookup ,
|
||||
.Nm archive_read_close ,
|
||||
.Nm archive_read_finish ,
|
||||
.Nm archive_read_free
|
||||
.Nd functions for reading objects from disk
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft struct archive *
|
||||
.Fn archive_read_disk_new "void"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_set_symlink_logical "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_set_symlink_physical "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_set_symlink_hybrid "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_gname "struct archive *" "gid_t"
|
||||
.Ft int
|
||||
.Fn archive_read_disk_uname "struct archive *" "uid_t"
|
||||
.Ft int
|
||||
.Fo archive_read_disk_set_gname_lookup
|
||||
.Fa "struct archive *"
|
||||
.Fa "void *"
|
||||
.Fa "const char *(*lookup)(void *, gid_t)"
|
||||
.Fa "void (*cleanup)(void *)"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_disk_set_uname_lookup
|
||||
.Fa "struct archive *"
|
||||
.Fa "void *"
|
||||
.Fa "const char *(*lookup)(void *, uid_t)"
|
||||
.Fa "void (*cleanup)(void *)"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_read_disk_set_standard_lookup "struct archive *"
|
||||
.Ft int
|
||||
.Fo archive_read_disk_entry_from_file
|
||||
.Fa "struct archive *"
|
||||
.Fa "struct archive_entry *"
|
||||
.Fa "int fd"
|
||||
.Fa "const struct stat *"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_read_close "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_finish "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_free "struct archive *"
|
||||
.Sh DESCRIPTION
|
||||
These functions provide an API for reading information about
|
||||
objects on disk.
|
||||
In particular, they provide an interface for populating
|
||||
.Tn struct archive_entry
|
||||
objects.
|
||||
.Bl -tag -width indent
|
||||
.It Fn archive_read_disk_new
|
||||
Allocates and initializes a
|
||||
.Tn struct archive
|
||||
object suitable for reading object information from disk.
|
||||
.It Xo
|
||||
.Fn archive_read_disk_set_symlink_logical ,
|
||||
.Fn archive_read_disk_set_symlink_physical ,
|
||||
.Fn archive_read_disk_set_symlink_hybrid
|
||||
.Xc
|
||||
This sets the mode used for handling symbolic links.
|
||||
The
|
||||
.Dq logical
|
||||
mode follows all symbolic links.
|
||||
The
|
||||
.Dq physical
|
||||
mode does not follow any symbolic links.
|
||||
The
|
||||
.Dq hybrid
|
||||
mode currently behaves identically to the
|
||||
.Dq logical
|
||||
mode.
|
||||
.It Xo
|
||||
.Fn archive_read_disk_gname ,
|
||||
.Fn archive_read_disk_uname
|
||||
.Xc
|
||||
Returns a user or group name given a gid or uid value.
|
||||
By default, these always return a NULL string.
|
||||
.It Xo
|
||||
.Fn archive_read_disk_set_gname_lookup ,
|
||||
.Fn archive_read_disk_set_uname_lookup
|
||||
.Xc
|
||||
These allow you to override the functions used for
|
||||
user and group name lookups.
|
||||
You may also provide a
|
||||
.Tn void *
|
||||
pointer to a private data structure and a cleanup function for
|
||||
that data.
|
||||
The cleanup function will be invoked when the
|
||||
.Tn struct archive
|
||||
object is destroyed or when new lookup functions are registered.
|
||||
.It Fn archive_read_disk_set_standard_lookup
|
||||
This convenience function installs a standard set of user
|
||||
and group name lookup functions.
|
||||
These functions use
|
||||
.Xr getpwuid 3
|
||||
and
|
||||
.Xr getgrgid 3
|
||||
to convert ids to names, defaulting to NULL if the names cannot
|
||||
be looked up.
|
||||
These functions also implement a simple memory cache to reduce
|
||||
the number of calls to
|
||||
.Xr getpwuid 3
|
||||
and
|
||||
.Xr getgrgid 3 .
|
||||
.It Fn archive_read_disk_entry_from_file
|
||||
Populates a
|
||||
.Tn struct archive_entry
|
||||
object with information about a particular file.
|
||||
The
|
||||
.Tn archive_entry
|
||||
object must have already been created with
|
||||
.Xr archive_entry_new 3
|
||||
and at least one of the source path or path fields must already be set.
|
||||
(If both are set, the source path will be used.)
|
||||
.Pp
|
||||
Information is read from disk using the path name from the
|
||||
.Tn struct archive_entry
|
||||
object.
|
||||
If a file descriptor is provided, some information will be obtained using
|
||||
that file descriptor, on platforms that support the appropriate
|
||||
system calls.
|
||||
.Pp
|
||||
If a pointer to a
|
||||
.Tn struct stat
|
||||
is provided, information from that structure will be used instead
|
||||
of reading from the disk where appropriate.
|
||||
This can provide performance benefits in scenarios where
|
||||
.Tn struct stat
|
||||
information has already been read from the disk as a side effect
|
||||
of some other operation.
|
||||
(For example, directory traversal libraries often provide this information.)
|
||||
.Pp
|
||||
Where necessary, user and group ids are converted to user and group names
|
||||
using the currently registered lookup functions above.
|
||||
This affects the file ownership fields and ACL values in the
|
||||
.Tn struct archive_entry
|
||||
object.
|
||||
.It Fn archive_read_close
|
||||
Does nothing for
|
||||
.Tn archive_read_disk
|
||||
handles.
|
||||
.It Fn archive_read_finish
|
||||
This is a deprecated synonym for
|
||||
.Fn archive_read_free .
|
||||
.It Fn archive_read_free
|
||||
Invokes
|
||||
.Fn archive_read_close
|
||||
if it was not invoked manually, then releases all resources.
|
||||
.El
|
||||
More information about the
|
||||
.Va struct archive
|
||||
object and the overall design of the library can be found in the
|
||||
.Xr libarchive 3
|
||||
overview.
|
||||
.Sh EXAMPLE
|
||||
The following illustrates basic usage of the library by
|
||||
showing how to use it to copy an item on disk into an archive.
|
||||
.Bd -literal -offset indent
|
||||
void
|
||||
file_to_archive(struct archive *a, const char *name)
|
||||
{
|
||||
char buff[8192];
|
||||
size_t bytes_read;
|
||||
struct archive *ard;
|
||||
struct archive_entry *entry;
|
||||
int fd;
|
||||
|
||||
ard = archive_read_disk_new();
|
||||
archive_read_disk_set_standard_lookup(ard);
|
||||
entry = archive_entry_new();
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
archive_entry_copy_pathname(entry, name);
|
||||
archive_read_disk_entry_from_file(ard, entry, fd, NULL);
|
||||
archive_write_header(a, entry);
|
||||
while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
|
||||
archive_write_data(a, buff, bytes_read);
|
||||
archive_write_finish_entry(a);
|
||||
archive_read_free(ard);
|
||||
archive_entry_free(entry);
|
||||
}
|
||||
.Ed
|
||||
.Sh RETURN VALUES
|
||||
Most functions return
|
||||
.Cm ARCHIVE_OK
|
||||
(zero) on success, or one of several negative
|
||||
error codes for errors.
|
||||
Specific error codes include:
|
||||
.Cm ARCHIVE_RETRY
|
||||
for operations that might succeed if retried,
|
||||
.Cm ARCHIVE_WARN
|
||||
for unusual conditions that do not prevent further operations, and
|
||||
.Cm ARCHIVE_FATAL
|
||||
for serious errors that make remaining operations impossible.
|
||||
.Pp
|
||||
.Fn archive_read_disk_new
|
||||
returns a pointer to a newly-allocated
|
||||
.Tn struct archive
|
||||
object or NULL if the allocation failed for any reason.
|
||||
.Pp
|
||||
.Fn archive_read_disk_gname
|
||||
and
|
||||
.Fn archive_read_disk_uname
|
||||
return
|
||||
.Tn const char *
|
||||
pointers to the textual name or NULL if the lookup failed for any reason.
|
||||
The returned pointer points to internal storage that
|
||||
may be reused on the next call to either of these functions;
|
||||
callers should copy the string if they need to continue accessing it.
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr archive_write 3 ,
|
||||
.Xr archive_write_disk 3 ,
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm libarchive
|
||||
library first appeared in
|
||||
.Fx 5.3 .
|
||||
The
|
||||
.Nm archive_read_disk
|
||||
interface was added to
|
||||
.Nm libarchive 2.6
|
||||
and first appeared in
|
||||
.Fx 8.0 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm libarchive
|
||||
library was written by
|
||||
.An Tim Kientzle Aq kientzle@freebsd.org .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Dq standard
|
||||
user name and group name lookup functions are not the defaults because
|
||||
.Xr getgrgid 3
|
||||
and
|
||||
.Xr getpwuid 3
|
||||
are sometimes too large for particular applications.
|
||||
The current design allows the application author to use a more
|
||||
compact implementation when appropriate.
|
||||
.Pp
|
||||
The full list of metadata read from disk by
|
||||
.Fn archive_read_disk_entry_from_file
|
||||
is necessarily system-dependent.
|
||||
.Pp
|
||||
The
|
||||
.Fn archive_read_disk_entry_from_file
|
||||
function reads as much information as it can from disk.
|
||||
Some method should be provided to limit this so that clients who
|
||||
do not need ACLs, for instance, can avoid the extra work needed
|
||||
to look up such information.
|
||||
.Pp
|
||||
This API should provide a set of methods for walking a directory tree.
|
||||
That would make it a direct parallel of the
|
||||
.Xr archive_read 3
|
||||
API.
|
||||
When such methods are implemented, the
|
||||
.Dq hybrid
|
||||
symbolic link mode will make sense.
|
File diff suppressed because it is too large
Load Diff
2309
Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
Normal file
2309
Utilities/cmlibarchive/libarchive/archive_read_disk_posix.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,71 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2009 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_read_disk_private.h 201105 2009-12-28 03:20:54Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED
|
||||
|
||||
struct tree;
|
||||
|
||||
struct archive_read_disk {
|
||||
struct archive archive;
|
||||
|
||||
/*
|
||||
* Symlink mode is one of 'L'ogical, 'P'hysical, or 'H'ybrid,
|
||||
* following an old BSD convention. 'L' follows all symlinks,
|
||||
* 'P' follows none, 'H' follows symlinks only for the first
|
||||
* item.
|
||||
*/
|
||||
char symlink_mode;
|
||||
|
||||
/*
|
||||
* Since symlink interaction changes, we need to track whether
|
||||
* we're following symlinks for the current item. 'L' mode above
|
||||
* sets this true, 'P' sets it false, 'H' changes it as we traverse.
|
||||
*/
|
||||
char follow_symlinks; /* Either 'L' or 'P'. */
|
||||
|
||||
/* Directory traversals. */
|
||||
struct tree *tree;
|
||||
|
||||
/* Set 1 if users request to restore atime . */
|
||||
int restore_time;
|
||||
int entry_wd_fd;
|
||||
|
||||
const char * (*lookup_gname)(void *private, int64_t gid);
|
||||
void (*cleanup_gname)(void *private);
|
||||
void *lookup_gname_data;
|
||||
const char * (*lookup_uname)(void *private, int64_t uid);
|
||||
void (*cleanup_uname)(void *private);
|
||||
void *lookup_uname_data;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,311 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_set_standard_lookup.c 201109 2009-12-28 03:30:31Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
int
|
||||
archive_read_disk_set_standard_lookup(struct archive *a)
|
||||
{
|
||||
archive_set_error(a, -1, "Standard lookups not available on Windows");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else /* ! (_WIN32 && !__CYGWIN__) */
|
||||
#define name_cache_size 127
|
||||
|
||||
static const char * const NO_NAME = "(noname)";
|
||||
|
||||
struct name_cache {
|
||||
struct archive *archive;
|
||||
char *buff;
|
||||
size_t buff_size;
|
||||
int probes;
|
||||
int hits;
|
||||
size_t size;
|
||||
struct {
|
||||
id_t id;
|
||||
const char *name;
|
||||
} cache[name_cache_size];
|
||||
};
|
||||
|
||||
static const char * lookup_gname(void *, int64_t);
|
||||
static const char * lookup_uname(void *, int64_t);
|
||||
static void cleanup(void *);
|
||||
static const char * lookup_gname_helper(struct name_cache *, id_t gid);
|
||||
static const char * lookup_uname_helper(struct name_cache *, id_t uid);
|
||||
|
||||
/*
|
||||
* Installs functions that use getpwuid()/getgrgid()---along with
|
||||
* a simple cache to accelerate such lookups---into the archive_read_disk
|
||||
* object. This is in a separate file because getpwuid()/getgrgid()
|
||||
* can pull in a LOT of library code (including NIS/LDAP functions, which
|
||||
* pull in DNS resolveers, etc). This can easily top 500kB, which makes
|
||||
* it inappropriate for some space-constrained applications.
|
||||
*
|
||||
* Applications that are size-sensitive may want to just use the
|
||||
* real default functions (defined in archive_read_disk.c) that just
|
||||
* use the uid/gid without the lookup. Or define your own custom functions
|
||||
* if you prefer.
|
||||
*/
|
||||
int
|
||||
archive_read_disk_set_standard_lookup(struct archive *a)
|
||||
{
|
||||
struct name_cache *ucache = malloc(sizeof(struct name_cache));
|
||||
struct name_cache *gcache = malloc(sizeof(struct name_cache));
|
||||
|
||||
if (ucache == NULL || gcache == NULL) {
|
||||
archive_set_error(a, ENOMEM,
|
||||
"Can't allocate uname/gname lookup cache");
|
||||
free(ucache);
|
||||
free(gcache);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
memset(ucache, 0, sizeof(*ucache));
|
||||
ucache->archive = a;
|
||||
ucache->size = name_cache_size;
|
||||
memset(gcache, 0, sizeof(*gcache));
|
||||
gcache->archive = a;
|
||||
gcache->size = name_cache_size;
|
||||
|
||||
archive_read_disk_set_gname_lookup(a, gcache, lookup_gname, cleanup);
|
||||
archive_read_disk_set_uname_lookup(a, ucache, lookup_uname, cleanup);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(void *data)
|
||||
{
|
||||
struct name_cache *cache = (struct name_cache *)data;
|
||||
size_t i;
|
||||
|
||||
if (cache != NULL) {
|
||||
for (i = 0; i < cache->size; i++) {
|
||||
if (cache->cache[i].name != NULL &&
|
||||
cache->cache[i].name != NO_NAME)
|
||||
free((void *)(uintptr_t)cache->cache[i].name);
|
||||
}
|
||||
free(cache->buff);
|
||||
free(cache);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup uid/gid from uname/gname, return NULL if no match.
|
||||
*/
|
||||
static const char *
|
||||
lookup_name(struct name_cache *cache,
|
||||
const char * (*lookup_fn)(struct name_cache *, id_t), id_t id)
|
||||
{
|
||||
const char *name;
|
||||
int slot;
|
||||
|
||||
|
||||
cache->probes++;
|
||||
|
||||
slot = id % cache->size;
|
||||
if (cache->cache[slot].name != NULL) {
|
||||
if (cache->cache[slot].id == id) {
|
||||
cache->hits++;
|
||||
if (cache->cache[slot].name == NO_NAME)
|
||||
return (NULL);
|
||||
return (cache->cache[slot].name);
|
||||
}
|
||||
if (cache->cache[slot].name != NO_NAME)
|
||||
free((void *)(uintptr_t)cache->cache[slot].name);
|
||||
cache->cache[slot].name = NULL;
|
||||
}
|
||||
|
||||
name = (lookup_fn)(cache, id);
|
||||
if (name == NULL) {
|
||||
/* Cache and return the negative response. */
|
||||
cache->cache[slot].name = NO_NAME;
|
||||
cache->cache[slot].id = id;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cache->cache[slot].name = name;
|
||||
cache->cache[slot].id = id;
|
||||
return (cache->cache[slot].name);
|
||||
}
|
||||
|
||||
static const char *
|
||||
lookup_uname(void *data, int64_t uid)
|
||||
{
|
||||
struct name_cache *uname_cache = (struct name_cache *)data;
|
||||
return (lookup_name(uname_cache,
|
||||
&lookup_uname_helper, (id_t)uid));
|
||||
}
|
||||
|
||||
#if HAVE_GETPWUID_R
|
||||
static const char *
|
||||
lookup_uname_helper(struct name_cache *cache, id_t id)
|
||||
{
|
||||
struct passwd pwent, *result;
|
||||
char * nbuff;
|
||||
size_t nbuff_size;
|
||||
int r;
|
||||
|
||||
if (cache->buff_size == 0) {
|
||||
cache->buff_size = 256;
|
||||
cache->buff = malloc(cache->buff_size);
|
||||
}
|
||||
if (cache->buff == NULL)
|
||||
return (NULL);
|
||||
for (;;) {
|
||||
result = &pwent; /* Old getpwuid_r ignores last arg. */
|
||||
r = getpwuid_r((uid_t)id, &pwent,
|
||||
cache->buff, cache->buff_size, &result);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
/* ERANGE means our buffer was too small, but POSIX
|
||||
* doesn't tell us how big the buffer should be, so
|
||||
* we just double it and try again. Because the buffer
|
||||
* is kept around in the cache object, we shouldn't
|
||||
* have to do this very often. */
|
||||
nbuff_size = cache->buff_size * 2;
|
||||
nbuff = realloc(cache->buff, nbuff_size);
|
||||
if (nbuff == NULL)
|
||||
break;
|
||||
cache->buff = nbuff;
|
||||
cache->buff_size = nbuff_size;
|
||||
}
|
||||
if (r != 0) {
|
||||
archive_set_error(cache->archive, errno,
|
||||
"Can't lookup user for id %d", (int)id);
|
||||
return (NULL);
|
||||
}
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
return strdup(result->pw_name);
|
||||
}
|
||||
#else
|
||||
static const char *
|
||||
lookup_uname_helper(struct name_cache *cache, id_t id)
|
||||
{
|
||||
struct passwd *result;
|
||||
|
||||
result = getpwuid((uid_t)id);
|
||||
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
return strdup(result->pw_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *
|
||||
lookup_gname(void *data, int64_t gid)
|
||||
{
|
||||
struct name_cache *gname_cache = (struct name_cache *)data;
|
||||
return (lookup_name(gname_cache,
|
||||
&lookup_gname_helper, (id_t)gid));
|
||||
}
|
||||
|
||||
#if HAVE_GETGRGID_R
|
||||
static const char *
|
||||
lookup_gname_helper(struct name_cache *cache, id_t id)
|
||||
{
|
||||
struct group grent, *result;
|
||||
char * nbuff;
|
||||
size_t nbuff_size;
|
||||
int r;
|
||||
|
||||
if (cache->buff_size == 0) {
|
||||
cache->buff_size = 256;
|
||||
cache->buff = malloc(cache->buff_size);
|
||||
}
|
||||
if (cache->buff == NULL)
|
||||
return (NULL);
|
||||
for (;;) {
|
||||
result = &grent; /* Old getgrgid_r ignores last arg. */
|
||||
r = getgrgid_r((gid_t)id, &grent,
|
||||
cache->buff, cache->buff_size, &result);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r != ERANGE)
|
||||
break;
|
||||
/* ERANGE means our buffer was too small, but POSIX
|
||||
* doesn't tell us how big the buffer should be, so
|
||||
* we just double it and try again. */
|
||||
nbuff_size = cache->buff_size * 2;
|
||||
nbuff = realloc(cache->buff, nbuff_size);
|
||||
if (nbuff == NULL)
|
||||
break;
|
||||
cache->buff = nbuff;
|
||||
cache->buff_size = nbuff_size;
|
||||
}
|
||||
if (r != 0) {
|
||||
archive_set_error(cache->archive, errno,
|
||||
"Can't lookup group for id %d", (int)id);
|
||||
return (NULL);
|
||||
}
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
return strdup(result->gr_name);
|
||||
}
|
||||
#else
|
||||
static const char *
|
||||
lookup_gname_helper(struct name_cache *cache, id_t id)
|
||||
{
|
||||
struct group *result;
|
||||
|
||||
result = getgrgid((gid_t)id);
|
||||
|
||||
if (result == NULL)
|
||||
return (NULL);
|
||||
|
||||
return strdup(result->gr_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! (_WIN32 && !__CYGWIN__) */
|
1983
Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
Normal file
1983
Utilities/cmlibarchive/libarchive/archive_read_disk_windows.c
Normal file
File diff suppressed because it is too large
Load Diff
135
Utilities/cmlibarchive/libarchive/archive_read_extract.3
Normal file
135
Utilities/cmlibarchive/libarchive/archive_read_extract.3
Normal file
@ -0,0 +1,135 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 22, 2011
|
||||
.Dt archive_read_extract 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_extract ,
|
||||
.Nm archive_read_extract2 ,
|
||||
.Nm archive_read_extract_set_progress_callback
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft int
|
||||
.Fo archive_read_extract
|
||||
.Fa "struct archive *"
|
||||
.Fa "struct archive_entry *"
|
||||
.Fa "int flags"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_extract2
|
||||
.Fa "struct archive *src"
|
||||
.Fa "struct archive_entry *"
|
||||
.Fa "struct archive *dest"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo archive_read_extract_set_progress_callback
|
||||
.Fa "struct archive *"
|
||||
.Fa "void (*func)(void *)"
|
||||
.Fa "void *user_data"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_read_extract , Fn archive_read_extract_set_skip_file
|
||||
A convenience function that wraps the corresponding
|
||||
.Xr archive_write_disk 3
|
||||
interfaces.
|
||||
The first call to
|
||||
.Fn archive_read_extract
|
||||
creates a restore object using
|
||||
.Xr archive_write_disk_new 3
|
||||
and
|
||||
.Xr archive_write_disk_set_standard_lookup 3 ,
|
||||
then transparently invokes
|
||||
.Xr archive_write_disk_set_options 3 ,
|
||||
.Xr archive_write_header 3 ,
|
||||
.Xr archive_write_data 3 ,
|
||||
and
|
||||
.Xr archive_write_finish_entry 3
|
||||
to create the entry on disk and copy data into it.
|
||||
The
|
||||
.Va flags
|
||||
argument is passed unmodified to
|
||||
.Xr archive_write_disk_set_options 3 .
|
||||
.It Fn archive_read_extract2
|
||||
This is another version of
|
||||
.Fn archive_read_extract
|
||||
that allows you to provide your own restore object.
|
||||
In particular, this allows you to override the standard lookup functions
|
||||
using
|
||||
.Xr archive_write_disk_set_group_lookup 3 ,
|
||||
and
|
||||
.Xr archive_write_disk_set_user_lookup 3 .
|
||||
Note that
|
||||
.Fn archive_read_extract2
|
||||
does not accept a
|
||||
.Va flags
|
||||
argument; you should use
|
||||
.Fn archive_write_disk_set_options
|
||||
to set the restore options yourself.
|
||||
.It Fn archive_read_extract_set_progress_callback
|
||||
Sets a pointer to a user-defined callback that can be used
|
||||
for updating progress displays during extraction.
|
||||
The progress function will be invoked during the extraction of large
|
||||
regular files.
|
||||
The progress function will be invoked with the pointer provided to this call.
|
||||
Generally, the data pointed to should include a reference to the archive
|
||||
object and the archive_entry object so that various statistics
|
||||
can be retrieved for the progress display.
|
||||
.El
|
||||
.\"
|
||||
.Sh RETURN VALUES
|
||||
Most functions return zero on success, non-zero on error.
|
||||
The possible return codes include:
|
||||
.Cm ARCHIVE_OK
|
||||
(the operation succeeded),
|
||||
.Cm ARCHIVE_WARN
|
||||
(the operation succeeded but a non-critical error was encountered),
|
||||
.Cm ARCHIVE_EOF
|
||||
(end-of-archive was encountered),
|
||||
.Cm ARCHIVE_RETRY
|
||||
(the operation failed but can be retried),
|
||||
and
|
||||
.Cm ARCHIVE_FATAL
|
||||
(there was a fatal error; the archive should be closed immediately).
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_open 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
183
Utilities/cmlibarchive/libarchive/archive_read_extract.c
Normal file
183
Utilities/cmlibarchive/libarchive/archive_read_extract.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $");
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_write_disk_private.h"
|
||||
|
||||
struct extract {
|
||||
struct archive *ad; /* archive_write_disk object */
|
||||
|
||||
/* Progress function invoked during extract. */
|
||||
void (*extract_progress)(void *);
|
||||
void *extract_progress_user_data;
|
||||
};
|
||||
|
||||
static int archive_read_extract_cleanup(struct archive_read *);
|
||||
static int copy_data(struct archive *ar, struct archive *aw);
|
||||
static struct extract *get_extract(struct archive_read *);
|
||||
|
||||
static struct extract *
|
||||
get_extract(struct archive_read *a)
|
||||
{
|
||||
/* If we haven't initialized, do it now. */
|
||||
/* This also sets up a lot of global state. */
|
||||
if (a->extract == NULL) {
|
||||
a->extract = (struct extract *)malloc(sizeof(*a->extract));
|
||||
if (a->extract == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't extract");
|
||||
return (NULL);
|
||||
}
|
||||
memset(a->extract, 0, sizeof(*a->extract));
|
||||
a->extract->ad = archive_write_disk_new();
|
||||
if (a->extract->ad == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM, "Can't extract");
|
||||
return (NULL);
|
||||
}
|
||||
archive_write_disk_set_standard_lookup(a->extract->ad);
|
||||
a->cleanup_archive_extract = archive_read_extract_cleanup;
|
||||
}
|
||||
return (a->extract);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_extract(struct archive *_a, struct archive_entry *entry, int flags)
|
||||
{
|
||||
struct extract *extract;
|
||||
|
||||
extract = get_extract((struct archive_read *)_a);
|
||||
if (extract == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
archive_write_disk_set_options(extract->ad, flags);
|
||||
return (archive_read_extract2(_a, entry, extract->ad));
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_extract2(struct archive *_a, struct archive_entry *entry,
|
||||
struct archive *ad)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r, r2;
|
||||
|
||||
/* Set up for this particular entry. */
|
||||
if (a->skip_file_set)
|
||||
archive_write_disk_set_skip_file(ad,
|
||||
a->skip_file_dev, a->skip_file_ino);
|
||||
r = archive_write_header(ad, entry);
|
||||
if (r < ARCHIVE_WARN)
|
||||
r = ARCHIVE_WARN;
|
||||
if (r != ARCHIVE_OK)
|
||||
/* If _write_header failed, copy the error. */
|
||||
archive_copy_error(&a->archive, ad);
|
||||
else if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) > 0)
|
||||
/* Otherwise, pour data into the entry. */
|
||||
r = copy_data(_a, ad);
|
||||
r2 = archive_write_finish_entry(ad);
|
||||
if (r2 < ARCHIVE_WARN)
|
||||
r2 = ARCHIVE_WARN;
|
||||
/* Use the first message. */
|
||||
if (r2 != ARCHIVE_OK && r == ARCHIVE_OK)
|
||||
archive_copy_error(&a->archive, ad);
|
||||
/* Use the worst error return. */
|
||||
if (r2 < r)
|
||||
r = r2;
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
archive_read_extract_set_progress_callback(struct archive *_a,
|
||||
void (*progress_func)(void *), void *user_data)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct extract *extract = get_extract(a);
|
||||
if (extract != NULL) {
|
||||
extract->extract_progress = progress_func;
|
||||
extract->extract_progress_user_data = user_data;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
copy_data(struct archive *ar, struct archive *aw)
|
||||
{
|
||||
int64_t offset;
|
||||
const void *buff;
|
||||
struct extract *extract;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
extract = get_extract((struct archive_read *)ar);
|
||||
if (extract == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
for (;;) {
|
||||
r = archive_read_data_block(ar, &buff, &size, &offset);
|
||||
if (r == ARCHIVE_EOF)
|
||||
return (ARCHIVE_OK);
|
||||
if (r != ARCHIVE_OK)
|
||||
return (r);
|
||||
r = archive_write_data_block(aw, buff, size, offset);
|
||||
if (r < ARCHIVE_WARN)
|
||||
r = ARCHIVE_WARN;
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(ar, archive_errno(aw),
|
||||
"%s", archive_error_string(aw));
|
||||
return (r);
|
||||
}
|
||||
if (extract->extract_progress)
|
||||
(extract->extract_progress)
|
||||
(extract->extract_progress_user_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup function for archive_extract.
|
||||
*/
|
||||
static int
|
||||
archive_read_extract_cleanup(struct archive_read *a)
|
||||
{
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
ret = archive_write_free(a->extract->ad);
|
||||
free(a->extract);
|
||||
a->extract = NULL;
|
||||
return (ret);
|
||||
}
|
127
Utilities/cmlibarchive/libarchive/archive_read_filter.3
Normal file
127
Utilities/cmlibarchive/libarchive/archive_read_filter.3
Normal file
@ -0,0 +1,127 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 19, 2011
|
||||
.Dt archive_read_filter 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_support_filter_all ,
|
||||
.Nm archive_read_support_filter_bzip2 ,
|
||||
.Nm archive_read_support_filter_compress ,
|
||||
.Nm archive_read_support_filter_gzip ,
|
||||
.Nm archive_read_support_filter_lzma ,
|
||||
.Nm archive_read_support_filter_none ,
|
||||
.Nm archive_read_support_filter_xz ,
|
||||
.Nm archive_read_support_filter_program ,
|
||||
.Nm archive_read_support_filter_program_signature
|
||||
.Nd functions for reading streaming archives
|
||||
.\"
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_all "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_bzip2 "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_compress "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_gzip "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_lzma "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_none "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_xz "struct archive *"
|
||||
.Ft int
|
||||
.Fo archive_read_support_filter_program
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *cmd"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_support_filter_program_signature
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *cmd"
|
||||
.Fa "const void *signature"
|
||||
.Fa "size_t signature_length"
|
||||
.Fc
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Xo
|
||||
.Fn archive_read_support_filter_bzip2 ,
|
||||
.Fn archive_read_support_filter_compress ,
|
||||
.Fn archive_read_support_filter_gzip ,
|
||||
.Fn archive_read_support_filter_lzma ,
|
||||
.Fn archive_read_support_filter_none ,
|
||||
.Fn archive_read_support_filter_xz
|
||||
.Xc
|
||||
Enables auto-detection code and decompression support for the
|
||||
specified compression.
|
||||
These functions may fall back on external programs if an appropriate
|
||||
library was not available at build time.
|
||||
Decompression using an external program is usually slower than
|
||||
decompression through built-in libraries.
|
||||
Note that
|
||||
.Dq none
|
||||
is always enabled by default.
|
||||
.It Fn archive_read_support_filter_all
|
||||
Enables all available decompression filters.
|
||||
.It Fn archive_read_support_filter_program
|
||||
Data is fed through the specified external program before being dearchived.
|
||||
Note that this disables automatic detection of the compression format,
|
||||
so it makes no sense to specify this in conjunction with any other
|
||||
decompression option.
|
||||
.It Fn archive_read_support_filter_program_signature
|
||||
This feeds data through the specified external program
|
||||
but only if the initial bytes of the data match the specified
|
||||
signature value.
|
||||
.El
|
||||
.\"
|
||||
.\". Sh EXAMPLE
|
||||
.\"
|
||||
.Sh RETURN VALUES
|
||||
These functions return
|
||||
.Cm ARCHIVE_OK
|
||||
if the compression is fully supported,
|
||||
.Cm ARCHIVE_WARN
|
||||
if the compression is supported only through an external program.
|
||||
.Pp
|
||||
.Fn archive_read_support_filter_none
|
||||
always succeeds.
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_format 3
|
175
Utilities/cmlibarchive/libarchive/archive_read_format.3
Normal file
175
Utilities/cmlibarchive/libarchive/archive_read_format.3
Normal file
@ -0,0 +1,175 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
|
||||
.\"
|
||||
.Dd March 19, 2011
|
||||
.Dt archive_read_format 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_support_format_7zip ,
|
||||
.Nm archive_read_support_format_all ,
|
||||
.Nm archive_read_support_format_ar ,
|
||||
.Nm archive_read_support_format_by_code ,
|
||||
.Nm archive_read_support_format_cab ,
|
||||
.Nm archive_read_support_format_cpio ,
|
||||
.Nm archive_read_support_format_empty ,
|
||||
.Nm archive_read_support_format_iso9660 ,
|
||||
.Nm archive_read_support_format_lha ,
|
||||
.Nm archive_read_support_format_mtree,
|
||||
.Nm archive_read_support_format_rar,
|
||||
.Nm archive_read_support_format_raw,
|
||||
.Nm archive_read_support_format_tar ,
|
||||
.Nm archive_read_support_format_xar ,
|
||||
.Nm archive_read_support_format_zip
|
||||
.Nd functions for reading streaming archives
|
||||
.\"
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_7zip "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_all "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_ar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_by_code "struct archive *" "int"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_cab "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_cpio "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_empty "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_iso9660 "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_lha "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_mtree "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_rar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_raw "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_tar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_xar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_zip "struct archive *"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Xo
|
||||
.Fn archive_read_support_format_7zip ,
|
||||
.Fn archive_read_support_format_ar ,
|
||||
.Fn archive_read_support_format_cab ,
|
||||
.Fn archive_read_support_format_cpio ,
|
||||
.Fn archive_read_support_format_iso9660 ,
|
||||
.Fn archive_read_support_format_lha ,
|
||||
.Fn archive_read_support_format_mtree ,
|
||||
.Fn archive_read_support_format_rar ,
|
||||
.Fn archive_read_support_format_raw ,
|
||||
.Fn archive_read_support_format_tar ,
|
||||
.Fn archive_read_support_format_xar ,
|
||||
.Fn archive_read_support_format_zip
|
||||
.Xc
|
||||
Enables support---including auto-detection code---for the
|
||||
specified archive format.
|
||||
For example,
|
||||
.Fn archive_read_support_format_tar
|
||||
enables support for a variety of standard tar formats, old-style tar,
|
||||
ustar, pax interchange format, and many common variants.
|
||||
.It Fn archive_read_support_format_all
|
||||
Enables support for all available formats except the
|
||||
.Dq raw
|
||||
format (see below).
|
||||
.It Fn archive_read_support_format_by_code
|
||||
Enables a single format specified by the format code.
|
||||
This can be useful when reading a single archive twice;
|
||||
use
|
||||
.Fn archive_format
|
||||
after reading the first time and pass the resulting code
|
||||
to this function to selectively enable only the necessary
|
||||
format support.
|
||||
Note: In statically-linked executables, this will cause
|
||||
your program to include support for every format.
|
||||
If executable size is a concern, you may wish to avoid
|
||||
using this function.
|
||||
.It Fn archive_read_support_format_empty
|
||||
Enables support for treating empty files as empty archives.
|
||||
Because empty files are valid for several different formats,
|
||||
it is not possible to accurately determine a format for
|
||||
an empty file based purely on contents.
|
||||
So empty files are treated by libarchive as a distinct
|
||||
format.
|
||||
.It Fn archive_read_support_format_raw
|
||||
The
|
||||
.Dq raw
|
||||
format handler allows libarchive to be used to read arbitrary data.
|
||||
It treats any data stream as an archive with a single entry.
|
||||
The pathname of this entry is
|
||||
.Dq data ;
|
||||
all other entry fields are unset.
|
||||
This is not enabled by
|
||||
.Fn archive_read_support_format_all
|
||||
in order to avoid erroneous handling of damaged archives.
|
||||
.El
|
||||
.\" .Sh EXAMPLE
|
||||
.Sh RETURN VALUES
|
||||
These functions return
|
||||
.Cm ARCHIVE_OK
|
||||
on success, or
|
||||
.Cm ARCHIVE_FATAL .
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
||||
.Sh BUGS
|
||||
Many traditional archiver programs treat
|
||||
empty files as valid empty archives.
|
||||
For example, many implementations of
|
||||
.Xr tar 1
|
||||
allow you to append entries to an empty file.
|
||||
Of course, it is impossible to determine the format of an empty file
|
||||
by inspecting the contents, so this library treats empty files as
|
||||
having a special
|
||||
.Dq empty
|
||||
format.
|
||||
.Pp
|
||||
Using the
|
||||
.Dq raw
|
||||
handler together with any other handler will often work
|
||||
but can produce surprising results.
|
91
Utilities/cmlibarchive/libarchive/archive_read_free.3
Normal file
91
Utilities/cmlibarchive/libarchive/archive_read_free.3
Normal file
@ -0,0 +1,91 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
|
||||
.\"
|
||||
.Dd March 20, 2011
|
||||
.Dt archive_read_free 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_close ,
|
||||
.Nm archive_read_finish ,
|
||||
.Nm archive_read_free
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft int
|
||||
.Fn archive_read_close "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_finish "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_free "struct archive *"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_read_close
|
||||
Complete the archive and invoke the close callback.
|
||||
.It Fn archive_read_finish
|
||||
This is a deprecated synonym for
|
||||
.Fn archive_read_free .
|
||||
The new name was introduced with libarchive 3.0.
|
||||
Applications that need to compile with either libarchive 2
|
||||
or libarchive 3 should continue to use the
|
||||
.Fn archive_read_finish
|
||||
name.
|
||||
Both names will be supported until libarchive 4.0 is
|
||||
released, which is not expected to occur earlier
|
||||
than 2013.
|
||||
.It Fn archive_read_free
|
||||
Invokes
|
||||
.Fn archive_read_close
|
||||
if it was not invoked manually, then release all resources.
|
||||
Note: In libarchive 1.x, this function was declared to return
|
||||
.Ft void ,
|
||||
which made it impossible to detect certain errors when
|
||||
.Fn archive_read_close
|
||||
was invoked implicitly from this function.
|
||||
The declaration is corrected beginning with libarchive 2.0.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
These functions return
|
||||
.Cm ARCHIVE_OK
|
||||
on success, or
|
||||
.Cm ARCHIVE_FATAL .
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read_new 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_open 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3
|
89
Utilities/cmlibarchive/libarchive/archive_read_header.3
Normal file
89
Utilities/cmlibarchive/libarchive/archive_read_header.3
Normal file
@ -0,0 +1,89 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 22, 2011
|
||||
.Dt archive_read_header 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_next_header ,
|
||||
.Nm archive_read_next_header2
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft int
|
||||
.Fn archive_read_next_header "struct archive *" "struct archive_entry **"
|
||||
.Ft int
|
||||
.Fn archive_read_next_header2 "struct archive *" "struct archive_entry *"
|
||||
.\"
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_read_next_header
|
||||
Read the header for the next entry and return a pointer to
|
||||
a
|
||||
.Tn struct archive_entry .
|
||||
This is a convenience wrapper around
|
||||
.Fn archive_read_next_header2
|
||||
that reuses an internal
|
||||
.Tn struct archive_entry
|
||||
object for each request.
|
||||
.It Fn archive_read_next_header2
|
||||
Read the header for the next entry and populate the provided
|
||||
.Tn struct archive_entry .
|
||||
.El
|
||||
.\"
|
||||
.Sh RETURN VALUES
|
||||
These functions return
|
||||
.Cm ARCHIVE_OK
|
||||
(the operation succeeded),
|
||||
.Cm ARCHIVE_WARN
|
||||
(the operation succeeded but a non-critical error was encountered),
|
||||
.Cm ARCHIVE_EOF
|
||||
(end-of-archive was encountered),
|
||||
.Cm ARCHIVE_RETRY
|
||||
(the operation failed but can be retried),
|
||||
and
|
||||
.Cm ARCHIVE_FATAL
|
||||
(there was a fatal error; the archive should be closed immediately).
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_extract 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_open 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
57
Utilities/cmlibarchive/libarchive/archive_read_new.3
Normal file
57
Utilities/cmlibarchive/libarchive/archive_read_new.3
Normal file
@ -0,0 +1,57 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
|
||||
.\"
|
||||
.Dd March 20, 2011
|
||||
.Dt archive_read_new 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_new
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft struct archive *
|
||||
.Fn archive_read_new "void"
|
||||
.Sh DESCRIPTION
|
||||
Allocates and initializes a
|
||||
.Tn struct archive
|
||||
object suitable for reading from an archive.
|
||||
.Dv NULL
|
||||
is returned on error.
|
||||
.Pp
|
||||
A complete description of the
|
||||
.Tn struct archive
|
||||
object can be found in the overview manual page for
|
||||
.Xr libarchive 3 .
|
||||
.\" .Sh ERRORS
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
231
Utilities/cmlibarchive/libarchive/archive_read_open.3
Normal file
231
Utilities/cmlibarchive/libarchive/archive_read_open.3
Normal file
@ -0,0 +1,231 @@
|
||||
.\" Copyright (c) 2003-2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: head/lib/libarchive/archive_read.3 191595 2009-04-27 20:13:13Z kientzle $
|
||||
.\"
|
||||
.Dd March 19, 2011
|
||||
.Dt archive_read_open 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_open ,
|
||||
.Nm archive_read_open2 ,
|
||||
.Nm archive_read_open_fd ,
|
||||
.Nm archive_read_open_FILE ,
|
||||
.Nm archive_read_open_filename ,
|
||||
.Nm archive_read_open_memory ,
|
||||
.Nd functions for reading streaming archives
|
||||
.Sh SYNOPSIS
|
||||
.In archive.h
|
||||
.Ft int
|
||||
.Fo archive_read_open
|
||||
.Fa "struct archive *"
|
||||
.Fa "void *client_data"
|
||||
.Fa "archive_open_callback *"
|
||||
.Fa "archive_read_callback *"
|
||||
.Fa "archive_close_callback *"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_open2
|
||||
.Fa "struct archive *"
|
||||
.Fa "void *client_data"
|
||||
.Fa "archive_open_callback *"
|
||||
.Fa "archive_read_callback *"
|
||||
.Fa "archive_skip_callback *"
|
||||
.Fa "archive_close_callback *"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_read_open_FILE "struct archive *" "FILE *file"
|
||||
.Ft int
|
||||
.Fn archive_read_open_fd "struct archive *" "int fd" "size_t block_size"
|
||||
.Ft int
|
||||
.Fo archive_read_open_filename
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *filename"
|
||||
.Fa "size_t block_size"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fn archive_read_open_memory "struct archive *" "void *buff" "size_t size"
|
||||
.Sh DESCRIPTION
|
||||
.Bl -tag -compact -width indent
|
||||
.It Fn archive_read_open
|
||||
The same as
|
||||
.Fn archive_read_open2 ,
|
||||
except that the skip callback is assumed to be
|
||||
.Dv NULL .
|
||||
.It Fn archive_read_open2
|
||||
Freeze the settings, open the archive, and prepare for reading entries.
|
||||
This is the most generic version of this call, which accepts
|
||||
four callback functions.
|
||||
Most clients will want to use
|
||||
.Fn archive_read_open_filename ,
|
||||
.Fn archive_read_open_FILE ,
|
||||
.Fn archive_read_open_fd ,
|
||||
or
|
||||
.Fn archive_read_open_memory
|
||||
instead.
|
||||
The library invokes the client-provided functions to obtain
|
||||
raw bytes from the archive.
|
||||
.It Fn archive_read_open_FILE
|
||||
Like
|
||||
.Fn archive_read_open ,
|
||||
except that it accepts a
|
||||
.Ft "FILE *"
|
||||
pointer.
|
||||
This function should not be used with tape drives or other devices
|
||||
that require strict I/O blocking.
|
||||
.It Fn archive_read_open_fd
|
||||
Like
|
||||
.Fn archive_read_open ,
|
||||
except that it accepts a file descriptor and block size rather than
|
||||
a set of function pointers.
|
||||
Note that the file descriptor will not be automatically closed at
|
||||
end-of-archive.
|
||||
This function is safe for use with tape drives or other blocked devices.
|
||||
.It Fn archive_read_open_file
|
||||
This is a deprecated synonym for
|
||||
.Fn archive_read_open_filename .
|
||||
.It Fn archive_read_open_filename
|
||||
Like
|
||||
.Fn archive_read_open ,
|
||||
except that it accepts a simple filename and a block size.
|
||||
A NULL filename represents standard input.
|
||||
This function is safe for use with tape drives or other blocked devices.
|
||||
.It Fn archive_read_open_memory
|
||||
Like
|
||||
.Fn archive_read_open ,
|
||||
except that it accepts a pointer and size of a block of
|
||||
memory containing the archive data.
|
||||
.El
|
||||
.Pp
|
||||
A complete description of the
|
||||
.Tn struct archive
|
||||
and
|
||||
.Tn struct archive_entry
|
||||
objects can be found in the overview manual page for
|
||||
.Xr libarchive 3 .
|
||||
.Sh CLIENT CALLBACKS
|
||||
The callback functions must match the following prototypes:
|
||||
.Bl -item -offset indent
|
||||
.It
|
||||
.Ft typedef ssize_t
|
||||
.Fo archive_read_callback
|
||||
.Fa "struct archive *"
|
||||
.Fa "void *client_data"
|
||||
.Fa "const void **buffer"
|
||||
.Fc
|
||||
.It
|
||||
.Ft typedef off_t
|
||||
.Fo archive_skip_callback
|
||||
.Fa "struct archive *"
|
||||
.Fa "void *client_data"
|
||||
.Fa "off_t request"
|
||||
.Fc
|
||||
.It
|
||||
.Ft typedef int
|
||||
.Fn archive_open_callback "struct archive *" "void *client_data"
|
||||
.It
|
||||
.Ft typedef int
|
||||
.Fn archive_close_callback "struct archive *" "void *client_data"
|
||||
.El
|
||||
.Pp
|
||||
The open callback is invoked by
|
||||
.Fn archive_open .
|
||||
It should return
|
||||
.Cm ARCHIVE_OK
|
||||
if the underlying file or data source is successfully
|
||||
opened.
|
||||
If the open fails, it should call
|
||||
.Fn archive_set_error
|
||||
to register an error code and message and return
|
||||
.Cm ARCHIVE_FATAL .
|
||||
.Pp
|
||||
The read callback is invoked whenever the library
|
||||
requires raw bytes from the archive.
|
||||
The read callback should read data into a buffer,
|
||||
set the
|
||||
.Li const void **buffer
|
||||
argument to point to the available data, and
|
||||
return a count of the number of bytes available.
|
||||
The library will invoke the read callback again
|
||||
only after it has consumed this data.
|
||||
The library imposes no constraints on the size
|
||||
of the data blocks returned.
|
||||
On end-of-file, the read callback should
|
||||
return zero.
|
||||
On error, the read callback should invoke
|
||||
.Fn archive_set_error
|
||||
to register an error code and message and
|
||||
return -1.
|
||||
.Pp
|
||||
The skip callback is invoked when the
|
||||
library wants to ignore a block of data.
|
||||
The return value is the number of bytes actually
|
||||
skipped, which may differ from the request.
|
||||
If the callback cannot skip data, it should return
|
||||
zero.
|
||||
If the skip callback is not provided (the
|
||||
function pointer is
|
||||
.Dv NULL ),
|
||||
the library will invoke the read function
|
||||
instead and simply discard the result.
|
||||
A skip callback can provide significant
|
||||
performance gains when reading uncompressed
|
||||
archives from slow disk drives or other media
|
||||
that can skip quickly.
|
||||
.Pp
|
||||
The close callback is invoked by archive_close when
|
||||
the archive processing is complete.
|
||||
The callback should return
|
||||
.Cm ARCHIVE_OK
|
||||
on success.
|
||||
On failure, the callback should invoke
|
||||
.Fn archive_set_error
|
||||
to register an error code and message and
|
||||
return
|
||||
.Cm ARCHIVE_FATAL.
|
||||
.\" .Sh EXAMPLE
|
||||
.\"
|
||||
.Sh RETURN VALUES
|
||||
These functions return
|
||||
.Cm ARCHIVE_OK
|
||||
on success, or
|
||||
.Cm ARCHIVE_FATAL .
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_read 3 ,
|
||||
.Xr archive_read_data 3 ,
|
||||
.Xr archive_read_filter 3 ,
|
||||
.Xr archive_read_format 3 ,
|
||||
.Xr archive_read_set_options 3 ,
|
||||
.Xr archive_util 3 ,
|
||||
.Xr tar 5
|
181
Utilities/cmlibarchive/libarchive/archive_read_open_fd.c
Normal file
181
Utilities/cmlibarchive/libarchive/archive_read_open_fd.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_fd.c 201103 2009-12-28 03:13:49Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
struct read_fd_data {
|
||||
int fd;
|
||||
size_t block_size;
|
||||
char use_lseek;
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
static int file_close(struct archive *, void *);
|
||||
static ssize_t file_read(struct archive *, void *, const void **buff);
|
||||
static int64_t file_skip(struct archive *, void *, int64_t request);
|
||||
|
||||
int
|
||||
archive_read_open_fd(struct archive *a, int fd, size_t block_size)
|
||||
{
|
||||
struct stat st;
|
||||
struct read_fd_data *mine;
|
||||
void *b;
|
||||
|
||||
archive_clear_error(a);
|
||||
if (fstat(fd, &st) != 0) {
|
||||
archive_set_error(a, errno, "Can't stat fd %d", fd);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
mine = (struct read_fd_data *)calloc(1, sizeof(*mine));
|
||||
b = malloc(block_size);
|
||||
if (mine == NULL || b == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
free(mine);
|
||||
free(b);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
mine->block_size = block_size;
|
||||
mine->buffer = b;
|
||||
mine->fd = fd;
|
||||
/*
|
||||
* Skip support is a performance optimization for anything
|
||||
* that supports lseek(). On FreeBSD, only regular files and
|
||||
* raw disk devices support lseek() and there's no portable
|
||||
* way to determine if a device is a raw disk device, so we
|
||||
* only enable this optimization for regular files.
|
||||
*/
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
mine->use_lseek = 1;
|
||||
}
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(mine->fd, O_BINARY);
|
||||
#endif
|
||||
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
file_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
ssize_t bytes_read;
|
||||
|
||||
*buff = mine->buffer;
|
||||
for (;;) {
|
||||
bytes_read = read(mine->fd, mine->buffer, mine->block_size);
|
||||
if (bytes_read < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
archive_set_error(a, errno, "Error reading fd %d", mine->fd);
|
||||
}
|
||||
return (bytes_read);
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
off_t skip = (off_t)request;
|
||||
off_t old_offset, new_offset;
|
||||
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
|
||||
|
||||
if (!mine->use_lseek)
|
||||
return (0);
|
||||
|
||||
/* Reduce a request that would overflow the 'skip' variable. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
}
|
||||
|
||||
/* Reduce request to the next smallest multiple of block_size */
|
||||
request = (request / mine->block_size) * mine->block_size;
|
||||
if (request == 0)
|
||||
return (0);
|
||||
|
||||
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
|
||||
((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
|
||||
return (new_offset - old_offset);
|
||||
|
||||
/* If seek failed once, it will probably fail again. */
|
||||
mine->use_lseek = 0;
|
||||
|
||||
/* Let libarchive recover with read+discard. */
|
||||
if (errno == ESPIPE)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* There's been an error other than ESPIPE. This is most
|
||||
* likely caused by a programmer error (too large request)
|
||||
* or a corrupted archive file.
|
||||
*/
|
||||
archive_set_error(a, errno, "Error seeking");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
free(mine->buffer);
|
||||
free(mine);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
177
Utilities/cmlibarchive/libarchive/archive_read_open_file.c
Normal file
177
Utilities/cmlibarchive/libarchive/archive_read_open_file.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_file.c 201093 2009-12-28 02:28:44Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
struct read_FILE_data {
|
||||
FILE *f;
|
||||
size_t block_size;
|
||||
void *buffer;
|
||||
char can_skip;
|
||||
};
|
||||
|
||||
static int file_close(struct archive *, void *);
|
||||
static ssize_t file_read(struct archive *, void *, const void **buff);
|
||||
static int64_t file_skip(struct archive *, void *, int64_t request);
|
||||
|
||||
int
|
||||
archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
{
|
||||
struct stat st;
|
||||
struct read_FILE_data *mine;
|
||||
size_t block_size = 128 * 1024;
|
||||
void *b;
|
||||
|
||||
archive_clear_error(a);
|
||||
mine = (struct read_FILE_data *)malloc(sizeof(*mine));
|
||||
b = malloc(block_size);
|
||||
if (mine == NULL || b == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
free(mine);
|
||||
free(b);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
mine->block_size = block_size;
|
||||
mine->buffer = b;
|
||||
mine->f = f;
|
||||
/*
|
||||
* If we can't fstat() the file, it may just be that it's not
|
||||
* a file. (FILE * objects can wrap many kinds of I/O
|
||||
* streams, some of which don't support fileno()).)
|
||||
*/
|
||||
if (fstat(fileno(mine->f), &st) == 0 && S_ISREG(st.st_mode)) {
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
/* Enable the seek optimization only for regular files. */
|
||||
mine->can_skip = 1;
|
||||
} else
|
||||
mine->can_skip = 0;
|
||||
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(fileno(mine->f), O_BINARY);
|
||||
#endif
|
||||
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
file_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
ssize_t bytes_read;
|
||||
|
||||
*buff = mine->buffer;
|
||||
bytes_read = fread(mine->buffer, 1, mine->block_size, mine->f);
|
||||
if (bytes_read < 0) {
|
||||
archive_set_error(a, errno, "Error reading file");
|
||||
}
|
||||
return (bytes_read);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
#if HAVE_FSEEKO
|
||||
off_t skip = (off_t)request;
|
||||
#elif HAVE__FSEEKI64
|
||||
int64_t skip = request;
|
||||
#else
|
||||
long skip = (long)request;
|
||||
#endif
|
||||
int skip_bits = sizeof(skip) * 8 - 1;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
|
||||
/*
|
||||
* If we can't skip, return 0 as the amount we did step and
|
||||
* the caller will work around by reading and discarding.
|
||||
*/
|
||||
if (!mine->can_skip)
|
||||
return (0);
|
||||
if (request == 0)
|
||||
return (0);
|
||||
|
||||
/* If request is too big for a long or an off_t, reduce it. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
}
|
||||
|
||||
#if HAVE_FSEEKO
|
||||
if (fseeko(mine->f, skip, SEEK_CUR) != 0)
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
|
||||
#else
|
||||
if (fseek(mine->f, skip, SEEK_CUR) != 0)
|
||||
#endif
|
||||
{
|
||||
mine->can_skip = 0;
|
||||
return (0);
|
||||
}
|
||||
return (request);
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
if (mine->buffer != NULL)
|
||||
free(mine->buffer);
|
||||
free(mine);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
509
Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
Normal file
509
Utilities/cmlibarchive/libarchive/archive_read_open_filename.c
Normal file
@ -0,0 +1,509 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2010 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_filename.c 201093 2009-12-28 02:28:44Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#include <sys/disk.h>
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/dkio.h>
|
||||
#elif defined(__DragonFly__)
|
||||
#include <sys/diskslice.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
struct read_file_data {
|
||||
int fd;
|
||||
size_t block_size;
|
||||
void *buffer;
|
||||
mode_t st_mode; /* Mode bits for opened file. */
|
||||
char use_lseek;
|
||||
enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
|
||||
union {
|
||||
char m[1];/* MBS filename. */
|
||||
wchar_t w[1];/* WCS filename. */
|
||||
} filename; /* Must be last! */
|
||||
};
|
||||
|
||||
static int file_close(struct archive *, void *);
|
||||
static int file_open_filename(struct archive *, enum fnt_e, const void *,
|
||||
size_t);
|
||||
static ssize_t file_read(struct archive *, void *, const void **buff);
|
||||
static int64_t file_seek(struct archive *, void *, int64_t request, int);
|
||||
static int64_t file_skip(struct archive *, void *, int64_t request);
|
||||
static int64_t file_skip_lseek(struct archive *, void *, int64_t request);
|
||||
|
||||
int
|
||||
archive_read_open_file(struct archive *a, const char *filename,
|
||||
size_t block_size)
|
||||
{
|
||||
return (archive_read_open_filename(a, filename, block_size));
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_open_filename(struct archive *a, const char *filename,
|
||||
size_t block_size)
|
||||
{
|
||||
enum fnt_e filename_type;
|
||||
|
||||
if (filename == NULL || filename[0] == '\0') {
|
||||
filename_type = FNT_STDIN;
|
||||
} else
|
||||
filename_type = FNT_MBS;
|
||||
return (file_open_filename(a, filename_type, filename, block_size));
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_open_filename_w(struct archive *a, const wchar_t *wfilename,
|
||||
size_t block_size)
|
||||
{
|
||||
enum fnt_e filename_type;
|
||||
|
||||
if (wfilename == NULL || wfilename[0] == L'\0') {
|
||||
filename_type = FNT_STDIN;
|
||||
} else {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
filename_type = FNT_WCS;
|
||||
#else
|
||||
/*
|
||||
* POSIX system does not support a wchar_t interface for
|
||||
* open() system call, so we have to translate a whcar_t
|
||||
* filename to multi-byte one and use it.
|
||||
*/
|
||||
struct archive_string fn;
|
||||
int r;
|
||||
|
||||
archive_string_init(&fn);
|
||||
if (archive_string_append_from_wcs(&fn, wfilename,
|
||||
wcslen(wfilename)) != 0) {
|
||||
archive_set_error(a, EINVAL,
|
||||
"Failed to convert a wide-character filename to"
|
||||
" a multi-byte filename");
|
||||
archive_string_free(&fn);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
r = file_open_filename(a, FNT_MBS, fn.s, block_size);
|
||||
archive_string_free(&fn);
|
||||
return (r);
|
||||
#endif
|
||||
}
|
||||
return (file_open_filename(a, filename_type, wfilename, block_size));
|
||||
}
|
||||
|
||||
static int
|
||||
file_open_filename(struct archive *a, enum fnt_e filename_type,
|
||||
const void *_filename, size_t block_size)
|
||||
{
|
||||
struct stat st;
|
||||
struct read_file_data *mine;
|
||||
void *buffer;
|
||||
const char *filename = NULL;
|
||||
const wchar_t *wfilename = NULL;
|
||||
int fd;
|
||||
int is_disk_like = 0;
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct disklabel dl;
|
||||
#elif defined(__DragonFly__)
|
||||
struct partinfo pi;
|
||||
#endif
|
||||
|
||||
archive_clear_error(a);
|
||||
if (filename_type == FNT_STDIN) {
|
||||
/* We used to delegate stdin support by
|
||||
* directly calling archive_read_open_fd(a,0,block_size)
|
||||
* here, but that doesn't (and shouldn't) handle the
|
||||
* end-of-file flush when reading stdout from a pipe.
|
||||
* Basically, read_open_fd() is intended for folks who
|
||||
* are willing to handle such details themselves. This
|
||||
* API is intended to be a little smarter for folks who
|
||||
* want easy handling of the common case.
|
||||
*/
|
||||
fd = 0;
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(0, O_BINARY);
|
||||
#endif
|
||||
filename = "";
|
||||
} else if (filename_type == FNT_MBS) {
|
||||
filename = (const char *)_filename;
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
if (fd < 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to open '%s'", filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
} else {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
wfilename = (const wchar_t *)_filename;
|
||||
fd = _wopen(wfilename, O_RDONLY | O_BINARY);
|
||||
if (fd < 0 && errno == ENOENT) {
|
||||
wchar_t *fullpath;
|
||||
fullpath = __la_win_permissive_name_w(wfilename);
|
||||
if (fullpath != NULL) {
|
||||
fd = _wopen(fullpath, O_RDONLY | O_BINARY);
|
||||
free(fullpath);
|
||||
}
|
||||
}
|
||||
if (fd < 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to open '%S'", wfilename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unexpedted operation in archive_read_open_filename");
|
||||
return (ARCHIVE_FATAL);
|
||||
#endif
|
||||
}
|
||||
if (fstat(fd, &st) != 0) {
|
||||
if (filename_type == FNT_WCS)
|
||||
archive_set_error(a, errno, "Can't stat '%S'",
|
||||
wfilename);
|
||||
else
|
||||
archive_set_error(a, errno, "Can't stat '%s'",
|
||||
filename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether the input looks like a disk device or a
|
||||
* tape device. The results are used below to select an I/O
|
||||
* strategy:
|
||||
* = "disk-like" devices support arbitrary lseek() and will
|
||||
* support I/O requests of any size. So we get easy skipping
|
||||
* and can cheat on block sizes to get better performance.
|
||||
* = "tape-like" devices require strict blocking and use
|
||||
* specialized ioctls for seeking.
|
||||
* = "socket-like" devices cannot seek at all but can improve
|
||||
* performance by using nonblocking I/O to read "whatever is
|
||||
* available right now".
|
||||
*
|
||||
* Right now, we only specially recognize disk-like devices,
|
||||
* but it should be straightforward to add probes and strategy
|
||||
* here for tape-like and socket-like devices.
|
||||
*/
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
/* Safety: Tell the extractor not to overwrite the input. */
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
/* Regular files act like disks. */
|
||||
is_disk_like = 1;
|
||||
}
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
/* FreeBSD: if it supports DIOCGMEDIASIZE ioctl, it's disk-like. */
|
||||
else if (S_ISCHR(st.st_mode) &&
|
||||
ioctl(fd, DIOCGMEDIASIZE, &mediasize) == 0 &&
|
||||
mediasize > 0) {
|
||||
is_disk_like = 1;
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
/* Net/OpenBSD: if it supports DIOCGDINFO ioctl, it's disk-like. */
|
||||
else if ((S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) &&
|
||||
ioctl(fd, DIOCGDINFO, &dl) == 0 &&
|
||||
dl.d_partitions[DISKPART(st.st_rdev)].p_size > 0) {
|
||||
is_disk_like = 1;
|
||||
}
|
||||
#elif defined(__DragonFly__)
|
||||
/* DragonFly BSD: if it supports DIOCGPART ioctl, it's disk-like. */
|
||||
else if (S_ISCHR(st.st_mode) &&
|
||||
ioctl(fd, DIOCGPART, &pi) == 0 &&
|
||||
pi.media_size > 0) {
|
||||
is_disk_like = 1;
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
/* Linux: All block devices are disk-like. */
|
||||
else if (S_ISBLK(st.st_mode) &&
|
||||
lseek(fd, 0, SEEK_CUR) == 0 &&
|
||||
lseek(fd, 0, SEEK_SET) == 0 &&
|
||||
lseek(fd, 0, SEEK_END) > 0 &&
|
||||
lseek(fd, 0, SEEK_SET) == 0) {
|
||||
is_disk_like = 1;
|
||||
}
|
||||
#endif
|
||||
/* TODO: Add an "is_tape_like" variable and appropriate tests. */
|
||||
|
||||
if (filename_type == FNT_WCS)
|
||||
mine = (struct read_file_data *)calloc(1,
|
||||
sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t));
|
||||
else
|
||||
mine = (struct read_file_data *)calloc(1,
|
||||
sizeof(*mine) + strlen(filename));
|
||||
/* Disk-like devices prefer power-of-two block sizes. */
|
||||
/* Use provided block_size as a guide so users have some control. */
|
||||
if (is_disk_like) {
|
||||
size_t new_block_size = 64 * 1024;
|
||||
while (new_block_size < block_size
|
||||
&& new_block_size < 64 * 1024 * 1024)
|
||||
new_block_size *= 2;
|
||||
block_size = new_block_size;
|
||||
}
|
||||
buffer = malloc(block_size);
|
||||
if (mine == NULL || buffer == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
free(mine);
|
||||
free(buffer);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (filename_type == FNT_WCS)
|
||||
wcscpy(mine->filename.w, wfilename);
|
||||
else
|
||||
strcpy(mine->filename.m, filename);
|
||||
mine->filename_type = filename_type;
|
||||
mine->block_size = block_size;
|
||||
mine->buffer = buffer;
|
||||
mine->fd = fd;
|
||||
/* Remember mode so close can decide whether to flush. */
|
||||
mine->st_mode = st.st_mode;
|
||||
|
||||
/* Disk-like inputs can use lseek(). */
|
||||
if (is_disk_like) {
|
||||
archive_read_set_seek_callback(a, file_seek);
|
||||
mine->use_lseek = 1;
|
||||
}
|
||||
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
file_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
ssize_t bytes_read;
|
||||
|
||||
/* TODO: If a recent lseek() operation has left us
|
||||
* mis-aligned, read and return a short block to try to get
|
||||
* us back in alignment. */
|
||||
|
||||
/* TODO: Someday, try mmap() here; if that succeeds, give
|
||||
* the entire file to libarchive as a single block. That
|
||||
* could be a lot faster than block-by-block manual I/O. */
|
||||
|
||||
/* TODO: We might be able to improve performance on pipes and
|
||||
* sockets by setting non-blocking I/O and just accepting
|
||||
* whatever we get here instead of waiting for a full block
|
||||
* worth of data. */
|
||||
|
||||
*buff = mine->buffer;
|
||||
for (;;) {
|
||||
bytes_read = read(mine->fd, mine->buffer, mine->block_size);
|
||||
if (bytes_read < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if (mine->filename_type == FNT_STDIN)
|
||||
archive_set_error(a, errno,
|
||||
"Error reading stdin");
|
||||
else if (mine->filename_type == FNT_MBS)
|
||||
archive_set_error(a, errno,
|
||||
"Error reading '%s'", mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno,
|
||||
"Error reading '%S'", mine->filename.w);
|
||||
}
|
||||
return (bytes_read);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Regular files and disk-like block devices can use simple lseek
|
||||
* without needing to round the request to the block size.
|
||||
*
|
||||
* TODO: This can leave future reads mis-aligned. Since we know the
|
||||
* offset here, we should store it and use it in file_read() above
|
||||
* to determine whether we should perform a short read to get back
|
||||
* into alignment. Long series of mis-aligned reads can negatively
|
||||
* impact disk throughput. (Of course, the performance impact should
|
||||
* be carefully tested; extra code complexity is only worthwhile if
|
||||
* it does provide measurable improvement.)
|
||||
*
|
||||
* TODO: Be lazy about the actual seek. There are a few pathological
|
||||
* cases where libarchive makes a bunch of seek requests in a row
|
||||
* without any intervening reads. This isn't a huge performance
|
||||
* problem, since the kernel handles seeks lazily already, but
|
||||
* it would be very slightly faster if we simply remembered the
|
||||
* seek request here and then actually performed the seek at the
|
||||
* top of the read callback above.
|
||||
*/
|
||||
static int64_t
|
||||
file_skip_lseek(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* We use _lseeki64() on Windows. */
|
||||
int64_t old_offset, new_offset;
|
||||
#else
|
||||
off_t old_offset, new_offset;
|
||||
#endif
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
|
||||
/* TODO: Deal with case where off_t isn't 64 bits.
|
||||
* This shouldn't be a problem on Linux or other POSIX
|
||||
* systems, since the configuration logic for libarchive
|
||||
* tries to obtain a 64-bit off_t. It's still an issue
|
||||
* on Windows, though, so it might suffice to just use
|
||||
* _lseeki64() on Windows.
|
||||
*/
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
|
||||
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
|
||||
/* If lseek() fails, don't bother trying again. */
|
||||
mine->use_lseek = 0;
|
||||
|
||||
/* Let libarchive recover with read+discard */
|
||||
if (errno == ESPIPE)
|
||||
return (0);
|
||||
|
||||
/* If the input is corrupted or truncated, fail. */
|
||||
if (mine->filename_type == FNT_STDIN)
|
||||
archive_set_error(a, errno, "Error seeking in stdin");
|
||||
else if (mine->filename_type == FNT_MBS)
|
||||
archive_set_error(a, errno, "Error seeking in '%s'",
|
||||
mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno, "Error seeking in '%S'",
|
||||
mine->filename.w);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO: Implement another file_skip_XXXX that uses MTIO ioctls to
|
||||
* accelerate operation on tape drives.
|
||||
*/
|
||||
|
||||
static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
|
||||
/* Delegate skip requests. */
|
||||
if (mine->use_lseek)
|
||||
return (file_skip_lseek(a, client_data, request));
|
||||
|
||||
/* If we can't skip, return 0; libarchive will read+discard instead. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Store the offset and use it in the read callback.
|
||||
*/
|
||||
static int64_t
|
||||
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
off_t r;
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
/* See above for notes about when off_t is less than 64 bits. */
|
||||
r = lseek(mine->fd, request, whence);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
/* If the input is corrupted or truncated, fail. */
|
||||
if (mine->filename_type == FNT_STDIN)
|
||||
archive_set_error(a, errno, "Error seeking in stdin");
|
||||
else if (mine->filename_type == FNT_MBS)
|
||||
archive_set_error(a, errno, "Error seeking in '%s'",
|
||||
mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno, "Error seeking in '%S'",
|
||||
mine->filename.w);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
|
||||
/* Only flush and close if open succeeded. */
|
||||
if (mine->fd >= 0) {
|
||||
/*
|
||||
* Sometimes, we should flush the input before closing.
|
||||
* Regular files: faster to just close without flush.
|
||||
* Disk-like devices: Ditto.
|
||||
* Tapes: must not flush (user might need to
|
||||
* read the "next" item on a non-rewind device).
|
||||
* Pipes and sockets: must flush (otherwise, the
|
||||
* program feeding the pipe or socket may complain).
|
||||
* Here, I flush everything except for regular files and
|
||||
* device nodes.
|
||||
*/
|
||||
if (!S_ISREG(mine->st_mode)
|
||||
&& !S_ISCHR(mine->st_mode)
|
||||
&& !S_ISBLK(mine->st_mode)) {
|
||||
ssize_t bytesRead;
|
||||
do {
|
||||
bytesRead = read(mine->fd, mine->buffer,
|
||||
mine->block_size);
|
||||
} while (bytesRead > 0);
|
||||
}
|
||||
/* If a named file was opened, then it needs to be closed. */
|
||||
if (mine->filename_type != FNT_STDIN)
|
||||
close(mine->fd);
|
||||
}
|
||||
free(mine->buffer);
|
||||
free(mine);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
186
Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
Normal file
186
Utilities/cmlibarchive/libarchive/archive_read_open_memory.c
Normal file
@ -0,0 +1,186 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_open_memory.c,v 1.6 2007/07/06 15:51:59 kientzle Exp $");
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
/*
|
||||
* Glue to read an archive from a block of memory.
|
||||
*
|
||||
* This is mostly a huge help in building test harnesses;
|
||||
* test programs can build archives in memory and read them
|
||||
* back again without having to mess with files on disk.
|
||||
*/
|
||||
|
||||
struct read_memory_data {
|
||||
unsigned char *start;
|
||||
unsigned char *p;
|
||||
unsigned char *end;
|
||||
ssize_t read_size;
|
||||
};
|
||||
|
||||
static int memory_read_close(struct archive *, void *);
|
||||
static int memory_read_open(struct archive *, void *);
|
||||
static int64_t memory_read_seek(struct archive *, void *, int64_t offset, int whence);
|
||||
static int64_t memory_read_skip(struct archive *, void *, int64_t request);
|
||||
static ssize_t memory_read(struct archive *, void *, const void **buff);
|
||||
|
||||
int
|
||||
archive_read_open_memory(struct archive *a, void *buff, size_t size)
|
||||
{
|
||||
return archive_read_open_memory2(a, buff, size, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't use _open_memory2() in production code; the archive_read_open_memory()
|
||||
* version is the one you really want. This is just here so that
|
||||
* test harnesses can exercise block operations inside the library.
|
||||
*/
|
||||
int
|
||||
archive_read_open_memory2(struct archive *a, void *buff,
|
||||
size_t size, size_t read_size)
|
||||
{
|
||||
struct read_memory_data *mine;
|
||||
|
||||
mine = (struct read_memory_data *)malloc(sizeof(*mine));
|
||||
if (mine == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(mine, 0, sizeof(*mine));
|
||||
mine->start = mine->p = (unsigned char *)buff;
|
||||
mine->end = mine->start + size;
|
||||
mine->read_size = read_size;
|
||||
archive_read_set_open_callback(a, memory_read_open);
|
||||
archive_read_set_read_callback(a, memory_read);
|
||||
archive_read_set_seek_callback(a, memory_read_seek);
|
||||
archive_read_set_skip_callback(a, memory_read_skip);
|
||||
archive_read_set_close_callback(a, memory_read_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* There's nothing to open.
|
||||
*/
|
||||
static int
|
||||
memory_read_open(struct archive *a, void *client_data)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)client_data; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is scary simple: Just advance a pointer. Limiting
|
||||
* to read_size is not technically necessary, but it exercises
|
||||
* more of the internal logic when used with a small block size
|
||||
* in a test harness. Production use should not specify a block
|
||||
* size; then this is much faster.
|
||||
*/
|
||||
static ssize_t
|
||||
memory_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_memory_data *mine = (struct read_memory_data *)client_data;
|
||||
ssize_t size;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
*buff = mine->p;
|
||||
size = mine->end - mine->p;
|
||||
if (size > mine->read_size)
|
||||
size = mine->read_size;
|
||||
mine->p += size;
|
||||
return (size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Advancing is just as simple. Again, this is doing more than
|
||||
* necessary in order to better exercise internal code when used
|
||||
* as a test harness.
|
||||
*/
|
||||
static int64_t
|
||||
memory_read_skip(struct archive *a, void *client_data, int64_t skip)
|
||||
{
|
||||
struct read_memory_data *mine = (struct read_memory_data *)client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
if ((int64_t)skip > (int64_t)(mine->end - mine->p))
|
||||
skip = mine->end - mine->p;
|
||||
/* Round down to block size. */
|
||||
skip /= mine->read_size;
|
||||
skip *= mine->read_size;
|
||||
mine->p += skip;
|
||||
return (skip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Seeking.
|
||||
*/
|
||||
static int64_t
|
||||
memory_read_seek(struct archive *a, void *client_data, int64_t offset, int whence)
|
||||
{
|
||||
struct read_memory_data *mine = (struct read_memory_data *)client_data;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
mine->p = mine->start + offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
mine->p += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
mine->p = mine->end + offset;
|
||||
break;
|
||||
default:
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
if (mine->p < mine->start) {
|
||||
mine->p = mine->start;
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
if (mine->p > mine->end) {
|
||||
mine->p = mine->end;
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
return (mine->p - mine->start);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close is just cleaning up our one small bit of data.
|
||||
*/
|
||||
static int
|
||||
memory_read_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_memory_data *mine = (struct read_memory_data *)client_data;
|
||||
(void)a; /* UNUSED */
|
||||
free(mine);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
210
Utilities/cmlibarchive/libarchive/archive_read_private.h
Normal file
210
Utilities/cmlibarchive/libarchive/archive_read_private.h
Normal file
@ -0,0 +1,210 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/lib/libarchive/archive_read_private.h 201088 2009-12-28 02:18:55Z kientzle $
|
||||
*/
|
||||
|
||||
#ifndef __LIBARCHIVE_BUILD
|
||||
#error This header is only to be used internally to libarchive.
|
||||
#endif
|
||||
|
||||
#ifndef ARCHIVE_READ_PRIVATE_H_INCLUDED
|
||||
#define ARCHIVE_READ_PRIVATE_H_INCLUDED
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
struct archive_read;
|
||||
struct archive_read_filter_bidder;
|
||||
struct archive_read_filter;
|
||||
|
||||
/*
|
||||
* How bidding works for filters:
|
||||
* * The bid manager initializes the client-provided reader as the
|
||||
* first filter.
|
||||
* * It invokes the bidder for each registered filter with the
|
||||
* current head filter.
|
||||
* * The bidders can use archive_read_filter_ahead() to peek ahead
|
||||
* at the incoming data to compose their bids.
|
||||
* * The bid manager creates a new filter structure for the winning
|
||||
* bidder and gives the winning bidder a chance to initialize it.
|
||||
* * The new filter becomes the new top filter and we repeat the
|
||||
* process.
|
||||
* This ends only when no bidder provides a non-zero bid. Then
|
||||
* we perform a similar dance with the registered format handlers.
|
||||
*/
|
||||
struct archive_read_filter_bidder {
|
||||
/* Configuration data for the bidder. */
|
||||
void *data;
|
||||
/* Taste the upstream filter to see if we handle this. */
|
||||
int (*bid)(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
/* Initialize a newly-created filter. */
|
||||
int (*init)(struct archive_read_filter *);
|
||||
/* Set an option for the filter bidder. */
|
||||
int (*options)(struct archive_read_filter_bidder *,
|
||||
const char *key, const char *value);
|
||||
/* Release the bidder's configuration data. */
|
||||
int (*free)(struct archive_read_filter_bidder *);
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure is allocated within the archive_read core
|
||||
* and initialized by archive_read and the init() method of the
|
||||
* corresponding bidder above.
|
||||
*/
|
||||
struct archive_read_filter {
|
||||
int64_t position;
|
||||
/* Essentially all filters will need these values, so
|
||||
* just declare them here. */
|
||||
struct archive_read_filter_bidder *bidder; /* My bidder. */
|
||||
struct archive_read_filter *upstream; /* Who I read from. */
|
||||
struct archive_read *archive; /* Associated archive. */
|
||||
/* Return next block. */
|
||||
ssize_t (*read)(struct archive_read_filter *, const void **);
|
||||
/* Skip forward this many bytes. */
|
||||
int64_t (*skip)(struct archive_read_filter *self, int64_t request);
|
||||
/* Seek to an absolute location. */
|
||||
int64_t (*seek)(struct archive_read_filter *self, int64_t offset, int whence);
|
||||
/* Close (just this filter) and free(self). */
|
||||
int (*close)(struct archive_read_filter *self);
|
||||
/* My private data. */
|
||||
void *data;
|
||||
|
||||
const char *name;
|
||||
int code;
|
||||
|
||||
/* Used by reblocking logic. */
|
||||
char *buffer;
|
||||
size_t buffer_size;
|
||||
char *next; /* Current read location. */
|
||||
size_t avail; /* Bytes in my buffer. */
|
||||
const void *client_buff; /* Client buffer information. */
|
||||
size_t client_total;
|
||||
const char *client_next;
|
||||
size_t client_avail;
|
||||
char end_of_file;
|
||||
char closed;
|
||||
char fatal;
|
||||
};
|
||||
|
||||
/*
|
||||
* The client looks a lot like a filter, so we just wrap it here.
|
||||
*
|
||||
* TODO: Make archive_read_filter and archive_read_client identical so
|
||||
* that users of the library can easily register their own
|
||||
* transformation filters. This will probably break the API/ABI and
|
||||
* so should be deferred at least until libarchive 3.0.
|
||||
*/
|
||||
struct archive_read_client {
|
||||
archive_open_callback *opener;
|
||||
archive_read_callback *reader;
|
||||
archive_skip_callback *skipper;
|
||||
archive_seek_callback *seeker;
|
||||
archive_close_callback *closer;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct archive_read {
|
||||
struct archive archive;
|
||||
|
||||
struct archive_entry *entry;
|
||||
|
||||
/* Dev/ino of the archive being read/written. */
|
||||
int skip_file_set;
|
||||
dev_t skip_file_dev;
|
||||
ino_t skip_file_ino;
|
||||
|
||||
/*
|
||||
* Used by archive_read_data() to track blocks and copy
|
||||
* data to client buffers, filling gaps with zero bytes.
|
||||
*/
|
||||
const char *read_data_block;
|
||||
int64_t read_data_offset;
|
||||
int64_t read_data_output_offset;
|
||||
size_t read_data_remaining;
|
||||
|
||||
/* Callbacks to open/read/write/close client archive stream. */
|
||||
struct archive_read_client client;
|
||||
|
||||
/* Registered filter bidders. */
|
||||
struct archive_read_filter_bidder bidders[9];
|
||||
|
||||
/* Last filter in chain */
|
||||
struct archive_read_filter *filter;
|
||||
|
||||
/* File offset of beginning of most recently-read header. */
|
||||
int64_t header_position;
|
||||
|
||||
/*
|
||||
* Format detection is mostly the same as compression
|
||||
* detection, with one significant difference: The bidders
|
||||
* use the read_ahead calls above to examine the stream rather
|
||||
* than having the supervisor hand them a block of data to
|
||||
* examine.
|
||||
*/
|
||||
|
||||
struct archive_format_descriptor {
|
||||
void *data;
|
||||
const char *name;
|
||||
int (*bid)(struct archive_read *, int best_bid);
|
||||
int (*options)(struct archive_read *, const char *key,
|
||||
const char *value);
|
||||
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 *);
|
||||
int (*cleanup)(struct archive_read *);
|
||||
} formats[16];
|
||||
struct archive_format_descriptor *format; /* Active format. */
|
||||
|
||||
/*
|
||||
* Various information needed by archive_extract.
|
||||
*/
|
||||
struct extract *extract;
|
||||
int (*cleanup_archive_extract)(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 *),
|
||||
int (*cleanup)(struct archive_read *));
|
||||
|
||||
int __archive_read_get_bidder(struct archive_read *a,
|
||||
struct archive_read_filter_bidder **bidder);
|
||||
|
||||
const void *__archive_read_ahead(struct archive_read *, size_t, ssize_t *);
|
||||
const void *__archive_read_filter_ahead(struct archive_read_filter *,
|
||||
size_t, ssize_t *);
|
||||
int64_t __archive_read_seek(struct archive_read*, int64_t, int);
|
||||
int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
|
||||
int64_t __archive_read_consume(struct archive_read *, int64_t);
|
||||
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
|
||||
int __archive_read_program(struct archive_read_filter *, const char *);
|
||||
#endif
|
207
Utilities/cmlibarchive/libarchive/archive_read_set_options.3
Normal file
207
Utilities/cmlibarchive/libarchive/archive_read_set_options.3
Normal file
@ -0,0 +1,207 @@
|
||||
.\" Copyright (c) 2011 Tim Kientzle
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 13, 2009
|
||||
.Dt archive_read_options 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_read_set_filter_option ,
|
||||
.Nm archive_read_set_format_option ,
|
||||
.Nm archive_read_set_option ,
|
||||
.Nm archive_read_set_options
|
||||
.Nd functions controlling options for reading archives
|
||||
.\"
|
||||
.Sh SYNOPSIS
|
||||
.Ft int
|
||||
.Fo archive_read_set_filter_option
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *module"
|
||||
.Fa "const char *option"
|
||||
.Fa "const char *value"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_set_format_option
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *module"
|
||||
.Fa "const char *option"
|
||||
.Fa "const char *value"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_set_option
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *module"
|
||||
.Fa "const char *option"
|
||||
.Fa "const char *value"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo archive_read_set_options
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *options"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
These functions provide a way for libarchive clients to configure
|
||||
specific read modules.
|
||||
.Bl -tag -width indent
|
||||
.It Xo
|
||||
.Fn archive_read_set_filter_option ,
|
||||
.Fn archive_read_set_format_option
|
||||
.Xc
|
||||
Specifies an option that will be passed to currently-registered
|
||||
filters (including decompression filters) or format readers.
|
||||
.Pp
|
||||
If
|
||||
.Ar option
|
||||
and
|
||||
.Ar value
|
||||
are both
|
||||
.Dv NULL ,
|
||||
these functions will do nothing and
|
||||
.Cm ARCHIVE_OK
|
||||
will be returned.
|
||||
If
|
||||
.Ar option
|
||||
is
|
||||
.Dv NULL
|
||||
but
|
||||
.Ar value
|
||||
is not, these functions will do nothing and
|
||||
.Cm ARCHIVE_FAILED
|
||||
will be returned.
|
||||
.Pp
|
||||
If
|
||||
.Ar module
|
||||
is not
|
||||
.Dv NULL ,
|
||||
.Ar option
|
||||
and
|
||||
.Ar value
|
||||
will be provided to the filter or reader named
|
||||
.Ar module .
|
||||
The return value will be that of the module.
|
||||
If there is no such module,
|
||||
.Cm ARCHIVE_FAILED
|
||||
will be returned.
|
||||
.Pp
|
||||
If
|
||||
.Ar module
|
||||
is
|
||||
.Dv NULL ,
|
||||
.Ar option
|
||||
and
|
||||
.Ar value
|
||||
will be provided to every registered module.
|
||||
If any module returns
|
||||
.Cm ARCHIVE_FATAL ,
|
||||
this value will be returned immediately.
|
||||
Otherwise,
|
||||
.Cm ARCHIVE_OK
|
||||
will be returned if any module accepts the option, and
|
||||
.Cm ARCHIVE_FAILED
|
||||
in all other cases.
|
||||
.\"
|
||||
.It Xo
|
||||
.Fn archive_read_set_option
|
||||
.Xc
|
||||
Calls
|
||||
.Fn archive_read_set_format_option ,
|
||||
then
|
||||
.Fn archive_read_set_filter_option .
|
||||
If either function returns
|
||||
.Cm ARCHIVE_FATAL ,
|
||||
.Cm ARCHIVE_FATAL
|
||||
will be returned
|
||||
immediately.
|
||||
Otherwise, greater of the two values will be returned.
|
||||
.\"
|
||||
.It Xo
|
||||
.Fn archive_read_set_options
|
||||
.Xc
|
||||
.Ar options
|
||||
is a comma-separated list of options.
|
||||
If
|
||||
.Ar options
|
||||
is
|
||||
.Dv NULL
|
||||
or empty,
|
||||
.Cm ARCHIVE_OK
|
||||
will be returned immediately.
|
||||
.Pp
|
||||
Calls
|
||||
.Fn archive_read_set_option
|
||||
with each option in turn.
|
||||
If any
|
||||
.Fn archive_read_set_option
|
||||
call returns
|
||||
.Cm ARCHIVE_FATAL ,
|
||||
.Cm ARCHIVE_FATAL
|
||||
will be returned immediately.
|
||||
.Pp
|
||||
Individual options have one of the following forms:
|
||||
.Bl -tag -compact -width indent
|
||||
.It Ar option=value
|
||||
The option/value pair will be provided to every module.
|
||||
Modules that do not accept an option with this name will ignore it.
|
||||
.It Ar option
|
||||
The option will be provided to every module with a value of
|
||||
.Dq 1 .
|
||||
.It Ar !option
|
||||
The option will be provided to every module with a NULL value.
|
||||
.It Ar module:option=value , Ar module:option , Ar module:!option
|
||||
As above, but the corresponding option and value will be provided
|
||||
only to modules whose name matches
|
||||
.Ar module .
|
||||
.El
|
||||
.El
|
||||
.\"
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -compact -width indent
|
||||
.It Format iso9660
|
||||
.Bl -tag -compact -width indent
|
||||
.It Cm joliet
|
||||
Support Joliet extensions.
|
||||
Defaults to enabled, use
|
||||
.Cm !joliet
|
||||
to disable.
|
||||
.It Cm rockridge
|
||||
Support RockRidge extensions.
|
||||
Defaults to enabled, use
|
||||
.Cm !rockridge
|
||||
to disable.
|
||||
.El
|
||||
.El
|
||||
.\"
|
||||
.Sh ERRORS
|
||||
Detailed error codes and textual descriptions are available from the
|
||||
.Fn archive_errno
|
||||
and
|
||||
.Fn archive_error_string
|
||||
functions.
|
||||
.\"
|
||||
.Sh SEE ALSO
|
||||
.Xr tar 1 ,
|
||||
.Xr libarchive 3 ,
|
||||
.Xr archive_write_set_options 3 ,
|
||||
.Xr archive_read 3
|
148
Utilities/cmlibarchive/libarchive/archive_read_set_options.c
Normal file
148
Utilities/cmlibarchive/libarchive/archive_read_set_options.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_options_private.h"
|
||||
|
||||
static int archive_set_format_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v);
|
||||
static int archive_set_filter_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v);
|
||||
static int archive_set_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v);
|
||||
|
||||
int
|
||||
archive_read_set_format_option(struct archive *a, const char *m, const char *o,
|
||||
const char *v)
|
||||
{
|
||||
return _archive_set_option(a, m, o, v,
|
||||
ARCHIVE_READ_MAGIC, "archive_read_set_format_option",
|
||||
archive_set_format_option);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_filter_option(struct archive *a, const char *m, const char *o,
|
||||
const char *v)
|
||||
{
|
||||
return _archive_set_option(a, m, o, v,
|
||||
ARCHIVE_READ_MAGIC, "archive_read_set_filter_option",
|
||||
archive_set_filter_option);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_option(struct archive *a, const char *m, const char *o,
|
||||
const char *v)
|
||||
{
|
||||
return _archive_set_option(a, m, o, v,
|
||||
ARCHIVE_READ_MAGIC, "archive_read_set_option",
|
||||
archive_set_option);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_set_options(struct archive *a, const char *options)
|
||||
{
|
||||
return _archive_set_options(a, options,
|
||||
ARCHIVE_READ_MAGIC, "archive_read_set_options",
|
||||
archive_set_option);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_set_format_option(struct archive *_a, const char *m, const char *o,
|
||||
const char *v)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_format_descriptor *format;
|
||||
size_t i;
|
||||
int r, rv = ARCHIVE_FAILED;
|
||||
|
||||
for (i = 0; i < sizeof(a->formats)/sizeof(a->formats[0]); i++) {
|
||||
format = &a->formats[i];
|
||||
if (format == NULL || format->options == NULL ||
|
||||
format->name == NULL)
|
||||
/* This format does not support option. */
|
||||
continue;
|
||||
if (m != NULL && strcmp(format->name, m) != 0)
|
||||
continue;
|
||||
|
||||
a->format = format;
|
||||
r = format->options(a, o, v);
|
||||
a->format = NULL;
|
||||
|
||||
if (r == ARCHIVE_FATAL)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
if (m != NULL)
|
||||
return (r);
|
||||
|
||||
if (r == ARCHIVE_OK)
|
||||
rv = ARCHIVE_OK;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_set_filter_option(struct archive *_a, const char *m, const char *o,
|
||||
const char *v)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter *filter;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
int r, rv = ARCHIVE_FAILED;
|
||||
|
||||
for (filter = a->filter; filter != NULL; filter = filter->upstream) {
|
||||
bidder = filter->bidder;
|
||||
if (bidder == NULL)
|
||||
continue;
|
||||
if (bidder->options == NULL)
|
||||
/* This bidder does not support option */
|
||||
continue;
|
||||
if (m != NULL && strcmp(filter->name, m) != 0)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_set_option(struct archive *a, const char *m, const char *o,
|
||||
const char *v)
|
||||
{
|
||||
return _archive_set_either_option(a, m, o, v,
|
||||
archive_set_format_option,
|
||||
archive_set_filter_option);
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2011 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_all(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_all(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_all(struct archive *a)
|
||||
{
|
||||
archive_check_magic(a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_all");
|
||||
|
||||
/* Bzip falls back to "bunzip2" command-line */
|
||||
archive_read_support_filter_bzip2(a);
|
||||
/* The decompress code doesn't use an outside library. */
|
||||
archive_read_support_filter_compress(a);
|
||||
/* Gzip decompress falls back to "gunzip" command-line. */
|
||||
archive_read_support_filter_gzip(a);
|
||||
/* Lzip falls back to "unlzip" command-line program. */
|
||||
archive_read_support_filter_lzip(a);
|
||||
/* The LZMA file format has a very weak signature, so it
|
||||
* may not be feasible to keep this here, but we'll try.
|
||||
* This will come back out if there are problems. */
|
||||
/* Lzma falls back to "unlzma" command-line program. */
|
||||
archive_read_support_filter_lzma(a);
|
||||
/* Xz falls back to "unxz" command-line program. */
|
||||
archive_read_support_filter_xz(a);
|
||||
/* The decode code doesn't use an outside library. */
|
||||
archive_read_support_filter_uu(a);
|
||||
/* The decode code doesn't use an outside library. */
|
||||
archive_read_support_filter_rpm(a);
|
||||
|
||||
/* Note: We always return ARCHIVE_OK here, even if some of the
|
||||
* above return ARCHIVE_WARN. The intent here is to enable
|
||||
* "as much as possible." Clients who need specific
|
||||
* compression should enable those individually so they can
|
||||
* verify the level of support. */
|
||||
/* Clear any warning messages set by the above functions. */
|
||||
archive_clear_error(a);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
@ -0,0 +1,370 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_BZLIB_H
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
struct private_data {
|
||||
bz_stream stream;
|
||||
char *out_block;
|
||||
size_t out_block_size;
|
||||
char valid; /* True = decompressor is initialized */
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
/* Bzip2 filter */
|
||||
static ssize_t bzip2_filter_read(struct archive_read_filter *, const void **);
|
||||
static int bzip2_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that we can detect bzip2 archives even if we can't decompress
|
||||
* them. (In fact, we like detecting them because we can give better
|
||||
* error messages.) So the bid framework here gets compiled even
|
||||
* if bzlib is unavailable.
|
||||
*/
|
||||
static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
|
||||
static int bzip2_reader_init(struct archive_read_filter *);
|
||||
static int bzip2_reader_free(struct archive_read_filter_bidder *);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_bzip2(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_bzip2(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_bzip2(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *reader;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_bzip2");
|
||||
|
||||
if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
reader->data = NULL;
|
||||
reader->bid = bzip2_reader_bid;
|
||||
reader->init = bzip2_reader_init;
|
||||
reader->options = NULL;
|
||||
reader->free = bzip2_reader_free;
|
||||
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external bunzip2 program");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
bzip2_reader_free(struct archive_read_filter_bidder *self){
|
||||
(void)self; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether we can handle this data.
|
||||
*
|
||||
* This logic returns zero if any part of the signature fails. It
|
||||
* also tries to Do The Right Thing if a very short buffer prevents us
|
||||
* from verifying as much as we would like.
|
||||
*/
|
||||
static int
|
||||
bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
int bits_checked;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
/* Minimal bzip2 archive is 14 bytes. */
|
||||
buffer = __archive_read_filter_ahead(filter, 14, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
/* First three bytes must be "BZh" */
|
||||
bits_checked = 0;
|
||||
if (memcmp(buffer, "BZh", 3) != 0)
|
||||
return (0);
|
||||
bits_checked += 24;
|
||||
|
||||
/* Next follows a compression flag which must be an ASCII digit. */
|
||||
if (buffer[3] < '1' || buffer[3] > '9')
|
||||
return (0);
|
||||
bits_checked += 5;
|
||||
|
||||
/* After BZh[1-9], there must be either a data block
|
||||
* which begins with 0x314159265359 or an end-of-data
|
||||
* marker of 0x177245385090. */
|
||||
if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0)
|
||||
bits_checked += 48;
|
||||
else if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", 6) == 0)
|
||||
bits_checked += 48;
|
||||
else
|
||||
return (0);
|
||||
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR)
|
||||
|
||||
/*
|
||||
* If we don't have the library on this system, we can't actually do the
|
||||
* decompression. We can, however, still detect compressed archives
|
||||
* and emit a useful message.
|
||||
*/
|
||||
static int
|
||||
bzip2_reader_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "bunzip2");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
self->name = "bzip2";
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
bzip2_reader_init(struct archive_read_filter *self)
|
||||
{
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
struct private_data *state;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_BZIP2;
|
||||
self->name = "bzip2";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for bzip2 decompression");
|
||||
free(out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = bzip2_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = bzip2_filter_close;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next block of decompressed data.
|
||||
*/
|
||||
static ssize_t
|
||||
bzip2_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
const char *read_buf;
|
||||
ssize_t ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
if (state->eof) {
|
||||
*p = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
for (;;) {
|
||||
if (!state->valid) {
|
||||
if (bzip2_reader_bid(self->bidder, self->upstream) == 0) {
|
||||
state->eof = 1;
|
||||
*p = state->out_block;
|
||||
decompressed = state->stream.next_out
|
||||
- state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
/* Initialize compression library. */
|
||||
ret = BZ2_bzDecompressInit(&(state->stream),
|
||||
0 /* library verbosity */,
|
||||
0 /* don't use low-mem algorithm */);
|
||||
|
||||
/* If init fails, try low-memory algorithm instead. */
|
||||
if (ret == BZ_MEM_ERROR)
|
||||
ret = BZ2_bzDecompressInit(&(state->stream),
|
||||
0 /* library verbosity */,
|
||||
1 /* do use low-mem algo */);
|
||||
|
||||
if (ret != BZ_OK) {
|
||||
const char *detail = NULL;
|
||||
int err = ARCHIVE_ERRNO_MISC;
|
||||
switch (ret) {
|
||||
case BZ_PARAM_ERROR:
|
||||
detail = "invalid setup parameter";
|
||||
break;
|
||||
case BZ_MEM_ERROR:
|
||||
err = ENOMEM;
|
||||
detail = "out of memory";
|
||||
break;
|
||||
case BZ_CONFIG_ERROR:
|
||||
detail = "mis-compiled library";
|
||||
break;
|
||||
}
|
||||
archive_set_error(&self->archive->archive, err,
|
||||
"Internal error initializing decompressor%s%s",
|
||||
detail == NULL ? "" : ": ",
|
||||
detail);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->valid = 1;
|
||||
}
|
||||
|
||||
/* stream.next_in is really const, but bzlib
|
||||
* doesn't declare it so. <sigh> */
|
||||
read_buf =
|
||||
__archive_read_filter_ahead(self->upstream, 1, &ret);
|
||||
if (read_buf == NULL) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"truncated bzip2 input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.next_in = (char *)(uintptr_t)read_buf;
|
||||
state->stream.avail_in = ret;
|
||||
/* There is no more data, return whatever we have. */
|
||||
if (ret == 0) {
|
||||
state->eof = 1;
|
||||
*p = state->out_block;
|
||||
decompressed = state->stream.next_out
|
||||
- state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/* Decompress as much as we can in one pass. */
|
||||
ret = BZ2_bzDecompress(&(state->stream));
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
state->stream.next_in - read_buf);
|
||||
|
||||
switch (ret) {
|
||||
case BZ_STREAM_END: /* Found end of stream. */
|
||||
switch (BZ2_bzDecompressEnd(&(state->stream))) {
|
||||
case BZ_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up decompressor");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->valid = 0;
|
||||
/* FALLTHROUGH */
|
||||
case BZ_OK: /* Decompressor made some progress. */
|
||||
/* If we filled our buffer, update stats and return. */
|
||||
if (state->stream.avail_out == 0) {
|
||||
*p = state->out_block;
|
||||
decompressed = state->stream.next_out
|
||||
- state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
break;
|
||||
default: /* Return an error. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "bzip decompression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
bzip2_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
if (state->valid) {
|
||||
switch (BZ2_bzDecompressEnd(&state->stream)) {
|
||||
case BZ_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up decompressor");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
state->valid = 0;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */
|
@ -0,0 +1,454 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code borrows heavily from "compress" source code, which is
|
||||
* protected by the following copyright. (Clause 3 dropped by request
|
||||
* of the Regents.)
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1985, 1986, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Diomidis Spinellis and James A. Woods, derived from original
|
||||
* work by Spencer Thomas and Joseph Orost.
|
||||
*
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
/*
|
||||
* Because LZW decompression is pretty simple, I've just implemented
|
||||
* the whole decompressor here (cribbing from "compress" source code,
|
||||
* of course), rather than relying on an external library. I have
|
||||
* made an effort to clarify and simplify the algorithm, so the
|
||||
* names and structure here don't exactly match those used by compress.
|
||||
*/
|
||||
|
||||
struct private_data {
|
||||
/* Input variables. */
|
||||
const unsigned char *next_in;
|
||||
size_t avail_in;
|
||||
size_t consume_unnotified;
|
||||
int bit_buffer;
|
||||
int bits_avail;
|
||||
size_t bytes_in_section;
|
||||
|
||||
/* Output variables. */
|
||||
size_t out_block_size;
|
||||
void *out_block;
|
||||
|
||||
/* Decompression status variables. */
|
||||
int use_reset_code;
|
||||
int end_of_stream; /* EOF status. */
|
||||
int maxcode; /* Largest code. */
|
||||
int maxcode_bits; /* Length of largest code. */
|
||||
int section_end_code; /* When to increase bits. */
|
||||
int bits; /* Current code length. */
|
||||
int oldcode; /* Previous code. */
|
||||
int finbyte; /* Last byte of prev code. */
|
||||
|
||||
/* Dictionary. */
|
||||
int free_ent; /* Next dictionary entry. */
|
||||
unsigned char suffix[65536];
|
||||
uint16_t prefix[65536];
|
||||
|
||||
/*
|
||||
* Scratch area for expanding dictionary entries. Note:
|
||||
* "worst" case here comes from compressing /dev/zero: the
|
||||
* last code in the dictionary will code a sequence of
|
||||
* 65536-256 zero bytes. Thus, we need stack space to expand
|
||||
* a 65280-byte dictionary entry. (Of course, 32640:1
|
||||
* compression could also be considered the "best" case. ;-)
|
||||
*/
|
||||
unsigned char *stackp;
|
||||
unsigned char stack[65300];
|
||||
};
|
||||
|
||||
static int compress_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
|
||||
static int compress_bidder_init(struct archive_read_filter *);
|
||||
static int compress_bidder_free(struct archive_read_filter_bidder *);
|
||||
|
||||
static ssize_t compress_filter_read(struct archive_read_filter *, const void **);
|
||||
static int compress_filter_close(struct archive_read_filter *);
|
||||
|
||||
static int getbits(struct archive_read_filter *, int n);
|
||||
static int next_code(struct archive_read_filter *);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_compress(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_compress(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_compress(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_compress");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = compress_bidder_bid;
|
||||
bidder->init = compress_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = compress_bidder_free;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether we can handle this data.
|
||||
* This logic returns zero if any part of the signature fails.
|
||||
*/
|
||||
static int
|
||||
compress_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
int bits_checked;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, 2, &avail);
|
||||
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
bits_checked = 0;
|
||||
if (buffer[0] != 0x1F || buffer[1] != 0x9D)
|
||||
return (0);
|
||||
bits_checked += 16;
|
||||
|
||||
/*
|
||||
* TODO: Verify more.
|
||||
*/
|
||||
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
compress_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
int code;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_COMPRESS;
|
||||
self->name = "compress (.Z)";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
free(out_block);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for %s decompression",
|
||||
self->name);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = compress_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = compress_filter_close;
|
||||
|
||||
/* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */
|
||||
|
||||
(void)getbits(self, 8); /* Skip first signature byte. */
|
||||
(void)getbits(self, 8); /* Skip second signature byte. */
|
||||
|
||||
code = getbits(self, 8);
|
||||
state->maxcode_bits = code & 0x1f;
|
||||
state->maxcode = (1 << state->maxcode_bits);
|
||||
state->use_reset_code = code & 0x80;
|
||||
|
||||
/* Initialize decompressor. */
|
||||
state->free_ent = 256;
|
||||
state->stackp = state->stack;
|
||||
if (state->use_reset_code)
|
||||
state->free_ent++;
|
||||
state->bits = 9;
|
||||
state->section_end_code = (1<<state->bits) - 1;
|
||||
state->oldcode = -1;
|
||||
for (code = 255; code >= 0; code--) {
|
||||
state->prefix[code] = 0;
|
||||
state->suffix[code] = code;
|
||||
}
|
||||
next_code(self);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a block of data from the decompression buffer. Decompress more
|
||||
* as necessary.
|
||||
*/
|
||||
static ssize_t
|
||||
compress_filter_read(struct archive_read_filter *self, const void **pblock)
|
||||
{
|
||||
struct private_data *state;
|
||||
unsigned char *p, *start, *end;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
if (state->end_of_stream) {
|
||||
*pblock = NULL;
|
||||
return (0);
|
||||
}
|
||||
p = start = (unsigned char *)state->out_block;
|
||||
end = start + state->out_block_size;
|
||||
|
||||
while (p < end && !state->end_of_stream) {
|
||||
if (state->stackp > state->stack) {
|
||||
*p++ = *--state->stackp;
|
||||
} else {
|
||||
ret = next_code(self);
|
||||
if (ret == -1)
|
||||
state->end_of_stream = ret;
|
||||
else if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
|
||||
*pblock = start;
|
||||
return (p - start);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the reader.
|
||||
*/
|
||||
static int
|
||||
compress_bidder_free(struct archive_read_filter_bidder *self)
|
||||
{
|
||||
self->data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close and release the filter.
|
||||
*/
|
||||
static int
|
||||
compress_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state = (struct private_data *)self->data;
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the next code and fill the stack with the expansion
|
||||
* of the code. Returns ARCHIVE_FATAL if there is a fatal I/O or
|
||||
* format error, ARCHIVE_EOF if we hit end of data, ARCHIVE_OK otherwise.
|
||||
*/
|
||||
static int
|
||||
next_code(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state = (struct private_data *)self->data;
|
||||
int code, newcode;
|
||||
|
||||
static int debug_buff[1024];
|
||||
static unsigned debug_index;
|
||||
|
||||
code = newcode = getbits(self, state->bits);
|
||||
if (code < 0)
|
||||
return (code);
|
||||
|
||||
debug_buff[debug_index++] = code;
|
||||
if (debug_index >= sizeof(debug_buff)/sizeof(debug_buff[0]))
|
||||
debug_index = 0;
|
||||
|
||||
/* If it's a reset code, reset the dictionary. */
|
||||
if ((code == 256) && state->use_reset_code) {
|
||||
/*
|
||||
* The original 'compress' implementation blocked its
|
||||
* I/O in a manner that resulted in junk bytes being
|
||||
* inserted after every reset. The next section skips
|
||||
* this junk. (Yes, the number of *bytes* to skip is
|
||||
* a function of the current *bit* length.)
|
||||
*/
|
||||
int skip_bytes = state->bits -
|
||||
(state->bytes_in_section % state->bits);
|
||||
skip_bytes %= state->bits;
|
||||
state->bits_avail = 0; /* Discard rest of this byte. */
|
||||
while (skip_bytes-- > 0) {
|
||||
code = getbits(self, 8);
|
||||
if (code < 0)
|
||||
return (code);
|
||||
}
|
||||
/* Now, actually do the reset. */
|
||||
state->bytes_in_section = 0;
|
||||
state->bits = 9;
|
||||
state->section_end_code = (1 << state->bits) - 1;
|
||||
state->free_ent = 257;
|
||||
state->oldcode = -1;
|
||||
return (next_code(self));
|
||||
}
|
||||
|
||||
if (code > state->free_ent) {
|
||||
/* An invalid code is a fatal error. */
|
||||
archive_set_error(&(self->archive->archive), -1,
|
||||
"Invalid compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Special case for KwKwK string. */
|
||||
if (code >= state->free_ent) {
|
||||
*state->stackp++ = state->finbyte;
|
||||
code = state->oldcode;
|
||||
}
|
||||
|
||||
/* Generate output characters in reverse order. */
|
||||
while (code >= 256) {
|
||||
*state->stackp++ = state->suffix[code];
|
||||
code = state->prefix[code];
|
||||
}
|
||||
*state->stackp++ = state->finbyte = code;
|
||||
|
||||
/* Generate the new entry. */
|
||||
code = state->free_ent;
|
||||
if (code < state->maxcode && state->oldcode >= 0) {
|
||||
state->prefix[code] = state->oldcode;
|
||||
state->suffix[code] = state->finbyte;
|
||||
++state->free_ent;
|
||||
}
|
||||
if (state->free_ent > state->section_end_code) {
|
||||
state->bits++;
|
||||
state->bytes_in_section = 0;
|
||||
if (state->bits == state->maxcode_bits)
|
||||
state->section_end_code = state->maxcode;
|
||||
else
|
||||
state->section_end_code = (1 << state->bits) - 1;
|
||||
}
|
||||
|
||||
/* Remember previous code. */
|
||||
state->oldcode = newcode;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return next 'n' bits from stream.
|
||||
*
|
||||
* -1 indicates end of available data.
|
||||
*/
|
||||
static int
|
||||
getbits(struct archive_read_filter *self, int n)
|
||||
{
|
||||
struct private_data *state = (struct private_data *)self->data;
|
||||
int code;
|
||||
ssize_t ret;
|
||||
static const int mask[] = {
|
||||
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
|
||||
0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
||||
};
|
||||
|
||||
while (state->bits_avail < n) {
|
||||
if (state->avail_in <= 0) {
|
||||
if (state->consume_unnotified) {
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
state->consume_unnotified);
|
||||
state->consume_unnotified = 0;
|
||||
}
|
||||
state->next_in
|
||||
= __archive_read_filter_ahead(self->upstream,
|
||||
1, &ret);
|
||||
if (ret == 0)
|
||||
return (-1);
|
||||
if (ret < 0 || state->next_in == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
state->consume_unnotified = state->avail_in = ret;
|
||||
}
|
||||
state->bit_buffer |= *state->next_in++ << state->bits_avail;
|
||||
state->avail_in--;
|
||||
state->bits_avail += 8;
|
||||
state->bytes_in_section++;
|
||||
}
|
||||
|
||||
code = state->bit_buffer;
|
||||
state->bit_buffer >>= n;
|
||||
state->bits_avail -= n;
|
||||
|
||||
return (code & mask[n]);
|
||||
}
|
@ -0,0 +1,476 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
struct private_data {
|
||||
z_stream stream;
|
||||
char in_stream;
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
unsigned long crc;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
/* Gzip Filter. */
|
||||
static ssize_t gzip_filter_read(struct archive_read_filter *, const void **);
|
||||
static int gzip_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that we can detect gzip archives even if we can't decompress
|
||||
* them. (In fact, we like detecting them because we can give better
|
||||
* error messages.) So the bid framework here gets compiled even
|
||||
* if zlib is unavailable.
|
||||
*
|
||||
* TODO: If zlib is unavailable, gzip_bidder_init() should
|
||||
* use the compress_program framework to try to fire up an external
|
||||
* gunzip program.
|
||||
*/
|
||||
static int gzip_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int gzip_bidder_init(struct archive_read_filter *);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_gzip(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_gzip(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_gzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_gzip");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = gzip_bidder_bid;
|
||||
bidder->init = gzip_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL; /* No data, so no cleanup necessary. */
|
||||
/* Signal the extent of gzip support with the return value here. */
|
||||
#if HAVE_ZLIB_H
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external gunzip program");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Read and verify the header.
|
||||
*
|
||||
* Returns zero if the header couldn't be validated, else returns
|
||||
* number of bytes in header. If pbits is non-NULL, it receives a
|
||||
* count of bits verified, suitable for use by bidder.
|
||||
*/
|
||||
static int
|
||||
peek_at_header(struct archive_read_filter *filter, int *pbits)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t avail, len;
|
||||
int bits = 0;
|
||||
int header_flags;
|
||||
|
||||
/* Start by looking at the first ten bytes of the header, which
|
||||
* is all fixed layout. */
|
||||
len = 10;
|
||||
p = __archive_read_filter_ahead(filter, len, &avail);
|
||||
if (p == NULL || avail == 0)
|
||||
return (0);
|
||||
/* We only support deflation- third byte must be 0x08. */
|
||||
if (memcmp(p, "\x1F\x8B\x08", 3) != 0)
|
||||
return (0);
|
||||
bits += 24;
|
||||
if ((p[3] & 0xE0)!= 0) /* No reserved flags set. */
|
||||
return (0);
|
||||
bits += 3;
|
||||
header_flags = p[3];
|
||||
/* Bytes 4-7 are mod time. */
|
||||
/* Byte 8 is deflate flags. */
|
||||
/* XXXX TODO: return deflate flags back to consume_header for use
|
||||
in initializing the decompressor. */
|
||||
/* Byte 9 is OS. */
|
||||
|
||||
/* Optional extra data: 2 byte length plus variable body. */
|
||||
if (header_flags & 4) {
|
||||
p = __archive_read_filter_ahead(filter, len + 2, &avail);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
len += ((int)p[len + 1] << 8) | (int)p[len];
|
||||
len += 2;
|
||||
}
|
||||
|
||||
/* Null-terminated optional filename. */
|
||||
if (header_flags & 8) {
|
||||
do {
|
||||
++len;
|
||||
if (avail < len)
|
||||
p = __archive_read_filter_ahead(filter,
|
||||
len, &avail);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
} while (p[len - 1] != 0);
|
||||
}
|
||||
|
||||
/* Null-terminated optional comment. */
|
||||
if (header_flags & 16) {
|
||||
do {
|
||||
++len;
|
||||
if (avail < len)
|
||||
p = __archive_read_filter_ahead(filter,
|
||||
len, &avail);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
} while (p[len - 1] != 0);
|
||||
}
|
||||
|
||||
/* Optional header CRC */
|
||||
if ((header_flags & 2)) {
|
||||
p = __archive_read_filter_ahead(filter, len + 2, &avail);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
#if 0
|
||||
int hcrc = ((int)p[len + 1] << 8) | (int)p[len];
|
||||
int crc = /* XXX TODO: Compute header CRC. */;
|
||||
if (crc != hcrc)
|
||||
return (0);
|
||||
bits += 16;
|
||||
#endif
|
||||
len += 2;
|
||||
}
|
||||
|
||||
if (pbits != NULL)
|
||||
*pbits = bits;
|
||||
return (len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bidder just verifies the header and returns the number of verified bits.
|
||||
*/
|
||||
static int
|
||||
gzip_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
int bits_checked;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
if (peek_at_header(filter, &bits_checked))
|
||||
return (bits_checked);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
|
||||
/*
|
||||
* If we don't have the library on this system, we can't do the
|
||||
* decompression directly. We can, however, try to run gunzip
|
||||
* in case that's available.
|
||||
*/
|
||||
static int
|
||||
gzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "gunzip");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_GZIP;
|
||||
self->name = "gzip";
|
||||
return (r);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Initialize the filter object.
|
||||
*/
|
||||
static int
|
||||
gzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_GZIP;
|
||||
self->name = "gzip";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
free(out_block);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for gzip decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = gzip_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = gzip_filter_close;
|
||||
|
||||
state->in_stream = 0; /* We're not actually within a stream yet. */
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
consume_header(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
ssize_t avail;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* If this is a real header, consume it. */
|
||||
len = peek_at_header(self->upstream, NULL);
|
||||
if (len == 0)
|
||||
return (ARCHIVE_EOF);
|
||||
__archive_read_filter_consume(self->upstream, len);
|
||||
|
||||
/* Initialize CRC accumulator. */
|
||||
state->crc = crc32(0L, NULL, 0);
|
||||
|
||||
/* Initialize compression library. */
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail);
|
||||
state->stream.avail_in = avail;
|
||||
ret = inflateInit2(&(state->stream),
|
||||
-15 /* Don't check for zlib header */);
|
||||
|
||||
/* Decipher the error code. */
|
||||
switch (ret) {
|
||||
case Z_OK:
|
||||
state->in_stream = 1;
|
||||
return (ARCHIVE_OK);
|
||||
case Z_STREAM_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid setup parameter");
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid library version");
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
" Zlib error %d", ret);
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
consume_trailer(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
const unsigned char *p;
|
||||
ssize_t avail;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
state->in_stream = 0;
|
||||
switch (inflateEnd(&(state->stream))) {
|
||||
case Z_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up gzip decompressor");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* GZip trailer is a fixed 8 byte structure. */
|
||||
p = __archive_read_filter_ahead(self->upstream, 8, &avail);
|
||||
if (p == NULL || avail == 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
/* XXX TODO: Verify the length and CRC. */
|
||||
|
||||
/* We've verified the trailer, so consume it now. */
|
||||
__archive_read_filter_consume(self->upstream, 8);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
gzip_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (state->stream.avail_out > 0 && !state->eof) {
|
||||
/* If we're not in a stream, read a header
|
||||
* and initialize the decompression library. */
|
||||
if (!state->in_stream) {
|
||||
ret = consume_header(self);
|
||||
if (ret == ARCHIVE_EOF) {
|
||||
state->eof = 1;
|
||||
break;
|
||||
}
|
||||
if (ret < ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Peek at the next available data. */
|
||||
/* ZLib treats stream.next_in as const but doesn't declare
|
||||
* it so, hence this ugly cast. */
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail_in);
|
||||
if (state->stream.next_in == NULL) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"truncated gzip input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.avail_in = avail_in;
|
||||
|
||||
/* Decompress and consume some of that data. */
|
||||
ret = inflate(&(state->stream), 0);
|
||||
switch (ret) {
|
||||
case Z_OK: /* Decompressor made some progress. */
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
break;
|
||||
case Z_STREAM_END: /* Found end of stream. */
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
/* Consume the stream trailer; release the
|
||||
* decompression library. */
|
||||
ret = consume_trailer(self);
|
||||
if (ret < ARCHIVE_OK)
|
||||
return (ret);
|
||||
break;
|
||||
default:
|
||||
/* Return an error. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"gzip decompression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* We've read as much as we can. */
|
||||
decompressed = state->stream.next_out - state->out_block;
|
||||
state->total_out += decompressed;
|
||||
if (decompressed == 0)
|
||||
*p = NULL;
|
||||
else
|
||||
*p = state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
gzip_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
ret = ARCHIVE_OK;
|
||||
|
||||
if (state->in_stream) {
|
||||
switch (inflateEnd(&(state->stream))) {
|
||||
case Z_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up gzip compressor");
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ZLIB_H */
|
@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_none(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_none(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncompressed streams are handled implicitly by the read core,
|
||||
* so this is now a no-op.
|
||||
*/
|
||||
int
|
||||
archive_read_support_filter_none(struct archive *a)
|
||||
{
|
||||
archive_check_magic(a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_none");
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
@ -0,0 +1,476 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Joerg Sonnenberger
|
||||
* 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"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
# include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_program(struct archive *a, const char *cmd)
|
||||
{
|
||||
return archive_read_support_filter_program(a, cmd);
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_support_compression_program_signature(struct archive *a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
return archive_read_support_filter_program_signature(a,
|
||||
cmd, signature, signature_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_program(struct archive *a, const char *cmd)
|
||||
{
|
||||
return (archive_read_support_filter_program_signature(a, cmd, NULL, 0));
|
||||
}
|
||||
|
||||
|
||||
/* This capability is only available on POSIX systems. */
|
||||
#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
|
||||
!(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
|
||||
|
||||
/*
|
||||
* On non-Posix systems, allow the program to build, but choke if
|
||||
* this function is actually invoked.
|
||||
*/
|
||||
int
|
||||
archive_read_support_filter_program_signature(struct archive *_a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
(void)_a; /* UNUSED */
|
||||
(void)cmd; /* UNUSED */
|
||||
(void)signature; /* UNUSED */
|
||||
(void)signature_len; /* UNUSED */
|
||||
|
||||
archive_set_error(_a, -1,
|
||||
"External compression programs not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
__archive_read_program(struct archive_read_filter *self, const char *cmd)
|
||||
{
|
||||
(void)self; /* UNUSED */
|
||||
(void)cmd; /* UNUSED */
|
||||
|
||||
archive_set_error(&self->archive->archive, -1,
|
||||
"External compression programs not supported on this platform");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "filter_fork.h"
|
||||
|
||||
/*
|
||||
* The bidder object stores the command and the signature to watch for.
|
||||
* The 'inhibit' entry here is used to ensure that unchecked filters never
|
||||
* bid twice in the same pipeline.
|
||||
*/
|
||||
struct program_bidder {
|
||||
char *cmd;
|
||||
void *signature;
|
||||
size_t signature_len;
|
||||
int inhibit;
|
||||
};
|
||||
|
||||
static int program_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *upstream);
|
||||
static int program_bidder_init(struct archive_read_filter *);
|
||||
static int program_bidder_free(struct archive_read_filter_bidder *);
|
||||
|
||||
/*
|
||||
* The actual filter needs to track input and output data.
|
||||
*/
|
||||
struct program_filter {
|
||||
char *description;
|
||||
pid_t child;
|
||||
int exit_status;
|
||||
int waitpid_return;
|
||||
int child_stdin, child_stdout;
|
||||
|
||||
char *out_buf;
|
||||
size_t out_buf_len;
|
||||
};
|
||||
|
||||
static ssize_t program_filter_read(struct archive_read_filter *,
|
||||
const void **);
|
||||
static int program_filter_close(struct archive_read_filter *);
|
||||
|
||||
int
|
||||
archive_read_support_filter_program_signature(struct archive *_a,
|
||||
const char *cmd, const void *signature, size_t signature_len)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
struct program_bidder *state;
|
||||
|
||||
/*
|
||||
* Get a bidder object from the read core.
|
||||
*/
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
/*
|
||||
* Allocate our private state.
|
||||
*/
|
||||
state = (struct program_bidder *)calloc(sizeof (*state), 1);
|
||||
if (state == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
state->cmd = strdup(cmd);
|
||||
if (signature != NULL && signature_len > 0) {
|
||||
state->signature_len = signature_len;
|
||||
state->signature = malloc(signature_len);
|
||||
memcpy(state->signature, signature, signature_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the bidder object.
|
||||
*/
|
||||
bidder->data = state;
|
||||
bidder->bid = program_bidder_bid;
|
||||
bidder->init = program_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = program_bidder_free;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
program_bidder_free(struct archive_read_filter_bidder *self)
|
||||
{
|
||||
struct program_bidder *state = (struct program_bidder *)self->data;
|
||||
free(state->cmd);
|
||||
free(state->signature);
|
||||
free(self->data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we do have a signature, bid only if that matches.
|
||||
*
|
||||
* If there's no signature, we bid INT_MAX the first time
|
||||
* we're called, then never bid again.
|
||||
*/
|
||||
static int
|
||||
program_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *upstream)
|
||||
{
|
||||
struct program_bidder *state = self->data;
|
||||
const char *p;
|
||||
|
||||
/* If we have a signature, use that to match. */
|
||||
if (state->signature_len > 0) {
|
||||
p = __archive_read_filter_ahead(upstream,
|
||||
state->signature_len, NULL);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
/* No match, so don't bid. */
|
||||
if (memcmp(p, state->signature, state->signature_len) != 0)
|
||||
return (0);
|
||||
return ((int)state->signature_len * 8);
|
||||
}
|
||||
|
||||
/* Otherwise, bid once and then never bid again. */
|
||||
if (state->inhibit)
|
||||
return (0);
|
||||
state->inhibit = 1;
|
||||
return (INT_MAX);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shut down the child, return ARCHIVE_OK if it exited normally.
|
||||
*
|
||||
* Note that the return value is sticky; if we're called again,
|
||||
* we won't reap the child again, but we will return the same status
|
||||
* (including error message if the child came to a bad end).
|
||||
*/
|
||||
static int
|
||||
child_stop(struct archive_read_filter *self, struct program_filter *state)
|
||||
{
|
||||
/* Close our side of the I/O with the child. */
|
||||
if (state->child_stdin != -1) {
|
||||
close(state->child_stdin);
|
||||
state->child_stdin = -1;
|
||||
}
|
||||
if (state->child_stdout != -1) {
|
||||
close(state->child_stdout);
|
||||
state->child_stdout = -1;
|
||||
}
|
||||
|
||||
if (state->child != 0) {
|
||||
/* Reap the child. */
|
||||
do {
|
||||
state->waitpid_return
|
||||
= waitpid(state->child, &state->exit_status, 0);
|
||||
} while (state->waitpid_return == -1 && errno == EINTR);
|
||||
state->child = 0;
|
||||
}
|
||||
|
||||
if (state->waitpid_return < 0) {
|
||||
/* waitpid() failed? This is ugly. */
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Child process exited badly");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
if (WIFSIGNALED(state->exit_status)) {
|
||||
#ifdef SIGPIPE
|
||||
/* If the child died because we stopped reading before
|
||||
* it was done, that's okay. Some archive formats
|
||||
* have padding at the end that we routinely ignore. */
|
||||
/* The alternative to this would be to add a step
|
||||
* before close(child_stdout) above to read from the
|
||||
* child until the child has no more to write. */
|
||||
if (WTERMSIG(state->exit_status) == SIGPIPE)
|
||||
return (ARCHIVE_OK);
|
||||
#endif
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Child process exited with signal %d",
|
||||
WTERMSIG(state->exit_status));
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
#endif /* !_WIN32 || __CYGWIN__ */
|
||||
|
||||
if (WIFEXITED(state->exit_status)) {
|
||||
if (WEXITSTATUS(state->exit_status) == 0)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Child process exited with status %d",
|
||||
WEXITSTATUS(state->exit_status));
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use select() to decide whether the child is ready for read or write.
|
||||
*/
|
||||
static ssize_t
|
||||
child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
|
||||
{
|
||||
struct program_filter *state = self->data;
|
||||
ssize_t ret, requested, avail;
|
||||
const char *p;
|
||||
|
||||
requested = buf_len > SSIZE_MAX ? SSIZE_MAX : buf_len;
|
||||
|
||||
for (;;) {
|
||||
do {
|
||||
ret = read(state->child_stdout, buf, requested);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret > 0)
|
||||
return (ret);
|
||||
if (ret == 0 || (ret == -1 && errno == EPIPE))
|
||||
/* Child has closed its output; reap the child
|
||||
* and return the status. */
|
||||
return (child_stop(self, state));
|
||||
if (ret == -1 && errno != EAGAIN)
|
||||
return (-1);
|
||||
|
||||
if (state->child_stdin == -1) {
|
||||
/* Block until child has some I/O ready. */
|
||||
__archive_check_child(state->child_stdin,
|
||||
state->child_stdout);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get some more data from upstream. */
|
||||
p = __archive_read_filter_ahead(self->upstream, 1, &avail);
|
||||
if (p == NULL) {
|
||||
close(state->child_stdin);
|
||||
state->child_stdin = -1;
|
||||
fcntl(state->child_stdout, F_SETFL, 0);
|
||||
if (avail < 0)
|
||||
return (avail);
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
ret = write(state->child_stdin, p, avail);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
if (ret > 0) {
|
||||
/* Consume whatever we managed to write. */
|
||||
__archive_read_filter_consume(self->upstream, ret);
|
||||
} else if (ret == -1 && errno == EAGAIN) {
|
||||
/* Block until child has some I/O ready. */
|
||||
__archive_check_child(state->child_stdin,
|
||||
state->child_stdout);
|
||||
} else {
|
||||
/* Write failed. */
|
||||
close(state->child_stdin);
|
||||
state->child_stdin = -1;
|
||||
fcntl(state->child_stdout, F_SETFL, 0);
|
||||
/* If it was a bad error, we're done; otherwise
|
||||
* it was EPIPE or EOF, and we can still read
|
||||
* from the child. */
|
||||
if (ret == -1 && errno != EPIPE)
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
__archive_read_program(struct archive_read_filter *self, const char *cmd)
|
||||
{
|
||||
struct program_filter *state;
|
||||
static const size_t out_buf_len = 65536;
|
||||
char *out_buf;
|
||||
char *description;
|
||||
const char *prefix = "Program: ";
|
||||
|
||||
state = (struct program_filter *)calloc(1, sizeof(*state));
|
||||
out_buf = (char *)malloc(out_buf_len);
|
||||
description = (char *)malloc(strlen(prefix) + strlen(cmd) + 1);
|
||||
if (state == NULL || out_buf == NULL || description == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate input data");
|
||||
free(state);
|
||||
free(out_buf);
|
||||
free(description);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_PROGRAM;
|
||||
state->description = description;
|
||||
strcpy(state->description, prefix);
|
||||
strcat(state->description, cmd);
|
||||
self->name = state->description;
|
||||
|
||||
state->out_buf = out_buf;
|
||||
state->out_buf_len = out_buf_len;
|
||||
|
||||
if ((state->child = __archive_create_child(cmd,
|
||||
&state->child_stdin, &state->child_stdout)) == -1) {
|
||||
free(state->out_buf);
|
||||
free(state);
|
||||
archive_set_error(&self->archive->archive, EINVAL,
|
||||
"Can't initialize filter; unable to run program \"%s\"", cmd);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
self->read = program_filter_read;
|
||||
self->skip = NULL;
|
||||
self->close = program_filter_close;
|
||||
|
||||
/* XXX Check that we can read at least one byte? */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
program_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct program_bidder *bidder_state;
|
||||
|
||||
bidder_state = (struct program_bidder *)self->bidder->data;
|
||||
return (__archive_read_program(self, bidder_state->cmd));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
program_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
{
|
||||
struct program_filter *state;
|
||||
ssize_t bytes;
|
||||
size_t total;
|
||||
char *p;
|
||||
|
||||
state = (struct program_filter *)self->data;
|
||||
|
||||
total = 0;
|
||||
p = state->out_buf;
|
||||
while (state->child_stdout != -1 && total < state->out_buf_len) {
|
||||
bytes = child_read(self, p, state->out_buf_len - total);
|
||||
if (bytes < 0)
|
||||
/* No recovery is possible if we can no longer
|
||||
* read from the child. */
|
||||
return (ARCHIVE_FATAL);
|
||||
if (bytes == 0)
|
||||
/* We got EOF from the child. */
|
||||
break;
|
||||
total += bytes;
|
||||
p += bytes;
|
||||
}
|
||||
|
||||
*buff = state->out_buf;
|
||||
return (total);
|
||||
}
|
||||
|
||||
static int
|
||||
program_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct program_filter *state;
|
||||
int e;
|
||||
|
||||
state = (struct program_filter *)self->data;
|
||||
e = child_stop(self, state);
|
||||
|
||||
/* Release our private data. */
|
||||
free(state->out_buf);
|
||||
free(state->description);
|
||||
free(state);
|
||||
|
||||
return (e);
|
||||
}
|
||||
|
||||
#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
|
@ -0,0 +1,288 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Michihiro NAKAJIMA
|
||||
* 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
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_endian.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
struct rpm {
|
||||
int64_t total_in;
|
||||
size_t hpos;
|
||||
size_t hlen;
|
||||
unsigned char header[16];
|
||||
enum {
|
||||
ST_LEAD, /* Skipping 'Lead' section. */
|
||||
ST_HEADER, /* Reading 'Header' section;
|
||||
* first 16 bytes. */
|
||||
ST_HEADER_DATA, /* Skipping 'Header' section. */
|
||||
ST_PADDING, /* Skipping padding data after the
|
||||
* 'Header' section. */
|
||||
ST_ARCHIVE /* Reading 'Archive' section. */
|
||||
} state;
|
||||
int first_header;
|
||||
};
|
||||
#define RPM_LEAD_SIZE 96 /* Size of 'Lead' section. */
|
||||
|
||||
static int rpm_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int rpm_bidder_init(struct archive_read_filter *);
|
||||
|
||||
static ssize_t rpm_filter_read(struct archive_read_filter *,
|
||||
const void **);
|
||||
static int rpm_filter_close(struct archive_read_filter *);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_rpm(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_rpm(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_rpm(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_rpm");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = rpm_bidder_bid;
|
||||
bidder->init = rpm_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
rpm_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *b;
|
||||
ssize_t avail;
|
||||
int bits_checked;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
b = __archive_read_filter_ahead(filter, 8, &avail);
|
||||
if (b == NULL)
|
||||
return (0);
|
||||
|
||||
bits_checked = 0;
|
||||
/*
|
||||
* Verify Header Magic Bytes : 0XED 0XAB 0XEE 0XDB
|
||||
*/
|
||||
if (memcmp(b, "\xED\xAB\xEE\xDB", 4) != 0)
|
||||
return (0);
|
||||
bits_checked += 32;
|
||||
/*
|
||||
* Check major version.
|
||||
*/
|
||||
if (b[4] != 3 && b[4] != 4)
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
/*
|
||||
* Check package type; binary or source.
|
||||
*/
|
||||
if (b[6] != 0)
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
if (b[7] != 0 && b[7] != 1)
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
static int
|
||||
rpm_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct rpm *rpm;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_RPM;
|
||||
self->name = "rpm";
|
||||
self->read = rpm_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = rpm_filter_close;
|
||||
|
||||
rpm = (struct rpm *)calloc(sizeof(*rpm), 1);
|
||||
if (rpm == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for rpm");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = rpm;
|
||||
rpm->state = ST_LEAD;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
rpm_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
{
|
||||
struct rpm *rpm;
|
||||
const unsigned char *b;
|
||||
ssize_t avail_in, total;
|
||||
size_t used, n;
|
||||
uint32_t section;
|
||||
uint32_t bytes;
|
||||
|
||||
rpm = (struct rpm *)self->data;
|
||||
*buff = NULL;
|
||||
total = avail_in = 0;
|
||||
b = NULL;
|
||||
used = 0;
|
||||
do {
|
||||
if (b == NULL) {
|
||||
b = __archive_read_filter_ahead(self->upstream, 1,
|
||||
&avail_in);
|
||||
if (b == NULL) {
|
||||
if (avail_in < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (rpm->state) {
|
||||
case ST_LEAD:
|
||||
if (rpm->total_in + avail_in < RPM_LEAD_SIZE)
|
||||
used += avail_in;
|
||||
else {
|
||||
n = RPM_LEAD_SIZE - rpm->total_in;
|
||||
used += n;
|
||||
b += n;
|
||||
rpm->state = ST_HEADER;
|
||||
rpm->hpos = 0;
|
||||
rpm->hlen = 0;
|
||||
rpm->first_header = 1;
|
||||
}
|
||||
break;
|
||||
case ST_HEADER:
|
||||
n = 16 - rpm->hpos;
|
||||
if (n > avail_in - used)
|
||||
n = avail_in - used;
|
||||
memcpy(rpm->header+rpm->hpos, b, n);
|
||||
b += n;
|
||||
used += n;
|
||||
rpm->hpos += n;
|
||||
|
||||
if (rpm->hpos == 16) {
|
||||
if (rpm->header[0] != 0x8e ||
|
||||
rpm->header[1] != 0xad ||
|
||||
rpm->header[2] != 0xe8 ||
|
||||
rpm->header[3] != 0x01) {
|
||||
if (rpm->first_header) {
|
||||
archive_set_error(
|
||||
&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unrecoginized rpm header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rpm->state = ST_ARCHIVE;
|
||||
*buff = rpm->header;
|
||||
total = rpm->hpos;
|
||||
break;
|
||||
}
|
||||
/* Calculate 'Header' length. */
|
||||
section = archive_be32dec(rpm->header+8);
|
||||
bytes = archive_be32dec(rpm->header+12);
|
||||
rpm->hlen = 16 + section * 16 + bytes;
|
||||
rpm->state = ST_HEADER_DATA;
|
||||
rpm->first_header = 0;
|
||||
}
|
||||
break;
|
||||
case ST_HEADER_DATA:
|
||||
n = rpm->hlen - rpm->hpos;
|
||||
if (n > avail_in - used)
|
||||
n = avail_in - used;
|
||||
b += n;
|
||||
used += n;
|
||||
rpm->hpos += n;
|
||||
if (rpm->hpos == rpm->hlen)
|
||||
rpm->state = ST_PADDING;
|
||||
break;
|
||||
case ST_PADDING:
|
||||
while (used < (size_t)avail_in) {
|
||||
if (*b != 0) {
|
||||
/* Read next header. */
|
||||
rpm->state = ST_HEADER;
|
||||
rpm->hpos = 0;
|
||||
rpm->hlen = 0;
|
||||
break;
|
||||
}
|
||||
b++;
|
||||
used++;
|
||||
}
|
||||
break;
|
||||
case ST_ARCHIVE:
|
||||
*buff = b;
|
||||
total = avail_in;
|
||||
used = avail_in;
|
||||
break;
|
||||
}
|
||||
if (used == (size_t)avail_in) {
|
||||
rpm->total_in += used;
|
||||
__archive_read_filter_consume(self->upstream, used);
|
||||
b = NULL;
|
||||
used = 0;
|
||||
}
|
||||
} while (total == 0 && avail_in > 0);
|
||||
|
||||
if (used > 0 && b != NULL) {
|
||||
rpm->total_in += used;
|
||||
__archive_read_filter_consume(self->upstream, used);
|
||||
}
|
||||
return (total);
|
||||
}
|
||||
|
||||
static int
|
||||
rpm_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct rpm *rpm;
|
||||
|
||||
rpm = (struct rpm *)self->data;
|
||||
free(rpm);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -0,0 +1,680 @@
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 Michihiro NAKAJIMA
|
||||
* 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"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
/* Maximum lookahead during bid phase */
|
||||
#define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */
|
||||
|
||||
struct uudecode {
|
||||
int64_t total;
|
||||
unsigned char *in_buff;
|
||||
#define IN_BUFF_SIZE (1024)
|
||||
int in_cnt;
|
||||
size_t in_allocated;
|
||||
unsigned char *out_buff;
|
||||
#define OUT_BUFF_SIZE (64 * 1024)
|
||||
int state;
|
||||
#define ST_FIND_HEAD 0
|
||||
#define ST_READ_UU 1
|
||||
#define ST_UUEND 2
|
||||
#define ST_READ_BASE64 3
|
||||
};
|
||||
|
||||
static int uudecode_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *filter);
|
||||
static int uudecode_bidder_init(struct archive_read_filter *);
|
||||
|
||||
static ssize_t uudecode_filter_read(struct archive_read_filter *,
|
||||
const void **);
|
||||
static int uudecode_filter_close(struct archive_read_filter *);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_uu(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_uu(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_uu(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_uu");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = uudecode_bidder_bid;
|
||||
bidder->init = uudecode_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static const unsigned char ascii[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, '\r', 0, 0, /* 00 - 0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
|
||||
};
|
||||
|
||||
static const unsigned char uuchar[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 7F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
|
||||
};
|
||||
|
||||
static const unsigned char base64[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, /* 20 - 2F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 30 - 3F */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 50 - 5F */
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 70 - 7F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
|
||||
};
|
||||
|
||||
static const int base64num[128] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 62, 0, 0, 0, 63, /* 20 - 2F */
|
||||
52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 0, 0, 0, 0, 0, 0, /* 30 - 3F */
|
||||
0, 0, 1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 14, /* 40 - 4F */
|
||||
15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 24, 25, 0, 0, 0, 0, 0, /* 50 - 5F */
|
||||
0, 26, 27, 28, 29, 30, 31, 32,
|
||||
33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */
|
||||
41, 42, 43, 44, 45, 46, 47, 48,
|
||||
49, 50, 51, 0, 0, 0, 0, 0, /* 70 - 7F */
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
get_line(const unsigned char *b, ssize_t avail, ssize_t *nlsize)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = 0;
|
||||
while (len < avail) {
|
||||
switch (ascii[*b]) {
|
||||
case 0: /* Non-ascii character or control character. */
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 0;
|
||||
return (-1);
|
||||
case '\r':
|
||||
if (avail-len > 1 && b[1] == '\n') {
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 2;
|
||||
return (len+2);
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case '\n':
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 1;
|
||||
return (len+1);
|
||||
case 1:
|
||||
b++;
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nlsize != NULL)
|
||||
*nlsize = 0;
|
||||
return (avail);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
bid_get_line(struct archive_read_filter *filter,
|
||||
const unsigned char **b, ssize_t *avail, ssize_t *ravail,
|
||||
ssize_t *nl, size_t* nbytes_read)
|
||||
{
|
||||
ssize_t len;
|
||||
int quit;
|
||||
|
||||
quit = 0;
|
||||
if (*avail == 0) {
|
||||
*nl = 0;
|
||||
len = 0;
|
||||
} else
|
||||
len = get_line(*b, *avail, nl);
|
||||
|
||||
/*
|
||||
* Read bytes more while it does not reach the end of line.
|
||||
*/
|
||||
while (*nl == 0 && len == *avail && !quit &&
|
||||
*nbytes_read < UUENCODE_BID_MAX_READ) {
|
||||
ssize_t diff = *ravail - *avail;
|
||||
size_t nbytes_req = (*ravail+1023) & ~1023U;
|
||||
ssize_t tested;
|
||||
|
||||
/* Increase reading bytes if it is not enough to at least
|
||||
* new two lines. */
|
||||
if (nbytes_req < (size_t)*ravail + 160)
|
||||
nbytes_req <<= 1;
|
||||
|
||||
*b = __archive_read_filter_ahead(filter, nbytes_req, avail);
|
||||
if (*b == NULL) {
|
||||
if (*ravail >= *avail)
|
||||
return (0);
|
||||
/* Reading bytes reaches the end of a stream. */
|
||||
*b = __archive_read_filter_ahead(filter, *avail, avail);
|
||||
quit = 1;
|
||||
}
|
||||
*nbytes_read = *avail;
|
||||
*ravail = *avail;
|
||||
*b += diff;
|
||||
*avail -= diff;
|
||||
tested = len;/* Skip some bytes we already determinated. */
|
||||
len = get_line(*b + tested, *avail - tested, nl);
|
||||
if (len >= 0)
|
||||
len += tested;
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
#define UUDECODE(c) (((c) - 0x20) & 0x3f)
|
||||
|
||||
static int
|
||||
uudecode_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *b;
|
||||
ssize_t avail, ravail;
|
||||
ssize_t len, nl;
|
||||
int l;
|
||||
int firstline;
|
||||
size_t nbytes_read;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
b = __archive_read_filter_ahead(filter, 1, &avail);
|
||||
if (b == NULL)
|
||||
return (0);
|
||||
|
||||
firstline = 20;
|
||||
ravail = avail;
|
||||
nbytes_read = avail;
|
||||
for (;;) {
|
||||
len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read);
|
||||
if (len < 0 || nl == 0)
|
||||
return (0); /* No match found. */
|
||||
if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0)
|
||||
l = 6;
|
||||
else if (len -nl >= 18 && memcmp(b, "begin-base64 ", 13) == 0)
|
||||
l = 13;
|
||||
else
|
||||
l = 0;
|
||||
|
||||
if (l > 0 && (b[l] < '0' || b[l] > '7' ||
|
||||
b[l+1] < '0' || b[l+1] > '7' ||
|
||||
b[l+2] < '0' || b[l+2] > '7' || b[l+3] != ' '))
|
||||
l = 0;
|
||||
|
||||
b += len;
|
||||
avail -= len;
|
||||
if (l)
|
||||
break;
|
||||
firstline = 0;
|
||||
|
||||
/* Do not read more than UUENCODE_BID_MAX_READ bytes */
|
||||
if (nbytes_read >= UUENCODE_BID_MAX_READ)
|
||||
return (0);
|
||||
}
|
||||
if (!avail)
|
||||
return (0);
|
||||
len = bid_get_line(filter, &b, &avail, &ravail, &nl, &nbytes_read);
|
||||
if (len < 0 || nl == 0)
|
||||
return (0);/* There are non-ascii characters. */
|
||||
avail -= len;
|
||||
|
||||
if (l == 6) {
|
||||
if (!uuchar[*b])
|
||||
return (0);
|
||||
/* Get a length of decoded bytes. */
|
||||
l = UUDECODE(*b++); len--;
|
||||
if (l > 45)
|
||||
/* Normally, maximum length is 45(character 'M'). */
|
||||
return (0);
|
||||
while (l && len-nl > 0) {
|
||||
if (l > 0) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
len -= 2;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
--len;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (!uuchar[*b++])
|
||||
return (0);
|
||||
--len;
|
||||
--l;
|
||||
}
|
||||
}
|
||||
if (len-nl < 0)
|
||||
return (0);
|
||||
if (len-nl == 1 &&
|
||||
(uuchar[*b] || /* Check sum. */
|
||||
(*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */
|
||||
++b;
|
||||
--len;
|
||||
}
|
||||
b += nl;
|
||||
if (avail && uuchar[*b])
|
||||
return (firstline+30);
|
||||
}
|
||||
if (l == 13) {
|
||||
while (len-nl > 0) {
|
||||
if (!base64[*b++])
|
||||
return (0);
|
||||
--len;
|
||||
}
|
||||
b += nl;
|
||||
|
||||
if (avail >= 5 && memcmp(b, "====\n", 5) == 0)
|
||||
return (firstline+40);
|
||||
if (avail >= 6 && memcmp(b, "====\r\n", 6) == 0)
|
||||
return (firstline+40);
|
||||
if (avail > 0 && base64[*b])
|
||||
return (firstline+30);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uudecode_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct uudecode *uudecode;
|
||||
void *out_buff;
|
||||
void *in_buff;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_UU;
|
||||
self->name = "uu";
|
||||
self->read = uudecode_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = uudecode_filter_close;
|
||||
|
||||
uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1);
|
||||
out_buff = malloc(OUT_BUFF_SIZE);
|
||||
in_buff = malloc(IN_BUFF_SIZE);
|
||||
if (uudecode == NULL || out_buff == NULL || in_buff == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for uudecode");
|
||||
free(uudecode);
|
||||
free(out_buff);
|
||||
free(in_buff);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = uudecode;
|
||||
uudecode->in_buff = in_buff;
|
||||
uudecode->in_cnt = 0;
|
||||
uudecode->in_allocated = IN_BUFF_SIZE;
|
||||
uudecode->out_buff = out_buff;
|
||||
uudecode->state = ST_FIND_HEAD;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
ensure_in_buff_size(struct archive_read_filter *self,
|
||||
struct uudecode *uudecode, size_t size)
|
||||
{
|
||||
|
||||
if (size > uudecode->in_allocated) {
|
||||
unsigned char *ptr;
|
||||
size_t newsize;
|
||||
|
||||
/*
|
||||
* Calculate a new buffer size for in_buff.
|
||||
* Increase its value until it has enough size we need.
|
||||
*/
|
||||
newsize = uudecode->in_allocated;
|
||||
do {
|
||||
if (newsize < IN_BUFF_SIZE*32)
|
||||
newsize <<= 1;
|
||||
else
|
||||
newsize += IN_BUFF_SIZE;
|
||||
} while (size > newsize);
|
||||
/* Allocate the new buffer. */
|
||||
ptr = malloc(newsize);
|
||||
if (ptr == NULL) {
|
||||
free(ptr);
|
||||
archive_set_error(&self->archive->archive,
|
||||
ENOMEM,
|
||||
"Can't allocate data for uudecode");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Move the remaining data in in_buff into the new buffer. */
|
||||
if (uudecode->in_cnt)
|
||||
memmove(ptr, uudecode->in_buff, uudecode->in_cnt);
|
||||
/* Replace in_buff with the new buffer. */
|
||||
free(uudecode->in_buff);
|
||||
uudecode->in_buff = ptr;
|
||||
uudecode->in_allocated = newsize;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
uudecode_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
{
|
||||
struct uudecode *uudecode;
|
||||
const unsigned char *b, *d;
|
||||
unsigned char *out;
|
||||
ssize_t avail_in, ravail;
|
||||
ssize_t used;
|
||||
ssize_t total;
|
||||
ssize_t len, llen, nl;
|
||||
|
||||
uudecode = (struct uudecode *)self->data;
|
||||
|
||||
read_more:
|
||||
d = __archive_read_filter_ahead(self->upstream, 1, &avail_in);
|
||||
if (d == NULL && avail_in < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
/* Quiet a code analyzer; make sure avail_in must be zero
|
||||
* when d is NULL. */
|
||||
if (d == NULL)
|
||||
avail_in = 0;
|
||||
used = 0;
|
||||
total = 0;
|
||||
out = uudecode->out_buff;
|
||||
ravail = avail_in;
|
||||
if (uudecode->in_cnt) {
|
||||
/*
|
||||
* If there is remaining data which is saved by
|
||||
* previous calling, use it first.
|
||||
*/
|
||||
if (ensure_in_buff_size(self, uudecode,
|
||||
avail_in + uudecode->in_cnt) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
memcpy(uudecode->in_buff + uudecode->in_cnt,
|
||||
d, avail_in);
|
||||
d = uudecode->in_buff;
|
||||
avail_in += uudecode->in_cnt;
|
||||
uudecode->in_cnt = 0;
|
||||
}
|
||||
for (;used < avail_in; d += llen, used += llen) {
|
||||
int l, body;
|
||||
|
||||
b = d;
|
||||
len = get_line(b, avail_in - used, &nl);
|
||||
if (len < 0) {
|
||||
/* Non-ascii character is found. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
llen = len;
|
||||
if (nl == 0) {
|
||||
/*
|
||||
* Save remaining data which does not contain
|
||||
* NL('\n','\r').
|
||||
*/
|
||||
if (ensure_in_buff_size(self, uudecode, len)
|
||||
!= ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (uudecode->in_buff != b)
|
||||
memmove(uudecode->in_buff, b, len);
|
||||
uudecode->in_cnt = len;
|
||||
if (total == 0) {
|
||||
/* Do not return 0; it means end-of-file.
|
||||
* We should try to read bytes more. */
|
||||
__archive_read_filter_consume(
|
||||
self->upstream, ravail);
|
||||
goto read_more;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (uudecode->state) {
|
||||
default:
|
||||
case ST_FIND_HEAD:
|
||||
/* Do not read more than UUENCODE_BID_MAX_READ bytes */
|
||||
if (total + len >= UUENCODE_BID_MAX_READ) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid format data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0)
|
||||
l = 6;
|
||||
else if (len - nl >= 18 &&
|
||||
memcmp(b, "begin-base64 ", 13) == 0)
|
||||
l = 13;
|
||||
else
|
||||
l = 0;
|
||||
if (l != 0 && b[l] >= '0' && b[l] <= '7' &&
|
||||
b[l+1] >= '0' && b[l+1] <= '7' &&
|
||||
b[l+2] >= '0' && b[l+2] <= '7' && b[l+3] == ' ') {
|
||||
if (l == 6)
|
||||
uudecode->state = ST_READ_UU;
|
||||
else
|
||||
uudecode->state = ST_READ_BASE64;
|
||||
}
|
||||
break;
|
||||
case ST_READ_UU:
|
||||
if (total + len * 2 > OUT_BUFF_SIZE)
|
||||
break;
|
||||
body = len - nl;
|
||||
if (!uuchar[*b] || body <= 0) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Get length of undecoded bytes of curent line. */
|
||||
l = UUDECODE(*b++);
|
||||
body--;
|
||||
if (l > body) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (l == 0) {
|
||||
uudecode->state = ST_UUEND;
|
||||
break;
|
||||
}
|
||||
while (l > 0) {
|
||||
int n = 0;
|
||||
|
||||
if (l > 0) {
|
||||
if (!uuchar[b[0]] || !uuchar[b[1]])
|
||||
break;
|
||||
n = UUDECODE(*b++) << 18;
|
||||
n |= UUDECODE(*b++) << 12;
|
||||
*out++ = n >> 16; total++;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (!uuchar[b[0]])
|
||||
break;
|
||||
n |= UUDECODE(*b++) << 6;
|
||||
*out++ = (n >> 8) & 0xFF; total++;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (!uuchar[b[0]])
|
||||
break;
|
||||
n |= UUDECODE(*b++);
|
||||
*out++ = n & 0xFF; total++;
|
||||
--l;
|
||||
}
|
||||
}
|
||||
if (l) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
break;
|
||||
case ST_UUEND:
|
||||
if (len - nl == 3 && memcmp(b, "end ", 3) == 0)
|
||||
uudecode->state = ST_FIND_HEAD;
|
||||
else {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
break;
|
||||
case ST_READ_BASE64:
|
||||
if (total + len * 2 > OUT_BUFF_SIZE)
|
||||
break;
|
||||
l = len - nl;
|
||||
if (l >= 3 && b[0] == '=' && b[1] == '=' &&
|
||||
b[2] == '=') {
|
||||
uudecode->state = ST_FIND_HEAD;
|
||||
break;
|
||||
}
|
||||
while (l > 0) {
|
||||
int n = 0;
|
||||
|
||||
if (l > 0) {
|
||||
if (!base64[b[0]] || !base64[b[1]])
|
||||
break;
|
||||
n = base64num[*b++] << 18;
|
||||
n |= base64num[*b++] << 12;
|
||||
*out++ = n >> 16; total++;
|
||||
l -= 2;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (*b == '=')
|
||||
break;
|
||||
if (!base64[*b])
|
||||
break;
|
||||
n |= base64num[*b++] << 6;
|
||||
*out++ = (n >> 8) & 0xFF; total++;
|
||||
--l;
|
||||
}
|
||||
if (l > 0) {
|
||||
if (*b == '=')
|
||||
break;
|
||||
if (!base64[*b])
|
||||
break;
|
||||
n |= base64num[*b++];
|
||||
*out++ = n & 0xFF; total++;
|
||||
--l;
|
||||
}
|
||||
}
|
||||
if (l && *b != '=') {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__archive_read_filter_consume(self->upstream, ravail);
|
||||
|
||||
*buff = uudecode->out_buff;
|
||||
uudecode->total += total;
|
||||
return (total);
|
||||
}
|
||||
|
||||
static int
|
||||
uudecode_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct uudecode *uudecode;
|
||||
|
||||
uudecode = (struct uudecode *)self->data;
|
||||
free(uudecode->in_buff);
|
||||
free(uudecode->out_buff);
|
||||
free(uudecode);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -0,0 +1,985 @@
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 Michihiro NAKAJIMA
|
||||
* Copyright (c) 2003-2008 Tim Kientzle and Miklos Vajna
|
||||
* 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"
|
||||
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_LZMA_H
|
||||
#include <lzma.h>
|
||||
#elif HAVE_LZMADEC_H
|
||||
#include <lzmadec.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_endian.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
|
||||
struct private_data {
|
||||
lzma_stream stream;
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
char in_stream;
|
||||
|
||||
/* Following variables are used for lzip only. */
|
||||
char lzip_ver;
|
||||
uint32_t crc32;
|
||||
int64_t member_in;
|
||||
int64_t member_out;
|
||||
};
|
||||
|
||||
#if LZMA_VERSION_MAJOR >= 5
|
||||
/* Effectively disable the limiter. */
|
||||
#define LZMA_MEMLIMIT UINT64_MAX
|
||||
#else
|
||||
/* NOTE: This needs to check memory size which running system has. */
|
||||
#define LZMA_MEMLIMIT (1U << 30)
|
||||
#endif
|
||||
|
||||
/* Combined lzip/lzma/xz filter */
|
||||
static ssize_t xz_filter_read(struct archive_read_filter *, const void **);
|
||||
static int xz_filter_close(struct archive_read_filter *);
|
||||
static int xz_lzma_bidder_init(struct archive_read_filter *);
|
||||
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
|
||||
struct private_data {
|
||||
lzmadec_stream stream;
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
/* Lzma-only filter */
|
||||
static ssize_t lzma_filter_read(struct archive_read_filter *, const void **);
|
||||
static int lzma_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that we can detect xz and lzma compressed files even if we
|
||||
* can't decompress them. (In fact, we like detecting them because we
|
||||
* can give better error messages.) So the bid framework here gets
|
||||
* compiled even if no lzma library is available.
|
||||
*/
|
||||
static int xz_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int xz_bidder_init(struct archive_read_filter *);
|
||||
static int lzma_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int lzma_bidder_init(struct archive_read_filter *);
|
||||
static int lzip_has_member(struct archive_read_filter *);
|
||||
static int lzip_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int lzip_bidder_init(struct archive_read_filter *);
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Deprecated; remove in libarchive 4.0 */
|
||||
int
|
||||
archive_read_support_compression_xz(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_xz(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_xz(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_xz");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = xz_bidder_bid;
|
||||
bidder->init = xz_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external unxz program for xz decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
int
|
||||
archive_read_support_compression_lzma(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_lzma(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_lzma(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_lzma");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = lzma_bidder_bid;
|
||||
bidder->init = lzma_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
return (ARCHIVE_OK);
|
||||
#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external unlzma program for lzma decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
int
|
||||
archive_read_support_compression_lzip(struct archive *a)
|
||||
{
|
||||
return archive_read_support_filter_lzip(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
archive_read_support_filter_lzip(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_lzip");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->bid = lzip_bidder_bid;
|
||||
bidder->init = lzip_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external lzip program for lzip decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether we can handle this data.
|
||||
*/
|
||||
static int
|
||||
xz_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, 6, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Verify Header Magic Bytes : FD 37 7A 58 5A 00
|
||||
*/
|
||||
if (memcmp(buffer, "\xFD\x37\x7A\x58\x5A\x00", 6) != 0)
|
||||
return (0);
|
||||
|
||||
return (48);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether we can handle this data.
|
||||
*
|
||||
* <sigh> LZMA has a rather poor file signature. Zeros do not
|
||||
* make good signature bytes as a rule, and the only non-zero byte
|
||||
* here is an ASCII character. For example, an uncompressed tar
|
||||
* archive whose first file is ']' would satisfy this check. It may
|
||||
* be necessary to exclude LZMA from compression_all() because of
|
||||
* this. Clients of libarchive would then have to explicitly enable
|
||||
* LZMA checking instead of (or in addition to) compression_all() when
|
||||
* they have other evidence (file name, command-line option) to go on.
|
||||
*/
|
||||
static int
|
||||
lzma_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
uint32_t dicsize;
|
||||
uint64_t uncompressed_size;
|
||||
int bits_checked;
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, 14, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
/* First byte of raw LZMA stream is commonly 0x5d.
|
||||
* The first byte is a special number, which consists of
|
||||
* three parameters of LZMA compression, a number of literal
|
||||
* context bits(which is from 0 to 8, default is 3), a number
|
||||
* of literal pos bits(which is from 0 to 4, default is 0),
|
||||
* a number of pos bits(which is from 0 to 4, default is 2).
|
||||
* The first byte is made by
|
||||
* (pos bits * 5 + literal pos bit) * 9 + * literal contest bit,
|
||||
* and so the default value in this field is
|
||||
* (2 * 5 + 0) * 9 + 3 = 0x5d.
|
||||
* lzma of LZMA SDK has options to change those parameters.
|
||||
* It means a range of this field is from 0 to 224. And lzma of
|
||||
* XZ Utils with option -e records 0x5e in this field. */
|
||||
/* NOTE: If this checking of the first byte increases false
|
||||
* recognition, we should allow only 0x5d and 0x5e for the first
|
||||
* byte of LZMA stream. */
|
||||
bits_checked = 0;
|
||||
if (buffer[0] > (4 * 5 + 4) * 9 + 8)
|
||||
return (0);
|
||||
/* Most likely value in the first byte of LZMA stream. */
|
||||
if (buffer[0] == 0x5d || buffer[0] == 0x5e)
|
||||
bits_checked += 8;
|
||||
|
||||
/* Sixth through fourteenth bytes are uncompressed size,
|
||||
* stored in little-endian order. `-1' means uncompressed
|
||||
* size is unknown and lzma of XZ Utils always records `-1'
|
||||
* in this field. */
|
||||
uncompressed_size = archive_le64dec(buffer+5);
|
||||
if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1))
|
||||
bits_checked += 64;
|
||||
|
||||
/* Second through fifth bytes are dictionary size, stored in
|
||||
* little-endian order. The minimum dictionary size is
|
||||
* 1 << 12(4KiB) which the lzma of LZMA SDK uses with option
|
||||
* -d12 and the maxinam dictionary size is 1 << 27(128MiB)
|
||||
* which the one uses with option -d27.
|
||||
* NOTE: A comment of LZMA SDK source code says this dictionary
|
||||
* range is from 1 << 12 to 1 << 30. */
|
||||
dicsize = archive_le32dec(buffer+1);
|
||||
switch (dicsize) {
|
||||
case 0x00001000:/* lzma of LZMA SDK option -d12. */
|
||||
case 0x00002000:/* lzma of LZMA SDK option -d13. */
|
||||
case 0x00004000:/* lzma of LZMA SDK option -d14. */
|
||||
case 0x00008000:/* lzma of LZMA SDK option -d15. */
|
||||
case 0x00010000:/* lzma of XZ Utils option -0 and -1.
|
||||
* lzma of LZMA SDK option -d16. */
|
||||
case 0x00020000:/* lzma of LZMA SDK option -d17. */
|
||||
case 0x00040000:/* lzma of LZMA SDK option -d18. */
|
||||
case 0x00080000:/* lzma of XZ Utils option -2.
|
||||
* lzma of LZMA SDK option -d19. */
|
||||
case 0x00100000:/* lzma of XZ Utils option -3.
|
||||
* lzma of LZMA SDK option -d20. */
|
||||
case 0x00200000:/* lzma of XZ Utils option -4.
|
||||
* lzma of LZMA SDK option -d21. */
|
||||
case 0x00400000:/* lzma of XZ Utils option -5.
|
||||
* lzma of LZMA SDK option -d22. */
|
||||
case 0x00800000:/* lzma of XZ Utils option -6.
|
||||
* lzma of LZMA SDK option -d23. */
|
||||
case 0x01000000:/* lzma of XZ Utils option -7.
|
||||
* lzma of LZMA SDK option -d24. */
|
||||
case 0x02000000:/* lzma of XZ Utils option -8.
|
||||
* lzma of LZMA SDK option -d25. */
|
||||
case 0x04000000:/* lzma of XZ Utils option -9.
|
||||
* lzma of LZMA SDK option -d26. */
|
||||
case 0x08000000:/* lzma of LZMA SDK option -d27. */
|
||||
bits_checked += 32;
|
||||
break;
|
||||
default:
|
||||
/* If a memory usage for encoding was not enough on
|
||||
* the platform where LZMA stream was made, lzma of
|
||||
* XZ Utils automatically decreased the dictionary
|
||||
* size to enough memory for encoding by 1Mi bytes
|
||||
* (1 << 20).*/
|
||||
if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 &&
|
||||
(dicsize & ((1 << 20)-1)) == 0 &&
|
||||
bits_checked == 8 + 64) {
|
||||
bits_checked += 32;
|
||||
break;
|
||||
}
|
||||
/* Otherwise dictionary size is unlikely. But it is
|
||||
* possible that someone makes lzma stream with
|
||||
* liblzma/LZMA SDK in one's dictionary size. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* TODO: The above test is still very weak. It would be
|
||||
* good to do better. */
|
||||
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
static int
|
||||
lzip_has_member(struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
int bits_checked;
|
||||
int log2dic;
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, 6, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Verify Header Magic Bytes : 4C 5A 49 50 (`LZIP')
|
||||
*/
|
||||
bits_checked = 0;
|
||||
if (memcmp(buffer, "LZIP", 4) != 0)
|
||||
return (0);
|
||||
bits_checked += 32;
|
||||
|
||||
/* A version number must be 0 or 1 */
|
||||
if (buffer[4] != 0 && buffer[4] != 1)
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
|
||||
/* Dictionary size. */
|
||||
log2dic = buffer[5] & 0x1f;
|
||||
if (log2dic < 12 || log2dic > 27)
|
||||
return (0);
|
||||
bits_checked += 8;
|
||||
|
||||
return (bits_checked);
|
||||
}
|
||||
|
||||
static int
|
||||
lzip_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
|
||||
(void)self; /* UNUSED */
|
||||
return (lzip_has_member(filter));
|
||||
}
|
||||
|
||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||
|
||||
/*
|
||||
* liblzma 4.999.7 and later support both lzma and xz streams.
|
||||
*/
|
||||
static int
|
||||
xz_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
self->code = ARCHIVE_COMPRESSION_XZ;
|
||||
self->name = "xz";
|
||||
return (xz_lzma_bidder_init(self));
|
||||
}
|
||||
|
||||
static int
|
||||
lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
self->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
self->name = "lzma";
|
||||
return (xz_lzma_bidder_init(self));
|
||||
}
|
||||
|
||||
static int
|
||||
lzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
self->code = ARCHIVE_COMPRESSION_LZIP;
|
||||
self->name = "lzip";
|
||||
return (xz_lzma_bidder_init(self));
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an error code and choose an error message
|
||||
*/
|
||||
static void
|
||||
set_error(struct archive_read_filter *self, int ret)
|
||||
{
|
||||
|
||||
switch (ret) {
|
||||
case LZMA_STREAM_END: /* Found end of stream. */
|
||||
case LZMA_OK: /* Decompressor made some progress. */
|
||||
break;
|
||||
case LZMA_MEM_ERROR:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Lzma library error: Cannot allocate memory");
|
||||
break;
|
||||
case LZMA_MEMLIMIT_ERROR:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Lzma library error: Out of memory");
|
||||
break;
|
||||
case LZMA_FORMAT_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma library error: format not recognized");
|
||||
break;
|
||||
case LZMA_OPTIONS_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma library error: Invalid options");
|
||||
break;
|
||||
case LZMA_DATA_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma library error: Corrupted input data");
|
||||
break;
|
||||
case LZMA_BUF_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma library error: No progress is possible");
|
||||
break;
|
||||
default:
|
||||
/* Return an error. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma decompression failed: Unknown error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
xz_lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for xz decompression");
|
||||
free(out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = xz_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = xz_filter_close;
|
||||
|
||||
state->stream.avail_in = 0;
|
||||
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
state->crc32 = 0;
|
||||
if (self->code == ARCHIVE_COMPRESSION_LZIP) {
|
||||
/*
|
||||
* We have to read a lzip header and use it to initialize
|
||||
* compression library, thus we cannot initialize the
|
||||
* library for lzip here.
|
||||
*/
|
||||
state->in_stream = 0;
|
||||
return (ARCHIVE_OK);
|
||||
} else
|
||||
state->in_stream = 1;
|
||||
|
||||
/* Initialize compression library. */
|
||||
if (self->code == ARCHIVE_COMPRESSION_XZ)
|
||||
ret = lzma_stream_decoder(&(state->stream),
|
||||
LZMA_MEMLIMIT,/* memlimit */
|
||||
LZMA_CONCATENATED);
|
||||
else
|
||||
ret = lzma_alone_decoder(&(state->stream),
|
||||
LZMA_MEMLIMIT);/* memlimit */
|
||||
|
||||
if (ret == LZMA_OK)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/* Library setup failed: Choose an error message and clean up. */
|
||||
set_error(self, ret);
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
self->data = NULL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
lzip_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
const unsigned char *h;
|
||||
lzma_filter filters[2];
|
||||
unsigned char props[5];
|
||||
ssize_t avail_in;
|
||||
uint32_t dicsize;
|
||||
int log2dic, ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
h = __archive_read_filter_ahead(self->upstream, 6, &avail_in);
|
||||
if (h == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
/* Get a version number. */
|
||||
state->lzip_ver = h[4];
|
||||
|
||||
/*
|
||||
* Setup lzma property.
|
||||
*/
|
||||
props[0] = 0x5d;
|
||||
|
||||
/* Get dictionary size. */
|
||||
log2dic = h[5] & 0x1f;
|
||||
if (log2dic < 12 || log2dic > 27)
|
||||
return (ARCHIVE_FATAL);
|
||||
dicsize = 1U << log2dic;
|
||||
if (log2dic > 12)
|
||||
dicsize -= (dicsize / 16) * (h[5] >> 5);
|
||||
archive_le32enc(props+1, dicsize);
|
||||
|
||||
/* Consume lzip header. */
|
||||
__archive_read_filter_consume(self->upstream, 6);
|
||||
state->member_in = 6;
|
||||
|
||||
filters[0].id = LZMA_FILTER_LZMA1;
|
||||
filters[0].options = NULL;
|
||||
filters[1].id = LZMA_VLI_UNKNOWN;
|
||||
filters[1].options = NULL;
|
||||
|
||||
ret = lzma_properties_decode(&filters[0], NULL, props, sizeof(props));
|
||||
if (ret != LZMA_OK) {
|
||||
set_error(self, ret);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ret = lzma_raw_decoder(&(state->stream), filters);
|
||||
#if LZMA_VERSION < 50000030
|
||||
free(filters[0].options);
|
||||
#endif
|
||||
if (ret != LZMA_OK) {
|
||||
set_error(self, ret);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
lzip_tail(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
const unsigned char *f;
|
||||
ssize_t avail_in;
|
||||
int tail;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
if (state->lzip_ver == 0)
|
||||
tail = 12;
|
||||
else
|
||||
tail = 20;
|
||||
f = __archive_read_filter_ahead(self->upstream, tail, &avail_in);
|
||||
if (f == NULL && avail_in < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (avail_in < tail) {
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Lzip: Remaining data is less bytes");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
/* Check the crc32 value of the uncompressed data of the current
|
||||
* member */
|
||||
if (state->crc32 != archive_le32dec(f)) {
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Lzip: CRC32 error");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
/* Check the uncompressed size of the current member */
|
||||
if ((uint64_t)state->member_out != archive_le64dec(f + 4)) {
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Lzip: Uncompressed size error");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
/* Check the total size of the current member */
|
||||
if (state->lzip_ver == 1 &&
|
||||
(uint64_t)state->member_in + tail != archive_le64dec(f + 12)) {
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Lzip: Member size error");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
__archive_read_filter_consume(self->upstream, tail);
|
||||
|
||||
/* If current lzip data consists of multi member, try decompressing
|
||||
* a next member. */
|
||||
if (lzip_has_member(self->upstream) != 0) {
|
||||
state->in_stream = 0;
|
||||
state->crc32 = 0;
|
||||
state->member_out = 0;
|
||||
state->member_in = 0;
|
||||
state->eof = 0;
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next block of decompressed data.
|
||||
*/
|
||||
static ssize_t
|
||||
xz_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (state->stream.avail_out > 0 && !state->eof) {
|
||||
if (!state->in_stream) {
|
||||
/*
|
||||
* Initialize liblzma for lzip
|
||||
*/
|
||||
ret = lzip_init(self);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
state->in_stream = 1;
|
||||
}
|
||||
state->stream.next_in =
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail_in);
|
||||
if (state->stream.next_in == NULL && avail_in < 0) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"truncated input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.avail_in = avail_in;
|
||||
|
||||
/* Decompress as much as we can in one pass. */
|
||||
ret = lzma_code(&(state->stream),
|
||||
(state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN);
|
||||
switch (ret) {
|
||||
case LZMA_STREAM_END: /* Found end of stream. */
|
||||
state->eof = 1;
|
||||
/* FALL THROUGH */
|
||||
case LZMA_OK: /* Decompressor made some progress. */
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
state->member_in +=
|
||||
avail_in - state->stream.avail_in;
|
||||
break;
|
||||
default:
|
||||
set_error(self, ret);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
decompressed = state->stream.next_out - state->out_block;
|
||||
state->total_out += decompressed;
|
||||
state->member_out += decompressed;
|
||||
if (decompressed == 0)
|
||||
*p = NULL;
|
||||
else {
|
||||
*p = state->out_block;
|
||||
if (self->code == ARCHIVE_COMPRESSION_LZIP) {
|
||||
state->crc32 = lzma_crc32(state->out_block,
|
||||
decompressed, state->crc32);
|
||||
if (state->eof) {
|
||||
ret = lzip_tail(self);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
xz_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
lzma_end(&(state->stream));
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC
|
||||
|
||||
/*
|
||||
* If we have the older liblzmadec library, then we can handle
|
||||
* LZMA streams but not XZ streams.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Setup the callbacks.
|
||||
*/
|
||||
static int
|
||||
lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
static const size_t out_block_size = 64 * 1024;
|
||||
void *out_block;
|
||||
struct private_data *state;
|
||||
ssize_t ret, avail_in;
|
||||
|
||||
self->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
self->name = "lzma";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
if (state == NULL || out_block == NULL) {
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for lzma decompression");
|
||||
free(out_block);
|
||||
free(state);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
self->read = lzma_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = lzma_filter_close;
|
||||
|
||||
/* Prime the lzma library with 18 bytes of input. */
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 18, &avail_in);
|
||||
if (state->stream.next_in == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
state->stream.avail_in = avail_in;
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Initialize compression library. */
|
||||
ret = lzmadec_init(&(state->stream));
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
if (ret == LZMADEC_OK)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/* Library setup failed: Clean up. */
|
||||
archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing lzma library");
|
||||
|
||||
/* Override the error message if we know what really went wrong. */
|
||||
switch (ret) {
|
||||
case LZMADEC_HEADER_ERROR:
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Internal error initializing compression library: "
|
||||
"invalid header");
|
||||
break;
|
||||
case LZMADEC_MEM_ERROR:
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Internal error initializing compression library: "
|
||||
"out of memory");
|
||||
break;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
self->data = NULL;
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next block of decompressed data.
|
||||
*/
|
||||
static ssize_t
|
||||
lzma_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in, ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* Empty our output buffer. */
|
||||
state->stream.next_out = state->out_block;
|
||||
state->stream.avail_out = state->out_block_size;
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (state->stream.avail_out > 0 && !state->eof) {
|
||||
state->stream.next_in = (unsigned char *)(uintptr_t)
|
||||
__archive_read_filter_ahead(self->upstream, 1, &avail_in);
|
||||
if (state->stream.next_in == NULL && avail_in < 0) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"truncated lzma input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
state->stream.avail_in = avail_in;
|
||||
|
||||
/* Decompress as much as we can in one pass. */
|
||||
ret = lzmadec_decode(&(state->stream), avail_in == 0);
|
||||
switch (ret) {
|
||||
case LZMADEC_STREAM_END: /* Found end of stream. */
|
||||
state->eof = 1;
|
||||
/* FALL THROUGH */
|
||||
case LZMADEC_OK: /* Decompressor made some progress. */
|
||||
__archive_read_filter_consume(self->upstream,
|
||||
avail_in - state->stream.avail_in);
|
||||
break;
|
||||
case LZMADEC_BUF_ERROR: /* Insufficient input data? */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Insufficient compressed data");
|
||||
return (ARCHIVE_FATAL);
|
||||
default:
|
||||
/* Return an error. */
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Lzma decompression failed");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
decompressed = state->stream.next_out - state->out_block;
|
||||
state->total_out += decompressed;
|
||||
if (decompressed == 0)
|
||||
*p = NULL;
|
||||
else
|
||||
*p = state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
lzma_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
ret = ARCHIVE_OK;
|
||||
switch (lzmadec_end(&(state->stream))) {
|
||||
case LZMADEC_OK:
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&(self->archive->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to clean up %s compressor",
|
||||
self->archive->archive.compression_name);
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
*
|
||||
* If we have no suitable library on this system, we can't actually do
|
||||
* the decompression. We can, however, still detect compressed
|
||||
* archives and emit a useful message.
|
||||
*
|
||||
*/
|
||||
static int
|
||||
lzma_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "unlzma");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_LZMA;
|
||||
self->name = "lzma";
|
||||
return (r);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LZMADEC_H */
|
||||
|
||||
|
||||
static int
|
||||
xz_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "unxz");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_XZ;
|
||||
self->name = "xz";
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
lzip_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "unlzip");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_COMPRESSION_LZIP;
|
||||
self->name = "lzip";
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_LZMA_H */
|
3687
Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
Normal file
3687
Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,87 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2011 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_all.c 174991 2007-12-30 04:58:22Z kientzle $");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
int
|
||||
archive_read_support_format_all(struct archive *a)
|
||||
{
|
||||
archive_check_magic(a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_all");
|
||||
|
||||
/* TODO: It would be nice to compute the ordering
|
||||
* here automatically so that people who enable just
|
||||
* a few formats can still get the benefits. That
|
||||
* may just require the format registration to include
|
||||
* a "maximum read-ahead" value (anything that uses seek
|
||||
* would be essentially infinite read-ahead). The core
|
||||
* bid management can then sort the bidders before calling
|
||||
* them.
|
||||
*
|
||||
* If you implement the above, please return the list below
|
||||
* to alphabetic order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These bidders are all pretty cheap; they just examine a
|
||||
* small initial part of the archive. If one of these bids
|
||||
* high, we can maybe avoid running any of the more expensive
|
||||
* bidders below.
|
||||
*/
|
||||
archive_read_support_format_ar(a);
|
||||
archive_read_support_format_cpio(a);
|
||||
archive_read_support_format_empty(a);
|
||||
archive_read_support_format_lha(a);
|
||||
archive_read_support_format_mtree(a);
|
||||
archive_read_support_format_tar(a);
|
||||
archive_read_support_format_xar(a);
|
||||
|
||||
/*
|
||||
* Install expensive bidders last. By doing them last, we
|
||||
* increase the chance that a high bid from someone else will
|
||||
* make it unnecessary for these to do anything at all.
|
||||
*/
|
||||
/* These three have potentially large look-ahead. */
|
||||
archive_read_support_format_7zip(a);
|
||||
archive_read_support_format_cab(a);
|
||||
archive_read_support_format_rar(a);
|
||||
archive_read_support_format_iso9660(a);
|
||||
/* Seek is really bad, since it forces the read-ahead
|
||||
* logic to discard buffered data. */
|
||||
archive_read_support_format_zip(a);
|
||||
|
||||
/* Note: We always return ARCHIVE_OK here, even if some of the
|
||||
* above return ARCHIVE_WARN. The intent here is to enable
|
||||
* "as much as possible." Clients who need specific
|
||||
* compression should enable those individually so they can
|
||||
* verify the level of support. */
|
||||
/* Clear any warning messages set by the above functions. */
|
||||
archive_clear_error(a);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
@ -0,0 +1,625 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Kai Wang
|
||||
* Copyright (c) 2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_ar.c 201101 2009-12-28 03:06:27Z kientzle $");
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
struct ar {
|
||||
int64_t entry_bytes_remaining;
|
||||
/* unconsumed is purely to track data we've gotten from readahead,
|
||||
* but haven't yet marked as consumed. Must be paired with
|
||||
* entry_bytes_remaining usage/modification.
|
||||
*/
|
||||
size_t entry_bytes_unconsumed;
|
||||
int64_t entry_offset;
|
||||
int64_t entry_padding;
|
||||
char *strtab;
|
||||
size_t strtab_size;
|
||||
char read_global_header;
|
||||
};
|
||||
|
||||
/*
|
||||
* Define structure of the "ar" header.
|
||||
*/
|
||||
#define AR_name_offset 0
|
||||
#define AR_name_size 16
|
||||
#define AR_date_offset 16
|
||||
#define AR_date_size 12
|
||||
#define AR_uid_offset 28
|
||||
#define AR_uid_size 6
|
||||
#define AR_gid_offset 34
|
||||
#define AR_gid_size 6
|
||||
#define AR_mode_offset 40
|
||||
#define AR_mode_size 8
|
||||
#define AR_size_offset 48
|
||||
#define AR_size_size 10
|
||||
#define AR_fmag_offset 58
|
||||
#define AR_fmag_size 2
|
||||
|
||||
static int archive_read_format_ar_bid(struct archive_read *a, int);
|
||||
static int archive_read_format_ar_cleanup(struct archive_read *a);
|
||||
static int archive_read_format_ar_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, int64_t *offset);
|
||||
static int archive_read_format_ar_skip(struct archive_read *a);
|
||||
static int archive_read_format_ar_read_header(struct archive_read *a,
|
||||
struct archive_entry *e);
|
||||
static uint64_t ar_atol8(const char *p, unsigned char_cnt);
|
||||
static uint64_t ar_atol10(const char *p, unsigned char_cnt);
|
||||
static int ar_parse_gnu_filename_table(struct archive_read *a);
|
||||
static int ar_parse_common_header(struct ar *ar, struct archive_entry *,
|
||||
const char *h);
|
||||
|
||||
int
|
||||
archive_read_support_format_ar(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct ar *ar;
|
||||
int r;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
|
||||
|
||||
ar = (struct ar *)malloc(sizeof(*ar));
|
||||
if (ar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate ar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memset(ar, 0, sizeof(*ar));
|
||||
ar->strtab = NULL;
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
ar,
|
||||
"ar",
|
||||
archive_read_format_ar_bid,
|
||||
NULL,
|
||||
archive_read_format_ar_read_header,
|
||||
archive_read_format_ar_read_data,
|
||||
archive_read_format_ar_skip,
|
||||
archive_read_format_ar_cleanup);
|
||||
|
||||
if (r != ARCHIVE_OK) {
|
||||
free(ar);
|
||||
return (r);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_ar_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct ar *ar;
|
||||
|
||||
ar = (struct ar *)(a->format->data);
|
||||
if (ar->strtab)
|
||||
free(ar->strtab);
|
||||
free(ar);
|
||||
(a->format->data) = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_ar_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
const void *h;
|
||||
|
||||
(void)best_bid; /* UNUSED */
|
||||
|
||||
/*
|
||||
* Verify the 8-byte file signature.
|
||||
* TODO: Do we need to check more than this?
|
||||
*/
|
||||
if ((h = __archive_read_ahead(a, 8, NULL)) == NULL)
|
||||
return (-1);
|
||||
if (memcmp(h, "!<arch>\n", 8) == 0) {
|
||||
return (64);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
_ar_read_header(struct archive_read *a, struct archive_entry *entry,
|
||||
struct ar *ar, const char *h, size_t *unconsumed)
|
||||
{
|
||||
char filename[AR_name_size + 1];
|
||||
uint64_t number; /* Used to hold parsed numbers before validation. */
|
||||
size_t bsd_name_length, entry_size;
|
||||
char *p, *st;
|
||||
const void *b;
|
||||
int r;
|
||||
|
||||
/* Verify the magic signature on the file header. */
|
||||
if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Incorrect file header signature");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/* Copy filename into work buffer. */
|
||||
strncpy(filename, h + AR_name_offset, AR_name_size);
|
||||
filename[AR_name_size] = '\0';
|
||||
|
||||
/*
|
||||
* Guess the format variant based on the filename.
|
||||
*/
|
||||
if (a->archive.archive_format == ARCHIVE_FORMAT_AR) {
|
||||
/* We don't already know the variant, so let's guess. */
|
||||
/*
|
||||
* Biggest clue is presence of '/': GNU starts special
|
||||
* filenames with '/', appends '/' as terminator to
|
||||
* non-special names, so anything with '/' should be
|
||||
* GNU except for BSD long filenames.
|
||||
*/
|
||||
if (strncmp(filename, "#1/", 3) == 0)
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
|
||||
else if (strchr(filename, '/') != NULL)
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU;
|
||||
else if (strncmp(filename, "__.SYMDEF", 9) == 0)
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
|
||||
/*
|
||||
* XXX Do GNU/SVR4 'ar' programs ever omit trailing '/'
|
||||
* if name exactly fills 16-byte field? If so, we
|
||||
* can't assume entries without '/' are BSD. XXX
|
||||
*/
|
||||
}
|
||||
|
||||
/* Update format name from the code. */
|
||||
if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU)
|
||||
a->archive.archive_format_name = "ar (GNU/SVR4)";
|
||||
else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD)
|
||||
a->archive.archive_format_name = "ar (BSD)";
|
||||
else
|
||||
a->archive.archive_format_name = "ar";
|
||||
|
||||
/*
|
||||
* Remove trailing spaces from the filename. GNU and BSD
|
||||
* variants both pad filename area out with spaces.
|
||||
* This will only be wrong if GNU/SVR4 'ar' implementations
|
||||
* omit trailing '/' for 16-char filenames and we have
|
||||
* a 16-char filename that ends in ' '.
|
||||
*/
|
||||
p = filename + AR_name_size - 1;
|
||||
while (p >= filename && *p == ' ') {
|
||||
*p = '\0';
|
||||
p--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove trailing slash unless first character is '/'.
|
||||
* (BSD entries never end in '/', so this will only trim
|
||||
* GNU-format entries. GNU special entries start with '/'
|
||||
* and are not terminated in '/', so we don't trim anything
|
||||
* that starts with '/'.)
|
||||
*/
|
||||
if (filename[0] != '/' && *p == '/')
|
||||
*p = '\0';
|
||||
|
||||
/*
|
||||
* '//' is the GNU filename table.
|
||||
* Later entries can refer to names in this table.
|
||||
*/
|
||||
if (strcmp(filename, "//") == 0) {
|
||||
/* This must come before any call to _read_ahead. */
|
||||
ar_parse_common_header(ar, entry, h);
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
/* Get the size of the filename table. */
|
||||
number = ar_atol10(h + AR_size_offset, AR_size_size);
|
||||
if (number > SIZE_MAX) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Filename table too large");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
entry_size = (size_t)number;
|
||||
if (entry_size == 0) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid string table");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
if (ar->strtab != NULL) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"More than one string tables exist");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
/* Read the filename table into memory. */
|
||||
st = malloc(entry_size);
|
||||
if (st == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate filename table buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ar->strtab = st;
|
||||
ar->strtab_size = entry_size;
|
||||
|
||||
if (*unconsumed) {
|
||||
__archive_read_consume(a, *unconsumed);
|
||||
*unconsumed = 0;
|
||||
}
|
||||
|
||||
if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
memcpy(st, b, entry_size);
|
||||
__archive_read_consume(a, entry_size);
|
||||
/* All contents are consumed. */
|
||||
ar->entry_bytes_remaining = 0;
|
||||
archive_entry_set_size(entry, ar->entry_bytes_remaining);
|
||||
|
||||
/* Parse the filename table. */
|
||||
return (ar_parse_gnu_filename_table(a));
|
||||
}
|
||||
|
||||
/*
|
||||
* GNU variant handles long filenames by storing /<number>
|
||||
* to indicate a name stored in the filename table.
|
||||
* XXX TODO: Verify that it's all digits... Don't be fooled
|
||||
* by "/9xyz" XXX
|
||||
*/
|
||||
if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') {
|
||||
number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1);
|
||||
/*
|
||||
* If we can't look up the real name, warn and return
|
||||
* the entry with the wrong name.
|
||||
*/
|
||||
if (ar->strtab == NULL || number > ar->strtab_size) {
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Can't find long filename for entry");
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
/* Parse the time, owner, mode, size fields. */
|
||||
ar_parse_common_header(ar, entry, h);
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]);
|
||||
/* Parse the time, owner, mode, size fields. */
|
||||
return (ar_parse_common_header(ar, entry, h));
|
||||
}
|
||||
|
||||
/*
|
||||
* BSD handles long filenames by storing "#1/" followed by the
|
||||
* length of filename as a decimal number, then prepends the
|
||||
* the filename to the file contents.
|
||||
*/
|
||||
if (strncmp(filename, "#1/", 3) == 0) {
|
||||
/* Parse the time, owner, mode, size fields. */
|
||||
/* This must occur before _read_ahead is called again. */
|
||||
ar_parse_common_header(ar, entry, h);
|
||||
|
||||
/* Parse the size of the name, adjust the file size. */
|
||||
number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
|
||||
bsd_name_length = (size_t)number;
|
||||
/* Guard against the filename + trailing NUL
|
||||
* overflowing a size_t and against the filename size
|
||||
* being larger than the entire entry. */
|
||||
if (number > (uint64_t)(bsd_name_length + 1)
|
||||
|| (int64_t)bsd_name_length > ar->entry_bytes_remaining) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Bad input file size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
ar->entry_bytes_remaining -= bsd_name_length;
|
||||
/* Adjust file size reported to client. */
|
||||
archive_entry_set_size(entry, ar->entry_bytes_remaining);
|
||||
|
||||
if (*unconsumed) {
|
||||
__archive_read_consume(a, *unconsumed);
|
||||
*unconsumed = 0;
|
||||
}
|
||||
|
||||
/* Read the long name into memory. */
|
||||
if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Truncated input file");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
/* Store it in the entry. */
|
||||
p = (char *)malloc(bsd_name_length + 1);
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate fname buffer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
strncpy(p, b, bsd_name_length);
|
||||
p[bsd_name_length] = '\0';
|
||||
|
||||
__archive_read_consume(a, bsd_name_length);
|
||||
|
||||
archive_entry_copy_pathname(entry, p);
|
||||
free(p);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* "/" is the SVR4/GNU archive symbol table.
|
||||
*/
|
||||
if (strcmp(filename, "/") == 0) {
|
||||
archive_entry_copy_pathname(entry, "/");
|
||||
/* Parse the time, owner, mode, size fields. */
|
||||
r = ar_parse_common_header(ar, entry, h);
|
||||
/* Force the file type to a regular file. */
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* "__.SYMDEF" is a BSD archive symbol table.
|
||||
*/
|
||||
if (strcmp(filename, "__.SYMDEF") == 0) {
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
/* Parse the time, owner, mode, size fields. */
|
||||
return (ar_parse_common_header(ar, entry, h));
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, this is a standard entry. The filename
|
||||
* has already been trimmed as much as possible, based
|
||||
* on our current knowledge of the format.
|
||||
*/
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
return (ar_parse_common_header(ar, entry, h));
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_ar_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct ar *ar = (struct ar*)(a->format->data);
|
||||
size_t unconsumed;
|
||||
const void *header_data;
|
||||
int ret;
|
||||
|
||||
if (!ar->read_global_header) {
|
||||
/*
|
||||
* We are now at the beginning of the archive,
|
||||
* so we need first consume the ar global header.
|
||||
*/
|
||||
__archive_read_consume(a, 8);
|
||||
ar->read_global_header = 1;
|
||||
/* Set a default format code for now. */
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_AR;
|
||||
}
|
||||
|
||||
/* Read the header for the next file entry. */
|
||||
if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL)
|
||||
/* Broken header. */
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
unconsumed = 60;
|
||||
|
||||
ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed);
|
||||
|
||||
if (unconsumed)
|
||||
__archive_read_consume(a, unconsumed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ar_parse_common_header(struct ar *ar, struct archive_entry *entry,
|
||||
const char *h)
|
||||
{
|
||||
uint64_t n;
|
||||
|
||||
/* Copy remaining header */
|
||||
archive_entry_set_mtime(entry,
|
||||
(time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L);
|
||||
archive_entry_set_uid(entry,
|
||||
(uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size));
|
||||
archive_entry_set_gid(entry,
|
||||
(gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size));
|
||||
archive_entry_set_mode(entry,
|
||||
(mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size));
|
||||
n = ar_atol10(h + AR_size_offset, AR_size_size);
|
||||
|
||||
ar->entry_offset = 0;
|
||||
ar->entry_padding = n % 2;
|
||||
archive_entry_set_size(entry, n);
|
||||
ar->entry_bytes_remaining = n;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_ar_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, int64_t *offset)
|
||||
{
|
||||
ssize_t bytes_read;
|
||||
struct ar *ar;
|
||||
|
||||
ar = (struct ar *)(a->format->data);
|
||||
|
||||
if (ar->entry_bytes_unconsumed) {
|
||||
__archive_read_consume(a, ar->entry_bytes_unconsumed);
|
||||
ar->entry_bytes_unconsumed = 0;
|
||||
}
|
||||
|
||||
if (ar->entry_bytes_remaining > 0) {
|
||||
*buff = __archive_read_ahead(a, 1, &bytes_read);
|
||||
if (bytes_read == 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Truncated ar archive");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (bytes_read < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (bytes_read > ar->entry_bytes_remaining)
|
||||
bytes_read = (ssize_t)ar->entry_bytes_remaining;
|
||||
*size = bytes_read;
|
||||
ar->entry_bytes_unconsumed = bytes_read;
|
||||
*offset = ar->entry_offset;
|
||||
ar->entry_offset += bytes_read;
|
||||
ar->entry_bytes_remaining -= bytes_read;
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
int64_t skipped = __archive_read_consume(a, ar->entry_padding);
|
||||
if (skipped >= 0) {
|
||||
ar->entry_padding -= skipped;
|
||||
}
|
||||
if (ar->entry_padding) {
|
||||
if (skipped >= 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Truncated ar archive- failed consuming padding");
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
*buff = NULL;
|
||||
*size = 0;
|
||||
*offset = ar->entry_offset;
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_ar_skip(struct archive_read *a)
|
||||
{
|
||||
int64_t bytes_skipped;
|
||||
struct ar* ar;
|
||||
|
||||
ar = (struct ar *)(a->format->data);
|
||||
|
||||
bytes_skipped = __archive_read_consume(a,
|
||||
ar->entry_bytes_remaining + ar->entry_padding
|
||||
+ ar->entry_bytes_unconsumed);
|
||||
if (bytes_skipped < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
ar->entry_bytes_remaining = 0;
|
||||
ar->entry_bytes_unconsumed = 0;
|
||||
ar->entry_padding = 0;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
ar_parse_gnu_filename_table(struct archive_read *a)
|
||||
{
|
||||
struct ar *ar;
|
||||
char *p;
|
||||
size_t size;
|
||||
|
||||
ar = (struct ar*)(a->format->data);
|
||||
size = ar->strtab_size;
|
||||
|
||||
for (p = ar->strtab; p < ar->strtab + size - 1; ++p) {
|
||||
if (*p == '/') {
|
||||
*p++ = '\0';
|
||||
if (*p != '\n')
|
||||
goto bad_string_table;
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
/*
|
||||
* GNU ar always pads the table to an even size.
|
||||
* The pad character is either '\n' or '`'.
|
||||
*/
|
||||
if (p != ar->strtab + size && *p != '\n' && *p != '`')
|
||||
goto bad_string_table;
|
||||
|
||||
/* Enforce zero termination. */
|
||||
ar->strtab[size - 1] = '\0';
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
bad_string_table:
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Invalid string table");
|
||||
free(ar->strtab);
|
||||
ar->strtab = NULL;
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
ar_atol8(const char *p, unsigned char_cnt)
|
||||
{
|
||||
uint64_t l, limit, last_digit_limit;
|
||||
unsigned int digit, base;
|
||||
|
||||
base = 8;
|
||||
limit = UINT64_MAX / base;
|
||||
last_digit_limit = UINT64_MAX % base;
|
||||
|
||||
while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
|
||||
p++;
|
||||
|
||||
l = 0;
|
||||
digit = *p - '0';
|
||||
while (*p >= '0' && digit < base && char_cnt-- > 0) {
|
||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
||||
l = UINT64_MAX; /* Truncate on overflow. */
|
||||
break;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
digit = *++p - '0';
|
||||
}
|
||||
return (l);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
ar_atol10(const char *p, unsigned char_cnt)
|
||||
{
|
||||
uint64_t l, limit, last_digit_limit;
|
||||
unsigned int base, digit;
|
||||
|
||||
base = 10;
|
||||
limit = UINT64_MAX / base;
|
||||
last_digit_limit = UINT64_MAX % base;
|
||||
|
||||
while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
|
||||
p++;
|
||||
l = 0;
|
||||
digit = *p - '0';
|
||||
while (*p >= '0' && digit < base && char_cnt-- > 0) {
|
||||
if (l > limit || (l == limit && digit > last_digit_limit)) {
|
||||
l = UINT64_MAX; /* Truncate on overflow. */
|
||||
break;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
digit = *++p - '0';
|
||||
}
|
||||
return (l);
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2011 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
||||
int
|
||||
archive_read_support_format_by_code(struct archive *a, int format_code)
|
||||
{
|
||||
archive_check_magic(a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_by_code");
|
||||
|
||||
switch (format_code & ARCHIVE_FORMAT_BASE_MASK) {
|
||||
case ARCHIVE_FORMAT_7ZIP:
|
||||
return archive_read_support_format_7zip(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_AR:
|
||||
return archive_read_support_format_ar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CAB:
|
||||
return archive_read_support_format_cab(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CPIO:
|
||||
return archive_read_support_format_cpio(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ISO9660:
|
||||
return archive_read_support_format_iso9660(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_LHA:
|
||||
return archive_read_support_format_lha(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_MTREE:
|
||||
return archive_read_support_format_mtree(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR:
|
||||
return archive_read_support_format_rar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
return archive_read_support_format_tar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_XAR:
|
||||
return archive_read_support_format_xar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ZIP:
|
||||
return archive_read_support_format_zip(a);
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
3315
Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
Normal file
3315
Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c
Normal file
File diff suppressed because it is too large
Load Diff
1048
Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
Normal file
1048
Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2007 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_empty.c 191524 2009-04-26 18:24:14Z kientzle $");
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
static int archive_read_format_empty_bid(struct archive_read *, int);
|
||||
static int archive_read_format_empty_read_data(struct archive_read *,
|
||||
const void **, size_t *, int64_t *);
|
||||
static int archive_read_format_empty_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
int
|
||||
archive_read_support_format_empty(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_empty");
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
NULL,
|
||||
NULL,
|
||||
archive_read_format_empty_bid,
|
||||
NULL,
|
||||
archive_read_format_empty_read_header,
|
||||
archive_read_format_empty_read_data,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
archive_read_format_empty_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) == NULL)
|
||||
return (1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_empty_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)entry; /* UNUSED */
|
||||
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_EMPTY;
|
||||
a->archive.archive_format_name = "Empty file";
|
||||
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_empty_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, int64_t *offset)
|
||||
{
|
||||
(void)a; /* UNUSED */
|
||||
(void)buff; /* UNUSED */
|
||||
(void)size; /* UNUSED */
|
||||
(void)offset; /* UNUSED */
|
||||
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
2745
Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
Normal file
2745
Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2574
Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
Normal file
2574
Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,187 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2009 Tim Kientzle
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "archive_platform.h"
|
||||
__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_raw.c 201107 2009-12-28 03:25:33Z kientzle $");
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
struct raw_info {
|
||||
int64_t offset; /* Current position in the file. */
|
||||
int64_t unconsumed;
|
||||
int end_of_file;
|
||||
};
|
||||
|
||||
static int archive_read_format_raw_bid(struct archive_read *, int);
|
||||
static int archive_read_format_raw_cleanup(struct archive_read *);
|
||||
static int archive_read_format_raw_read_data(struct archive_read *,
|
||||
const void **, size_t *, int64_t *);
|
||||
static int archive_read_format_raw_read_data_skip(struct archive_read *);
|
||||
static int archive_read_format_raw_read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
|
||||
int
|
||||
archive_read_support_format_raw(struct archive *_a)
|
||||
{
|
||||
struct raw_info *info;
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
int r;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_format_raw");
|
||||
|
||||
info = (struct raw_info *)calloc(1, sizeof(*info));
|
||||
if (info == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate raw_info data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
info,
|
||||
"raw",
|
||||
archive_read_format_raw_bid,
|
||||
NULL,
|
||||
archive_read_format_raw_read_header,
|
||||
archive_read_format_raw_read_data,
|
||||
archive_read_format_raw_read_data_skip,
|
||||
archive_read_format_raw_cleanup);
|
||||
if (r != ARCHIVE_OK)
|
||||
free(info);
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bid 1 if this is a non-empty file. Anyone who can really support
|
||||
* this should outbid us, so it should generally be safe to use "raw"
|
||||
* in conjunction with other formats. But, this could really confuse
|
||||
* folks if there are bid errors or minor file damage, so we don't
|
||||
* include "raw" as part of support_format_all().
|
||||
*/
|
||||
static int
|
||||
archive_read_format_raw_bid(struct archive_read *a, int best_bid)
|
||||
{
|
||||
if (best_bid < 1 && __archive_read_ahead(a, 1, NULL) != NULL)
|
||||
return (1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mock up a fake header.
|
||||
*/
|
||||
static int
|
||||
archive_read_format_raw_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
{
|
||||
struct raw_info *info;
|
||||
|
||||
info = (struct raw_info *)(a->format->data);
|
||||
if (info->end_of_file)
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_RAW;
|
||||
a->archive.archive_format_name = "raw";
|
||||
archive_entry_set_pathname(entry, "data");
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_set_perm(entry, 0644);
|
||||
/* I'm deliberately leaving most fields unset here. */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_raw_read_data(struct archive_read *a,
|
||||
const void **buff, size_t *size, int64_t *offset)
|
||||
{
|
||||
struct raw_info *info;
|
||||
ssize_t avail;
|
||||
|
||||
info = (struct raw_info *)(a->format->data);
|
||||
|
||||
/* Consume the bytes we read last time. */
|
||||
if (info->unconsumed) {
|
||||
__archive_read_consume(a, info->unconsumed);
|
||||
info->unconsumed = 0;
|
||||
}
|
||||
|
||||
if (info->end_of_file)
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
/* Get whatever bytes are immediately available. */
|
||||
*buff = __archive_read_ahead(a, 1, &avail);
|
||||
if (avail > 0) {
|
||||
/* Return the bytes we just read */
|
||||
*size = avail;
|
||||
*offset = info->offset;
|
||||
info->offset += *size;
|
||||
info->unconsumed = avail;
|
||||
return (ARCHIVE_OK);
|
||||
} else if (0 == avail) {
|
||||
/* Record and return end-of-file. */
|
||||
info->end_of_file = 1;
|
||||
*size = 0;
|
||||
*offset = info->offset;
|
||||
return (ARCHIVE_EOF);
|
||||
} else {
|
||||
/* Record and return an error. */
|
||||
*size = 0;
|
||||
*offset = info->offset;
|
||||
return (avail);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_raw_read_data_skip(struct archive_read *a)
|
||||
{
|
||||
struct raw_info *info = (struct raw_info *)(a->format->data);
|
||||
|
||||
/* Consume the bytes we read last time. */
|
||||
if (info->unconsumed) {
|
||||
__archive_read_consume(a, info->unconsumed);
|
||||
info->unconsumed = 0;
|
||||
}
|
||||
info->end_of_file = 1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_raw_cleanup(struct archive_read *a)
|
||||
{
|
||||
struct raw_info *info;
|
||||
|
||||
info = (struct raw_info *)(a->format->data);
|
||||
free(info);
|
||||
a->format->data = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
2692
Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
Normal file
2692
Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c
Normal file
File diff suppressed because it is too large
Load Diff
3324
Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
Normal file
3324
Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user