Update upstream source from tag 'upstream/3.23.2'
Update to upstream version '3.23.2' with Debian dir eed3feb8e556c85a1a4a0647dd82033a895d0259
This commit is contained in:
commit
b46fe4adf6
@ -151,6 +151,7 @@ itself and is not included as a target in the generated buildsystem.
|
|||||||
``PUBLIC`` keywords.
|
``PUBLIC`` keywords.
|
||||||
|
|
||||||
If an interface library has source files (i.e. the :prop_tgt:`SOURCES`
|
If an interface library has source files (i.e. the :prop_tgt:`SOURCES`
|
||||||
|
target property is set), or header sets (i.e. the :prop_tgt:`HEADER_SETS`
|
||||||
target property is set), it will appear in the generated buildsystem
|
target property is set), it will appear in the generated buildsystem
|
||||||
as a build target much like a target defined by the
|
as a build target much like a target defined by the
|
||||||
:command:`add_custom_target` command. It does not compile any sources,
|
:command:`add_custom_target` command. It does not compile any sources,
|
||||||
|
@ -203,3 +203,47 @@ installer.
|
|||||||
|
|
||||||
Does the same as :variable:`CPACK_PRODUCTBUILD_BACKGROUND_UTI` option,
|
Does the same as :variable:`CPACK_PRODUCTBUILD_BACKGROUND_UTI` option,
|
||||||
but for the dark theme.
|
but for the dark theme.
|
||||||
|
|
||||||
|
Distribution XML Template
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
CPack uses a template file to generate the ``distribution.dist`` file used
|
||||||
|
internally by this package generator. Ordinarily, CMake provides the template
|
||||||
|
file, but projects may supply their own by placing a file called
|
||||||
|
``CPack.distribution.dist.in`` in one of the directories listed in the
|
||||||
|
:variable:`CMAKE_MODULE_PATH` variable. CPack will then pick up the project's
|
||||||
|
template file instead of using its own.
|
||||||
|
|
||||||
|
The ``distribution.dist`` file is generated by performing substitutions
|
||||||
|
similar to the :command:`configure_file` command. Any variable set when
|
||||||
|
CPack runs will be available for substitution using the usual ``@...@``
|
||||||
|
form. The following variables are also set internally and made available for
|
||||||
|
substitution:
|
||||||
|
|
||||||
|
``CPACK_RESOURCE_FILE_LICENSE_NOPATH``
|
||||||
|
Same as :variable:`CPACK_RESOURCE_FILE_LICENSE` except without the path.
|
||||||
|
The named file will be available in the same directory as the generated
|
||||||
|
``distribution.dist`` file.
|
||||||
|
|
||||||
|
``CPACK_RESOURCE_FILE_README_NOPATH``
|
||||||
|
Same as :variable:`CPACK_RESOURCE_FILE_README` except without the path.
|
||||||
|
The named file will be available in the same directory as the generated
|
||||||
|
``distribution.dist`` file.
|
||||||
|
|
||||||
|
``CPACK_RESOURCE_FILE_WELCOME_NOPATH``
|
||||||
|
Same as :variable:`CPACK_RESOURCE_FILE_WELCOME` except without the path.
|
||||||
|
The named file will be available in the same directory as the generated
|
||||||
|
``distribution.dist`` file.
|
||||||
|
|
||||||
|
``CPACK_APPLE_PKG_INSTALLER_CONTENT``
|
||||||
|
.. versionadded:: 3.23
|
||||||
|
|
||||||
|
This contains all the XML elements that specify installer-wide options
|
||||||
|
(including domain details), default backgrounds and the choices outline.
|
||||||
|
|
||||||
|
``CPACK_PACKAGEMAKER_CHOICES``
|
||||||
|
.. deprecated:: 3.23
|
||||||
|
|
||||||
|
This contains only the XML elements that specify the default backgrounds
|
||||||
|
and the choices outline. It does not include the installer-wide options or
|
||||||
|
any domain details. Use ``CPACK_APPLE_PKG_INSTALLER_CONTENT`` instead.
|
||||||
|
@ -23,8 +23,9 @@ directory:
|
|||||||
To make use of the new library we will add an :command:`add_subdirectory`
|
To make use of the new library we will add an :command:`add_subdirectory`
|
||||||
call in the top-level ``CMakeLists.txt`` file so that the library will get
|
call in the top-level ``CMakeLists.txt`` file so that the library will get
|
||||||
built. We add the new library to the executable, and add ``MathFunctions`` as
|
built. We add the new library to the executable, and add ``MathFunctions`` as
|
||||||
an include directory so that the ``mysqrt.h`` header file can be found. The
|
an include directory so that the ``MathFunctions.h`` header file can be found.
|
||||||
last few lines of the top-level ``CMakeLists.txt`` file should now look like:
|
The last few lines of the top-level ``CMakeLists.txt`` file should now look
|
||||||
|
like:
|
||||||
|
|
||||||
.. code-block:: cmake
|
.. code-block:: cmake
|
||||||
:caption: CMakeLists.txt
|
:caption: CMakeLists.txt
|
||||||
|
@ -11,8 +11,9 @@ work together in an example project can be very helpful.
|
|||||||
Steps
|
Steps
|
||||||
=====
|
=====
|
||||||
|
|
||||||
The tutorial documentation and source code for examples can be found in
|
.. include:: source.txt
|
||||||
the ``Help/guide/tutorial`` directory of the CMake source code tree.
|
|
||||||
|
|tutorial_source|
|
||||||
Each step has its own subdirectory containing code that may be used as a
|
Each step has its own subdirectory containing code that may be used as a
|
||||||
starting point. The tutorial examples are progressive so that each step
|
starting point. The tutorial examples are progressive so that each step
|
||||||
provides the complete solution for the previous step.
|
provides the complete solution for the previous step.
|
||||||
|
3
Help/guide/tutorial/source.txt
Normal file
3
Help/guide/tutorial/source.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.. |tutorial_source| replace::
|
||||||
|
The tutorial documentation and source code examples can be found in
|
||||||
|
the ``Help/guide/tutorial`` directory of the CMake source code tree.
|
@ -197,6 +197,8 @@ Variable Queries
|
|||||||
|
|
||||||
.. genex:: $<HIP_COMPILER_ID:compiler_ids>
|
.. genex:: $<HIP_COMPILER_ID:compiler_ids>
|
||||||
|
|
||||||
|
.. versionadded:: 3.21
|
||||||
|
|
||||||
where ``compiler_ids`` is a comma-separated list.
|
where ``compiler_ids`` is a comma-separated list.
|
||||||
``1`` if the CMake's compiler id of the HIP compiler matches any one
|
``1`` if the CMake's compiler id of the HIP compiler matches any one
|
||||||
of the entries in ``compiler_ids``, otherwise ``0``.
|
of the entries in ``compiler_ids``, otherwise ``0``.
|
||||||
@ -249,6 +251,8 @@ Variable Queries
|
|||||||
|
|
||||||
.. genex:: $<HIP_COMPILER_VERSION:version>
|
.. genex:: $<HIP_COMPILER_VERSION:version>
|
||||||
|
|
||||||
|
.. versionadded:: 3.21
|
||||||
|
|
||||||
``1`` if the version of the HIP compiler matches ``version``, otherwise ``0``.
|
``1`` if the version of the HIP compiler matches ``version``, otherwise ``0``.
|
||||||
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
|
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
|
||||||
|
|
||||||
@ -714,6 +718,8 @@ Variable Queries
|
|||||||
|
|
||||||
.. genex:: $<HIP_COMPILER_ID>
|
.. genex:: $<HIP_COMPILER_ID>
|
||||||
|
|
||||||
|
.. versionadded:: 3.21
|
||||||
|
|
||||||
The CMake's compiler id of the HIP compiler used.
|
The CMake's compiler id of the HIP compiler used.
|
||||||
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
|
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
|
||||||
|
|
||||||
@ -760,6 +766,8 @@ Variable Queries
|
|||||||
|
|
||||||
.. genex:: $<HIP_COMPILER_VERSION>
|
.. genex:: $<HIP_COMPILER_VERSION>
|
||||||
|
|
||||||
|
.. versionadded:: 3.21
|
||||||
|
|
||||||
The version of the HIP compiler used.
|
The version of the HIP compiler used.
|
||||||
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
|
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
|
||||||
|
|
||||||
@ -1057,10 +1065,10 @@ which is just the string ``tgt``.
|
|||||||
.. versionadded:: 3.21
|
.. versionadded:: 3.21
|
||||||
|
|
||||||
List of DLLs that the target depends on at runtime. This is determined by
|
List of DLLs that the target depends on at runtime. This is determined by
|
||||||
the locations of all the ``SHARED`` and ``MODULE`` targets in the target's
|
the locations of all the ``SHARED`` targets in the target's transitive
|
||||||
transitive dependencies. Using this generator expression on targets other
|
dependencies. Using this generator expression on targets other than
|
||||||
than executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error.
|
executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error. On
|
||||||
On non-DLL platforms, it evaluates to an empty string.
|
non-DLL platforms, it evaluates to an empty string.
|
||||||
|
|
||||||
This generator expression can be used to copy all of the DLLs that a target
|
This generator expression can be used to copy all of the DLLs that a target
|
||||||
depends on into its output directory in a ``POST_BUILD`` custom command. For
|
depends on into its output directory in a ``POST_BUILD`` custom command. For
|
||||||
@ -1080,9 +1088,9 @@ which is just the string ``tgt``.
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
:ref:`Imported Targets` are supported only if they know the location
|
:ref:`Imported Targets` are supported only if they know the location
|
||||||
of their ``.dll`` files. An imported ``SHARED`` or ``MODULE`` library
|
of their ``.dll`` files. An imported ``SHARED`` library must have
|
||||||
must have :prop_tgt:`IMPORTED_LOCATION` set to its ``.dll`` file. See
|
:prop_tgt:`IMPORTED_LOCATION` set to its ``.dll`` file. See the
|
||||||
the :ref:`add_library imported libraries <add_library imported libraries>`
|
:ref:`add_library imported libraries <add_library imported libraries>`
|
||||||
section for details. Many :ref:`Find Modules` produce imported targets
|
section for details. Many :ref:`Find Modules` produce imported targets
|
||||||
with the ``UNKNOWN`` type and therefore will be ignored.
|
with the ``UNKNOWN`` type and therefore will be ignored.
|
||||||
|
|
||||||
|
@ -185,6 +185,13 @@ CPack
|
|||||||
:variable:`CPACK_PRODUCTBUILD_IDENTIFIER`, used to customize the unique
|
:variable:`CPACK_PRODUCTBUILD_IDENTIFIER`, used to customize the unique
|
||||||
product identifier associated with the product.
|
product identifier associated with the product.
|
||||||
|
|
||||||
|
* The ``CPack.distribution.dist.in`` template used by the
|
||||||
|
:cpack_gen:`CPack productbuild Generator` and
|
||||||
|
:cpack_gen:`CPack PackageMaker Generator` was updated to use a new
|
||||||
|
``CPACK_APPLE_PKG_INSTALLER_CONTENT`` variable for its main content.
|
||||||
|
This replaced the previously undocumented and now deprecated
|
||||||
|
``CPACK_PACKAGEMAKER_CHOICES`` variable.
|
||||||
|
|
||||||
* The :cpack_gen:`CPack IFW Generator` gained the new
|
* The :cpack_gen:`CPack IFW Generator` gained the new
|
||||||
:variable:`CPACK_IFW_ARCHIVE_FORMAT` and
|
:variable:`CPACK_IFW_ARCHIVE_FORMAT` and
|
||||||
:variable:`CPACK_IFW_ARCHIVE_COMPRESSION` variables for setting the
|
:variable:`CPACK_IFW_ARCHIVE_COMPRESSION` variables for setting the
|
||||||
@ -230,6 +237,15 @@ Deprecated and Removed Features
|
|||||||
|
|
||||||
* The :manual:`cpack(1)` undocumented ``OSXX11`` generator has been removed.
|
* The :manual:`cpack(1)` undocumented ``OSXX11`` generator has been removed.
|
||||||
|
|
||||||
|
* The previously undocumented ``CPACK_PACKAGEMAKER_CHOICES`` variable used in
|
||||||
|
the ``CPack.distribution.dist.in`` template has been replaced by a new
|
||||||
|
``CPACK_APPLE_PKG_INSTALLER_CONTENT`` variable. This only affects projects
|
||||||
|
that were providing their own custom ``CPack.distribution.dist.in`` template
|
||||||
|
file, but still relied on ``CPACK_PACKAGEMAKER_CHOICES`` being set. Those
|
||||||
|
custom template files should be updated to use
|
||||||
|
``CPACK_APPLE_PKG_INSTALLER_CONTENT`` instead, or to fully define all the
|
||||||
|
template file's contents without relying on substitution of either variable.
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
@ -282,3 +298,14 @@ Changes made since CMake 3.23.0 include the following.
|
|||||||
* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target
|
* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target
|
||||||
properties added in CMake 3.23.0 are now read-only records of the header
|
properties added in CMake 3.23.0 are now read-only records of the header
|
||||||
sets created by the :command:`target_sources` command.
|
sets created by the :command:`target_sources` command.
|
||||||
|
|
||||||
|
3.23.2
|
||||||
|
------
|
||||||
|
|
||||||
|
* The ``CPACK_PACKAGEMAKER_CHOICES`` variable used in the
|
||||||
|
``CPack.distribution.dist.in`` template file was replaced by a new
|
||||||
|
``CPACK_APPLE_PKG_INSTALLER_CONTENT`` variable in CMake 3.23.0.
|
||||||
|
This broke projects that provided their own template file but still
|
||||||
|
expected the ``CPACK_PACKAGEMAKER_CHOICES`` variable to be defined.
|
||||||
|
The old ``CPACK_PACKAGEMAKER_CHOICES`` variable is now also set to the
|
||||||
|
same content as it was before, but it is formally deprecated.
|
||||||
|
@ -13,7 +13,6 @@ macro (CHECK_COMPILER_FLAG_COMMON_PATTERNS _VAR)
|
|||||||
FAIL_REGEX "unknown .*option" # Clang
|
FAIL_REGEX "unknown .*option" # Clang
|
||||||
FAIL_REGEX "optimization flag .* not supported" # Clang
|
FAIL_REGEX "optimization flag .* not supported" # Clang
|
||||||
FAIL_REGEX "unknown argument ignored" # Clang (cl)
|
FAIL_REGEX "unknown argument ignored" # Clang (cl)
|
||||||
FAIL_REGEX "warning: .* ignored" # Clang (linker)
|
|
||||||
FAIL_REGEX "ignoring unknown option" # MSVC, Intel
|
FAIL_REGEX "ignoring unknown option" # MSVC, Intel
|
||||||
FAIL_REGEX "warning D9002" # MSVC, any lang
|
FAIL_REGEX "warning D9002" # MSVC, any lang
|
||||||
FAIL_REGEX "option.*not supported" # Intel
|
FAIL_REGEX "option.*not supported" # Intel
|
||||||
|
@ -177,9 +177,9 @@ macro.
|
|||||||
packages with no binaries.
|
packages with no binaries.
|
||||||
|
|
||||||
.. versionadded:: 3.19
|
.. versionadded:: 3.19
|
||||||
``COMPATIBILITY_MODE`` ``AnyNewerVersion``, ``SameMajorVersion`` and
|
The version file generated by ``AnyNewerVersion``, ``SameMajorVersion`` and
|
||||||
``SameMinorVersion`` handle the version range if any is specified
|
``SameMinorVersion`` arguments of ``COMPATIBILITY`` handle the version range
|
||||||
(see :command:`find_package` command for the details).
|
if any is specified (see :command:`find_package` command for the details).
|
||||||
``ExactVersion`` mode is incompatible with version ranges and will display an
|
``ExactVersion`` mode is incompatible with version ranges and will display an
|
||||||
author warning if one is specified.
|
author warning if one is specified.
|
||||||
|
|
||||||
|
@ -1380,7 +1380,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
|
|||||||
set(_Boost_TIMER_DEPENDENCIES chrono)
|
set(_Boost_TIMER_DEPENDENCIES chrono)
|
||||||
set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic)
|
set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic)
|
||||||
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
|
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
|
||||||
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.79.0 AND NOT Boost_NO_WARN_NEW_VERSIONS)
|
if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.80.0 AND NOT Boost_NO_WARN_NEW_VERSIONS)
|
||||||
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
|
message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -1653,6 +1653,7 @@ else()
|
|||||||
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
|
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
|
||||||
# _Boost_COMPONENT_DEPENDENCIES.
|
# _Boost_COMPONENT_DEPENDENCIES.
|
||||||
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
|
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
|
||||||
|
"1.79.0" "1.79"
|
||||||
"1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74"
|
"1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74"
|
||||||
"1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69"
|
"1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69"
|
||||||
"1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65"
|
"1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65"
|
||||||
|
@ -145,46 +145,41 @@ endif()
|
|||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set (_JNI_HINTS)
|
set (_JNI_HINTS)
|
||||||
execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\JDK
|
macro (_JNI_GET_INSTALLED_VERSIONS _KIND)
|
||||||
RESULT_VARIABLE _JNI_RESULT
|
execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}"
|
||||||
OUTPUT_VARIABLE _JNI_VERSIONS
|
RESULT_VARIABLE _JAVA_RESULT
|
||||||
|
OUTPUT_VARIABLE _JAVA_VERSIONS
|
||||||
ERROR_QUIET)
|
ERROR_QUIET)
|
||||||
if (NOT _JNI_RESULT)
|
if (NOT _JAVA_RESULT)
|
||||||
string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}")
|
string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9._]+" _JNI_VERSIONS "${_JAVA_VERSIONS}")
|
||||||
|
string (REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\([0-9._]+)" "\\1" _JNI_VERSIONS "${_JNI_VERSIONS}")
|
||||||
if (_JNI_VERSIONS)
|
if (_JNI_VERSIONS)
|
||||||
# sort versions. Most recent first
|
# sort versions. Most recent first
|
||||||
## handle version 9 apart from other versions to get correct ordering
|
list (SORT _JNI_VERSIONS COMPARE NATURAL ORDER DESCENDING)
|
||||||
set (_JNI_V9 ${_JNI_VERSIONS})
|
foreach (_JNI_VERSION IN LISTS _JNI_VERSIONS)
|
||||||
list (FILTER _JNI_VERSIONS EXCLUDE REGEX "JDK\\\\9")
|
string(REPLACE "_" "." _JNI_CMAKE_VERSION "${_JNI_VERSION}")
|
||||||
list (SORT _JNI_VERSIONS)
|
if (JNI_FIND_VERSION_EXACT
|
||||||
list (REVERSE _JNI_VERSIONS)
|
AND NOT _JNI_CMAKE_VERSION MATCHES "^${JNI_FIND_VERSION}")
|
||||||
list (FILTER _JNI_V9 INCLUDE REGEX "JDK\\\\9")
|
continue()
|
||||||
list (SORT _JNI_V9)
|
endif()
|
||||||
list (REVERSE _JNI_V9)
|
if (DEFINED JNI_FIND_VERSION AND _JNI_CMAKE_VERSION VERSION_LESS JNI_FIND_VERSION)
|
||||||
list (APPEND _JNI_VERSIONS ${_JNI_V9})
|
break()
|
||||||
foreach (_JNI_HINT IN LISTS _JNI_VERSIONS)
|
endif()
|
||||||
list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]")
|
list(APPEND _JNI_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JNI_VERSION};JavaHome]")
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# for version 9 and upper
|
||||||
|
_JNI_GET_INSTALLED_VERSIONS("JDK")
|
||||||
|
|
||||||
|
# for versions older than 9
|
||||||
|
_JNI_GET_INSTALLED_VERSIONS("Java Development Kit")
|
||||||
|
|
||||||
foreach (_JNI_HINT IN LISTS _JNI_HINTS)
|
foreach (_JNI_HINT IN LISTS _JNI_HINTS)
|
||||||
list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${_JNI_HINT}/lib")
|
list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${_JNI_HINT}/lib")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
get_filename_component(java_install_version
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit;CurrentVersion]" NAME)
|
|
||||||
|
|
||||||
list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/lib"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/lib"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(_JNI_JAVA_DIRECTORIES_BASE
|
set(_JNI_JAVA_DIRECTORIES_BASE
|
||||||
@ -268,16 +263,6 @@ if (WIN32)
|
|||||||
foreach (_JNI_HINT IN LISTS _JNI_HINTS)
|
foreach (_JNI_HINT IN LISTS _JNI_HINTS)
|
||||||
list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${_JNI_HINT}/include")
|
list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${_JNI_HINT}/include")
|
||||||
endforeach()
|
endforeach()
|
||||||
list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/include"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\${java_install_version};JavaHome]/include"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES
|
JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES
|
||||||
|
@ -90,50 +90,35 @@ if(_JAVA_HOME)
|
|||||||
endif()
|
endif()
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
macro (_JAVA_GET_INSTALLED_VERSIONS _KIND)
|
macro (_JAVA_GET_INSTALLED_VERSIONS _KIND)
|
||||||
execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\${_KIND}
|
execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}"
|
||||||
RESULT_VARIABLE _JAVA_RESULT
|
RESULT_VARIABLE _JAVA_RESULT
|
||||||
OUTPUT_VARIABLE _JAVA_VERSIONS
|
OUTPUT_VARIABLE _JAVA_VERSIONS
|
||||||
ERROR_QUIET)
|
ERROR_QUIET)
|
||||||
if (NOT _JAVA_RESULT)
|
if (NOT _JAVA_RESULT)
|
||||||
string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9.]+" _JAVA_VERSIONS "${_JAVA_VERSIONS}")
|
string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\[0-9._]+" _JAVA_VERSIONS "${_JAVA_VERSIONS}")
|
||||||
|
string (REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\${_KIND}\\\\([0-9._]+)" "\\1" _JAVA_VERSIONS "${_JAVA_VERSIONS}")
|
||||||
if (_JAVA_VERSIONS)
|
if (_JAVA_VERSIONS)
|
||||||
# sort versions. Most recent first
|
# sort versions. Most recent first
|
||||||
## handle version 9 apart from other versions to get correct ordering
|
list (SORT _JAVA_VERSIONS COMPARE NATURAL ORDER DESCENDING)
|
||||||
set (_JAVA_V9 ${_JAVA_VERSIONS})
|
foreach (_JAVA_VERSION IN LISTS _JAVA_VERSIONS)
|
||||||
list (FILTER _JAVA_VERSIONS EXCLUDE REGEX "${_KIND}\\\\9")
|
string(REPLACE "_" "." _JAVA_CMAKE_VERSION "${_JAVA_VERSION}")
|
||||||
list (SORT _JAVA_VERSIONS)
|
if (Java_FIND_VERSION_EXACT
|
||||||
list (REVERSE _JAVA_VERSIONS)
|
AND NOT _JAVA_CMAKE_VERSION MATCHES "^${Java_FIND_VERSION}")
|
||||||
list (FILTER _JAVA_V9 INCLUDE REGEX "${_KIND}\\\\9")
|
continue()
|
||||||
list (SORT _JAVA_V9)
|
endif()
|
||||||
list (REVERSE _JAVA_V9)
|
list(APPEND _JAVA_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JAVA_VERSION};JavaHome]/bin")
|
||||||
list (APPEND _JAVA_VERSIONS ${_JAVA_V9})
|
|
||||||
foreach (_JAVA_HINT IN LISTS _JAVA_VERSIONS)
|
|
||||||
list(APPEND _JAVA_HINTS "[${_JAVA_HINT};JavaHome]/bin")
|
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# search for installed versions for version 9 and upper
|
# for version 9 and upper
|
||||||
_JAVA_GET_INSTALLED_VERSIONS("JDK")
|
_JAVA_GET_INSTALLED_VERSIONS("JDK")
|
||||||
_JAVA_GET_INSTALLED_VERSIONS("JRE")
|
_JAVA_GET_INSTALLED_VERSIONS("JRE")
|
||||||
|
|
||||||
list(APPEND _JAVA_HINTS
|
# for versions older than 9
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/bin"
|
_JAVA_GET_INSTALLED_VERSIONS("Java Development Kit")
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/bin"
|
_JAVA_GET_INSTALLED_VERSIONS("Java Runtime Environment")
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.7;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.6;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.5;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.4;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.3;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.9;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.8;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.7;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.6;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.5;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.4;JavaHome]/bin"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\1.3;JavaHome]/bin"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Hard-coded guesses should still go in PATHS. This ensures that the user
|
# Hard-coded guesses should still go in PATHS. This ensures that the user
|
||||||
@ -336,13 +321,13 @@ else()
|
|||||||
find_package_handle_standard_args(Java
|
find_package_handle_standard_args(Java
|
||||||
REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
|
REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
|
||||||
Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
|
Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
|
||||||
VERSION_VAR Java_VERSION_STRING
|
VERSION_VAR Java_VERSION
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
find_package_handle_standard_args(Java
|
find_package_handle_standard_args(Java
|
||||||
REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
|
REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
|
||||||
Java_JAVADOC_EXECUTABLE
|
Java_JAVADOC_EXECUTABLE
|
||||||
VERSION_VAR Java_VERSION_STRING
|
VERSION_VAR Java_VERSION
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
@ -429,7 +429,7 @@ macro(_pkg_set_path_internal)
|
|||||||
else()
|
else()
|
||||||
unset(_pkgconfig_allow_system_libs_old)
|
unset(_pkgconfig_allow_system_libs_old)
|
||||||
endif()
|
endif()
|
||||||
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 0)
|
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 1)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
macro(_pkg_restore_path_internal)
|
macro(_pkg_restore_path_internal)
|
||||||
@ -440,6 +440,8 @@ macro(_pkg_restore_path_internal)
|
|||||||
if(DEFINED _pkgconfig_allow_system_libs_old)
|
if(DEFINED _pkgconfig_allow_system_libs_old)
|
||||||
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} "${_pkgconfig_allow_system_libs_old}")
|
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} "${_pkgconfig_allow_system_libs_old}")
|
||||||
unset(_pkgconfig_allow_system_libs_old)
|
unset(_pkgconfig_allow_system_libs_old)
|
||||||
|
else()
|
||||||
|
unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
unset(_extra_paths)
|
unset(_extra_paths)
|
||||||
|
@ -22,7 +22,7 @@ if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
|
|||||||
message (FATAL_ERROR "FindPython: INTERNAL ERROR")
|
message (FATAL_ERROR "FindPython: INTERNAL ERROR")
|
||||||
endif()
|
endif()
|
||||||
if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3")
|
if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3")
|
||||||
set(_${_PYTHON_PREFIX}_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
set(_${_PYTHON_PREFIX}_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||||
elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2")
|
elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2")
|
||||||
set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||||
else()
|
else()
|
||||||
@ -415,7 +415,6 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
|
|||||||
if (_PGN_WIN32)
|
if (_PGN_WIN32)
|
||||||
foreach (version IN LISTS _PGN_VERSION)
|
foreach (version IN LISTS _PGN_VERSION)
|
||||||
string (REPLACE "." "" version_no_dots ${version})
|
string (REPLACE "." "" version_no_dots ${version})
|
||||||
|
|
||||||
set (name "python${version_no_dots}")
|
set (name "python${version_no_dots}")
|
||||||
if (_PGN_DEBUG)
|
if (_PGN_DEBUG)
|
||||||
string (APPEND name "_d")
|
string (APPEND name "_d")
|
||||||
@ -423,6 +422,13 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
|
|||||||
list (APPEND names "${name}")
|
list (APPEND names "${name}")
|
||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (_PGN_POSIX)
|
||||||
|
foreach(version IN LISTS _PGN_VERSION)
|
||||||
|
list (APPEND names "pypy${version}-c")
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
list (APPEND names ${_${_PYTHON_PREFIX}_PYPY_LIB_NAMES})
|
list (APPEND names ${_${_PYTHON_PREFIX}_PYPY_LIB_NAMES})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
@ -588,6 +594,11 @@ function (_PYTHON_GET_VERSION)
|
|||||||
set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
|
set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
|
||||||
set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
|
set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
|
||||||
set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_3}" PARENT_SCOPE)
|
set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_3}" PARENT_SCOPE)
|
||||||
|
elseif (library_name MATCHES "pypy([23])\\.([0-9]+)-c")
|
||||||
|
set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE)
|
||||||
|
set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
|
||||||
|
set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
|
||||||
|
set (${_PGV_PREFIX}ABI "" PARENT_SCOPE)
|
||||||
elseif (library_name MATCHES "pypy(3)?-c")
|
elseif (library_name MATCHES "pypy(3)?-c")
|
||||||
set (version "${CMAKE_MATCH_1}")
|
set (version "${CMAKE_MATCH_1}")
|
||||||
# try to pick-up a more precise version from the path
|
# try to pick-up a more precise version from the path
|
||||||
@ -663,7 +674,7 @@ endfunction()
|
|||||||
function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME)
|
function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME)
|
||||||
cmake_parse_arguments (PARSE_ARGV 1 _PGL "INTERPRETER;COMPILER" "" "")
|
cmake_parse_arguments (PARSE_ARGV 1 _PGL "INTERPRETER;COMPILER" "" "")
|
||||||
|
|
||||||
unset ({_PYTHON_PGL_NAME} PARENT_SCOPE)
|
unset (${_PYTHON_PGL_NAME} PARENT_SCOPE)
|
||||||
|
|
||||||
if ((_PGL_INTERPRETER AND NOT _${_PYTHON_PREFIX}_EXECUTABLE)
|
if ((_PGL_INTERPRETER AND NOT _${_PYTHON_PREFIX}_EXECUTABLE)
|
||||||
OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER))
|
OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER))
|
||||||
|
@ -54,7 +54,7 @@ unset(_Python_NAMES)
|
|||||||
|
|
||||||
set(_PYTHON1_VERSIONS 1.6 1.5)
|
set(_PYTHON1_VERSIONS 1.6 1.5)
|
||||||
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||||
set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||||
|
|
||||||
if(PythonInterp_FIND_VERSION)
|
if(PythonInterp_FIND_VERSION)
|
||||||
if(PythonInterp_FIND_VERSION_COUNT GREATER 1)
|
if(PythonInterp_FIND_VERSION_COUNT GREATER 1)
|
||||||
|
@ -79,7 +79,7 @@ set(CMAKE_FIND_FRAMEWORK LAST)
|
|||||||
|
|
||||||
set(_PYTHON1_VERSIONS 1.6 1.5)
|
set(_PYTHON1_VERSIONS 1.6 1.5)
|
||||||
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||||
set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
|
||||||
|
|
||||||
if(PythonLibs_FIND_VERSION)
|
if(PythonLibs_FIND_VERSION)
|
||||||
if(PythonLibs_FIND_VERSION_COUNT GREATER 1)
|
if(PythonLibs_FIND_VERSION_COUNT GREATER 1)
|
||||||
|
@ -112,6 +112,9 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND
|
|||||||
CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
|
CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
|
||||||
target_compile_options(FortranCInterface PRIVATE "-fno-lto")
|
target_compile_options(FortranCInterface PRIVATE "-fno-lto")
|
||||||
target_compile_options(myfort PRIVATE "-flto=auto" "-ffat-lto-objects")
|
target_compile_options(myfort PRIVATE "-flto=auto" "-ffat-lto-objects")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
|
||||||
|
CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
|
||||||
target_compile_options(symbols PRIVATE "-flto=auto" "-ffat-lto-objects")
|
target_compile_options(symbols PRIVATE "-flto=auto" "-ffat-lto-objects")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -332,7 +332,9 @@ endfunction()
|
|||||||
function(_cpack_nuget_make_files_tag)
|
function(_cpack_nuget_make_files_tag)
|
||||||
set(_files)
|
set(_files)
|
||||||
foreach(_comp IN LISTS ARGN)
|
foreach(_comp IN LISTS ARGN)
|
||||||
string(APPEND _files " <file src=\"${_comp}/**\" target=\".\" />\n")
|
cmake_path(APPEND _comp "**")
|
||||||
|
cmake_path(NATIVE_PATH _comp _comp)
|
||||||
|
string(APPEND _files " <file src=\"${_comp}\" target=\".\" />\n")
|
||||||
endforeach()
|
endforeach()
|
||||||
set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE)
|
set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -25,6 +25,15 @@ function(CMAKE_CHECK_LINKER_FLAG _lang _flag _var)
|
|||||||
set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
|
set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
|
||||||
|
|
||||||
check_compiler_flag_common_patterns(_common_patterns)
|
check_compiler_flag_common_patterns(_common_patterns)
|
||||||
|
|
||||||
|
# Match linker warnings if the exact flag is ignored.
|
||||||
|
foreach(flag IN LISTS _flag)
|
||||||
|
string(REGEX REPLACE "([][+.*?()^$])" [[\\\1]] _flag_regex "${flag}")
|
||||||
|
list(APPEND _common_patterns
|
||||||
|
FAIL_REGEX "warning: .*${_flag_regex}.* ignored"
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
cmake_check_source_compiles(${_lang}
|
cmake_check_source_compiles(${_lang}
|
||||||
"${_lang_src}"
|
"${_lang_src}"
|
||||||
${_var}
|
${_var}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# CMake version number components.
|
# CMake version number components.
|
||||||
set(CMake_VERSION_MAJOR 3)
|
set(CMake_VERSION_MAJOR 3)
|
||||||
set(CMake_VERSION_MINOR 23)
|
set(CMake_VERSION_MINOR 23)
|
||||||
set(CMake_VERSION_PATCH 1)
|
set(CMake_VERSION_PATCH 2)
|
||||||
#set(CMake_VERSION_RC 0)
|
#set(CMake_VERSION_RC 0)
|
||||||
set(CMake_VERSION_IS_DIRTY 0)
|
set(CMake_VERSION_IS_DIRTY 0)
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ endif()
|
|||||||
|
|
||||||
if(NOT CMake_VERSION_NO_GIT)
|
if(NOT CMake_VERSION_NO_GIT)
|
||||||
# If this source was exported by 'git archive', use its commit info.
|
# If this source was exported by 'git archive', use its commit info.
|
||||||
set(git_info [==[efe08e2894 CMake 3.23.1]==])
|
set(git_info [==[a8bd06dfd4 CMake 3.23.2]==])
|
||||||
|
|
||||||
# Otherwise, try to identify the current development source version.
|
# Otherwise, try to identify the current development source version.
|
||||||
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
|
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
|
||||||
|
@ -424,7 +424,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
|
|||||||
if (!this->Logo.empty()) {
|
if (!this->Logo.empty()) {
|
||||||
std::string srcName = cmSystemTools::GetFilenameName(this->Logo);
|
std::string srcName = cmSystemTools::GetFilenameName(this->Logo);
|
||||||
std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
|
std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
|
||||||
std::string name = "cm_logo." + suffix;
|
std::string name = "cm_logo" + suffix;
|
||||||
std::string path = this->Directory + "/config/" + name;
|
std::string path = this->Directory + "/config/" + name;
|
||||||
cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path);
|
cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path);
|
||||||
xout.Element("Logo", name);
|
xout.Element("Logo", name);
|
||||||
@ -461,7 +461,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
|
|||||||
std::string srcName =
|
std::string srcName =
|
||||||
cmSystemTools::GetFilenameName(this->InstallerApplicationIcon);
|
cmSystemTools::GetFilenameName(this->InstallerApplicationIcon);
|
||||||
std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
|
std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
|
||||||
std::string name = "cm_appicon." + suffix;
|
std::string name = "cm_appicon" + suffix;
|
||||||
std::string path = this->Directory + "/config/" + name;
|
std::string path = this->Directory + "/config/" + name;
|
||||||
cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon,
|
cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon,
|
||||||
path);
|
path);
|
||||||
@ -476,7 +476,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
|
|||||||
std::string srcName =
|
std::string srcName =
|
||||||
cmSystemTools::GetFilenameName(this->InstallerWindowIcon);
|
cmSystemTools::GetFilenameName(this->InstallerWindowIcon);
|
||||||
std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
|
std::string suffix = cmSystemTools::GetFilenameLastExtension(srcName);
|
||||||
std::string name = "cm_winicon." + suffix;
|
std::string name = "cm_winicon" + suffix;
|
||||||
std::string path = this->Directory + "/config/" + name;
|
std::string path = this->Directory + "/config/" + name;
|
||||||
cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path);
|
cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path);
|
||||||
xout.Element("InstallerWindowIcon", name);
|
xout.Element("InstallerWindowIcon", name);
|
||||||
|
@ -123,7 +123,9 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile,
|
|||||||
std::ostringstream xContents;
|
std::ostringstream xContents;
|
||||||
cmXMLWriter xout(xContents, 1);
|
cmXMLWriter xout(xContents, 1);
|
||||||
|
|
||||||
// Installer-wide options
|
// Installer-wide options and domains. These need to be separate from the
|
||||||
|
// choices and background elements added further below so that we can
|
||||||
|
// preserve backward compatibility.
|
||||||
xout.StartElement("options");
|
xout.StartElement("options");
|
||||||
xout.Attribute("allow-external-scripts", "no");
|
xout.Attribute("allow-external-scripts", "no");
|
||||||
xout.Attribute("customize", "allow");
|
xout.Attribute("customize", "allow");
|
||||||
@ -131,55 +133,69 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile,
|
|||||||
xout.Attribute("rootVolumeOnly", "false");
|
xout.Attribute("rootVolumeOnly", "false");
|
||||||
}
|
}
|
||||||
xout.EndElement();
|
xout.EndElement();
|
||||||
|
this->CreateDomains(xout);
|
||||||
|
|
||||||
|
// In order to preserve backward compatibility, all elements added below
|
||||||
|
// here need to be made available in a variable named
|
||||||
|
// CPACK_PACKAGEMAKER_CHOICES. The above elements are new and only appear
|
||||||
|
// in the CPACK_APPLE_PKG_INSTALLER_CONTENT variable, which is a superset
|
||||||
|
// of what CPACK_PACKAGEMAKER_CHOICES used to provide. The renaming reflects
|
||||||
|
// the fact that CMake has deprecated the PackageMaker generator.
|
||||||
|
|
||||||
// Create the choice outline, which provides a tree-based view of
|
// Create the choice outline, which provides a tree-based view of
|
||||||
// the components in their groups.
|
// the components in their groups.
|
||||||
xout.StartElement("choices-outline");
|
std::ostringstream choiceOut;
|
||||||
|
cmXMLWriter xChoiceOut(choiceOut, 1);
|
||||||
|
xChoiceOut.StartElement("choices-outline");
|
||||||
|
|
||||||
// Emit the outline for the groups
|
// Emit the outline for the groups
|
||||||
for (auto const& group : this->ComponentGroups) {
|
for (auto const& group : this->ComponentGroups) {
|
||||||
if (group.second.ParentGroup == nullptr) {
|
if (group.second.ParentGroup == nullptr) {
|
||||||
CreateChoiceOutline(group.second, xout);
|
CreateChoiceOutline(group.second, xChoiceOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the outline for the non-grouped components
|
// Emit the outline for the non-grouped components
|
||||||
for (auto const& comp : this->Components) {
|
for (auto const& comp : this->Components) {
|
||||||
if (!comp.second.Group) {
|
if (!comp.second.Group) {
|
||||||
xout.StartElement("line");
|
xChoiceOut.StartElement("line");
|
||||||
xout.Attribute("choice", comp.first + "Choice");
|
xChoiceOut.Attribute("choice", comp.first + "Choice");
|
||||||
xout.Content(""); // Avoid self-closing tag.
|
xChoiceOut.Content(""); // Avoid self-closing tag.
|
||||||
xout.EndElement();
|
xChoiceOut.EndElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this->PostFlightComponent.Name.empty()) {
|
if (!this->PostFlightComponent.Name.empty()) {
|
||||||
xout.StartElement("line");
|
xChoiceOut.StartElement("line");
|
||||||
xout.Attribute("choice", PostFlightComponent.Name + "Choice");
|
xChoiceOut.Attribute("choice", PostFlightComponent.Name + "Choice");
|
||||||
xout.Content(""); // Avoid self-closing tag.
|
xChoiceOut.Content(""); // Avoid self-closing tag.
|
||||||
xout.EndElement();
|
xChoiceOut.EndElement();
|
||||||
}
|
}
|
||||||
xout.EndElement(); // choices-outline>
|
xChoiceOut.EndElement(); // choices-outline>
|
||||||
|
|
||||||
// Create the actual choices
|
// Create the actual choices
|
||||||
for (auto const& group : this->ComponentGroups) {
|
for (auto const& group : this->ComponentGroups) {
|
||||||
CreateChoice(group.second, xout);
|
CreateChoice(group.second, xChoiceOut);
|
||||||
}
|
}
|
||||||
for (auto const& comp : this->Components) {
|
for (auto const& comp : this->Components) {
|
||||||
CreateChoice(comp.second, xout);
|
CreateChoice(comp.second, xChoiceOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->PostFlightComponent.Name.empty()) {
|
if (!this->PostFlightComponent.Name.empty()) {
|
||||||
CreateChoice(PostFlightComponent, xout);
|
CreateChoice(PostFlightComponent, xChoiceOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->CreateDomains(xout);
|
// default background. These are not strictly part of the choices, but they
|
||||||
|
// must be included in CPACK_PACKAGEMAKER_CHOICES to preserve backward
|
||||||
// default background
|
// compatibility.
|
||||||
this->CreateBackground(nullptr, metapackageFile, genName, xout);
|
this->CreateBackground(nullptr, metapackageFile, genName, xChoiceOut);
|
||||||
// Dark Aqua
|
// Dark Aqua
|
||||||
this->CreateBackground("darkAqua", metapackageFile, genName, xout);
|
this->CreateBackground("darkAqua", metapackageFile, genName, xChoiceOut);
|
||||||
|
|
||||||
this->SetOption("CPACK_APPLE_PKG_INSTALLER_CONTENT", xContents.str());
|
// Provide the content for substitution into the template. Support both the
|
||||||
|
// old and new variables.
|
||||||
|
this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str());
|
||||||
|
this->SetOption("CPACK_APPLE_PKG_INSTALLER_CONTENT",
|
||||||
|
cmStrCat(xContents.str(), " ", choiceOut.str()));
|
||||||
|
|
||||||
// Create the distribution.dist file in the metapackage to turn it
|
// Create the distribution.dist file in the metapackage to turn it
|
||||||
// into a distribution package.
|
// into a distribution package.
|
||||||
|
@ -35,11 +35,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
|
|||||||
: Args(std::move(args))
|
: Args(std::move(args))
|
||||||
, InitialWidth(initWidth)
|
, InitialWidth(initWidth)
|
||||||
{
|
{
|
||||||
this->HasNonStatusOutputs = false;
|
|
||||||
this->NumberOfPages = 0;
|
|
||||||
this->AdvancedMode = false;
|
|
||||||
this->NumberOfVisibleEntries = 0;
|
|
||||||
this->OkToGenerate = false;
|
|
||||||
this->HelpMessage.emplace_back(
|
this->HelpMessage.emplace_back(
|
||||||
"Welcome to ccmake, curses based user interface for CMake.");
|
"Welcome to ccmake, curses based user interface for CMake.");
|
||||||
this->HelpMessage.emplace_back();
|
this->HelpMessage.emplace_back();
|
||||||
@ -54,7 +49,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
|
|||||||
cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
|
cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
|
||||||
this->Args[0] = whereCMake;
|
this->Args[0] = whereCMake;
|
||||||
this->CMakeInstance->SetArgs(this->Args);
|
this->CMakeInstance->SetArgs(this->Args);
|
||||||
this->SearchMode = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmCursesMainForm::~cmCursesMainForm()
|
cmCursesMainForm::~cmCursesMainForm()
|
||||||
@ -99,13 +93,14 @@ void cmCursesMainForm::InitializeUI()
|
|||||||
|
|
||||||
int entrywidth = this->InitialWidth - 35;
|
int entrywidth = this->InitialWidth - 35;
|
||||||
|
|
||||||
if (count == 0) {
|
// Add a label to display when cache is empty
|
||||||
// If cache is empty, display a label saying so and a
|
|
||||||
// dummy entry widget (does not respond to input)
|
// dummy entry widget (does not respond to input)
|
||||||
cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
|
this->EmptyCacheEntry =
|
||||||
comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
|
cm::make_unique<cmCursesCacheEntryComposite>("EMPTY CACHE", 30, 30);
|
||||||
newEntries.emplace_back(std::move(comp));
|
this->EmptyCacheEntry->Entry =
|
||||||
} else {
|
cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
// Create the composites.
|
// Create the composites.
|
||||||
|
|
||||||
// First add entries which are new
|
// First add entries which are new
|
||||||
@ -196,11 +191,11 @@ void cmCursesMainForm::RePost()
|
|||||||
this->Fields.push_back(entry.Entry->Field);
|
this->Fields.push_back(entry.Entry->Field);
|
||||||
}
|
}
|
||||||
// if no cache entries there should still be one dummy field
|
// if no cache entries there should still be one dummy field
|
||||||
if (this->Fields.empty()) {
|
this->IsEmpty = this->Fields.empty();
|
||||||
const auto& front = this->Entries.front();
|
if (this->IsEmpty) {
|
||||||
this->Fields.push_back(front.Label->Field);
|
this->Fields.push_back(this->EmptyCacheEntry->Label->Field);
|
||||||
this->Fields.push_back(front.IsNewLabel->Field);
|
this->Fields.push_back(this->EmptyCacheEntry->IsNewLabel->Field);
|
||||||
this->Fields.push_back(front.Entry->Field);
|
this->Fields.push_back(this->EmptyCacheEntry->Entry->Field);
|
||||||
this->NumberOfVisibleEntries = 1;
|
this->NumberOfVisibleEntries = 1;
|
||||||
}
|
}
|
||||||
// Has to be null terminated.
|
// Has to be null terminated.
|
||||||
@ -875,7 +870,7 @@ void cmCursesMainForm::HandleInput()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// delete cache entry
|
// delete cache entry
|
||||||
else if (key == 'd' && this->NumberOfVisibleEntries) {
|
else if (key == 'd' && this->NumberOfVisibleEntries && !this->IsEmpty) {
|
||||||
this->OkToGenerate = false;
|
this->OkToGenerate = false;
|
||||||
FIELD* cur = current_field(this->Form);
|
FIELD* cur = current_field(this->Form);
|
||||||
size_t findex = field_index(cur);
|
size_t findex = field_index(cur);
|
||||||
|
@ -138,7 +138,7 @@ protected:
|
|||||||
// Output produced by the last pass
|
// Output produced by the last pass
|
||||||
std::vector<std::string> Outputs;
|
std::vector<std::string> Outputs;
|
||||||
// Did the last pass produced outputs of interest (errors, warnings, ...)
|
// Did the last pass produced outputs of interest (errors, warnings, ...)
|
||||||
bool HasNonStatusOutputs;
|
bool HasNonStatusOutputs = false;
|
||||||
// Last progress bar
|
// Last progress bar
|
||||||
std::string LastProgress;
|
std::string LastProgress;
|
||||||
|
|
||||||
@ -155,17 +155,19 @@ protected:
|
|||||||
// Fields displayed. Includes labels, new entry markers, entries
|
// Fields displayed. Includes labels, new entry markers, entries
|
||||||
std::vector<FIELD*> Fields;
|
std::vector<FIELD*> Fields;
|
||||||
// Number of entries shown (depends on mode -normal or advanced-)
|
// Number of entries shown (depends on mode -normal or advanced-)
|
||||||
size_t NumberOfVisibleEntries;
|
size_t NumberOfVisibleEntries = 0;
|
||||||
bool AdvancedMode;
|
bool AdvancedMode = false;
|
||||||
// Did the iteration converge (no new entries) ?
|
// Did the iteration converge (no new entries) ?
|
||||||
bool OkToGenerate;
|
bool OkToGenerate = false;
|
||||||
// Number of pages displayed
|
// Number of pages displayed
|
||||||
int NumberOfPages;
|
int NumberOfPages = 0;
|
||||||
|
bool IsEmpty = false;
|
||||||
|
std::unique_ptr<cmCursesCacheEntryComposite> EmptyCacheEntry;
|
||||||
|
|
||||||
int InitialWidth;
|
int InitialWidth;
|
||||||
std::unique_ptr<cmake> CMakeInstance;
|
std::unique_ptr<cmake> CMakeInstance;
|
||||||
|
|
||||||
std::string SearchString;
|
std::string SearchString;
|
||||||
std::string OldSearchString;
|
std::string OldSearchString;
|
||||||
bool SearchMode;
|
bool SearchMode = false;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||||
#include "cmExportBuildFileGenerator.h"
|
#include "cmExportBuildFileGenerator.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -15,7 +16,6 @@
|
|||||||
#include "cmGeneratorExpression.h"
|
#include "cmGeneratorExpression.h"
|
||||||
#include "cmGeneratorTarget.h"
|
#include "cmGeneratorTarget.h"
|
||||||
#include "cmGlobalGenerator.h"
|
#include "cmGlobalGenerator.h"
|
||||||
#include "cmListFileCache.h"
|
|
||||||
#include "cmLocalGenerator.h"
|
#include "cmLocalGenerator.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmMessageType.h"
|
#include "cmMessageType.h"
|
||||||
@ -362,16 +362,93 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
|
|||||||
return install_name_dir;
|
return install_name_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cmExportBuildFileGenerator::GetFileSetDirectories(
|
namespace {
|
||||||
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
|
bool EntryIsContextSensitive(
|
||||||
|
const std::unique_ptr<cmCompiledGeneratorExpression>& cge)
|
||||||
{
|
{
|
||||||
return cmOutputConverter::EscapeForCMake(
|
return cge->GetHadContextSensitiveCondition();
|
||||||
cmJoin(fileSet->GetDirectoryEntries(), ";"));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cmExportBuildFileGenerator::GetFileSetFiles(
|
std::string cmExportBuildFileGenerator::GetFileSetDirectories(
|
||||||
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
|
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* /*te*/)
|
||||||
{
|
{
|
||||||
return cmOutputConverter::EscapeForCMake(
|
std::vector<std::string> resultVector;
|
||||||
cmJoin(fileSet->GetFileEntries(), ";"));
|
|
||||||
|
auto configs =
|
||||||
|
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||||
|
auto directoryEntries = fileSet->CompileDirectoryEntries();
|
||||||
|
|
||||||
|
for (auto const& config : configs) {
|
||||||
|
auto directories = fileSet->EvaluateDirectoryEntries(
|
||||||
|
directoryEntries, gte->LocalGenerator, config, gte);
|
||||||
|
|
||||||
|
bool const contextSensitive =
|
||||||
|
std::any_of(directoryEntries.begin(), directoryEntries.end(),
|
||||||
|
EntryIsContextSensitive);
|
||||||
|
|
||||||
|
for (auto const& directory : directories) {
|
||||||
|
auto dest = cmOutputConverter::EscapeForCMake(
|
||||||
|
directory, cmOutputConverter::WrapQuotes::NoWrap);
|
||||||
|
|
||||||
|
if (contextSensitive && configs.size() != 1) {
|
||||||
|
resultVector.push_back(
|
||||||
|
cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
|
||||||
|
} else {
|
||||||
|
resultVector.push_back(cmStrCat('"', dest, '"'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmJoin(resultVector, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte,
|
||||||
|
cmFileSet* fileSet,
|
||||||
|
cmTargetExport* /*te*/)
|
||||||
|
{
|
||||||
|
std::vector<std::string> resultVector;
|
||||||
|
|
||||||
|
auto configs =
|
||||||
|
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||||
|
|
||||||
|
auto fileEntries = fileSet->CompileFileEntries();
|
||||||
|
auto directoryEntries = fileSet->CompileDirectoryEntries();
|
||||||
|
|
||||||
|
for (auto const& config : configs) {
|
||||||
|
auto directories = fileSet->EvaluateDirectoryEntries(
|
||||||
|
directoryEntries, gte->LocalGenerator, config, gte);
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<std::string>> files;
|
||||||
|
for (auto const& entry : fileEntries) {
|
||||||
|
fileSet->EvaluateFileEntry(directories, files, entry,
|
||||||
|
gte->LocalGenerator, config, gte);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const contextSensitive =
|
||||||
|
std::any_of(directoryEntries.begin(), directoryEntries.end(),
|
||||||
|
EntryIsContextSensitive) ||
|
||||||
|
std::any_of(fileEntries.begin(), fileEntries.end(),
|
||||||
|
EntryIsContextSensitive);
|
||||||
|
|
||||||
|
for (auto const& it : files) {
|
||||||
|
for (auto const& filename : it.second) {
|
||||||
|
auto escapedFile = cmOutputConverter::EscapeForCMake(
|
||||||
|
filename, cmOutputConverter::WrapQuotes::NoWrap);
|
||||||
|
if (contextSensitive && configs.size() != 1) {
|
||||||
|
resultVector.push_back(
|
||||||
|
cmStrCat("\"$<$<CONFIG:", config, ">:", escapedFile, ">\""));
|
||||||
|
} else {
|
||||||
|
resultVector.push_back(cmStrCat('"', escapedFile, '"'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(contextSensitive && configs.size() != 1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmJoin(resultVector, " ");
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,9 @@ bool cmGeneratedFileStreamBase::Close()
|
|||||||
// Else, the destination was not replaced.
|
// Else, the destination was not replaced.
|
||||||
//
|
//
|
||||||
// Always delete the temporary file. We never want it to stay around.
|
// Always delete the temporary file. We never want it to stay around.
|
||||||
|
if (!this->TempName.empty()) {
|
||||||
cmSystemTools::RemoveFile(this->TempName);
|
cmSystemTools::RemoveFile(this->TempName);
|
||||||
|
}
|
||||||
|
|
||||||
return replaced;
|
return replaced;
|
||||||
}
|
}
|
||||||
|
@ -1208,8 +1208,10 @@ bool cmGeneratorTarget::IsInBuildSystem() const
|
|||||||
case cmStateEnums::GLOBAL_TARGET:
|
case cmStateEnums::GLOBAL_TARGET:
|
||||||
return true;
|
return true;
|
||||||
case cmStateEnums::INTERFACE_LIBRARY:
|
case cmStateEnums::INTERFACE_LIBRARY:
|
||||||
// An INTERFACE library is in the build system if it has SOURCES.
|
// An INTERFACE library is in the build system if it has SOURCES or
|
||||||
if (!this->SourceEntries.empty()) {
|
// HEADER_SETS.
|
||||||
|
if (!this->SourceEntries.empty() ||
|
||||||
|
!this->Target->GetHeaderSetsEntries().empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -741,9 +741,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
|||||||
[=](const cmInstallCommandFileSetArguments& fileSetArg)
|
[=](const cmInstallCommandFileSetArguments& fileSetArg)
|
||||||
-> bool { return fileSetArg.GetFileSet() == name; });
|
-> bool { return fileSetArg.GetFileSet() == name; });
|
||||||
})) {
|
})) {
|
||||||
status.SetError(cmStrCat(
|
status.SetError(cmStrCat("TARGETS target ", target.GetName(),
|
||||||
"TARGETS target ", target.GetName(),
|
" is exported but not all of its interface "
|
||||||
" is exported but not all of its file sets are installed"));
|
"file sets are installed"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +236,7 @@ bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
|
|||||||
cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
|
cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
|
||||||
|
|
||||||
// Add newer Visual Studio paths
|
// Add newer Visual Studio paths
|
||||||
|
AddVisualStudioPath(paths, "Visual Studio 17 ", 17, gg);
|
||||||
AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
|
AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
|
||||||
AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
|
AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
|
||||||
|
|
||||||
|
@ -171,14 +171,15 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
|
|||||||
code.clear();
|
code.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arch.empty() && gencode.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a CodeGeneration field with [arch],[code] syntax in each entry.
|
// Create a CodeGeneration field with [arch],[code] syntax in each entry.
|
||||||
// CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
|
// CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
|
||||||
FlagValue& result = this->FlagMap["CodeGeneration"];
|
FlagValue& result = this->FlagMap["CodeGeneration"];
|
||||||
|
|
||||||
|
// If there are no flags, leave the CodeGeneration field empty.
|
||||||
|
if (arch.empty() && gencode.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// First entries for the -arch=<arch> [-code=<code>,...] pair.
|
// First entries for the -arch=<arch> [-code=<code>,...] pair.
|
||||||
if (!arch.empty()) {
|
if (!arch.empty()) {
|
||||||
std::string arch_name = arch[0];
|
std::string arch_name = arch[0];
|
||||||
|
@ -164,6 +164,7 @@ function(run_cmake test)
|
|||||||
|
|
||||||
"|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:"
|
"|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:"
|
||||||
"|[^\n]*xcodebuild[^\n]*DVTPlugInManager"
|
"|[^\n]*xcodebuild[^\n]*DVTPlugInManager"
|
||||||
|
"|[^\n]*xcodebuild[^\n]*Requested but did not find extension point with identifier"
|
||||||
"|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
|
"|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type"
|
||||||
"|[^\n]*objc[^\n]*: Class [^\n]* One of the two will be used. Which one is undefined."
|
"|[^\n]*objc[^\n]*: Class [^\n]* One of the two will be used. Which one is undefined."
|
||||||
"|[^\n]*is a member of multiple groups"
|
"|[^\n]*is a member of multiple groups"
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
enable_language(C)
|
||||||
|
|
||||||
|
add_library(lib INTERFACE)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dependency.h
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FileSetGeneratedDependency.h.in ${CMAKE_CURRENT_BINARY_DIR}/dependency.h
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
target_sources(lib PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} FILES ${CMAKE_CURRENT_BINARY_DIR}/dependency.h)
|
||||||
|
|
||||||
|
add_executable(exe dependency.c)
|
||||||
|
target_link_libraries(exe PRIVATE lib)
|
@ -0,0 +1 @@
|
|||||||
|
/* empty */
|
@ -19,20 +19,54 @@ include("${export_build_dir}/install/lib/cmake/export.cmake")
|
|||||||
assert_prop_eq(export::lib1 HEADER_SETS "")
|
assert_prop_eq(export::lib1 HEADER_SETS "")
|
||||||
assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
|
assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
|
||||||
assert_prop_eq(export::lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/error.c")
|
assert_prop_eq(export::lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/error.c")
|
||||||
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
else ()
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
assert_prop_eq(export::lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
assert_prop_eq(export::lib1 HEADER_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
|
assert_prop_eq(export::lib1 HEADER_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
|
||||||
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
else ()
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR}")
|
assert_prop_eq(export::lib1 HEADER_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
assert_prop_eq(export::lib1 HEADER_SET_c "$<1:dir/dir.h>")
|
endif ()
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS_c "$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>")
|
assert_prop_eq(export::lib1 HEADER_SET_c "${CMAKE_CURRENT_SOURCE_DIR}/dir/dir.h")
|
||||||
assert_prop_eq(export::lib1 HEADER_SET_d "${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>/empty.h")
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_c "${CMAKE_CURRENT_SOURCE_DIR}/dir;${CMAKE_CURRENT_SOURCE_DIR}/dir")
|
||||||
|
else ()
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_c "${CMAKE_CURRENT_SOURCE_DIR}/dir")
|
||||||
|
endif ()
|
||||||
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 HEADER_SET_d "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/debug/empty.h>;$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/release/empty.h>")
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_d "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
else ()
|
||||||
|
assert_prop_eq(export::lib1 HEADER_SET_d "${CMAKE_CURRENT_SOURCE_DIR}/debug/empty.h")
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS_d "${CMAKE_CURRENT_SOURCE_DIR}")
|
assert_prop_eq(export::lib1 HEADER_DIRS_d "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
assert_prop_eq(export::lib1 HEADER_SET_e "${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>/empty2.h")
|
endif ()
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS_e "${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>")
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 HEADER_SET_e "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/debug/empty2.h>;$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/release/empty2.h>")
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_e "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/debug>;$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/release>")
|
||||||
|
else ()
|
||||||
|
assert_prop_eq(export::lib1 HEADER_SET_e "${CMAKE_CURRENT_SOURCE_DIR}/debug/empty2.h")
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_e "${CMAKE_CURRENT_SOURCE_DIR}/debug")
|
||||||
|
endif ()
|
||||||
assert_prop_eq(export::lib1 HEADER_SET_f "${CMAKE_CURRENT_SOURCE_DIR}/empty3.h")
|
assert_prop_eq(export::lib1 HEADER_SET_f "${CMAKE_CURRENT_SOURCE_DIR}/empty3.h")
|
||||||
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_f "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
else ()
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS_f "${CMAKE_CURRENT_SOURCE_DIR}")
|
assert_prop_eq(export::lib1 HEADER_DIRS_f "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
endif ()
|
||||||
assert_prop_eq(export::lib1 HEADER_SET_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1/file1.h;${CMAKE_CURRENT_SOURCE_DIR}/dir2/file2.h")
|
assert_prop_eq(export::lib1 HEADER_SET_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1/file1.h;${CMAKE_CURRENT_SOURCE_DIR}/dir2/file2.h")
|
||||||
assert_prop_eq(export::lib1 HEADER_DIRS_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2")
|
if (_multi_config)
|
||||||
assert_prop_eq(export::lib1 INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR};$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2;${CMAKE_CURRENT_SOURCE_DIR}/dir3;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir2>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>")
|
assert_prop_eq(export::lib1 HEADER_DIRS_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir1")
|
||||||
|
else ()
|
||||||
|
assert_prop_eq(export::lib1 HEADER_DIRS_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1")
|
||||||
|
endif ()
|
||||||
|
if (_multi_config)
|
||||||
|
assert_prop_eq(export::lib1 INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR};$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2;${CMAKE_CURRENT_SOURCE_DIR}/dir3;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/debug>>;$<BUILD_INTERFACE:$<$<CONFIG:Release>:${CMAKE_CURRENT_SOURCE_DIR}/release>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>")
|
||||||
|
else ()
|
||||||
|
assert_prop_eq(export::lib1 INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR};$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2;${CMAKE_CURRENT_SOURCE_DIR}/dir3;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/debug>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>")
|
||||||
|
endif ()
|
||||||
|
|
||||||
assert_prop_eq(install::lib1 HEADER_SETS "")
|
assert_prop_eq(install::lib1 HEADER_SETS "")
|
||||||
assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
|
assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
^CMake Error at FileSetInstallMissingSetsInterface\.cmake:[0-9]+ \(install\):
|
^CMake Error at FileSetInstallMissingSetsInterface\.cmake:[0-9]+ \(install\):
|
||||||
install TARGETS target lib1 is exported but not all of its file sets are
|
install TARGETS target lib1 is exported but not all of its interface file
|
||||||
installed
|
sets are installed
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||||
|
@ -43,6 +43,15 @@ if(APPLE)
|
|||||||
run_cmake(FileSetFramework)
|
run_cmake(FileSetFramework)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(RunCMake_TEST_NO_CLEAN 1)
|
||||||
|
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/FileSetGeneratedDependency-build")
|
||||||
|
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||||
|
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
|
||||||
|
run_cmake(FileSetGeneratedDependency)
|
||||||
|
run_cmake_command(FileSetGeneratedDependency-build ${CMAKE_COMMAND} --build . --config Debug)
|
||||||
|
unset(RunCMake_TEST_BINARY_DIR)
|
||||||
|
unset(RunCMake_TEST_NO_CLEAN)
|
||||||
|
|
||||||
set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=NEW)
|
set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=NEW)
|
||||||
run_cmake(FileSetFileNoExist)
|
run_cmake(FileSetFileNoExist)
|
||||||
unset(RunCMake_TEST_OPTIONS)
|
unset(RunCMake_TEST_OPTIONS)
|
||||||
|
6
Tests/RunCMake/target_sources/dependency.c
Normal file
6
Tests/RunCMake/target_sources/dependency.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <dependency.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
@ -8,7 +8,7 @@ readonly name="LibArchive"
|
|||||||
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
|
readonly ownership="LibArchive Upstream <libarchive-discuss@googlegroups.com>"
|
||||||
readonly subtree="Utilities/cmlibarchive"
|
readonly subtree="Utilities/cmlibarchive"
|
||||||
readonly repo="https://github.com/libarchive/libarchive.git"
|
readonly repo="https://github.com/libarchive/libarchive.git"
|
||||||
readonly tag="v3.5.1"
|
readonly tag="v3.5.3"
|
||||||
readonly shortlog=false
|
readonly shortlog=false
|
||||||
readonly paths="
|
readonly paths="
|
||||||
CMakeLists.txt
|
CMakeLists.txt
|
||||||
|
@ -68,7 +68,7 @@ if(SPHINX_HTML)
|
|||||||
|
|
||||||
# we provide the path to the produced html output in the console
|
# we provide the path to the produced html output in the console
|
||||||
# for tools that support URI protocol schemes
|
# for tools that support URI protocol schemes
|
||||||
set(html_extra_commands
|
set(html_post_commands
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "sphinx-build html: HTML documentation generated in file://${CMAKE_CURRENT_BINARY_DIR}/html/index.html"
|
COMMAND ${CMAKE_COMMAND} -E echo "sphinx-build html: HTML documentation generated in file://${CMAKE_CURRENT_BINARY_DIR}/html/index.html"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ if(SPHINX_INFO)
|
|||||||
|
|
||||||
# Sphinx texinfo builder supports .info, .txt, .html and .pdf output.
|
# Sphinx texinfo builder supports .info, .txt, .html and .pdf output.
|
||||||
# SPHINX_INFO controls the .info output.
|
# SPHINX_INFO controls the .info output.
|
||||||
set(texinfo_extra_commands
|
set(texinfo_post_commands
|
||||||
COMMAND ${MAKEINFO_EXECUTABLE} --no-split -o
|
COMMAND ${MAKEINFO_EXECUTABLE} --no-split -o
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
|
${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.texi
|
${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.texi
|
||||||
@ -112,7 +112,7 @@ if(SPHINX_QTHELP)
|
|||||||
endif()
|
endif()
|
||||||
list(APPEND doc_formats qthelp)
|
list(APPEND doc_formats qthelp)
|
||||||
|
|
||||||
set(qthelp_extra_commands
|
set(qthelp_post_commands
|
||||||
# Workaround for assistant prior to
|
# Workaround for assistant prior to
|
||||||
# https://codereview.qt-project.org/#change,82250 in Qt 4.
|
# https://codereview.qt-project.org/#change,82250 in Qt 4.
|
||||||
COMMAND ${CMAKE_COMMAND} "-DCSS_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/_static"
|
COMMAND ${CMAKE_COMMAND} "-DCSS_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/_static"
|
||||||
@ -148,7 +148,11 @@ if(CMake_SPHINX_CMAKE_ORG)
|
|||||||
list(APPEND doc_html_opts -A outdated=1)
|
list(APPEND doc_html_opts -A outdated=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND qthelp_extra_commands
|
list(APPEND html_pre_commands
|
||||||
|
COMMAND ${CMAKE_COMMAND} -Dversion=${CMake_VERSION} -P ${CMAKE_CURRENT_SOURCE_DIR}/tutorial_archive.cmake
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND qthelp_post_commands
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qch"
|
"${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qch"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/html/CMake.qch"
|
"${CMAKE_CURRENT_BINARY_DIR}/html/CMake.qch"
|
||||||
@ -170,6 +174,7 @@ foreach(format ${doc_formats})
|
|||||||
# arguments in peculiar order
|
# arguments in peculiar order
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${doc_format_output}
|
OUTPUT ${doc_format_output}
|
||||||
|
${${format}_pre_commands}
|
||||||
COMMAND ${SPHINX_EXECUTABLE}
|
COMMAND ${SPHINX_EXECUTABLE}
|
||||||
-M ${format}
|
-M ${format}
|
||||||
${CMake_SOURCE_DIR}/Help
|
${CMake_SOURCE_DIR}/Help
|
||||||
@ -179,7 +184,7 @@ foreach(format ${doc_formats})
|
|||||||
${sphinx_flags}
|
${sphinx_flags}
|
||||||
${doc_${format}_opts}
|
${doc_${format}_opts}
|
||||||
> ${doc_format_log} # log stdout, pass stderr
|
> ${doc_format_log} # log stdout, pass stderr
|
||||||
${${format}_extra_commands}
|
${${format}_post_commands}
|
||||||
DEPENDS ${doc_format_last}
|
DEPENDS ${doc_format_last}
|
||||||
COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
|
COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
@ -188,6 +193,7 @@ foreach(format ${doc_formats})
|
|||||||
# other formats use standard builder (-b) mode
|
# other formats use standard builder (-b) mode
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${doc_format_output}
|
OUTPUT ${doc_format_output}
|
||||||
|
${${format}_pre_commands}
|
||||||
COMMAND ${SPHINX_EXECUTABLE}
|
COMMAND ${SPHINX_EXECUTABLE}
|
||||||
-c ${CMAKE_CURRENT_BINARY_DIR}
|
-c ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
-d ${CMAKE_CURRENT_BINARY_DIR}/${doctrees}
|
-d ${CMAKE_CURRENT_BINARY_DIR}/${doctrees}
|
||||||
@ -197,7 +203,7 @@ foreach(format ${doc_formats})
|
|||||||
${CMake_SOURCE_DIR}/Help
|
${CMake_SOURCE_DIR}/Help
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${format}
|
${CMAKE_CURRENT_BINARY_DIR}/${format}
|
||||||
> ${doc_format_log} # log stdout, pass stderr
|
> ${doc_format_log} # log stdout, pass stderr
|
||||||
${${format}_extra_commands}
|
${${format}_post_commands}
|
||||||
DEPENDS ${doc_format_last}
|
DEPENDS ${doc_format_last}
|
||||||
COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
|
COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
|
42
Utilities/Sphinx/tutorial_archive.cmake
Normal file
42
Utilities/Sphinx/tutorial_archive.cmake
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
if(NOT version)
|
||||||
|
message(FATAL_ERROR "Pass -Dversion=")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Name of the archive and its top-level directory.
|
||||||
|
set(archive_name "cmake-${version}-tutorial-source")
|
||||||
|
|
||||||
|
# Base directory for CMake Documentation.
|
||||||
|
set(help_dir "${CMAKE_CURRENT_LIST_DIR}/../../Help")
|
||||||
|
cmake_path(ABSOLUTE_PATH help_dir NORMALIZE)
|
||||||
|
|
||||||
|
# Collect the non-documentation part of the tutorial directory.
|
||||||
|
file(COPY "${help_dir}/guide/tutorial/"
|
||||||
|
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${archive_name}"
|
||||||
|
NO_SOURCE_PERMISSIONS
|
||||||
|
PATTERN *.rst EXCLUDE
|
||||||
|
PATTERN source.txt EXCLUDE
|
||||||
|
)
|
||||||
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${archive_name}/README.txt" [[
|
||||||
|
This directory contains source code examples for the CMake Tutorial.
|
||||||
|
Each step has its own subdirectory containing code that may be used as a
|
||||||
|
starting point. The tutorial examples are progressive so that each step
|
||||||
|
provides the complete solution for the previous step.
|
||||||
|
]])
|
||||||
|
|
||||||
|
# Create an archive containing the tutorial source examples.
|
||||||
|
file(MAKE_DIRECTORY "${help_dir}/_generated")
|
||||||
|
file(ARCHIVE_CREATE
|
||||||
|
OUTPUT "${help_dir}/_generated/${archive_name}.zip"
|
||||||
|
PATHS "${CMAKE_CURRENT_BINARY_DIR}/${archive_name}"
|
||||||
|
FORMAT zip
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write a reStructuredText snippet included from the tutorial index.
|
||||||
|
file(WRITE "${help_dir}/guide/tutorial/source.txt" "
|
||||||
|
.. |tutorial_source| replace::
|
||||||
|
The tutorial source code examples are available in
|
||||||
|
:download:`this archive </_generated/${archive_name}.zip>`.
|
||||||
|
")
|
||||||
|
|
||||||
|
# Remove temporary directory.
|
||||||
|
file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/${archive_name}")
|
@ -118,6 +118,7 @@ if(WIN32)
|
|||||||
set(HAVE_LIBWS2_32 1)
|
set(HAVE_LIBWS2_32 1)
|
||||||
set(HAVE_LIMITS_H 1)
|
set(HAVE_LIMITS_H 1)
|
||||||
set(HAVE_LINK 0)
|
set(HAVE_LINK 0)
|
||||||
|
set(HAVE_LINKAT 0)
|
||||||
set(HAVE_LINUX_FIEMAP_H 0)
|
set(HAVE_LINUX_FIEMAP_H 0)
|
||||||
set(HAVE_LINUX_FS_H 0)
|
set(HAVE_LINUX_FS_H 0)
|
||||||
set(HAVE_LINUX_MAGIC_H 0)
|
set(HAVE_LINUX_MAGIC_H 0)
|
||||||
@ -184,6 +185,7 @@ if(WIN32)
|
|||||||
set(HAVE_STROPTS_H 0)
|
set(HAVE_STROPTS_H 0)
|
||||||
set(HAVE__STRTOI64 1)
|
set(HAVE__STRTOI64 1)
|
||||||
set(HAVE_STRTOLL 1)
|
set(HAVE_STRTOLL 1)
|
||||||
|
set(HAVE_STRUCT_STATFS 0)
|
||||||
set(HAVE_STRUCT_STATFS_F_NAMEMAX 0)
|
set(HAVE_STRUCT_STATFS_F_NAMEMAX 0)
|
||||||
set(HAVE_STRUCT_STAT_ST_BIRTHTIME 0)
|
set(HAVE_STRUCT_STAT_ST_BIRTHTIME 0)
|
||||||
set(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 0)
|
set(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 0)
|
||||||
|
@ -81,7 +81,7 @@ math(EXPR INTERFACE_VERSION "13 + ${_minor}")
|
|||||||
# ?? Should there be more here ??
|
# ?? Should there be more here ??
|
||||||
SET(SOVERSION "${INTERFACE_VERSION}")
|
SET(SOVERSION "${INTERFACE_VERSION}")
|
||||||
|
|
||||||
# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros
|
# Enable CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros
|
||||||
# saving and restoring the state of the variables.
|
# saving and restoring the state of the variables.
|
||||||
INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake)
|
INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake)
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ IF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
|
|||||||
SET(__GNUWIN32PATH "C:/Program Files/GnuWin32")
|
SET(__GNUWIN32PATH "C:/Program Files/GnuWin32")
|
||||||
ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
|
ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
|
||||||
IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
|
IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}")
|
||||||
# You have to add a path availabel DLL file into PATH environment variable.
|
# You have to add a path available DLL file into PATH environment variable.
|
||||||
# Maybe DLL path is "C:/Program Files/GnuWin32/bin".
|
# Maybe DLL path is "C:/Program Files/GnuWin32/bin".
|
||||||
# The zlib and the bzip2 Setup program have installed programs and DLLs into
|
# The zlib and the bzip2 Setup program have installed programs and DLLs into
|
||||||
# "C:/Program Files/GnuWin32" by default.
|
# "C:/Program Files/GnuWin32" by default.
|
||||||
@ -1044,7 +1044,7 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
|
|||||||
CMAKE_C_COMPILER_ID MATCHES "^Clang$")
|
CMAKE_C_COMPILER_ID MATCHES "^Clang$")
|
||||||
#
|
#
|
||||||
# During checking iconv proto type, we should use -Werror to avoid the
|
# During checking iconv proto type, we should use -Werror to avoid the
|
||||||
# success of iconv detection with a warnig which success is a miss
|
# success of iconv detection with a warning which success is a miss
|
||||||
# detection. So this needs for all build mode(even it's a release mode).
|
# detection. So this needs for all build mode(even it's a release mode).
|
||||||
#
|
#
|
||||||
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
|
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
|
||||||
@ -1380,6 +1380,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS)
|
|||||||
CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD)
|
CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD)
|
||||||
CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN)
|
CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN)
|
||||||
CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK)
|
CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK)
|
||||||
|
CHECK_FUNCTION_EXISTS_GLIBC(linkat HAVE_LINKAT)
|
||||||
CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R)
|
CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R)
|
||||||
CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
|
CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT)
|
||||||
CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
|
CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES)
|
||||||
@ -1449,6 +1450,10 @@ CHECK_C_SOURCE_COMPILES(
|
|||||||
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct xvfsconf v; return sizeof(v);}"
|
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct xvfsconf v; return sizeof(v);}"
|
||||||
HAVE_STRUCT_XVFSCONF)
|
HAVE_STRUCT_XVFSCONF)
|
||||||
|
|
||||||
|
CHECK_C_SOURCE_COMPILES(
|
||||||
|
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct statfs s; return sizeof(s);}"
|
||||||
|
HAVE_STRUCT_STATFS)
|
||||||
|
|
||||||
# Make sure we have the POSIX version of readdir_r, not the
|
# Make sure we have the POSIX version of readdir_r, not the
|
||||||
# older 2-argument version.
|
# older 2-argument version.
|
||||||
CHECK_C_SOURCE_COMPILES(
|
CHECK_C_SOURCE_COMPILES(
|
||||||
@ -1512,9 +1517,14 @@ CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff
|
|||||||
CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
|
CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
|
||||||
"time.h" HAVE_STRUCT_TM___TM_GMTOFF)
|
"time.h" HAVE_STRUCT_TM___TM_GMTOFF)
|
||||||
|
|
||||||
|
IF(HAVE_STRUCT_STATFS)
|
||||||
# Check for f_namemax in struct statfs
|
# Check for f_namemax in struct statfs
|
||||||
CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax
|
CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax
|
||||||
"sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX)
|
"sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX)
|
||||||
|
# Check for f_iosize in struct statfs
|
||||||
|
CHECK_STRUCT_HAS_MEMBER("struct statfs" f_iosize
|
||||||
|
"sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_IOSIZE)
|
||||||
|
ENDIF(HAVE_STRUCT_STATFS)
|
||||||
|
|
||||||
# Check for birthtime in struct stat
|
# Check for birthtime in struct stat
|
||||||
CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime
|
CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime
|
||||||
|
@ -528,6 +528,9 @@
|
|||||||
/* Define to 1 if you have the `link' function. */
|
/* Define to 1 if you have the `link' function. */
|
||||||
#cmakedefine HAVE_LINK 1
|
#cmakedefine HAVE_LINK 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `linkat' function. */
|
||||||
|
#cmakedefine HAVE_LINKAT 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <linux/types.h> header file. */
|
/* Define to 1 if you have the <linux/types.h> header file. */
|
||||||
#cmakedefine HAVE_LINUX_TYPES_H 1
|
#cmakedefine HAVE_LINUX_TYPES_H 1
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ function hextoi(hex)
|
|||||||
# Exclusion code points specified by
|
# Exclusion code points specified by
|
||||||
# http://unicode.org/Public/6.0.0/ucd/CompositionExclusions.txt
|
# http://unicode.org/Public/6.0.0/ucd/CompositionExclusions.txt
|
||||||
##
|
##
|
||||||
# 1. Script Specifices
|
# 1. Script Specifics
|
||||||
##
|
##
|
||||||
\$1 ~/^095[89ABCDEF]\$/ {
|
\$1 ~/^095[89ABCDEF]\$/ {
|
||||||
next
|
next
|
||||||
|
@ -1 +1 @@
|
|||||||
3005001
|
3005003
|
||||||
|
@ -144,7 +144,9 @@ SET(libarchive_SOURCES
|
|||||||
archive_write_set_format_ar.c
|
archive_write_set_format_ar.c
|
||||||
archive_write_set_format_by_name.c
|
archive_write_set_format_by_name.c
|
||||||
archive_write_set_format_cpio.c
|
archive_write_set_format_cpio.c
|
||||||
|
archive_write_set_format_cpio_binary.c
|
||||||
archive_write_set_format_cpio_newc.c
|
archive_write_set_format_cpio_newc.c
|
||||||
|
archive_write_set_format_cpio_odc.c
|
||||||
archive_write_set_format_filter_by_ext.c
|
archive_write_set_format_filter_by_ext.c
|
||||||
archive_write_set_format_gnutar.c
|
archive_write_set_format_gnutar.c
|
||||||
archive_write_set_format_iso9660.c
|
archive_write_set_format_iso9660.c
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||||
*/
|
*/
|
||||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||||
#define ARCHIVE_VERSION_NUMBER 3005001
|
#define ARCHIVE_VERSION_NUMBER 3005003
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stddef.h> /* for wchar_t */
|
#include <stddef.h> /* for wchar_t */
|
||||||
@ -152,7 +152,7 @@ __LA_DECL int archive_version_number(void);
|
|||||||
/*
|
/*
|
||||||
* Textual name/version of the library, useful for version displays.
|
* Textual name/version of the library, useful for version displays.
|
||||||
*/
|
*/
|
||||||
#define ARCHIVE_VERSION_ONLY_STRING "3.5.1"
|
#define ARCHIVE_VERSION_ONLY_STRING "3.5.3"
|
||||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||||
__LA_DECL const char * archive_version_string(void);
|
__LA_DECL const char * archive_version_string(void);
|
||||||
|
|
||||||
@ -316,6 +316,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
|
|||||||
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
|
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
|
||||||
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
||||||
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
|
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
|
||||||
|
#define ARCHIVE_FORMAT_CPIO_PWB (ARCHIVE_FORMAT_CPIO | 7)
|
||||||
#define ARCHIVE_FORMAT_SHAR 0x20000
|
#define ARCHIVE_FORMAT_SHAR 0x20000
|
||||||
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
||||||
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
|
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
|
||||||
@ -797,7 +798,10 @@ __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_bsd(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_ar_svr4(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(struct archive *);
|
||||||
|
__LA_DECL int archive_write_set_format_cpio_bin(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
||||||
|
__LA_DECL int archive_write_set_format_cpio_odc(struct archive *);
|
||||||
|
__LA_DECL int archive_write_set_format_cpio_pwb(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_gnutar(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_iso9660(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
https://blake2.net.
|
https://blake2.net.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "archive_platform.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
https://blake2.net.
|
https://blake2.net.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "archive_platform.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -319,7 +319,7 @@ translate_acl(struct archive_read_disk *a,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
set_acl(struct archive *a, int fd, const char *name,
|
set_acl(struct archive *a, int fd, const char *name,
|
||||||
struct archive_acl *abstract_acl,
|
struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||||||
int ae_requested_type, const char *tname)
|
int ae_requested_type, const char *tname)
|
||||||
{
|
{
|
||||||
int acl_type = 0;
|
int acl_type = 0;
|
||||||
@ -364,6 +364,13 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
archive_set_error(a, errno,
|
||||||
|
"Cannot set default ACL on non-directory");
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
acl = acl_init(entries);
|
acl = acl_init(entries);
|
||||||
if (acl == (acl_t)NULL) {
|
if (acl == (acl_t)NULL) {
|
||||||
archive_set_error(a, errno,
|
archive_set_error(a, errno,
|
||||||
@ -542,7 +549,10 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
else if (acl_set_link_np(name, acl_type, acl) != 0)
|
else if (acl_set_link_np(name, acl_type, acl) != 0)
|
||||||
#else
|
#else
|
||||||
/* FreeBSD older than 8.0 */
|
/* FreeBSD older than 8.0 */
|
||||||
else if (acl_set_file(name, acl_type, acl) != 0)
|
else if (S_ISLNK(mode)) {
|
||||||
|
/* acl_set_file() follows symbolic links, skip */
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
} else if (acl_set_file(name, acl_type, acl) != 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (errno == EOPNOTSUPP) {
|
if (errno == EOPNOTSUPP) {
|
||||||
@ -677,14 +687,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
||||||
if (ret != ARCHIVE_OK)
|
if (ret != ARCHIVE_OK)
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
||||||
|
|
||||||
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
||||||
@ -693,7 +703,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
#if ARCHIVE_ACL_FREEBSD_NFS4
|
#if ARCHIVE_ACL_FREEBSD_NFS4
|
||||||
else if ((archive_acl_types(abstract_acl) &
|
else if ((archive_acl_types(abstract_acl) &
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -343,6 +343,11 @@ set_richacl(struct archive *a, int fd, const char *name,
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (S_ISLNK(mode)) {
|
||||||
|
/* Linux does not support RichACLs on symbolic links */
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
richacl = richacl_alloc(entries);
|
richacl = richacl_alloc(entries);
|
||||||
if (richacl == NULL) {
|
if (richacl == NULL) {
|
||||||
archive_set_error(a, errno,
|
archive_set_error(a, errno,
|
||||||
@ -455,7 +460,7 @@ exit_free:
|
|||||||
#if ARCHIVE_ACL_LIBACL
|
#if ARCHIVE_ACL_LIBACL
|
||||||
static int
|
static int
|
||||||
set_acl(struct archive *a, int fd, const char *name,
|
set_acl(struct archive *a, int fd, const char *name,
|
||||||
struct archive_acl *abstract_acl,
|
struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||||||
int ae_requested_type, const char *tname)
|
int ae_requested_type, const char *tname)
|
||||||
{
|
{
|
||||||
int acl_type = 0;
|
int acl_type = 0;
|
||||||
@ -488,6 +493,18 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (S_ISLNK(mode)) {
|
||||||
|
/* Linux does not support ACLs on symbolic links */
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
archive_set_error(a, errno,
|
||||||
|
"Cannot set default ACL on non-directory");
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
acl = acl_init(entries);
|
acl = acl_init(entries);
|
||||||
if (acl == (acl_t)NULL) {
|
if (acl == (acl_t)NULL) {
|
||||||
archive_set_error(a, errno,
|
archive_set_error(a, errno,
|
||||||
@ -727,14 +744,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
||||||
if (ret != ARCHIVE_OK)
|
if (ret != ARCHIVE_OK)
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
||||||
}
|
}
|
||||||
#endif /* ARCHIVE_ACL_LIBACL */
|
#endif /* ARCHIVE_ACL_LIBACL */
|
||||||
|
@ -443,7 +443,7 @@ translate_acl(struct archive_read_disk *a,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
set_acl(struct archive *a, int fd, const char *name,
|
set_acl(struct archive *a, int fd, const char *name,
|
||||||
struct archive_acl *abstract_acl,
|
struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||||||
int ae_requested_type, const char *tname)
|
int ae_requested_type, const char *tname)
|
||||||
{
|
{
|
||||||
aclent_t *aclent;
|
aclent_t *aclent;
|
||||||
@ -467,7 +467,6 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
if (entries == 0)
|
if (entries == 0)
|
||||||
return (ARCHIVE_OK);
|
return (ARCHIVE_OK);
|
||||||
|
|
||||||
|
|
||||||
switch (ae_requested_type) {
|
switch (ae_requested_type) {
|
||||||
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
||||||
cmd = SETACL;
|
cmd = SETACL;
|
||||||
@ -492,6 +491,12 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (S_ISLNK(mode)) {
|
||||||
|
/* Skip ACLs on symbolic links */
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
goto exit_free;
|
||||||
|
}
|
||||||
|
|
||||||
e = 0;
|
e = 0;
|
||||||
|
|
||||||
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
|
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
|
||||||
@ -801,7 +806,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||||||
/* Solaris writes POSIX.1e access and default ACLs together */
|
/* Solaris writes POSIX.1e access and default ACLs together */
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
|
ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
|
||||||
|
|
||||||
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
||||||
@ -810,7 +815,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
#if ARCHIVE_ACL_SUNOS_NFS4
|
#if ARCHIVE_ACL_SUNOS_NFS4
|
||||||
else if ((archive_acl_types(abstract_acl) &
|
else if ((archive_acl_types(abstract_acl) &
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||||
|
|
||||||
/* Note: Compiler will complain if this does not match archive.h! */
|
/* Note: Compiler will complain if this does not match archive.h! */
|
||||||
#define ARCHIVE_VERSION_NUMBER 3005001
|
#define ARCHIVE_VERSION_NUMBER 3005003
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: archive_entry.h is for use outside of libarchive; the
|
* Note: archive_entry.h is for use outside of libarchive; the
|
||||||
|
@ -384,6 +384,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
|
|||||||
/* Empty pattern only matches the empty string. */
|
/* Empty pattern only matches the empty string. */
|
||||||
if (p == NULL || *p == '\0')
|
if (p == NULL || *p == '\0')
|
||||||
return (s == NULL || *s == '\0');
|
return (s == NULL || *s == '\0');
|
||||||
|
else if (s == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/* Leading '^' anchors the start of the pattern. */
|
/* Leading '^' anchors the start of the pattern. */
|
||||||
if (*p == '^') {
|
if (*p == '^') {
|
||||||
@ -424,6 +426,8 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
|
|||||||
/* Empty pattern only matches the empty string. */
|
/* Empty pattern only matches the empty string. */
|
||||||
if (p == NULL || *p == L'\0')
|
if (p == NULL || *p == L'\0')
|
||||||
return (s == NULL || *s == L'\0');
|
return (s == NULL || *s == L'\0');
|
||||||
|
else if (s == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/* Leading '^' anchors the start of the pattern. */
|
/* Leading '^' anchors the start of the pattern. */
|
||||||
if (*p == L'^') {
|
if (*p == L'^') {
|
||||||
|
@ -46,6 +46,13 @@
|
|||||||
#define __LA_DEAD
|
#define __LA_DEAD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ > 2 || \
|
||||||
|
(__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
|
||||||
|
#define __LA_UNUSED __attribute__((__unused__))
|
||||||
|
#else
|
||||||
|
#define __LA_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
|
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
|
||||||
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
|
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
|
||||||
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
||||||
|
@ -1522,8 +1522,40 @@ get_xfer_size(struct tree *t, int fd, const char *path)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \
|
#if defined(HAVE_STATVFS)
|
||||||
&& !defined(ST_LOCAL)
|
static inline __LA_UNUSED void
|
||||||
|
set_statvfs_transfer_size(struct filesystem *fs, const struct statvfs *sfs)
|
||||||
|
{
|
||||||
|
fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1;
|
||||||
|
fs->max_xfer_size = -1;
|
||||||
|
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
|
||||||
|
fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
#else
|
||||||
|
fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_STRUCT_STATFS)
|
||||||
|
static inline __LA_UNUSED void
|
||||||
|
set_statfs_transfer_size(struct filesystem *fs, const struct statfs *sfs)
|
||||||
|
{
|
||||||
|
fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
fs->max_xfer_size = -1;
|
||||||
|
#if defined(HAVE_STRUCT_STATFS_F_IOSIZE)
|
||||||
|
fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
#else
|
||||||
|
fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_STRUCT_STATFS) && defined(HAVE_STATFS) && \
|
||||||
|
defined(HAVE_FSTATFS) && defined(MNT_LOCAL) && !defined(ST_LOCAL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
|
* Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
|
||||||
@ -1593,10 +1625,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||||
t->current_filesystem->xfer_align = sfs.f_bsize;
|
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = sfs.f_iosize;
|
|
||||||
t->current_filesystem->incr_xfer_size = sfs.f_iosize;
|
|
||||||
}
|
}
|
||||||
if (sfs.f_flags & MNT_LOCAL)
|
if (sfs.f_flags & MNT_LOCAL)
|
||||||
t->current_filesystem->remote = 0;
|
t->current_filesystem->remote = 0;
|
||||||
@ -1688,15 +1717,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
||||||
* for pathconf() function. */
|
* for pathconf() function. */
|
||||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_iosize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_iosize;
|
|
||||||
#else
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (svfs.f_flag & ST_LOCAL)
|
if (svfs.f_flag & ST_LOCAL)
|
||||||
t->current_filesystem->remote = 0;
|
t->current_filesystem->remote = 0;
|
||||||
@ -1803,15 +1824,9 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||||
#if defined(HAVE_STATVFS)
|
#if defined(HAVE_STATVFS)
|
||||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
|
|
||||||
#else
|
#else
|
||||||
t->current_filesystem->xfer_align = sfs.f_frsize;
|
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = sfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = sfs.f_bsize;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
switch (sfs.f_type) {
|
switch (sfs.f_type) {
|
||||||
@ -1918,10 +1933,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ST_NOATIME)
|
#if defined(ST_NOATIME)
|
||||||
|
@ -1844,7 +1844,7 @@ tree_next(struct tree *t)
|
|||||||
continue;
|
continue;
|
||||||
return (r);
|
return (r);
|
||||||
} else {
|
} else {
|
||||||
HANDLE h = FindFirstFileW(d, &t->_findData);
|
HANDLE h = FindFirstFileW(t->stack->full_path.s, &t->_findData);
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
la_dosmaperr(GetLastError());
|
la_dosmaperr(GetLastError());
|
||||||
t->tree_errno = errno;
|
t->tree_errno = errno;
|
||||||
|
@ -188,9 +188,18 @@ used when translating file names.
|
|||||||
.El
|
.El
|
||||||
.It Format cpio
|
.It Format cpio
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
|
.It Cm compat-2x
|
||||||
|
Libarchive 2.x incorrectly encoded Unicode filenames on
|
||||||
|
some platforms.
|
||||||
|
This option mimics the libarchive 2.x filename handling
|
||||||
|
so that such archives can be read correctly.
|
||||||
.It Cm hdrcharset
|
.It Cm hdrcharset
|
||||||
The value is used as a character set name that will be
|
The value is used as a character set name that will be
|
||||||
used when translating file names.
|
used when translating file names.
|
||||||
|
.It Cm pwb
|
||||||
|
When reading a binary CPIO archive, assume that it is
|
||||||
|
in the original PWB cpio format, and handle file mode
|
||||||
|
bits accordingly. The default is to assume v7 format.
|
||||||
.El
|
.El
|
||||||
.It Format iso9660
|
.It Format iso9660
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
|
@ -216,7 +216,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
|
|||||||
archive_set_error(
|
archive_set_error(
|
||||||
&self->archive->archive,
|
&self->archive->archive,
|
||||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
"Unrecoginized rpm header");
|
"Unrecognized rpm header");
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
}
|
}
|
||||||
rpm->state = ST_ARCHIVE;
|
rpm->state = ST_ARCHIVE;
|
||||||
|
@ -248,7 +248,7 @@ bid_get_line(struct archive_read_filter *filter,
|
|||||||
*ravail = *avail;
|
*ravail = *avail;
|
||||||
*b += diff;
|
*b += diff;
|
||||||
*avail -= diff;
|
*avail -= diff;
|
||||||
tested = len;/* Skip some bytes we already determinated. */
|
tested = len;/* Skip some bytes we already determined. */
|
||||||
len = get_line(*b + tested, *avail - tested, nl);
|
len = get_line(*b + tested, *avail - tested, nl);
|
||||||
if (len >= 0)
|
if (len >= 0)
|
||||||
len += tested;
|
len += tested;
|
||||||
|
@ -808,8 +808,12 @@ archive_read_format_7zip_read_data(struct archive_read *a,
|
|||||||
if (zip->end_of_entry)
|
if (zip->end_of_entry)
|
||||||
return (ARCHIVE_EOF);
|
return (ARCHIVE_EOF);
|
||||||
|
|
||||||
bytes = read_stream(a, buff,
|
const uint64_t max_read_size = 16 * 1024 * 1024; // Don't try to read more than 16 MB at a time
|
||||||
(size_t)zip->entry_bytes_remaining, 0);
|
size_t bytes_to_read = max_read_size;
|
||||||
|
if ((uint64_t)bytes_to_read > zip->entry_bytes_remaining) {
|
||||||
|
bytes_to_read = zip->entry_bytes_remaining;
|
||||||
|
}
|
||||||
|
bytes = read_stream(a, buff, bytes_to_read, 0);
|
||||||
if (bytes < 0)
|
if (bytes < 0)
|
||||||
return ((int)bytes);
|
return ((int)bytes);
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
@ -1493,7 +1497,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
|||||||
zip->ppmd7_stat = -1;
|
zip->ppmd7_stat = -1;
|
||||||
archive_set_error(&a->archive,
|
archive_set_error(&a->archive,
|
||||||
ARCHIVE_ERRNO_MISC,
|
ARCHIVE_ERRNO_MISC,
|
||||||
"Failed to initialize PPMd range decorder");
|
"Failed to initialize PPMd range decoder");
|
||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
if (zip->ppstream.overconsumed) {
|
if (zip->ppstream.overconsumed) {
|
||||||
@ -3031,10 +3035,10 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
|
|||||||
"Truncated 7-Zip file body");
|
"Truncated 7-Zip file body");
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
}
|
}
|
||||||
if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining)
|
if ((uint64_t)bytes_avail > zip->pack_stream_inbytes_remaining)
|
||||||
bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
|
bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
|
||||||
zip->pack_stream_inbytes_remaining -= bytes_avail;
|
zip->pack_stream_inbytes_remaining -= bytes_avail;
|
||||||
if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining)
|
if ((uint64_t)bytes_avail > zip->folder_outbytes_remaining)
|
||||||
bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
|
bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
|
||||||
zip->folder_outbytes_remaining -= bytes_avail;
|
zip->folder_outbytes_remaining -= bytes_avail;
|
||||||
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
|
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
|
||||||
|
@ -2110,7 +2110,6 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
|
|||||||
ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
|
ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
|
||||||
if (ds->pos_tbl == NULL)
|
if (ds->pos_tbl == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
lzx_huffman_free(&(ds->mt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (footer = 0; footer < 18; footer++)
|
for (footer = 0; footer < 18; footer++)
|
||||||
|
@ -185,6 +185,8 @@ struct cpio {
|
|||||||
struct archive_string_conv *opt_sconv;
|
struct archive_string_conv *opt_sconv;
|
||||||
struct archive_string_conv *sconv_default;
|
struct archive_string_conv *sconv_default;
|
||||||
int init_default_conversion;
|
int init_default_conversion;
|
||||||
|
|
||||||
|
int option_pwb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int64_t atol16(const char *, unsigned);
|
static int64_t atol16(const char *, unsigned);
|
||||||
@ -343,6 +345,10 @@ archive_read_format_cpio_options(struct archive_read *a,
|
|||||||
ret = ARCHIVE_FATAL;
|
ret = ARCHIVE_FATAL;
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
|
} else if (strcmp(key, "pwb") == 0) {
|
||||||
|
if (val != NULL && val[0] != 0)
|
||||||
|
cpio->option_pwb = 1;
|
||||||
|
return (ARCHIVE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: The "warn" return is just to inform the options
|
/* Note: The "warn" return is just to inform the options
|
||||||
@ -891,6 +897,12 @@ header_bin_le(struct archive_read *a, struct cpio *cpio,
|
|||||||
archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256);
|
archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256);
|
||||||
archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256);
|
archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256);
|
||||||
archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256);
|
archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256);
|
||||||
|
if (cpio->option_pwb) {
|
||||||
|
/* turn off random bits left over from V6 inode */
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
|
||||||
|
if ((archive_entry_mode(entry) & AE_IFMT) == 0)
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
|
||||||
|
}
|
||||||
archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256);
|
archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256);
|
||||||
archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256);
|
archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256);
|
||||||
archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256);
|
archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256);
|
||||||
@ -930,6 +942,12 @@ header_bin_be(struct archive_read *a, struct cpio *cpio,
|
|||||||
archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
|
archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
|
||||||
archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
|
archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
|
||||||
archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
|
archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
|
||||||
|
if (cpio->option_pwb) {
|
||||||
|
/* turn off random bits left over from V6 inode */
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
|
||||||
|
if ((archive_entry_mode(entry) & AE_IFMT) == 0)
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
|
||||||
|
}
|
||||||
archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
|
archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
|
||||||
archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
|
archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
|
||||||
archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
|
archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
|
||||||
|
@ -408,7 +408,7 @@ next_line(struct archive_read *a,
|
|||||||
*ravail = *avail;
|
*ravail = *avail;
|
||||||
*b += diff;
|
*b += diff;
|
||||||
*avail -= diff;
|
*avail -= diff;
|
||||||
tested = len;/* Skip some bytes we already determinated. */
|
tested = len;/* Skip some bytes we already determined. */
|
||||||
len = get_line_size(*b + len, *avail - len, nl);
|
len = get_line_size(*b + len, *avail - len, nl);
|
||||||
if (len >= 0)
|
if (len >= 0)
|
||||||
len += tested;
|
len += tested;
|
||||||
@ -1074,7 +1074,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
|||||||
continue;
|
continue;
|
||||||
/* Non-printable characters are not allowed */
|
/* Non-printable characters are not allowed */
|
||||||
for (s = p;s < p + len - 1; s++) {
|
for (s = p;s < p + len - 1; s++) {
|
||||||
if (!isprint(*s)) {
|
if (!isprint((unsigned char)*s)) {
|
||||||
r = ARCHIVE_FATAL;
|
r = ARCHIVE_FATAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2035,13 +2035,13 @@ mtree_atol(char **p, int base)
|
|||||||
|
|
||||||
if (**p == '-') {
|
if (**p == '-') {
|
||||||
limit = INT64_MIN / base;
|
limit = INT64_MIN / base;
|
||||||
last_digit_limit = INT64_MIN % base;
|
last_digit_limit = -(INT64_MIN % base);
|
||||||
++(*p);
|
++(*p);
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
digit = parsedigit(**p);
|
digit = parsedigit(**p);
|
||||||
while (digit >= 0 && digit < base) {
|
while (digit >= 0 && digit < base) {
|
||||||
if (l < limit || (l == limit && digit > last_digit_limit))
|
if (l < limit || (l == limit && digit >= last_digit_limit))
|
||||||
return INT64_MIN;
|
return INT64_MIN;
|
||||||
l = (l * base) - digit;
|
l = (l * base) - digit;
|
||||||
digit = parsedigit(*++(*p));
|
digit = parsedigit(*++(*p));
|
||||||
|
@ -958,17 +958,17 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
|||||||
crc32_val = 0;
|
crc32_val = 0;
|
||||||
while (skip > 0) {
|
while (skip > 0) {
|
||||||
size_t to_read = skip;
|
size_t to_read = skip;
|
||||||
ssize_t did_read;
|
if (to_read > 32 * 1024)
|
||||||
if (to_read > 32 * 1024) {
|
|
||||||
to_read = 32 * 1024;
|
to_read = 32 * 1024;
|
||||||
}
|
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
|
||||||
if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Bad RAR file");
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
}
|
}
|
||||||
p = h;
|
p = h;
|
||||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
|
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
|
||||||
__archive_read_consume(a, did_read);
|
__archive_read_consume(a, to_read);
|
||||||
skip -= did_read;
|
skip -= to_read;
|
||||||
}
|
}
|
||||||
if ((crc32_val & 0xffff) != crc32_expected) {
|
if ((crc32_val & 0xffff) != crc32_expected) {
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
@ -1012,7 +1012,16 @@ static int read_var_sized(struct archive_read* a, size_t* pvalue,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
|
static int read_bits_32(struct archive_read* a, struct rar5* rar,
|
||||||
|
const uint8_t* p, uint32_t* value)
|
||||||
|
{
|
||||||
|
if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
|
||||||
|
archive_set_error(&a->archive,
|
||||||
|
ARCHIVE_ERRNO_PROGRAMMER,
|
||||||
|
"Premature end of stream during extraction of data (#1)");
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24;
|
uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24;
|
||||||
bits |= p[rar->bits.in_addr + 1] << 16;
|
bits |= p[rar->bits.in_addr + 1] << 16;
|
||||||
bits |= p[rar->bits.in_addr + 2] << 8;
|
bits |= p[rar->bits.in_addr + 2] << 8;
|
||||||
@ -1023,7 +1032,16 @@ static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
|
|||||||
return ARCHIVE_OK;
|
return ARCHIVE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_bits_16(struct rar5* rar, const uint8_t* p, uint16_t* value) {
|
static int read_bits_16(struct archive_read* a, struct rar5* rar,
|
||||||
|
const uint8_t* p, uint16_t* value)
|
||||||
|
{
|
||||||
|
if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
|
||||||
|
archive_set_error(&a->archive,
|
||||||
|
ARCHIVE_ERRNO_PROGRAMMER,
|
||||||
|
"Premature end of stream during extraction of data (#2)");
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16;
|
int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16;
|
||||||
bits |= (int) p[rar->bits.in_addr + 1] << 8;
|
bits |= (int) p[rar->bits.in_addr + 1] << 8;
|
||||||
bits |= (int) p[rar->bits.in_addr + 2];
|
bits |= (int) p[rar->bits.in_addr + 2];
|
||||||
@ -1039,8 +1057,8 @@ static void skip_bits(struct rar5* rar, int bits) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* n = up to 16 */
|
/* n = up to 16 */
|
||||||
static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
|
static int read_consume_bits(struct archive_read* a, struct rar5* rar,
|
||||||
int* value)
|
const uint8_t* p, int n, int* value)
|
||||||
{
|
{
|
||||||
uint16_t v;
|
uint16_t v;
|
||||||
int ret, num;
|
int ret, num;
|
||||||
@ -1051,7 +1069,7 @@ static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
|
|||||||
return ARCHIVE_FATAL;
|
return ARCHIVE_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = read_bits_16(rar, p, &v);
|
ret = read_bits_16(a, rar, p, &v);
|
||||||
if(ret != ARCHIVE_OK)
|
if(ret != ARCHIVE_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1712,13 +1730,28 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're currently switching volumes, ignore the new definition of
|
if(rar->cstate.window_size < (ssize_t) window_size &&
|
||||||
* window_size. */
|
rar->cstate.window_buf)
|
||||||
if(rar->cstate.switch_multivolume == 0) {
|
{
|
||||||
|
/* If window_buf has been allocated before, reallocate it, so
|
||||||
|
* that its size will match new window_size. */
|
||||||
|
|
||||||
|
uint8_t* new_window_buf =
|
||||||
|
realloc(rar->cstate.window_buf, window_size);
|
||||||
|
|
||||||
|
if(!new_window_buf) {
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
|
||||||
|
"Not enough memory when trying to realloc the window "
|
||||||
|
"buffer.");
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rar->cstate.window_buf = new_window_buf;
|
||||||
|
}
|
||||||
|
|
||||||
/* Values up to 64M should fit into ssize_t on every
|
/* Values up to 64M should fit into ssize_t on every
|
||||||
* architecture. */
|
* architecture. */
|
||||||
rar->cstate.window_size = (ssize_t) window_size;
|
rar->cstate.window_size = (ssize_t) window_size;
|
||||||
}
|
|
||||||
|
|
||||||
if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
|
if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
|
||||||
/* Solid files have to have the same window_size across
|
/* Solid files have to have the same window_size across
|
||||||
@ -2425,13 +2458,13 @@ static int create_decode_tables(uint8_t* bit_length,
|
|||||||
static int decode_number(struct archive_read* a, struct decode_table* table,
|
static int decode_number(struct archive_read* a, struct decode_table* table,
|
||||||
const uint8_t* p, uint16_t* num)
|
const uint8_t* p, uint16_t* num)
|
||||||
{
|
{
|
||||||
int i, bits, dist;
|
int i, bits, dist, ret;
|
||||||
uint16_t bitfield;
|
uint16_t bitfield;
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
struct rar5* rar = get_context(a);
|
struct rar5* rar = get_context(a);
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) {
|
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) {
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitfield &= 0xfffe;
|
bitfield &= 0xfffe;
|
||||||
@ -2537,14 +2570,6 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
|||||||
for(i = 0; i < HUFF_TABLE_SIZE;) {
|
for(i = 0; i < HUFF_TABLE_SIZE;) {
|
||||||
uint16_t num;
|
uint16_t num;
|
||||||
|
|
||||||
if((rar->bits.in_addr + 6) >= rar->cstate.cur_block_size) {
|
|
||||||
/* Truncated data, can't continue. */
|
|
||||||
archive_set_error(&a->archive,
|
|
||||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
|
||||||
"Truncated data in huffman tables (#2)");
|
|
||||||
return ARCHIVE_FATAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = decode_number(a, &rar->cstate.bd, p, &num);
|
ret = decode_number(a, &rar->cstate.bd, p, &num);
|
||||||
if(ret != ARCHIVE_OK) {
|
if(ret != ARCHIVE_OK) {
|
||||||
archive_set_error(&a->archive,
|
archive_set_error(&a->archive,
|
||||||
@ -2561,8 +2586,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
|||||||
/* 16..17: repeat previous code */
|
/* 16..17: repeat previous code */
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
|
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
if(num == 16) {
|
if(num == 16) {
|
||||||
n >>= 13;
|
n >>= 13;
|
||||||
@ -2590,8 +2615,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
|||||||
/* other codes: fill with zeroes `n` times */
|
/* other codes: fill with zeroes `n` times */
|
||||||
uint16_t n;
|
uint16_t n;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
|
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
if(num == 18) {
|
if(num == 18) {
|
||||||
n >>= 13;
|
n >>= 13;
|
||||||
@ -2707,22 +2732,22 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Convenience function used during filter processing. */
|
/* Convenience function used during filter processing. */
|
||||||
static int parse_filter_data(struct rar5* rar, const uint8_t* p,
|
static int parse_filter_data(struct archive_read* a, struct rar5* rar,
|
||||||
uint32_t* filter_data)
|
const uint8_t* p, uint32_t* filter_data)
|
||||||
{
|
{
|
||||||
int i, bytes;
|
int i, bytes, ret;
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes))
|
if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
bytes++;
|
bytes++;
|
||||||
|
|
||||||
for(i = 0; i < bytes; i++) {
|
for(i = 0; i < bytes; i++) {
|
||||||
uint16_t byte;
|
uint16_t byte;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) {
|
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) {
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cast to uint32_t will ensure the shift operation will not
|
/* Cast to uint32_t will ensure the shift operation will not
|
||||||
@ -2765,16 +2790,17 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
|||||||
uint16_t filter_type;
|
uint16_t filter_type;
|
||||||
struct filter_info* filt = NULL;
|
struct filter_info* filt = NULL;
|
||||||
struct rar5* rar = get_context(ar);
|
struct rar5* rar = get_context(ar);
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Read the parameters from the input stream. */
|
/* Read the parameters from the input stream. */
|
||||||
if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start))
|
if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length))
|
if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type))
|
if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
filter_type >>= 13;
|
filter_type >>= 13;
|
||||||
skip_bits(rar, 3);
|
skip_bits(rar, 3);
|
||||||
@ -2814,8 +2840,8 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
|||||||
if(filter_type == FILTER_DELTA) {
|
if(filter_type == FILTER_DELTA) {
|
||||||
int channels;
|
int channels;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels))
|
if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
|
|
||||||
filt->channels = channels + 1;
|
filt->channels = channels + 1;
|
||||||
}
|
}
|
||||||
@ -2823,10 +2849,11 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
|||||||
return ARCHIVE_OK;
|
return ARCHIVE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_code_length(struct rar5* rar, const uint8_t* p,
|
static int decode_code_length(struct archive_read* a, struct rar5* rar,
|
||||||
uint16_t code)
|
const uint8_t* p, uint16_t code)
|
||||||
{
|
{
|
||||||
int lbits, length = 2;
|
int lbits, length = 2;
|
||||||
|
|
||||||
if(code < 8) {
|
if(code < 8) {
|
||||||
lbits = 0;
|
lbits = 0;
|
||||||
length += code;
|
length += code;
|
||||||
@ -2838,7 +2865,7 @@ static int decode_code_length(struct rar5* rar, const uint8_t* p,
|
|||||||
if(lbits > 0) {
|
if(lbits > 0) {
|
||||||
int add;
|
int add;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_consume_bits(rar, p, lbits, &add))
|
if(ARCHIVE_OK != read_consume_bits(a, rar, p, lbits, &add))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
length += add;
|
length += add;
|
||||||
@ -2933,7 +2960,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
|||||||
continue;
|
continue;
|
||||||
} else if(num >= 262) {
|
} else if(num >= 262) {
|
||||||
uint16_t dist_slot;
|
uint16_t dist_slot;
|
||||||
int len = decode_code_length(rar, p, num - 262),
|
int len = decode_code_length(a, rar, p, num - 262),
|
||||||
dbits,
|
dbits,
|
||||||
dist = 1;
|
dist = 1;
|
||||||
|
|
||||||
@ -2975,12 +3002,12 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
|||||||
uint16_t low_dist;
|
uint16_t low_dist;
|
||||||
|
|
||||||
if(dbits > 4) {
|
if(dbits > 4) {
|
||||||
if(ARCHIVE_OK != read_bits_32(
|
if(ARCHIVE_OK != (ret = read_bits_32(
|
||||||
rar, p, &add)) {
|
a, rar, p, &add))) {
|
||||||
/* Return EOF if we
|
/* Return EOF if we
|
||||||
* can't read more
|
* can't read more
|
||||||
* data. */
|
* data. */
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_bits(rar, dbits - 4);
|
skip_bits(rar, dbits - 4);
|
||||||
@ -3015,11 +3042,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
|||||||
/* dbits is one of [0,1,2,3] */
|
/* dbits is one of [0,1,2,3] */
|
||||||
int add;
|
int add;
|
||||||
|
|
||||||
if(ARCHIVE_OK != read_consume_bits(rar,
|
if(ARCHIVE_OK != (ret = read_consume_bits(a, rar,
|
||||||
p, dbits, &add)) {
|
p, dbits, &add))) {
|
||||||
/* Return EOF if we can't read
|
/* Return EOF if we can't read
|
||||||
* more data. */
|
* more data. */
|
||||||
return ARCHIVE_EOF;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dist += add;
|
dist += add;
|
||||||
@ -3076,7 +3103,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
|||||||
return ARCHIVE_FATAL;
|
return ARCHIVE_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = decode_code_length(rar, p, len_slot);
|
len = decode_code_length(a, rar, p, len_slot);
|
||||||
|
if (len == -1) {
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
rar->cstate.last_len = len;
|
rar->cstate.last_len = len;
|
||||||
|
|
||||||
if(ARCHIVE_OK != copy_string(a, len, dist))
|
if(ARCHIVE_OK != copy_string(a, len, dist))
|
||||||
@ -3600,6 +3631,16 @@ static int do_uncompress_file(struct archive_read* a) {
|
|||||||
rar->cstate.initialized = 1;
|
rar->cstate.initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't allow extraction if window_size is invalid. */
|
||||||
|
if(rar->cstate.window_size == 0) {
|
||||||
|
archive_set_error(&a->archive,
|
||||||
|
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Invalid window size declaration in this file");
|
||||||
|
|
||||||
|
/* This should never happen in valid files. */
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
if(rar->cstate.all_filters_applied == 1) {
|
if(rar->cstate.all_filters_applied == 1) {
|
||||||
/* We use while(1) here, but standard case allows for just 1
|
/* We use while(1) here, but standard case allows for just 1
|
||||||
* iteration. The loop will iterate if process_block() didn't
|
* iteration. The loop will iterate if process_block() didn't
|
||||||
@ -4076,6 +4117,7 @@ int archive_read_support_format_rar5(struct archive *_a) {
|
|||||||
if(ARCHIVE_OK != rar5_init(rar)) {
|
if(ARCHIVE_OK != rar5_init(rar)) {
|
||||||
archive_set_error(&ar->archive, ENOMEM,
|
archive_set_error(&ar->archive, ENOMEM,
|
||||||
"Can't allocate rar5 filter buffer");
|
"Can't allocate rar5 filter buffer");
|
||||||
|
free(rar);
|
||||||
return ARCHIVE_FATAL;
|
return ARCHIVE_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1906,7 +1906,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
|||||||
}
|
}
|
||||||
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
|
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
|
||||||
tar->sparse_numbytes = tar_atol10(value, strlen(value));
|
tar->sparse_numbytes = tar_atol10(value, strlen(value));
|
||||||
if (tar->sparse_numbytes != -1) {
|
if (tar->sparse_offset != -1) {
|
||||||
if (gnu_add_sparse_entry(a, tar,
|
if (gnu_add_sparse_entry(a, tar,
|
||||||
tar->sparse_offset, tar->sparse_numbytes)
|
tar->sparse_offset, tar->sparse_numbytes)
|
||||||
!= ARCHIVE_OK)
|
!= ARCHIVE_OK)
|
||||||
@ -2643,14 +2643,14 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
|||||||
|
|
||||||
maxval = INT64_MIN;
|
maxval = INT64_MIN;
|
||||||
limit = -(INT64_MIN / base);
|
limit = -(INT64_MIN / base);
|
||||||
last_digit_limit = INT64_MIN % base;
|
last_digit_limit = -(INT64_MIN % base);
|
||||||
}
|
}
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
if (char_cnt != 0) {
|
if (char_cnt != 0) {
|
||||||
digit = *p - '0';
|
digit = *p - '0';
|
||||||
while (digit >= 0 && digit < base && char_cnt != 0) {
|
while (digit >= 0 && digit < base && char_cnt != 0) {
|
||||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
if (l>limit || (l == limit && digit >= last_digit_limit)) {
|
||||||
return maxval; /* Truncate on overflow. */
|
return maxval; /* Truncate on overflow. */
|
||||||
}
|
}
|
||||||
l = (l * base) + digit;
|
l = (l * base) + digit;
|
||||||
|
@ -142,6 +142,7 @@ struct zip {
|
|||||||
/* Structural information about the archive. */
|
/* Structural information about the archive. */
|
||||||
struct archive_string format_name;
|
struct archive_string format_name;
|
||||||
int64_t central_directory_offset;
|
int64_t central_directory_offset;
|
||||||
|
int64_t central_directory_offset_adjusted;
|
||||||
size_t central_directory_entries_total;
|
size_t central_directory_entries_total;
|
||||||
size_t central_directory_entries_on_this_disk;
|
size_t central_directory_entries_on_this_disk;
|
||||||
int has_encrypted_entries;
|
int has_encrypted_entries;
|
||||||
@ -246,6 +247,17 @@ struct zip {
|
|||||||
/* Many systems define min or MIN, but not all. */
|
/* Many systems define min or MIN, but not all. */
|
||||||
#define zipmin(a,b) ((a) < (b) ? (a) : (b))
|
#define zipmin(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
static int
|
||||||
|
zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||||
|
size_t *size, int64_t *offset);
|
||||||
|
#endif
|
||||||
|
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||||
|
static int
|
||||||
|
zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
|
||||||
|
size_t *size, int64_t *offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
|
/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
|
||||||
* streams inside ZIP files. It has 2 purposes: one is to fetch the next
|
* streams inside ZIP files. It has 2 purposes: one is to fetch the next
|
||||||
* compressed byte from the stream, second one is to increase the counter how
|
* compressed byte from the stream, second one is to increase the counter how
|
||||||
@ -899,81 +911,6 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
|||||||
return ARCHIVE_OK;
|
return ARCHIVE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
|
||||||
/*
|
|
||||||
* Auxiliary function to uncompress data chunk from zipx archive
|
|
||||||
* (zip with lzma compression).
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zipx_lzma_uncompress_buffer(const char *compressed_buffer,
|
|
||||||
size_t compressed_buffer_size,
|
|
||||||
char *uncompressed_buffer,
|
|
||||||
size_t uncompressed_buffer_size)
|
|
||||||
{
|
|
||||||
int status = ARCHIVE_FATAL;
|
|
||||||
// length of 'lzma properties data' in lzma compressed
|
|
||||||
// data segment (stream) inside zip archive
|
|
||||||
const size_t lzma_params_length = 5;
|
|
||||||
// offset of 'lzma properties data' from the beginning of lzma stream
|
|
||||||
const size_t lzma_params_offset = 4;
|
|
||||||
// end position of 'lzma properties data' in lzma stream
|
|
||||||
const size_t lzma_params_end = lzma_params_offset + lzma_params_length;
|
|
||||||
if (compressed_buffer == NULL ||
|
|
||||||
compressed_buffer_size < lzma_params_end ||
|
|
||||||
uncompressed_buffer == NULL)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
// prepare header for lzma_alone_decoder to replace zipx header
|
|
||||||
// (see comments in 'zipx_lzma_alone_init' for justification)
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
struct _alone_header
|
|
||||||
{
|
|
||||||
uint8_t bytes[5]; // lzma_params_length
|
|
||||||
uint64_t uncompressed_size;
|
|
||||||
} alone_header;
|
|
||||||
#pragma pack(pop)
|
|
||||||
// copy 'lzma properties data' blob
|
|
||||||
memcpy(&alone_header.bytes[0], compressed_buffer + lzma_params_offset,
|
|
||||||
lzma_params_length);
|
|
||||||
alone_header.uncompressed_size = UINT64_MAX;
|
|
||||||
|
|
||||||
// prepare new compressed buffer, see 'zipx_lzma_alone_init' for details
|
|
||||||
const size_t lzma_alone_buffer_size =
|
|
||||||
compressed_buffer_size - lzma_params_end + sizeof(alone_header);
|
|
||||||
unsigned char *lzma_alone_compressed_buffer =
|
|
||||||
(unsigned char*) malloc(lzma_alone_buffer_size);
|
|
||||||
if (lzma_alone_compressed_buffer == NULL)
|
|
||||||
return status;
|
|
||||||
// copy lzma_alone header into new buffer
|
|
||||||
memcpy(lzma_alone_compressed_buffer, (void*) &alone_header,
|
|
||||||
sizeof(alone_header));
|
|
||||||
// copy compressed data into new buffer
|
|
||||||
memcpy(lzma_alone_compressed_buffer + sizeof(alone_header),
|
|
||||||
compressed_buffer + lzma_params_end,
|
|
||||||
compressed_buffer_size - lzma_params_end);
|
|
||||||
|
|
||||||
// create and fill in lzma_alone_decoder stream
|
|
||||||
lzma_stream stream = LZMA_STREAM_INIT;
|
|
||||||
lzma_ret ret = lzma_alone_decoder(&stream, UINT64_MAX);
|
|
||||||
if (ret == LZMA_OK)
|
|
||||||
{
|
|
||||||
stream.next_in = lzma_alone_compressed_buffer;
|
|
||||||
stream.avail_in = lzma_alone_buffer_size;
|
|
||||||
stream.total_in = 0;
|
|
||||||
stream.next_out = (unsigned char*)uncompressed_buffer;
|
|
||||||
stream.avail_out = uncompressed_buffer_size;
|
|
||||||
stream.total_out = 0;
|
|
||||||
ret = lzma_code(&stream, LZMA_RUN);
|
|
||||||
if (ret == LZMA_OK || ret == LZMA_STREAM_END)
|
|
||||||
status = ARCHIVE_OK;
|
|
||||||
}
|
|
||||||
lzma_end(&stream);
|
|
||||||
free(lzma_alone_compressed_buffer);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assumes file pointer is at beginning of local file header.
|
* Assumes file pointer is at beginning of local file header.
|
||||||
*/
|
*/
|
||||||
@ -1242,36 +1179,30 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||||||
linkname_length = (size_t)zip_entry->compressed_size;
|
linkname_length = (size_t)zip_entry->compressed_size;
|
||||||
|
|
||||||
archive_entry_set_size(entry, 0);
|
archive_entry_set_size(entry, 0);
|
||||||
p = __archive_read_ahead(a, linkname_length, NULL);
|
|
||||||
if (p == NULL) {
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
||||||
"Truncated Zip file");
|
|
||||||
return ARCHIVE_FATAL;
|
|
||||||
}
|
|
||||||
// take into account link compression if any
|
// take into account link compression if any
|
||||||
size_t linkname_full_length = linkname_length;
|
size_t linkname_full_length = linkname_length;
|
||||||
if (zip->entry->compression != 0)
|
if (zip->entry->compression != 0)
|
||||||
{
|
{
|
||||||
// symlink target string appeared to be compressed
|
// symlink target string appeared to be compressed
|
||||||
int status = ARCHIVE_FATAL;
|
int status = ARCHIVE_FATAL;
|
||||||
char *uncompressed_buffer =
|
const void *uncompressed_buffer;
|
||||||
(char*) malloc(zip_entry->uncompressed_size);
|
|
||||||
if (uncompressed_buffer == NULL)
|
|
||||||
{
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"No memory for lzma decompression");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (zip->entry->compression)
|
switch (zip->entry->compression)
|
||||||
{
|
{
|
||||||
|
#if HAVE_ZLIB_H
|
||||||
|
case 8: /* Deflate compression. */
|
||||||
|
zip->entry_bytes_remaining = zip_entry->compressed_size;
|
||||||
|
status = zip_read_data_deflate(a, &uncompressed_buffer,
|
||||||
|
&linkname_full_length, NULL);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||||
case 14: /* ZIPx LZMA compression. */
|
case 14: /* ZIPx LZMA compression. */
|
||||||
/*(see zip file format specification, section 4.4.5)*/
|
/*(see zip file format specification, section 4.4.5)*/
|
||||||
status = zipx_lzma_uncompress_buffer(p,
|
zip->entry_bytes_remaining = zip_entry->compressed_size;
|
||||||
linkname_length,
|
status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
|
||||||
uncompressed_buffer,
|
&linkname_full_length, NULL);
|
||||||
(size_t)zip_entry->uncompressed_size);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: /* Unsupported compression. */
|
default: /* Unsupported compression. */
|
||||||
@ -1280,8 +1211,6 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||||||
if (status == ARCHIVE_OK)
|
if (status == ARCHIVE_OK)
|
||||||
{
|
{
|
||||||
p = uncompressed_buffer;
|
p = uncompressed_buffer;
|
||||||
linkname_full_length =
|
|
||||||
(size_t)zip_entry->uncompressed_size;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1294,6 +1223,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||||||
return ARCHIVE_FAILED;
|
return ARCHIVE_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = __archive_read_ahead(a, linkname_length, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == NULL) {
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||||
|
"Truncated Zip file");
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
sconv = zip->sconv;
|
sconv = zip->sconv;
|
||||||
if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
|
if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
|
||||||
@ -1663,7 +1602,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
|
|||||||
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
|
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
|
||||||
* that is a part of XZ Utils. The stream format stored inside ZIPX
|
* that is a part of XZ Utils. The stream format stored inside ZIPX
|
||||||
* file is a modified "lzma alone" file format, that was used by the
|
* file is a modified "lzma alone" file format, that was used by the
|
||||||
* `lzma` utility which was later deprecated in favour of `xz` utility. * Since those formats are nearly the same, we can use a standard
|
* `lzma` utility which was later deprecated in favour of `xz` utility.
|
||||||
|
* Since those formats are nearly the same, we can use a standard
|
||||||
* "lzma alone" decoder from XZ Utils. */
|
* "lzma alone" decoder from XZ Utils. */
|
||||||
|
|
||||||
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
|
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
|
||||||
@ -3415,24 +3355,31 @@ archive_read_support_format_zip_capabilities_seekable(struct archive_read * a)
|
|||||||
static int
|
static int
|
||||||
read_eocd(struct zip *zip, const char *p, int64_t current_offset)
|
read_eocd(struct zip *zip, const char *p, int64_t current_offset)
|
||||||
{
|
{
|
||||||
|
uint16_t disk_num;
|
||||||
|
uint32_t cd_size, cd_offset;
|
||||||
|
|
||||||
|
disk_num = archive_le16dec(p + 4);
|
||||||
|
cd_size = archive_le32dec(p + 12);
|
||||||
|
cd_offset = archive_le32dec(p + 16);
|
||||||
|
|
||||||
/* Sanity-check the EOCD we've found. */
|
/* Sanity-check the EOCD we've found. */
|
||||||
|
|
||||||
/* This must be the first volume. */
|
/* This must be the first volume. */
|
||||||
if (archive_le16dec(p + 4) != 0)
|
if (disk_num != 0)
|
||||||
return 0;
|
return 0;
|
||||||
/* Central directory must be on this volume. */
|
/* Central directory must be on this volume. */
|
||||||
if (archive_le16dec(p + 4) != archive_le16dec(p + 6))
|
if (disk_num != archive_le16dec(p + 6))
|
||||||
return 0;
|
return 0;
|
||||||
/* All central directory entries must be on this volume. */
|
/* All central directory entries must be on this volume. */
|
||||||
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
|
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
|
||||||
return 0;
|
return 0;
|
||||||
/* Central directory can't extend beyond start of EOCD record. */
|
/* Central directory can't extend beyond start of EOCD record. */
|
||||||
if (archive_le32dec(p + 16) + archive_le32dec(p + 12)
|
if (cd_offset + cd_size > current_offset)
|
||||||
> current_offset)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Save the central directory location for later use. */
|
/* Save the central directory location for later use. */
|
||||||
zip->central_directory_offset = archive_le32dec(p + 16);
|
zip->central_directory_offset = cd_offset;
|
||||||
|
zip->central_directory_offset_adjusted = current_offset - cd_size;
|
||||||
|
|
||||||
/* This is just a tiny bit higher than the maximum
|
/* This is just a tiny bit higher than the maximum
|
||||||
returned by the streaming Zip bidder. This ensures
|
returned by the streaming Zip bidder. This ensures
|
||||||
@ -3484,6 +3431,8 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
|
|||||||
|
|
||||||
/* Save the central directory offset for later use. */
|
/* Save the central directory offset for later use. */
|
||||||
zip->central_directory_offset = archive_le64dec(p + 48);
|
zip->central_directory_offset = archive_le64dec(p + 48);
|
||||||
|
/* TODO: Needs scanning backwards to find the eocd64 instead of assuming */
|
||||||
|
zip->central_directory_offset_adjusted = zip->central_directory_offset;
|
||||||
|
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
@ -3655,7 +3604,8 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
|
|||||||
* know the correction we need to apply to account for leading
|
* know the correction we need to apply to account for leading
|
||||||
* padding.
|
* padding.
|
||||||
*/
|
*/
|
||||||
if (__archive_read_seek(a, zip->central_directory_offset, SEEK_SET) < 0)
|
if (__archive_read_seek(a, zip->central_directory_offset_adjusted, SEEK_SET)
|
||||||
|
< 0)
|
||||||
return ARCHIVE_FATAL;
|
return ARCHIVE_FATAL;
|
||||||
|
|
||||||
found = 0;
|
found = 0;
|
||||||
|
@ -482,6 +482,8 @@ archive_write_client_close(struct archive_write_filter *f)
|
|||||||
ssize_t block_length;
|
ssize_t block_length;
|
||||||
ssize_t target_block_length;
|
ssize_t target_block_length;
|
||||||
ssize_t bytes_written;
|
ssize_t bytes_written;
|
||||||
|
size_t to_write;
|
||||||
|
char *p;
|
||||||
int ret = ARCHIVE_OK;
|
int ret = ARCHIVE_OK;
|
||||||
|
|
||||||
/* If there's pending data, pad and write the last block */
|
/* If there's pending data, pad and write the last block */
|
||||||
@ -504,9 +506,24 @@ archive_write_client_close(struct archive_write_filter *f)
|
|||||||
target_block_length - block_length);
|
target_block_length - block_length);
|
||||||
block_length = target_block_length;
|
block_length = target_block_length;
|
||||||
}
|
}
|
||||||
|
p = state->buffer;
|
||||||
|
to_write = block_length;
|
||||||
|
while (to_write > 0) {
|
||||||
bytes_written = (a->client_writer)(&a->archive,
|
bytes_written = (a->client_writer)(&a->archive,
|
||||||
a->client_data, state->buffer, block_length);
|
a->client_data, p, to_write);
|
||||||
ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
|
if (bytes_written <= 0) {
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((size_t)bytes_written > to_write) {
|
||||||
|
archive_set_error(&(a->archive),
|
||||||
|
-1, "write overrun");
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p += bytes_written;
|
||||||
|
to_write -= bytes_written;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (a->client_closer)
|
if (a->client_closer)
|
||||||
(*a->client_closer)(&a->archive, a->client_data);
|
(*a->client_closer)(&a->archive, a->client_data);
|
||||||
|
@ -173,6 +173,7 @@ struct fixup_entry {
|
|||||||
struct fixup_entry *next;
|
struct fixup_entry *next;
|
||||||
struct archive_acl acl;
|
struct archive_acl acl;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
__LA_MODE_T filetype;
|
||||||
int64_t atime;
|
int64_t atime;
|
||||||
int64_t birthtime;
|
int64_t birthtime;
|
||||||
int64_t mtime;
|
int64_t mtime;
|
||||||
@ -357,10 +358,11 @@ struct archive_write_disk {
|
|||||||
|
|
||||||
static int la_opendirat(int, const char *);
|
static int la_opendirat(int, const char *);
|
||||||
static int la_mktemp(struct archive_write_disk *);
|
static int la_mktemp(struct archive_write_disk *);
|
||||||
|
static int la_verify_filetype(mode_t, __LA_MODE_T);
|
||||||
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
||||||
const char *);
|
const char *);
|
||||||
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
||||||
int);
|
int, int);
|
||||||
static int check_symlinks(struct archive_write_disk *);
|
static int check_symlinks(struct archive_write_disk *);
|
||||||
static int create_filesystem_object(struct archive_write_disk *);
|
static int create_filesystem_object(struct archive_write_disk *);
|
||||||
static struct fixup_entry *current_fixup(struct archive_write_disk *,
|
static struct fixup_entry *current_fixup(struct archive_write_disk *,
|
||||||
@ -464,6 +466,39 @@ la_opendirat(int fd, const char *path) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
la_verify_filetype(mode_t mode, __LA_MODE_T filetype) {
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (filetype) {
|
||||||
|
case AE_IFREG:
|
||||||
|
ret = (S_ISREG(mode));
|
||||||
|
break;
|
||||||
|
case AE_IFDIR:
|
||||||
|
ret = (S_ISDIR(mode));
|
||||||
|
break;
|
||||||
|
case AE_IFLNK:
|
||||||
|
ret = (S_ISLNK(mode));
|
||||||
|
break;
|
||||||
|
case AE_IFSOCK:
|
||||||
|
ret = (S_ISSOCK(mode));
|
||||||
|
break;
|
||||||
|
case AE_IFCHR:
|
||||||
|
ret = (S_ISCHR(mode));
|
||||||
|
break;
|
||||||
|
case AE_IFBLK:
|
||||||
|
ret = (S_ISBLK(mode));
|
||||||
|
break;
|
||||||
|
case AE_IFIFO:
|
||||||
|
ret = (S_ISFIFO(mode));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lazy_stat(struct archive_write_disk *a)
|
lazy_stat(struct archive_write_disk *a)
|
||||||
{
|
{
|
||||||
@ -822,6 +857,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
|||||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||||
if (fe == NULL)
|
if (fe == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
|
fe->filetype = archive_entry_filetype(entry);
|
||||||
fe->fixup |= TODO_MODE_BASE;
|
fe->fixup |= TODO_MODE_BASE;
|
||||||
fe->mode = a->mode;
|
fe->mode = a->mode;
|
||||||
}
|
}
|
||||||
@ -832,6 +868,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
|||||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||||
if (fe == NULL)
|
if (fe == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
|
fe->filetype = archive_entry_filetype(entry);
|
||||||
fe->mode = a->mode;
|
fe->mode = a->mode;
|
||||||
fe->fixup |= TODO_TIMES;
|
fe->fixup |= TODO_TIMES;
|
||||||
if (archive_entry_atime_is_set(entry)) {
|
if (archive_entry_atime_is_set(entry)) {
|
||||||
@ -865,6 +902,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
|||||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||||
if (fe == NULL)
|
if (fe == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
|
fe->filetype = archive_entry_filetype(entry);
|
||||||
fe->fixup |= TODO_ACLS;
|
fe->fixup |= TODO_ACLS;
|
||||||
archive_acl_copy(&fe->acl, archive_entry_acl(entry));
|
archive_acl_copy(&fe->acl, archive_entry_acl(entry));
|
||||||
}
|
}
|
||||||
@ -877,6 +915,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
|||||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||||
if (fe == NULL)
|
if (fe == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
|
fe->filetype = archive_entry_filetype(entry);
|
||||||
fe->mac_metadata = malloc(metadata_size);
|
fe->mac_metadata = malloc(metadata_size);
|
||||||
if (fe->mac_metadata != NULL) {
|
if (fe->mac_metadata != NULL) {
|
||||||
memcpy(fe->mac_metadata, metadata,
|
memcpy(fe->mac_metadata, metadata,
|
||||||
@ -891,6 +930,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
|
|||||||
fe = current_fixup(a, archive_entry_pathname(entry));
|
fe = current_fixup(a, archive_entry_pathname(entry));
|
||||||
if (fe == NULL)
|
if (fe == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
|
fe->filetype = archive_entry_filetype(entry);
|
||||||
fe->fixup |= TODO_FFLAGS;
|
fe->fixup |= TODO_FFLAGS;
|
||||||
/* TODO: Complete this.. defer fflags from below. */
|
/* TODO: Complete this.. defer fflags from below. */
|
||||||
}
|
}
|
||||||
@ -2263,7 +2303,7 @@ create_filesystem_object(struct archive_write_disk *a)
|
|||||||
return (EPERM);
|
return (EPERM);
|
||||||
}
|
}
|
||||||
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
||||||
&error_string, a->flags);
|
&error_string, a->flags, 1);
|
||||||
if (r != ARCHIVE_OK) {
|
if (r != ARCHIVE_OK) {
|
||||||
archive_set_error(&a->archive, error_number, "%s",
|
archive_set_error(&a->archive, error_number, "%s",
|
||||||
error_string.s);
|
error_string.s);
|
||||||
@ -2284,7 +2324,12 @@ create_filesystem_object(struct archive_write_disk *a)
|
|||||||
*/
|
*/
|
||||||
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
|
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
|
||||||
unlink(a->name);
|
unlink(a->name);
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name,
|
||||||
|
0) ? errno : 0;
|
||||||
|
#else
|
||||||
r = link(linkname, a->name) ? errno : 0;
|
r = link(linkname, a->name) ? errno : 0;
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* New cpio and pax formats allow hardlink entries
|
* New cpio and pax formats allow hardlink entries
|
||||||
* to carry data, so we may have to open the file
|
* to carry data, so we may have to open the file
|
||||||
@ -2456,7 +2501,9 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
{
|
{
|
||||||
struct archive_write_disk *a = (struct archive_write_disk *)_a;
|
struct archive_write_disk *a = (struct archive_write_disk *)_a;
|
||||||
struct fixup_entry *next, *p;
|
struct fixup_entry *next, *p;
|
||||||
int fd, ret;
|
struct stat st;
|
||||||
|
char *c;
|
||||||
|
int fd, ret, openflags;
|
||||||
|
|
||||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
|
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
|
||||||
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
|
||||||
@ -2469,10 +2516,70 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
fd = -1;
|
fd = -1;
|
||||||
a->pst = NULL; /* Mark stat cache as out-of-date. */
|
a->pst = NULL; /* Mark stat cache as out-of-date. */
|
||||||
if (p->fixup &
|
|
||||||
(TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
|
/* We must strip trailing slashes from the path to avoid
|
||||||
fd = open(p->name,
|
dereferencing symbolic links to directories */
|
||||||
O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
|
c = p->name;
|
||||||
|
while (*c != '\0')
|
||||||
|
c++;
|
||||||
|
while (c != p->name && *(c - 1) == '/') {
|
||||||
|
c--;
|
||||||
|
*c = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->fixup == 0)
|
||||||
|
goto skip_fixup_entry;
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* We need to verify if the type of the file
|
||||||
|
* we are going to open matches the file type
|
||||||
|
* of the fixup entry.
|
||||||
|
*/
|
||||||
|
openflags = O_BINARY | O_NOFOLLOW | O_RDONLY
|
||||||
|
| O_CLOEXEC;
|
||||||
|
#if defined(O_DIRECTORY)
|
||||||
|
if (p->filetype == AE_IFDIR)
|
||||||
|
openflags |= O_DIRECTORY;
|
||||||
|
#endif
|
||||||
|
fd = open(p->name, openflags);
|
||||||
|
|
||||||
|
#if defined(O_DIRECTORY)
|
||||||
|
/*
|
||||||
|
* If we support O_DIRECTORY and open was
|
||||||
|
* successful we can skip the file type check
|
||||||
|
* for directories. For other file types
|
||||||
|
* we need to verify via fstat() or lstat()
|
||||||
|
*/
|
||||||
|
if (fd == -1 || p->filetype != AE_IFDIR) {
|
||||||
|
#if HAVE_FSTAT
|
||||||
|
if (fd > 0 && (
|
||||||
|
fstat(fd, &st) != 0 ||
|
||||||
|
la_verify_filetype(st.st_mode,
|
||||||
|
p->filetype) == 0)) {
|
||||||
|
goto skip_fixup_entry;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (lstat(p->name, &st) != 0 ||
|
||||||
|
la_verify_filetype(st.st_mode,
|
||||||
|
p->filetype) == 0) {
|
||||||
|
goto skip_fixup_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#if HAVE_FSTAT
|
||||||
|
if (fd > 0 && (
|
||||||
|
fstat(fd, &st) != 0 ||
|
||||||
|
la_verify_filetype(st.st_mode,
|
||||||
|
p->filetype) == 0)) {
|
||||||
|
goto skip_fixup_entry;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (lstat(p->name, &st) != 0 ||
|
||||||
|
la_verify_filetype(st.st_mode,
|
||||||
|
p->filetype) == 0) {
|
||||||
|
goto skip_fixup_entry;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (p->fixup & TODO_TIMES) {
|
if (p->fixup & TODO_TIMES) {
|
||||||
set_times(a, fd, p->mode, p->name,
|
set_times(a, fd, p->mode, p->name,
|
||||||
@ -2484,10 +2591,14 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
if (p->fixup & TODO_MODE_BASE) {
|
if (p->fixup & TODO_MODE_BASE) {
|
||||||
#ifdef HAVE_FCHMOD
|
#ifdef HAVE_FCHMOD
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
fchmod(fd, p->mode);
|
fchmod(fd, p->mode & 07777);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
chmod(p->name, p->mode);
|
#ifdef HAVE_LCHMOD
|
||||||
|
lchmod(p->name, p->mode & 07777);
|
||||||
|
#else
|
||||||
|
chmod(p->name, p->mode & 07777);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (p->fixup & TODO_ACLS)
|
if (p->fixup & TODO_ACLS)
|
||||||
archive_write_disk_set_acls(&a->archive, fd,
|
archive_write_disk_set_acls(&a->archive, fd,
|
||||||
@ -2498,6 +2609,7 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
if (p->fixup & TODO_MAC_METADATA)
|
if (p->fixup & TODO_MAC_METADATA)
|
||||||
set_mac_metadata(a, p->name, p->mac_metadata,
|
set_mac_metadata(a, p->name, p->mac_metadata,
|
||||||
p->mac_metadata_size);
|
p->mac_metadata_size);
|
||||||
|
skip_fixup_entry:
|
||||||
next = p->next;
|
next = p->next;
|
||||||
archive_acl_clear(&p->acl);
|
archive_acl_clear(&p->acl);
|
||||||
free(p->mac_metadata);
|
free(p->mac_metadata);
|
||||||
@ -2638,6 +2750,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
|
|||||||
fe->next = a->fixup_list;
|
fe->next = a->fixup_list;
|
||||||
a->fixup_list = fe;
|
a->fixup_list = fe;
|
||||||
fe->fixup = 0;
|
fe->fixup = 0;
|
||||||
|
fe->filetype = 0;
|
||||||
fe->name = strdup(pathname);
|
fe->name = strdup(pathname);
|
||||||
return (fe);
|
return (fe);
|
||||||
}
|
}
|
||||||
@ -2675,7 +2788,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||||
int flags)
|
int flags, int checking_linkname)
|
||||||
{
|
{
|
||||||
#if !defined(HAVE_LSTAT) && \
|
#if !defined(HAVE_LSTAT) && \
|
||||||
!(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
|
!(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
|
||||||
@ -2684,6 +2797,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
|||||||
(void)error_number; /* UNUSED */
|
(void)error_number; /* UNUSED */
|
||||||
(void)error_string; /* UNUSED */
|
(void)error_string; /* UNUSED */
|
||||||
(void)flags; /* UNUSED */
|
(void)flags; /* UNUSED */
|
||||||
|
(void)checking_linkname; /* UNUSED */
|
||||||
return (ARCHIVE_OK);
|
return (ARCHIVE_OK);
|
||||||
#else
|
#else
|
||||||
int res = ARCHIVE_OK;
|
int res = ARCHIVE_OK;
|
||||||
@ -2805,6 +2919,28 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
|||||||
head = tail + 1;
|
head = tail + 1;
|
||||||
}
|
}
|
||||||
} else if (S_ISLNK(st.st_mode)) {
|
} else if (S_ISLNK(st.st_mode)) {
|
||||||
|
if (last && checking_linkname) {
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
/*
|
||||||
|
* Hardlinks to symlinks are safe to write
|
||||||
|
* if linkat() is supported as it does not
|
||||||
|
* follow symlinks.
|
||||||
|
*/
|
||||||
|
res = ARCHIVE_OK;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* We return ARCHIVE_FAILED here as we are
|
||||||
|
* not able to safely write hardlinks
|
||||||
|
* to symlinks.
|
||||||
|
*/
|
||||||
|
tail[0] = c;
|
||||||
|
fsobj_error(a_eno, a_estr, errno,
|
||||||
|
"Cannot write hardlink to symlink ",
|
||||||
|
path);
|
||||||
|
res = ARCHIVE_FAILED;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
} else
|
||||||
if (last) {
|
if (last) {
|
||||||
/*
|
/*
|
||||||
* Last element is symlink; remove it
|
* Last element is symlink; remove it
|
||||||
@ -2971,7 +3107,7 @@ check_symlinks(struct archive_write_disk *a)
|
|||||||
int rc;
|
int rc;
|
||||||
archive_string_init(&error_string);
|
archive_string_init(&error_string);
|
||||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
||||||
a->flags);
|
a->flags, 0);
|
||||||
if (rc != ARCHIVE_OK) {
|
if (rc != ARCHIVE_OK) {
|
||||||
archive_set_error(&a->archive, error_number, "%s",
|
archive_set_error(&a->archive, error_number, "%s",
|
||||||
error_string.s);
|
error_string.s);
|
||||||
@ -3737,6 +3873,7 @@ set_fflags(struct archive_write_disk *a)
|
|||||||
le = current_fixup(a, a->name);
|
le = current_fixup(a, a->name);
|
||||||
if (le == NULL)
|
if (le == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
|
le->filetype = archive_entry_filetype(a->entry);
|
||||||
le->fixup |= TODO_FFLAGS;
|
le->fixup |= TODO_FFLAGS;
|
||||||
le->fflags_set = set;
|
le->fflags_set = set;
|
||||||
/* Store the mode if it's not already there. */
|
/* Store the mode if it's not already there. */
|
||||||
@ -3899,7 +4036,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
|
|||||||
|
|
||||||
/* If we weren't given an fd, open it ourselves. */
|
/* If we weren't given an fd, open it ourselves. */
|
||||||
if (myfd < 0) {
|
if (myfd < 0) {
|
||||||
myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC);
|
myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY |
|
||||||
|
O_CLOEXEC | O_NOFOLLOW);
|
||||||
__archive_ensure_cloexec_flag(myfd);
|
__archive_ensure_cloexec_flag(myfd);
|
||||||
}
|
}
|
||||||
if (myfd < 0)
|
if (myfd < 0)
|
||||||
|
@ -35,7 +35,10 @@
|
|||||||
.Nm archive_write_set_format_ar_svr4 ,
|
.Nm archive_write_set_format_ar_svr4 ,
|
||||||
.Nm archive_write_set_format_by_name ,
|
.Nm archive_write_set_format_by_name ,
|
||||||
.Nm archive_write_set_format_cpio ,
|
.Nm archive_write_set_format_cpio ,
|
||||||
|
.Nm archive_write_set_format_cpio_bin ,
|
||||||
.Nm archive_write_set_format_cpio_newc ,
|
.Nm archive_write_set_format_cpio_newc ,
|
||||||
|
.Nm archive_write_set_format_cpio_odc ,
|
||||||
|
.Nm archive_write_set_format_cpio_pwb ,
|
||||||
.Nm archive_write_set_format_filter_by_ext ,
|
.Nm archive_write_set_format_filter_by_ext ,
|
||||||
.Nm archive_write_set_format_filter_by_ext_def ,
|
.Nm archive_write_set_format_filter_by_ext_def ,
|
||||||
.Nm archive_write_set_format_gnutar ,
|
.Nm archive_write_set_format_gnutar ,
|
||||||
@ -73,8 +76,14 @@ Streaming Archive Library (libarchive, -larchive)
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn archive_write_set_format_cpio "struct archive *"
|
.Fn archive_write_set_format_cpio "struct archive *"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn archive_write_set_format_cpio_bin "struct archive *"
|
||||||
|
.Ft int
|
||||||
.Fn archive_write_set_format_cpio_newc "struct archive *"
|
.Fn archive_write_set_format_cpio_newc "struct archive *"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn archive_write_set_format_cpio_odc "struct archive *"
|
||||||
|
.Ft int
|
||||||
|
.Fn archive_write_set_format_cpio_pwb "struct archive *"
|
||||||
|
.Ft int
|
||||||
.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *filename"
|
.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *filename"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *filename" "const char *def_ext"
|
.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *filename" "const char *def_ext"
|
||||||
@ -119,17 +128,20 @@ to create a new archive with the same format as an existing archive.
|
|||||||
.It Fn archive_write_set_format_by_name
|
.It Fn archive_write_set_format_by_name
|
||||||
Sets the corresponding format based on the common name.
|
Sets the corresponding format based on the common name.
|
||||||
.It Xo
|
.It Xo
|
||||||
.Fn archive_write_set_format_filter_by_ext ,
|
.Fn archive_write_set_format_filter_by_ext
|
||||||
.Fn archive_write_set_format_filter_by_ext_def
|
.Fn archive_write_set_format_filter_by_ext_def
|
||||||
.Xc
|
.Xc
|
||||||
Sets both filters and format based on the output filename.
|
Sets both filters and format based on the output filename.
|
||||||
Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
|
Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
|
||||||
.It Xo
|
.It Xo
|
||||||
.Fn archive_write_set_format_7zip
|
.Fn archive_write_set_format_7zip
|
||||||
.Fn archive_write_set_format_ar_bsd ,
|
.Fn archive_write_set_format_ar_bsd
|
||||||
.Fn archive_write_set_format_ar_svr4 ,
|
.Fn archive_write_set_format_ar_svr4
|
||||||
.Fn archive_write_set_format_cpio
|
.Fn archive_write_set_format_cpio
|
||||||
|
.Fn archive_write_set_format_cpio_bin
|
||||||
.Fn archive_write_set_format_cpio_newc
|
.Fn archive_write_set_format_cpio_newc
|
||||||
|
.Fn archive_write_set_format_cpio_odc
|
||||||
|
.Fn archive_write_set_format_cpio_pwb
|
||||||
.Fn archive_write_set_format_gnutar
|
.Fn archive_write_set_format_gnutar
|
||||||
.Fn archive_write_set_format_iso9660
|
.Fn archive_write_set_format_iso9660
|
||||||
.Fn archive_write_set_format_mtree
|
.Fn archive_write_set_format_mtree
|
||||||
|
@ -44,7 +44,9 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
|
|||||||
{
|
{
|
||||||
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
|
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
|
||||||
{ ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio },
|
{ ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio },
|
||||||
{ ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio },
|
{ ARCHIVE_FORMAT_CPIO_BIN_LE, archive_write_set_format_cpio_bin },
|
||||||
|
{ ARCHIVE_FORMAT_CPIO_PWB, archive_write_set_format_cpio_pwb },
|
||||||
|
{ ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio_odc },
|
||||||
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
|
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
|
||||||
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
|
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
|
||||||
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
|
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
|
||||||
|
@ -755,6 +755,10 @@ _7z_close(struct archive_write *a)
|
|||||||
*/
|
*/
|
||||||
#if HAVE_LZMA_H
|
#if HAVE_LZMA_H
|
||||||
header_compression = _7Z_LZMA1;
|
header_compression = _7Z_LZMA1;
|
||||||
|
if(zip->opt_compression == _7Z_LZMA2 ||
|
||||||
|
zip->opt_compression == _7Z_COPY)
|
||||||
|
header_compression = zip->opt_compression;
|
||||||
|
|
||||||
/* If the stored file is only one, do not encode the header.
|
/* If the stored file is only one, do not encode the header.
|
||||||
* This is the same way 7z command does. */
|
* This is the same way 7z command does. */
|
||||||
if (zip->total_number_entry == 1)
|
if (zip->total_number_entry == 1)
|
||||||
@ -762,7 +766,8 @@ _7z_close(struct archive_write *a)
|
|||||||
#else
|
#else
|
||||||
header_compression = _7Z_COPY;
|
header_compression = _7Z_COPY;
|
||||||
#endif
|
#endif
|
||||||
r = _7z_compression_init_encoder(a, header_compression, 6);
|
r = _7z_compression_init_encoder(a, header_compression,
|
||||||
|
zip->opt_compression_level);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return (r);
|
return (r);
|
||||||
zip->crc32flg = PRECODE_CRC32;
|
zip->crc32flg = PRECODE_CRC32;
|
||||||
|
@ -49,6 +49,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
|
|||||||
{ "arbsd", archive_write_set_format_ar_bsd },
|
{ "arbsd", archive_write_set_format_ar_bsd },
|
||||||
{ "argnu", archive_write_set_format_ar_svr4 },
|
{ "argnu", archive_write_set_format_ar_svr4 },
|
||||||
{ "arsvr4", archive_write_set_format_ar_svr4 },
|
{ "arsvr4", archive_write_set_format_ar_svr4 },
|
||||||
|
{ "bin", archive_write_set_format_cpio_bin },
|
||||||
{ "bsdtar", archive_write_set_format_pax_restricted },
|
{ "bsdtar", archive_write_set_format_pax_restricted },
|
||||||
{ "cd9660", archive_write_set_format_iso9660 },
|
{ "cd9660", archive_write_set_format_iso9660 },
|
||||||
{ "cpio", archive_write_set_format_cpio },
|
{ "cpio", archive_write_set_format_cpio },
|
||||||
@ -58,11 +59,12 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
|
|||||||
{ "mtree", archive_write_set_format_mtree },
|
{ "mtree", archive_write_set_format_mtree },
|
||||||
{ "mtree-classic", archive_write_set_format_mtree_classic },
|
{ "mtree-classic", archive_write_set_format_mtree_classic },
|
||||||
{ "newc", archive_write_set_format_cpio_newc },
|
{ "newc", archive_write_set_format_cpio_newc },
|
||||||
{ "odc", archive_write_set_format_cpio },
|
{ "odc", archive_write_set_format_cpio_odc },
|
||||||
{ "oldtar", archive_write_set_format_v7tar },
|
{ "oldtar", archive_write_set_format_v7tar },
|
||||||
{ "pax", archive_write_set_format_pax },
|
{ "pax", archive_write_set_format_pax },
|
||||||
{ "paxr", archive_write_set_format_pax_restricted },
|
{ "paxr", archive_write_set_format_pax_restricted },
|
||||||
{ "posix", archive_write_set_format_pax },
|
{ "posix", archive_write_set_format_pax },
|
||||||
|
{ "pwb", archive_write_set_format_cpio_pwb },
|
||||||
{ "raw", archive_write_set_format_raw },
|
{ "raw", archive_write_set_format_raw },
|
||||||
{ "rpax", archive_write_set_format_pax_restricted },
|
{ "rpax", archive_write_set_format_pax_restricted },
|
||||||
{ "shar", archive_write_set_format_shar },
|
{ "shar", archive_write_set_format_shar },
|
||||||
|
@ -1,500 +1,10 @@
|
|||||||
/*-
|
|
||||||
* Copyright (c) 2003-2007 Tim Kientzle
|
|
||||||
* Copyright (c) 2011-2012 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: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
|
|
||||||
|
|
||||||
#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.h"
|
||||||
#include "archive_entry.h"
|
|
||||||
#include "archive_entry_locale.h"
|
|
||||||
#include "archive_private.h"
|
|
||||||
#include "archive_write_private.h"
|
|
||||||
#include "archive_write_set_format_private.h"
|
|
||||||
|
|
||||||
static ssize_t archive_write_cpio_data(struct archive_write *,
|
|
||||||
const void *buff, size_t s);
|
|
||||||
static int archive_write_cpio_close(struct archive_write *);
|
|
||||||
static int archive_write_cpio_free(struct archive_write *);
|
|
||||||
static int archive_write_cpio_finish_entry(struct archive_write *);
|
|
||||||
static int archive_write_cpio_header(struct archive_write *,
|
|
||||||
struct archive_entry *);
|
|
||||||
static int archive_write_cpio_options(struct archive_write *,
|
|
||||||
const char *, const char *);
|
|
||||||
static int format_octal(int64_t, void *, int);
|
|
||||||
static int64_t format_octal_recursive(int64_t, char *, int);
|
|
||||||
static int write_header(struct archive_write *, struct archive_entry *);
|
|
||||||
|
|
||||||
struct cpio {
|
|
||||||
uint64_t entry_bytes_remaining;
|
|
||||||
|
|
||||||
int64_t ino_next;
|
|
||||||
|
|
||||||
struct { int64_t old; int new;} *ino_list;
|
|
||||||
size_t ino_list_size;
|
|
||||||
size_t ino_list_next;
|
|
||||||
|
|
||||||
struct archive_string_conv *opt_sconv;
|
|
||||||
struct archive_string_conv *sconv_default;
|
|
||||||
int init_default_conversion;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define c_magic_offset 0
|
|
||||||
#define c_magic_size 6
|
|
||||||
#define c_dev_offset 6
|
|
||||||
#define c_dev_size 6
|
|
||||||
#define c_ino_offset 12
|
|
||||||
#define c_ino_size 6
|
|
||||||
#define c_mode_offset 18
|
|
||||||
#define c_mode_size 6
|
|
||||||
#define c_uid_offset 24
|
|
||||||
#define c_uid_size 6
|
|
||||||
#define c_gid_offset 30
|
|
||||||
#define c_gid_size 6
|
|
||||||
#define c_nlink_offset 36
|
|
||||||
#define c_nlink_size 6
|
|
||||||
#define c_rdev_offset 42
|
|
||||||
#define c_rdev_size 6
|
|
||||||
#define c_mtime_offset 48
|
|
||||||
#define c_mtime_size 11
|
|
||||||
#define c_namesize_offset 59
|
|
||||||
#define c_namesize_size 6
|
|
||||||
#define c_filesize_offset 65
|
|
||||||
#define c_filesize_size 11
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set output format to 'cpio' format.
|
* Set output format to the default 'cpio' format.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
archive_write_set_format_cpio(struct archive *_a)
|
archive_write_set_format_cpio(struct archive *_a)
|
||||||
{
|
{
|
||||||
struct archive_write *a = (struct archive_write *)_a;
|
return archive_write_set_format_cpio_odc(_a);
|
||||||
struct cpio *cpio;
|
|
||||||
|
|
||||||
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
|
||||||
ARCHIVE_STATE_NEW, "archive_write_set_format_cpio");
|
|
||||||
|
|
||||||
/* If someone else was already registered, unregister them. */
|
|
||||||
if (a->format_free != NULL)
|
|
||||||
(a->format_free)(a);
|
|
||||||
|
|
||||||
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
|
||||||
if (cpio == NULL) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
|
||||||
return (ARCHIVE_FATAL);
|
|
||||||
}
|
|
||||||
a->format_data = cpio;
|
|
||||||
a->format_name = "cpio";
|
|
||||||
a->format_options = archive_write_cpio_options;
|
|
||||||
a->format_write_header = archive_write_cpio_header;
|
|
||||||
a->format_write_data = archive_write_cpio_data;
|
|
||||||
a->format_finish_entry = archive_write_cpio_finish_entry;
|
|
||||||
a->format_close = archive_write_cpio_close;
|
|
||||||
a->format_free = archive_write_cpio_free;
|
|
||||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
|
|
||||||
a->archive.archive_format_name = "POSIX cpio";
|
|
||||||
return (ARCHIVE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_options(struct archive_write *a, const char *key,
|
|
||||||
const char *val)
|
|
||||||
{
|
|
||||||
struct cpio *cpio = (struct cpio *)a->format_data;
|
|
||||||
int ret = ARCHIVE_FAILED;
|
|
||||||
|
|
||||||
if (strcmp(key, "hdrcharset") == 0) {
|
|
||||||
if (val == NULL || val[0] == 0)
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
||||||
"%s: hdrcharset option needs a character-set name",
|
|
||||||
a->format_name);
|
|
||||||
else {
|
|
||||||
cpio->opt_sconv = archive_string_conversion_to_charset(
|
|
||||||
&a->archive, val, 0);
|
|
||||||
if (cpio->opt_sconv != NULL)
|
|
||||||
ret = ARCHIVE_OK;
|
|
||||||
else
|
|
||||||
ret = ARCHIVE_FATAL;
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: The "warn" return is just to inform the options
|
|
||||||
* supervisor that we didn't handle it. It will generate
|
|
||||||
* a suitable error if no one used this option. */
|
|
||||||
return (ARCHIVE_WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ino values are as long as 64 bits on some systems; cpio format
|
|
||||||
* only allows 18 bits and relies on the ino values to identify hardlinked
|
|
||||||
* files. So, we can't merely "hash" the ino numbers since collisions
|
|
||||||
* would corrupt the archive. Instead, we generate synthetic ino values
|
|
||||||
* to store in the archive and maintain a map of original ino values to
|
|
||||||
* synthetic ones so we can preserve hardlink information.
|
|
||||||
*
|
|
||||||
* TODO: Make this more efficient. It's not as bad as it looks (most
|
|
||||||
* files don't have any hardlinks and we don't do any work here for those),
|
|
||||||
* but it wouldn't be hard to do better.
|
|
||||||
*
|
|
||||||
* TODO: Work with dev/ino pairs here instead of just ino values.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
int64_t ino = archive_entry_ino64(entry);
|
|
||||||
int ino_new;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no index number was given, don't assign one. In
|
|
||||||
* particular, this handles the end-of-archive marker
|
|
||||||
* correctly by giving it a zero index value. (This is also
|
|
||||||
* why we start our synthetic index numbers with one below.)
|
|
||||||
*/
|
|
||||||
if (ino == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
/* Don't store a mapping if we don't need to. */
|
|
||||||
if (archive_entry_nlink(entry) < 2) {
|
|
||||||
return (int)(++cpio->ino_next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look up old ino; if we have it, this is a hardlink
|
|
||||||
* and we reuse the same value. */
|
|
||||||
for (i = 0; i < cpio->ino_list_next; ++i) {
|
|
||||||
if (cpio->ino_list[i].old == ino)
|
|
||||||
return (cpio->ino_list[i].new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign a new index number. */
|
|
||||||
ino_new = (int)(++cpio->ino_next);
|
|
||||||
|
|
||||||
/* Ensure space for the new mapping. */
|
|
||||||
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
|
||||||
size_t newsize = cpio->ino_list_size < 512
|
|
||||||
? 512 : cpio->ino_list_size * 2;
|
|
||||||
void *newlist = realloc(cpio->ino_list,
|
|
||||||
sizeof(cpio->ino_list[0]) * newsize);
|
|
||||||
if (newlist == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
cpio->ino_list_size = newsize;
|
|
||||||
cpio->ino_list = newlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record and return the new value. */
|
|
||||||
cpio->ino_list[cpio->ino_list_next].old = ino;
|
|
||||||
cpio->ino_list[cpio->ino_list_next].new = ino_new;
|
|
||||||
++cpio->ino_list_next;
|
|
||||||
return (ino_new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct archive_string_conv *
|
|
||||||
get_sconv(struct archive_write *a)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
struct archive_string_conv *sconv;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
sconv = cpio->opt_sconv;
|
|
||||||
if (sconv == NULL) {
|
|
||||||
if (!cpio->init_default_conversion) {
|
|
||||||
cpio->sconv_default =
|
|
||||||
archive_string_default_conversion_for_write(
|
|
||||||
&(a->archive));
|
|
||||||
cpio->init_default_conversion = 1;
|
|
||||||
}
|
|
||||||
sconv = cpio->sconv_default;
|
|
||||||
}
|
|
||||||
return (sconv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
const char *path;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
|
|
||||||
archive_set_error(&a->archive, -1, "Filetype required");
|
|
||||||
return (ARCHIVE_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
|
|
||||||
&& errno == ENOMEM) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate memory for Pathname");
|
|
||||||
return (ARCHIVE_FATAL);
|
|
||||||
}
|
|
||||||
if (len == 0 || path == NULL || path[0] == '\0') {
|
|
||||||
archive_set_error(&a->archive, -1, "Pathname required");
|
|
||||||
return (ARCHIVE_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
|
|
||||||
archive_set_error(&a->archive, -1, "Size required");
|
|
||||||
return (ARCHIVE_FAILED);
|
|
||||||
}
|
|
||||||
return write_header(a, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_header(struct archive_write *a, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
const char *p, *path;
|
|
||||||
int pathlength, ret, ret_final;
|
|
||||||
int64_t ino;
|
|
||||||
char h[76];
|
|
||||||
struct archive_string_conv *sconv;
|
|
||||||
struct archive_entry *entry_main;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
ret_final = ARCHIVE_OK;
|
|
||||||
sconv = get_sconv(a);
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
||||||
/* Make sure the path separators in pathname, hardlink and symlink
|
|
||||||
* are all slash '/', not the Windows path separator '\'. */
|
|
||||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
|
||||||
if (entry_main == NULL) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate ustar data");
|
|
||||||
return(ARCHIVE_FATAL);
|
|
||||||
}
|
|
||||||
if (entry != entry_main)
|
|
||||||
entry = entry_main;
|
|
||||||
else
|
|
||||||
entry_main = NULL;
|
|
||||||
#else
|
|
||||||
entry_main = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
|
|
||||||
if (ret != 0) {
|
|
||||||
if (errno == ENOMEM) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate memory for Pathname");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
||||||
"Can't translate pathname '%s' to %s",
|
|
||||||
archive_entry_pathname(entry),
|
|
||||||
archive_string_conversion_charset_name(sconv));
|
|
||||||
ret_final = ARCHIVE_WARN;
|
|
||||||
}
|
|
||||||
/* Include trailing null. */
|
|
||||||
pathlength = (int)len + 1;
|
|
||||||
|
|
||||||
memset(h, 0, sizeof(h));
|
|
||||||
format_octal(070707, h + c_magic_offset, c_magic_size);
|
|
||||||
format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
|
|
||||||
|
|
||||||
ino = synthesize_ino_value(cpio, entry);
|
|
||||||
if (ino < 0) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"No memory for ino translation table");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
} else if (ino > 0777777) {
|
|
||||||
archive_set_error(&a->archive, ERANGE,
|
|
||||||
"Too many files for this cpio format");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
|
|
||||||
|
|
||||||
/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
|
|
||||||
format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
|
|
||||||
format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
|
|
||||||
format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
|
|
||||||
format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
|
|
||||||
if (archive_entry_filetype(entry) == AE_IFBLK
|
|
||||||
|| archive_entry_filetype(entry) == AE_IFCHR)
|
|
||||||
format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
|
|
||||||
else
|
|
||||||
format_octal(0, h + c_rdev_offset, c_rdev_size);
|
|
||||||
format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
|
|
||||||
format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
|
|
||||||
|
|
||||||
/* Non-regular files don't store bodies. */
|
|
||||||
if (archive_entry_filetype(entry) != AE_IFREG)
|
|
||||||
archive_entry_set_size(entry, 0);
|
|
||||||
|
|
||||||
/* Symlinks get the link written as the body of the entry. */
|
|
||||||
ret = archive_entry_symlink_l(entry, &p, &len, sconv);
|
|
||||||
if (ret != 0) {
|
|
||||||
if (errno == ENOMEM) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate memory for Linkname");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
||||||
"Can't translate linkname '%s' to %s",
|
|
||||||
archive_entry_symlink(entry),
|
|
||||||
archive_string_conversion_charset_name(sconv));
|
|
||||||
ret_final = ARCHIVE_WARN;
|
|
||||||
}
|
|
||||||
if (len > 0 && p != NULL && *p != '\0')
|
|
||||||
ret = format_octal(strlen(p), h + c_filesize_offset,
|
|
||||||
c_filesize_size);
|
|
||||||
else
|
|
||||||
ret = format_octal(archive_entry_size(entry),
|
|
||||||
h + c_filesize_offset, c_filesize_size);
|
|
||||||
if (ret) {
|
|
||||||
archive_set_error(&a->archive, ERANGE,
|
|
||||||
"File is too large for cpio format.");
|
|
||||||
ret_final = ARCHIVE_FAILED;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = __archive_write_output(a, h, sizeof(h));
|
|
||||||
if (ret != ARCHIVE_OK) {
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = __archive_write_output(a, path, pathlength);
|
|
||||||
if (ret != ARCHIVE_OK) {
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpio->entry_bytes_remaining = archive_entry_size(entry);
|
|
||||||
|
|
||||||
/* Write the symlink now. */
|
|
||||||
if (p != NULL && *p != '\0') {
|
|
||||||
ret = __archive_write_output(a, p, strlen(p));
|
|
||||||
if (ret != ARCHIVE_OK) {
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit_write_header:
|
|
||||||
archive_entry_free(entry_main);
|
|
||||||
return (ret_final);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
if (s > cpio->entry_bytes_remaining)
|
|
||||||
s = (size_t)cpio->entry_bytes_remaining;
|
|
||||||
|
|
||||||
ret = __archive_write_output(a, buff, s);
|
|
||||||
cpio->entry_bytes_remaining -= s;
|
|
||||||
if (ret >= 0)
|
|
||||||
return (s);
|
|
||||||
else
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Format a number into the specified field.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
format_octal(int64_t v, void *p, int digits)
|
|
||||||
{
|
|
||||||
int64_t max;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
max = (((int64_t)1) << (digits * 3)) - 1;
|
|
||||||
if (v >= 0 && v <= max) {
|
|
||||||
format_octal_recursive(v, (char *)p, digits);
|
|
||||||
ret = 0;
|
|
||||||
} else {
|
|
||||||
format_octal_recursive(max, (char *)p, digits);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t
|
|
||||||
format_octal_recursive(int64_t v, char *p, int s)
|
|
||||||
{
|
|
||||||
if (s == 0)
|
|
||||||
return (v);
|
|
||||||
v = format_octal_recursive(v, p+1, s-1);
|
|
||||||
*p = '0' + ((char)v & 7);
|
|
||||||
return (v >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_close(struct archive_write *a)
|
|
||||||
{
|
|
||||||
int er;
|
|
||||||
struct archive_entry *trailer;
|
|
||||||
|
|
||||||
trailer = archive_entry_new2(NULL);
|
|
||||||
/* nlink = 1 here for GNU cpio compat. */
|
|
||||||
archive_entry_set_nlink(trailer, 1);
|
|
||||||
archive_entry_set_size(trailer, 0);
|
|
||||||
archive_entry_set_pathname(trailer, "TRAILER!!!");
|
|
||||||
er = write_header(a, trailer);
|
|
||||||
archive_entry_free(trailer);
|
|
||||||
return (er);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_free(struct archive_write *a)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
free(cpio->ino_list);
|
|
||||||
free(cpio);
|
|
||||||
a->format_data = NULL;
|
|
||||||
return (ARCHIVE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_finish_entry(struct archive_write *a)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
return (__archive_write_nulls(a,
|
|
||||||
(size_t)cpio->entry_bytes_remaining));
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,610 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003-2007 Tim Kientzle
|
||||||
|
* Copyright (c) 2011-2012 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: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
|
||||||
|
|
||||||
|
#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"
|
||||||
|
#include "archive_entry_locale.h"
|
||||||
|
#include "archive_private.h"
|
||||||
|
#include "archive_write_private.h"
|
||||||
|
#include "archive_write_set_format_private.h"
|
||||||
|
|
||||||
|
static ssize_t archive_write_binary_data(struct archive_write *,
|
||||||
|
const void *buff, size_t s);
|
||||||
|
static int archive_write_binary_close(struct archive_write *);
|
||||||
|
static int archive_write_binary_free(struct archive_write *);
|
||||||
|
static int archive_write_binary_finish_entry(struct archive_write *);
|
||||||
|
static int archive_write_binary_header(struct archive_write *,
|
||||||
|
struct archive_entry *);
|
||||||
|
static int archive_write_binary_options(struct archive_write *,
|
||||||
|
const char *, const char *);
|
||||||
|
static int write_header(struct archive_write *, struct archive_entry *);
|
||||||
|
|
||||||
|
struct cpio {
|
||||||
|
uint64_t entry_bytes_remaining;
|
||||||
|
|
||||||
|
int64_t ino_next;
|
||||||
|
|
||||||
|
struct { int64_t old; int new;} *ino_list;
|
||||||
|
size_t ino_list_size;
|
||||||
|
size_t ino_list_next;
|
||||||
|
|
||||||
|
struct archive_string_conv *opt_sconv;
|
||||||
|
struct archive_string_conv *sconv_default;
|
||||||
|
int init_default_conversion;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This struct needs to be packed to get the header right */
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define PACKED(x) x __attribute__((packed))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||||
|
#else
|
||||||
|
#define PACKED(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HSIZE 26
|
||||||
|
|
||||||
|
PACKED(struct cpio_binary_header {
|
||||||
|
uint16_t h_magic;
|
||||||
|
uint16_t h_dev;
|
||||||
|
uint16_t h_ino;
|
||||||
|
uint16_t h_mode;
|
||||||
|
uint16_t h_uid;
|
||||||
|
uint16_t h_gid;
|
||||||
|
uint16_t h_nlink;
|
||||||
|
uint16_t h_majmin;
|
||||||
|
uint32_t h_mtime;
|
||||||
|
uint16_t h_namesize;
|
||||||
|
uint32_t h_filesize;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Back in the day, the 7th Edition cpio.c had this, to
|
||||||
|
* adapt to, as the comment said, "VAX, Interdata, ...":
|
||||||
|
*
|
||||||
|
* union { long l; short s[2]; char c[4]; } U;
|
||||||
|
* #define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];}
|
||||||
|
* long mklong(v)
|
||||||
|
* short v[];
|
||||||
|
* {
|
||||||
|
* U.l = 1;
|
||||||
|
* if(U.c[0])
|
||||||
|
* U.s[0] = v[1], U.s[1] = v[0];
|
||||||
|
* else
|
||||||
|
* U.s[0] = v[0], U.s[1] = v[1];
|
||||||
|
* return U.l;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Of course, that assumes that all machines have little-endian shorts,
|
||||||
|
* and just adapts the others to the special endianness of the PDP-11.
|
||||||
|
*
|
||||||
|
* Now, we could do this:
|
||||||
|
*
|
||||||
|
* union { uint32_t l; uint16_t s[2]; uint8_t c[4]; } U;
|
||||||
|
* #define PUTI16(v,sv) {U.s[0]=1;if(U.c[0]) v=sv; else U.s[0]=sv,U.c[2]=U.c[1],U.c[3]=U.c[0],v=U.s[1];}
|
||||||
|
* #define PUTI32(v,lv) {char_t Ut;U.l=1;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,Ut=U.c[0],U.c[0]=U.c[1],U.c[1]=Ut,Ut=U.c[2],U.c[2]=U.c[3],U.c[3]=Ut,v[0]=U.s[0],v[1]=U.s[1];}
|
||||||
|
*
|
||||||
|
* ...but it feels a little better to do it like this:
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint16_t swap16(uint16_t in) {
|
||||||
|
union {
|
||||||
|
uint16_t s[2];
|
||||||
|
uint8_t c[4];
|
||||||
|
} U;
|
||||||
|
U.s[0] = 1;
|
||||||
|
if (U.c[0])
|
||||||
|
return in;
|
||||||
|
else {
|
||||||
|
U.s[0] = in;
|
||||||
|
U.c[2] = U.c[1];
|
||||||
|
U.c[3] = U.c[0];
|
||||||
|
return U.s[1];
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t swap32(uint32_t in) {
|
||||||
|
union {
|
||||||
|
uint32_t l;
|
||||||
|
uint16_t s[2];
|
||||||
|
uint8_t c[4];
|
||||||
|
} U;
|
||||||
|
U.l = 1;
|
||||||
|
if (U.c[0]) { /* Little-endian */
|
||||||
|
uint16_t t;
|
||||||
|
U.l = in;
|
||||||
|
t = U.s[0];
|
||||||
|
U.s[0] = U.s[1];
|
||||||
|
U.s[1] = t;
|
||||||
|
} else if (U.c[3]) { /* Big-endian */
|
||||||
|
U.l = in;
|
||||||
|
U.s[0] = swap16(U.s[0]);
|
||||||
|
U.s[1] = swap16(U.s[1]);
|
||||||
|
} else { /* PDP-endian */
|
||||||
|
U.l = in;
|
||||||
|
}
|
||||||
|
return U.l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to the selected binary variant
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
archive_write_set_format_cpio_binary(struct archive *_a, int format)
|
||||||
|
{
|
||||||
|
struct archive_write *a = (struct archive_write *)_a;
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
if (sizeof(struct cpio_binary_header) != HSIZE) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"Binary cpio format not supported on this platform");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||||
|
ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_binary");
|
||||||
|
|
||||||
|
/* If someone else was already registered, unregister them. */
|
||||||
|
if (a->format_free != NULL)
|
||||||
|
(a->format_free)(a);
|
||||||
|
|
||||||
|
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
||||||
|
if (cpio == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
a->format_data = cpio;
|
||||||
|
a->format_name = "cpio";
|
||||||
|
a->format_options = archive_write_binary_options;
|
||||||
|
a->format_write_header = archive_write_binary_header;
|
||||||
|
a->format_write_data = archive_write_binary_data;
|
||||||
|
a->format_finish_entry = archive_write_binary_finish_entry;
|
||||||
|
a->format_close = archive_write_binary_close;
|
||||||
|
a->format_free = archive_write_binary_free;
|
||||||
|
a->archive.archive_format = format;
|
||||||
|
switch (format) {
|
||||||
|
case ARCHIVE_FORMAT_CPIO_PWB:
|
||||||
|
a->archive.archive_format_name = "PWB cpio";
|
||||||
|
break;
|
||||||
|
case ARCHIVE_FORMAT_CPIO_BIN_LE:
|
||||||
|
a->archive.archive_format_name = "7th Edition cpio";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
archive_set_error(&a->archive, EINVAL, "binary format must be 'pwb' or 'bin'");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to PWB (6th Edition) binary format
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
archive_write_set_format_cpio_pwb(struct archive *_a)
|
||||||
|
{
|
||||||
|
return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_PWB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to 7th Edition binary format
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
archive_write_set_format_cpio_bin(struct archive *_a)
|
||||||
|
{
|
||||||
|
return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_BIN_LE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_options(struct archive_write *a, const char *key,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
struct cpio *cpio = (struct cpio *)a->format_data;
|
||||||
|
int ret = ARCHIVE_FAILED;
|
||||||
|
|
||||||
|
if (strcmp(key, "hdrcharset") == 0) {
|
||||||
|
if (val == NULL || val[0] == 0)
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||||
|
"%s: hdrcharset option needs a character-set name",
|
||||||
|
a->format_name);
|
||||||
|
else {
|
||||||
|
cpio->opt_sconv = archive_string_conversion_to_charset(
|
||||||
|
&a->archive, val, 0);
|
||||||
|
if (cpio->opt_sconv != NULL)
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
else
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: The "warn" return is just to inform the options
|
||||||
|
* supervisor that we didn't handle it. It will generate
|
||||||
|
* a suitable error if no one used this option. */
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ino values are as long as 64 bits on some systems; cpio format
|
||||||
|
* only allows 16 bits and relies on the ino values to identify hardlinked
|
||||||
|
* files. So, we can't merely "hash" the ino numbers since collisions
|
||||||
|
* would corrupt the archive. Instead, we generate synthetic ino values
|
||||||
|
* to store in the archive and maintain a map of original ino values to
|
||||||
|
* synthetic ones so we can preserve hardlink information.
|
||||||
|
*
|
||||||
|
* TODO: Make this more efficient. It's not as bad as it looks (most
|
||||||
|
* files don't have any hardlinks and we don't do any work here for those),
|
||||||
|
* but it wouldn't be hard to do better.
|
||||||
|
*
|
||||||
|
* TODO: Work with dev/ino pairs here instead of just ino values.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
int64_t ino = archive_entry_ino64(entry);
|
||||||
|
int ino_new;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no index number was given, don't assign one. In
|
||||||
|
* particular, this handles the end-of-archive marker
|
||||||
|
* correctly by giving it a zero index value. (This is also
|
||||||
|
* why we start our synthetic index numbers with one below.)
|
||||||
|
*/
|
||||||
|
if (ino == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Don't store a mapping if we don't need to. */
|
||||||
|
if (archive_entry_nlink(entry) < 2) {
|
||||||
|
return (int)(++cpio->ino_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up old ino; if we have it, this is a hardlink
|
||||||
|
* and we reuse the same value. */
|
||||||
|
for (i = 0; i < cpio->ino_list_next; ++i) {
|
||||||
|
if (cpio->ino_list[i].old == ino)
|
||||||
|
return (cpio->ino_list[i].new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign a new index number. */
|
||||||
|
ino_new = (int)(++cpio->ino_next);
|
||||||
|
|
||||||
|
/* Ensure space for the new mapping. */
|
||||||
|
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
||||||
|
size_t newsize = cpio->ino_list_size < 512
|
||||||
|
? 512 : cpio->ino_list_size * 2;
|
||||||
|
void *newlist = realloc(cpio->ino_list,
|
||||||
|
sizeof(cpio->ino_list[0]) * newsize);
|
||||||
|
if (newlist == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
cpio->ino_list_size = newsize;
|
||||||
|
cpio->ino_list = newlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record and return the new value. */
|
||||||
|
cpio->ino_list[cpio->ino_list_next].old = ino;
|
||||||
|
cpio->ino_list[cpio->ino_list_next].new = ino_new;
|
||||||
|
++cpio->ino_list_next;
|
||||||
|
return (ino_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct archive_string_conv *
|
||||||
|
get_sconv(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
sconv = cpio->opt_sconv;
|
||||||
|
if (sconv == NULL) {
|
||||||
|
if (!cpio->init_default_conversion) {
|
||||||
|
cpio->sconv_default =
|
||||||
|
archive_string_default_conversion_for_write(
|
||||||
|
&(a->archive));
|
||||||
|
cpio->init_default_conversion = 1;
|
||||||
|
}
|
||||||
|
sconv = cpio->sconv_default;
|
||||||
|
}
|
||||||
|
return (sconv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
|
||||||
|
archive_set_error(&a->archive, -1, "Filetype required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
|
||||||
|
&& errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (len == 0 || path == NULL || path[0] == '\0') {
|
||||||
|
archive_set_error(&a->archive, -1, "Pathname required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
|
||||||
|
archive_set_error(&a->archive, -1, "Size required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
return write_header(a, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
const char *p, *path;
|
||||||
|
int pathlength, ret, ret_final;
|
||||||
|
int64_t ino;
|
||||||
|
struct cpio_binary_header h;
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
struct archive_entry *entry_main;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
ret_final = ARCHIVE_OK;
|
||||||
|
sconv = get_sconv(a);
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
/* Make sure the path separators in pathname, hardlink and symlink
|
||||||
|
* are all slash '/', not the Windows path separator '\'. */
|
||||||
|
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||||
|
if (entry_main == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate ustar data");
|
||||||
|
return(ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (entry != entry_main)
|
||||||
|
entry = entry_main;
|
||||||
|
else
|
||||||
|
entry_main = NULL;
|
||||||
|
#else
|
||||||
|
entry_main = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate pathname '%s' to %s",
|
||||||
|
archive_entry_pathname(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
/* Include trailing null */
|
||||||
|
pathlength = (int)len + 1;
|
||||||
|
|
||||||
|
h.h_magic = swap16(070707);
|
||||||
|
h.h_dev = swap16(archive_entry_dev(entry));
|
||||||
|
|
||||||
|
ino = synthesize_ino_value(cpio, entry);
|
||||||
|
if (ino < 0) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"No memory for ino translation table");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
} else if (ino > 077777) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"Too many files for this cpio format");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
h.h_ino = swap16(ino);
|
||||||
|
|
||||||
|
h.h_mode = archive_entry_mode(entry);
|
||||||
|
if (((h.h_mode & AE_IFMT) == AE_IFSOCK) || ((h.h_mode & AE_IFMT) == AE_IFIFO)) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"sockets and fifos cannot be represented in the binary cpio formats");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
|
||||||
|
if ((h.h_mode & AE_IFMT) == AE_IFLNK) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"symbolic links cannot be represented in the PWB cpio format");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
/* we could turn off AE_IFREG here, but it does no harm, */
|
||||||
|
/* and allows v7 cpio to read the entry without confusion */
|
||||||
|
}
|
||||||
|
h.h_mode = swap16(h.h_mode);
|
||||||
|
|
||||||
|
h.h_uid = swap16(archive_entry_uid(entry));
|
||||||
|
h.h_gid = swap16(archive_entry_gid(entry));
|
||||||
|
h.h_nlink = swap16(archive_entry_nlink(entry));
|
||||||
|
|
||||||
|
if (archive_entry_filetype(entry) == AE_IFBLK
|
||||||
|
|| archive_entry_filetype(entry) == AE_IFCHR)
|
||||||
|
h.h_majmin = swap16(archive_entry_rdev(entry));
|
||||||
|
else
|
||||||
|
h.h_majmin = 0;
|
||||||
|
|
||||||
|
h.h_mtime = swap32(archive_entry_mtime(entry));
|
||||||
|
h.h_namesize = swap16(pathlength);
|
||||||
|
|
||||||
|
/* Non-regular files don't store bodies. */
|
||||||
|
if (archive_entry_filetype(entry) != AE_IFREG)
|
||||||
|
archive_entry_set_size(entry, 0);
|
||||||
|
|
||||||
|
/* Symlinks get the link written as the body of the entry. */
|
||||||
|
ret = archive_entry_symlink_l(entry, &p, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Linkname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate linkname '%s' to %s",
|
||||||
|
archive_entry_symlink(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0 && p != NULL && *p != '\0') {
|
||||||
|
if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"symlinks are not supported by UNIX V6 or by PWB cpio");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
h.h_filesize = swap32(strlen(p)); /* symlink */
|
||||||
|
} else {
|
||||||
|
if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) &&
|
||||||
|
(archive_entry_size(entry) > 256*256*256-1)) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"File is too large for PWB binary cpio format.");
|
||||||
|
ret_final = ARCHIVE_FAILED;
|
||||||
|
goto exit_write_header;
|
||||||
|
} else if (archive_entry_size(entry) > INT32_MAX) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"File is too large for binary cpio format.");
|
||||||
|
ret_final = ARCHIVE_FAILED;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
h.h_filesize = swap32(archive_entry_size(entry)); /* file */
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, &h, HSIZE);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, path, pathlength);
|
||||||
|
if ((ret == ARCHIVE_OK) && ((pathlength % 2) != 0))
|
||||||
|
ret = __archive_write_nulls(a, 1);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpio->entry_bytes_remaining = archive_entry_size(entry);
|
||||||
|
if ((cpio->entry_bytes_remaining % 2) != 0)
|
||||||
|
cpio->entry_bytes_remaining++;
|
||||||
|
|
||||||
|
/* Write the symlink now. */
|
||||||
|
if (p != NULL && *p != '\0') {
|
||||||
|
ret = __archive_write_output(a, p, strlen(p));
|
||||||
|
if ((ret == ARCHIVE_OK) && ((strlen(p) % 2) != 0))
|
||||||
|
ret = __archive_write_nulls(a, 1);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_write_header:
|
||||||
|
archive_entry_free(entry_main);
|
||||||
|
return (ret_final);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
archive_write_binary_data(struct archive_write *a, const void *buff, size_t s)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
if (s > cpio->entry_bytes_remaining)
|
||||||
|
s = (size_t)cpio->entry_bytes_remaining;
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, buff, s);
|
||||||
|
cpio->entry_bytes_remaining -= s;
|
||||||
|
if (ret >= 0)
|
||||||
|
return (s);
|
||||||
|
else
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_close(struct archive_write *a)
|
||||||
|
{
|
||||||
|
int er;
|
||||||
|
struct archive_entry *trailer;
|
||||||
|
|
||||||
|
trailer = archive_entry_new2(NULL);
|
||||||
|
/* nlink = 1 here for GNU cpio compat. */
|
||||||
|
archive_entry_set_nlink(trailer, 1);
|
||||||
|
archive_entry_set_size(trailer, 0);
|
||||||
|
archive_entry_set_pathname(trailer, "TRAILER!!!");
|
||||||
|
er = write_header(a, trailer);
|
||||||
|
archive_entry_free(trailer);
|
||||||
|
return (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_free(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
free(cpio->ino_list);
|
||||||
|
free(cpio);
|
||||||
|
a->format_data = NULL;
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_finish_entry(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
return (__archive_write_nulls(a,
|
||||||
|
(size_t)cpio->entry_bytes_remaining));
|
||||||
|
}
|
@ -0,0 +1,500 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003-2007 Tim Kientzle
|
||||||
|
* Copyright (c) 2011-2012 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: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
|
||||||
|
|
||||||
|
#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"
|
||||||
|
#include "archive_entry_locale.h"
|
||||||
|
#include "archive_private.h"
|
||||||
|
#include "archive_write_private.h"
|
||||||
|
#include "archive_write_set_format_private.h"
|
||||||
|
|
||||||
|
static ssize_t archive_write_odc_data(struct archive_write *,
|
||||||
|
const void *buff, size_t s);
|
||||||
|
static int archive_write_odc_close(struct archive_write *);
|
||||||
|
static int archive_write_odc_free(struct archive_write *);
|
||||||
|
static int archive_write_odc_finish_entry(struct archive_write *);
|
||||||
|
static int archive_write_odc_header(struct archive_write *,
|
||||||
|
struct archive_entry *);
|
||||||
|
static int archive_write_odc_options(struct archive_write *,
|
||||||
|
const char *, const char *);
|
||||||
|
static int format_octal(int64_t, void *, int);
|
||||||
|
static int64_t format_octal_recursive(int64_t, char *, int);
|
||||||
|
static int write_header(struct archive_write *, struct archive_entry *);
|
||||||
|
|
||||||
|
struct cpio {
|
||||||
|
uint64_t entry_bytes_remaining;
|
||||||
|
|
||||||
|
int64_t ino_next;
|
||||||
|
|
||||||
|
struct { int64_t old; int new;} *ino_list;
|
||||||
|
size_t ino_list_size;
|
||||||
|
size_t ino_list_next;
|
||||||
|
|
||||||
|
struct archive_string_conv *opt_sconv;
|
||||||
|
struct archive_string_conv *sconv_default;
|
||||||
|
int init_default_conversion;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define c_magic_offset 0
|
||||||
|
#define c_magic_size 6
|
||||||
|
#define c_dev_offset 6
|
||||||
|
#define c_dev_size 6
|
||||||
|
#define c_ino_offset 12
|
||||||
|
#define c_ino_size 6
|
||||||
|
#define c_mode_offset 18
|
||||||
|
#define c_mode_size 6
|
||||||
|
#define c_uid_offset 24
|
||||||
|
#define c_uid_size 6
|
||||||
|
#define c_gid_offset 30
|
||||||
|
#define c_gid_size 6
|
||||||
|
#define c_nlink_offset 36
|
||||||
|
#define c_nlink_size 6
|
||||||
|
#define c_rdev_offset 42
|
||||||
|
#define c_rdev_size 6
|
||||||
|
#define c_mtime_offset 48
|
||||||
|
#define c_mtime_size 11
|
||||||
|
#define c_namesize_offset 59
|
||||||
|
#define c_namesize_size 6
|
||||||
|
#define c_filesize_offset 65
|
||||||
|
#define c_filesize_size 11
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to 'cpio' format.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
archive_write_set_format_cpio_odc(struct archive *_a)
|
||||||
|
{
|
||||||
|
struct archive_write *a = (struct archive_write *)_a;
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||||
|
ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_odc");
|
||||||
|
|
||||||
|
/* If someone else was already registered, unregister them. */
|
||||||
|
if (a->format_free != NULL)
|
||||||
|
(a->format_free)(a);
|
||||||
|
|
||||||
|
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
||||||
|
if (cpio == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
a->format_data = cpio;
|
||||||
|
a->format_name = "cpio";
|
||||||
|
a->format_options = archive_write_odc_options;
|
||||||
|
a->format_write_header = archive_write_odc_header;
|
||||||
|
a->format_write_data = archive_write_odc_data;
|
||||||
|
a->format_finish_entry = archive_write_odc_finish_entry;
|
||||||
|
a->format_close = archive_write_odc_close;
|
||||||
|
a->format_free = archive_write_odc_free;
|
||||||
|
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
|
||||||
|
a->archive.archive_format_name = "POSIX cpio";
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_options(struct archive_write *a, const char *key,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
struct cpio *cpio = (struct cpio *)a->format_data;
|
||||||
|
int ret = ARCHIVE_FAILED;
|
||||||
|
|
||||||
|
if (strcmp(key, "hdrcharset") == 0) {
|
||||||
|
if (val == NULL || val[0] == 0)
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||||
|
"%s: hdrcharset option needs a character-set name",
|
||||||
|
a->format_name);
|
||||||
|
else {
|
||||||
|
cpio->opt_sconv = archive_string_conversion_to_charset(
|
||||||
|
&a->archive, val, 0);
|
||||||
|
if (cpio->opt_sconv != NULL)
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
else
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: The "warn" return is just to inform the options
|
||||||
|
* supervisor that we didn't handle it. It will generate
|
||||||
|
* a suitable error if no one used this option. */
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ino values are as long as 64 bits on some systems; cpio format
|
||||||
|
* only allows 18 bits and relies on the ino values to identify hardlinked
|
||||||
|
* files. So, we can't merely "hash" the ino numbers since collisions
|
||||||
|
* would corrupt the archive. Instead, we generate synthetic ino values
|
||||||
|
* to store in the archive and maintain a map of original ino values to
|
||||||
|
* synthetic ones so we can preserve hardlink information.
|
||||||
|
*
|
||||||
|
* TODO: Make this more efficient. It's not as bad as it looks (most
|
||||||
|
* files don't have any hardlinks and we don't do any work here for those),
|
||||||
|
* but it wouldn't be hard to do better.
|
||||||
|
*
|
||||||
|
* TODO: Work with dev/ino pairs here instead of just ino values.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
int64_t ino = archive_entry_ino64(entry);
|
||||||
|
int ino_new;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no index number was given, don't assign one. In
|
||||||
|
* particular, this handles the end-of-archive marker
|
||||||
|
* correctly by giving it a zero index value. (This is also
|
||||||
|
* why we start our synthetic index numbers with one below.)
|
||||||
|
*/
|
||||||
|
if (ino == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Don't store a mapping if we don't need to. */
|
||||||
|
if (archive_entry_nlink(entry) < 2) {
|
||||||
|
return (int)(++cpio->ino_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up old ino; if we have it, this is a hardlink
|
||||||
|
* and we reuse the same value. */
|
||||||
|
for (i = 0; i < cpio->ino_list_next; ++i) {
|
||||||
|
if (cpio->ino_list[i].old == ino)
|
||||||
|
return (cpio->ino_list[i].new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign a new index number. */
|
||||||
|
ino_new = (int)(++cpio->ino_next);
|
||||||
|
|
||||||
|
/* Ensure space for the new mapping. */
|
||||||
|
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
||||||
|
size_t newsize = cpio->ino_list_size < 512
|
||||||
|
? 512 : cpio->ino_list_size * 2;
|
||||||
|
void *newlist = realloc(cpio->ino_list,
|
||||||
|
sizeof(cpio->ino_list[0]) * newsize);
|
||||||
|
if (newlist == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
cpio->ino_list_size = newsize;
|
||||||
|
cpio->ino_list = newlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record and return the new value. */
|
||||||
|
cpio->ino_list[cpio->ino_list_next].old = ino;
|
||||||
|
cpio->ino_list[cpio->ino_list_next].new = ino_new;
|
||||||
|
++cpio->ino_list_next;
|
||||||
|
return (ino_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct archive_string_conv *
|
||||||
|
get_sconv(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
sconv = cpio->opt_sconv;
|
||||||
|
if (sconv == NULL) {
|
||||||
|
if (!cpio->init_default_conversion) {
|
||||||
|
cpio->sconv_default =
|
||||||
|
archive_string_default_conversion_for_write(
|
||||||
|
&(a->archive));
|
||||||
|
cpio->init_default_conversion = 1;
|
||||||
|
}
|
||||||
|
sconv = cpio->sconv_default;
|
||||||
|
}
|
||||||
|
return (sconv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
|
||||||
|
archive_set_error(&a->archive, -1, "Filetype required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
|
||||||
|
&& errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (len == 0 || path == NULL || path[0] == '\0') {
|
||||||
|
archive_set_error(&a->archive, -1, "Pathname required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
|
||||||
|
archive_set_error(&a->archive, -1, "Size required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
return write_header(a, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
const char *p, *path;
|
||||||
|
int pathlength, ret, ret_final;
|
||||||
|
int64_t ino;
|
||||||
|
char h[76];
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
struct archive_entry *entry_main;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
ret_final = ARCHIVE_OK;
|
||||||
|
sconv = get_sconv(a);
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
/* Make sure the path separators in pathname, hardlink and symlink
|
||||||
|
* are all slash '/', not the Windows path separator '\'. */
|
||||||
|
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||||
|
if (entry_main == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate ustar data");
|
||||||
|
return(ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (entry != entry_main)
|
||||||
|
entry = entry_main;
|
||||||
|
else
|
||||||
|
entry_main = NULL;
|
||||||
|
#else
|
||||||
|
entry_main = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate pathname '%s' to %s",
|
||||||
|
archive_entry_pathname(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
/* Include trailing null. */
|
||||||
|
pathlength = (int)len + 1;
|
||||||
|
|
||||||
|
memset(h, 0, sizeof(h));
|
||||||
|
format_octal(070707, h + c_magic_offset, c_magic_size);
|
||||||
|
format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
|
||||||
|
|
||||||
|
ino = synthesize_ino_value(cpio, entry);
|
||||||
|
if (ino < 0) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"No memory for ino translation table");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
} else if (ino > 0777777) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"Too many files for this cpio format");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
|
||||||
|
|
||||||
|
/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
|
||||||
|
format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
|
||||||
|
format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
|
||||||
|
format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
|
||||||
|
format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
|
||||||
|
if (archive_entry_filetype(entry) == AE_IFBLK
|
||||||
|
|| archive_entry_filetype(entry) == AE_IFCHR)
|
||||||
|
format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
|
||||||
|
else
|
||||||
|
format_octal(0, h + c_rdev_offset, c_rdev_size);
|
||||||
|
format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
|
||||||
|
format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
|
||||||
|
|
||||||
|
/* Non-regular files don't store bodies. */
|
||||||
|
if (archive_entry_filetype(entry) != AE_IFREG)
|
||||||
|
archive_entry_set_size(entry, 0);
|
||||||
|
|
||||||
|
/* Symlinks get the link written as the body of the entry. */
|
||||||
|
ret = archive_entry_symlink_l(entry, &p, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Linkname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate linkname '%s' to %s",
|
||||||
|
archive_entry_symlink(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
if (len > 0 && p != NULL && *p != '\0')
|
||||||
|
ret = format_octal(strlen(p), h + c_filesize_offset,
|
||||||
|
c_filesize_size);
|
||||||
|
else
|
||||||
|
ret = format_octal(archive_entry_size(entry),
|
||||||
|
h + c_filesize_offset, c_filesize_size);
|
||||||
|
if (ret) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"File is too large for cpio format.");
|
||||||
|
ret_final = ARCHIVE_FAILED;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, h, sizeof(h));
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, path, pathlength);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpio->entry_bytes_remaining = archive_entry_size(entry);
|
||||||
|
|
||||||
|
/* Write the symlink now. */
|
||||||
|
if (p != NULL && *p != '\0') {
|
||||||
|
ret = __archive_write_output(a, p, strlen(p));
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit_write_header:
|
||||||
|
archive_entry_free(entry_main);
|
||||||
|
return (ret_final);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
archive_write_odc_data(struct archive_write *a, const void *buff, size_t s)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
if (s > cpio->entry_bytes_remaining)
|
||||||
|
s = (size_t)cpio->entry_bytes_remaining;
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, buff, s);
|
||||||
|
cpio->entry_bytes_remaining -= s;
|
||||||
|
if (ret >= 0)
|
||||||
|
return (s);
|
||||||
|
else
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a number into the specified field.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
format_octal(int64_t v, void *p, int digits)
|
||||||
|
{
|
||||||
|
int64_t max;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
max = (((int64_t)1) << (digits * 3)) - 1;
|
||||||
|
if (v >= 0 && v <= max) {
|
||||||
|
format_octal_recursive(v, (char *)p, digits);
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
format_octal_recursive(max, (char *)p, digits);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
format_octal_recursive(int64_t v, char *p, int s)
|
||||||
|
{
|
||||||
|
if (s == 0)
|
||||||
|
return (v);
|
||||||
|
v = format_octal_recursive(v, p+1, s-1);
|
||||||
|
*p = '0' + ((char)v & 7);
|
||||||
|
return (v >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_close(struct archive_write *a)
|
||||||
|
{
|
||||||
|
int er;
|
||||||
|
struct archive_entry *trailer;
|
||||||
|
|
||||||
|
trailer = archive_entry_new2(NULL);
|
||||||
|
/* nlink = 1 here for GNU cpio compat. */
|
||||||
|
archive_entry_set_nlink(trailer, 1);
|
||||||
|
archive_entry_set_size(trailer, 0);
|
||||||
|
archive_entry_set_pathname(trailer, "TRAILER!!!");
|
||||||
|
er = write_header(a, trailer);
|
||||||
|
archive_entry_free(trailer);
|
||||||
|
return (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_free(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
free(cpio->ino_list);
|
||||||
|
free(cpio);
|
||||||
|
a->format_data = NULL;
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_finish_entry(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
return (__archive_write_nulls(a,
|
||||||
|
(size_t)cpio->entry_bytes_remaining));
|
||||||
|
}
|
@ -279,7 +279,7 @@ Values between 0 and 9 are supported.
|
|||||||
The interpretation of the compression level depends on the chosen
|
The interpretation of the compression level depends on the chosen
|
||||||
compression method.
|
compression method.
|
||||||
.El
|
.El
|
||||||
.It Format cpio
|
.It Format bin
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
.It Cm hdrcharset
|
.It Cm hdrcharset
|
||||||
The value is used as a character set name that will be
|
The value is used as a character set name that will be
|
||||||
@ -519,6 +519,18 @@ XXX needs explanation XXX
|
|||||||
The value is used as a character set name that will be
|
The value is used as a character set name that will be
|
||||||
used when translating file names.
|
used when translating file names.
|
||||||
.El
|
.El
|
||||||
|
.It Format odc
|
||||||
|
.Bl -tag -compact -width indent
|
||||||
|
.It Cm hdrcharset
|
||||||
|
The value is used as a character set name that will be
|
||||||
|
used when translating file names.
|
||||||
|
.El
|
||||||
|
.It Format pwb
|
||||||
|
.Bl -tag -compact -width indent
|
||||||
|
.It Cm hdrcharset
|
||||||
|
The value is used as a character set name that will be
|
||||||
|
used when translating file names.
|
||||||
|
.El
|
||||||
.It Format pax
|
.It Format pax
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
.It Cm hdrcharset
|
.It Cm hdrcharset
|
||||||
|
@ -138,6 +138,7 @@
|
|||||||
#define HAVE_LIBZ 1
|
#define HAVE_LIBZ 1
|
||||||
#define HAVE_LIMITS_H 1
|
#define HAVE_LIMITS_H 1
|
||||||
#define HAVE_LINK 1
|
#define HAVE_LINK 1
|
||||||
|
#define HAVE_LINKAT 1
|
||||||
#define HAVE_LOCALE_H 1
|
#define HAVE_LOCALE_H 1
|
||||||
#define HAVE_LOCALTIME_R 1
|
#define HAVE_LOCALTIME_R 1
|
||||||
#define HAVE_LONG_LONG_INT 1
|
#define HAVE_LONG_LONG_INT 1
|
||||||
|
@ -56,40 +56,44 @@ The end of the archive is indicated by a special record with
|
|||||||
the pathname
|
the pathname
|
||||||
.Dq TRAILER!!! .
|
.Dq TRAILER!!! .
|
||||||
.Ss PWB format
|
.Ss PWB format
|
||||||
XXX Any documentation of the original PWB/UNIX 1.0 format? XXX
|
The PWB binary
|
||||||
.Ss Old Binary Format
|
|
||||||
The old binary
|
|
||||||
.Nm
|
.Nm
|
||||||
format stores numbers as 2-byte and 4-byte binary values.
|
format is the original format, when cpio was introduced as part of the
|
||||||
|
Programmer's Work Bench system, a variant of 6th Edition UNIX. It
|
||||||
|
stores numbers as 2-byte and 4-byte binary values.
|
||||||
Each entry begins with a header in the following format:
|
Each entry begins with a header in the following format:
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct header_old_cpio {
|
struct header_pwb_cpio {
|
||||||
unsigned short c_magic;
|
short h_magic;
|
||||||
unsigned short c_dev;
|
short h_dev;
|
||||||
unsigned short c_ino;
|
short h_ino;
|
||||||
unsigned short c_mode;
|
short h_mode;
|
||||||
unsigned short c_uid;
|
short h_uid;
|
||||||
unsigned short c_gid;
|
short h_gid;
|
||||||
unsigned short c_nlink;
|
short h_nlink;
|
||||||
unsigned short c_rdev;
|
short h_majmin;
|
||||||
unsigned short c_mtime[2];
|
long h_mtime;
|
||||||
unsigned short c_namesize;
|
short h_namesize;
|
||||||
unsigned short c_filesize[2];
|
long h_filesize;
|
||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Va unsigned short
|
.Va short
|
||||||
fields here are 16-bit integer values; the
|
fields here are 16-bit integer values, while the
|
||||||
.Va unsigned int
|
.Va long
|
||||||
fields are 32-bit integer values.
|
fields are 32 bit integers. Since PWB UNIX, like the 6th Edition UNIX
|
||||||
The fields are as follows
|
it was based on, only ran on PDP-11 computers, they
|
||||||
|
are in PDP-endian format, which has little-endian shorts, and
|
||||||
|
big-endian longs. That is, the long integer whose hexadecimal
|
||||||
|
representation is 0x12345678 would be stored in four successive bytes
|
||||||
|
as 0x34, 0x12, 0x78, 0x56.
|
||||||
|
The fields are as follows:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Va magic
|
.It Va h_magic
|
||||||
The integer value octal 070707.
|
The integer value octal 070707.
|
||||||
This value can be used to determine whether this archive is
|
.It Va h_dev , Va h_ino
|
||||||
written with little-endian or big-endian integers.
|
|
||||||
.It Va dev , Va ino
|
|
||||||
The device and inode numbers from the disk.
|
The device and inode numbers from the disk.
|
||||||
These are used by programs that read
|
These are used by programs that read
|
||||||
.Nm
|
.Nm
|
||||||
@ -97,9 +101,94 @@ archives to determine when two entries refer to the same file.
|
|||||||
Programs that synthesize
|
Programs that synthesize
|
||||||
.Nm
|
.Nm
|
||||||
archives should be careful to set these to distinct values for each entry.
|
archives should be careful to set these to distinct values for each entry.
|
||||||
.It Va mode
|
.It Va h_mode
|
||||||
The mode specifies both the regular permissions and the file type.
|
The mode specifies both the regular permissions and the file type, and
|
||||||
It consists of several bit fields as follows:
|
it also holds a couple of bits that are irrelevant to the cpio format,
|
||||||
|
because the field is actually a raw copy of the mode field in the inode
|
||||||
|
representing the file. These are the IALLOC flag, which shows that
|
||||||
|
the inode entry is in use, and the ILARG flag, which shows that the
|
||||||
|
file it represents is large enough to have indirect blocks pointers in
|
||||||
|
the inode.
|
||||||
|
The mode is decoded as follows:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width "MMMMMMM" -compact
|
||||||
|
.It 0100000
|
||||||
|
IALLOC flag - irrelevant to cpio.
|
||||||
|
.It 0060000
|
||||||
|
This masks the file type bits.
|
||||||
|
.It 0040000
|
||||||
|
File type value for directories.
|
||||||
|
.It 0020000
|
||||||
|
File type value for character special devices.
|
||||||
|
.It 0060000
|
||||||
|
File type value for block special devices.
|
||||||
|
.It 0010000
|
||||||
|
ILARG flag - irrelevant to cpio.
|
||||||
|
.It 0004000
|
||||||
|
SUID bit.
|
||||||
|
.It 0002000
|
||||||
|
SGID bit.
|
||||||
|
.It 0001000
|
||||||
|
Sticky bit.
|
||||||
|
.It 0000777
|
||||||
|
The lower 9 bits specify read/write/execute permissions
|
||||||
|
for world, group, and user following standard POSIX conventions.
|
||||||
|
.El
|
||||||
|
.It Va h_uid , Va h_gid
|
||||||
|
The numeric user id and group id of the owner.
|
||||||
|
.It Va h_nlink
|
||||||
|
The number of links to this file.
|
||||||
|
Directories always have a value of at least two here.
|
||||||
|
Note that hardlinked files include file data with every copy in the archive.
|
||||||
|
.It Va h_majmin
|
||||||
|
For block special and character special entries,
|
||||||
|
this field contains the associated device number, with the major
|
||||||
|
number in the high byte, and the minor number in the low byte.
|
||||||
|
For all other entry types, it should be set to zero by writers
|
||||||
|
and ignored by readers.
|
||||||
|
.It Va h_mtime
|
||||||
|
Modification time of the file, indicated as the number
|
||||||
|
of seconds since the start of the epoch,
|
||||||
|
00:00:00 UTC January 1, 1970.
|
||||||
|
.It Va h_namesize
|
||||||
|
The number of bytes in the pathname that follows the header.
|
||||||
|
This count includes the trailing NUL byte.
|
||||||
|
.It Va h_filesize
|
||||||
|
The size of the file. Note that this archive format is limited to 16
|
||||||
|
megabyte file sizes, because PWB UNIX, like 6th Edition, only used
|
||||||
|
an unsigned 24 bit integer for the file size internally.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The pathname immediately follows the fixed header.
|
||||||
|
If
|
||||||
|
.Cm h_namesize
|
||||||
|
is odd, an additional NUL byte is added after the pathname.
|
||||||
|
The file data is then appended, again with an additional NUL
|
||||||
|
appended if needed to get the next header at an even offset.
|
||||||
|
.Pp
|
||||||
|
Hardlinked files are not given special treatment;
|
||||||
|
the full file contents are included with each copy of the
|
||||||
|
file.
|
||||||
|
.Ss New Binary Format
|
||||||
|
The new binary
|
||||||
|
.Nm
|
||||||
|
format showed up when cpio was adopted into late 7th Edition UNIX.
|
||||||
|
It is exactly like the PWB binary format, described above, except for
|
||||||
|
three changes:
|
||||||
|
.Pp
|
||||||
|
First, UNIX now ran on more than one hardware type, so the endianness
|
||||||
|
of 16 bit integers must be determined by observing the magic number at
|
||||||
|
the start of the header. The 32 bit integers are still always stored
|
||||||
|
with the most significant word first, though, so each of those two, in
|
||||||
|
the struct shown above, was stored as an array of two 16 bit integers,
|
||||||
|
in the traditional order. Those 16 bit integers, like all the others
|
||||||
|
in the struct, were accessed using a macro that byte swapped them if
|
||||||
|
necessary.
|
||||||
|
.Pp
|
||||||
|
Next, 7th Edition had more file types to store, and the IALLOC and ILARG
|
||||||
|
flag bits were re-purposed to accommodate these. The revised use of the
|
||||||
|
various bits is as follows:
|
||||||
|
.Pp
|
||||||
.Bl -tag -width "MMMMMMM" -compact
|
.Bl -tag -width "MMMMMMM" -compact
|
||||||
.It 0170000
|
.It 0170000
|
||||||
This masks the file type bits.
|
This masks the file type bits.
|
||||||
@ -124,51 +213,26 @@ SUID bit.
|
|||||||
SGID bit.
|
SGID bit.
|
||||||
.It 0001000
|
.It 0001000
|
||||||
Sticky bit.
|
Sticky bit.
|
||||||
On some systems, this modifies the behavior of executables and/or directories.
|
|
||||||
.It 0000777
|
.It 0000777
|
||||||
The lower 9 bits specify read/write/execute permissions
|
The lower 9 bits specify read/write/execute permissions
|
||||||
for world, group, and user following standard POSIX conventions.
|
for world, group, and user following standard POSIX conventions.
|
||||||
.El
|
.El
|
||||||
.It Va uid , Va gid
|
|
||||||
The numeric user id and group id of the owner.
|
|
||||||
.It Va nlink
|
|
||||||
The number of links to this file.
|
|
||||||
Directories always have a value of at least two here.
|
|
||||||
Note that hardlinked files include file data with every copy in the archive.
|
|
||||||
.It Va rdev
|
|
||||||
For block special and character special entries,
|
|
||||||
this field contains the associated device number.
|
|
||||||
For all other entry types, it should be set to zero by writers
|
|
||||||
and ignored by readers.
|
|
||||||
.It Va mtime
|
|
||||||
Modification time of the file, indicated as the number
|
|
||||||
of seconds since the start of the epoch,
|
|
||||||
00:00:00 UTC January 1, 1970.
|
|
||||||
The four-byte integer is stored with the most-significant 16 bits first
|
|
||||||
followed by the least-significant 16 bits.
|
|
||||||
Each of the two 16 bit values are stored in machine-native byte order.
|
|
||||||
.It Va namesize
|
|
||||||
The number of bytes in the pathname that follows the header.
|
|
||||||
This count includes the trailing NUL byte.
|
|
||||||
.It Va filesize
|
|
||||||
The size of the file.
|
|
||||||
Note that this archive format is limited to
|
|
||||||
four gigabyte file sizes.
|
|
||||||
See
|
|
||||||
.Va mtime
|
|
||||||
above for a description of the storage of four-byte integers.
|
|
||||||
.El
|
|
||||||
.Pp
|
.Pp
|
||||||
The pathname immediately follows the fixed header.
|
Finally, the file size field now represents a signed 32 bit integer in
|
||||||
If the
|
the underlying file system, so the maximum file size has increased to
|
||||||
.Cm namesize
|
2 gigabytes.
|
||||||
is odd, an additional NUL byte is added after the pathname.
|
|
||||||
The file data is then appended, padded with NUL
|
|
||||||
bytes to an even length.
|
|
||||||
.Pp
|
.Pp
|
||||||
Hardlinked files are not given special treatment;
|
Note that there is no obvious way to tell which of the two binary
|
||||||
the full file contents are included with each copy of the
|
formats an archive uses, other than to see which one makes more
|
||||||
file.
|
sense. The typical error scenario is that a PWB format archive
|
||||||
|
unpacked as if it were in the new format will create named sockets
|
||||||
|
instead of directories, and then fail to unpack files that should
|
||||||
|
go in those directories. Running
|
||||||
|
.Va bsdcpio -itv
|
||||||
|
on an unknown archive will make it obvious which it is: if it's
|
||||||
|
PWB format, directories will be listed with an 's' instead of
|
||||||
|
a 'd' as the first character of the mode string, and the larger
|
||||||
|
files will have a '?' in that position.
|
||||||
.Ss Portable ASCII Format
|
.Ss Portable ASCII Format
|
||||||
.St -susv2
|
.St -susv2
|
||||||
standardized an ASCII variant that is portable across all
|
standardized an ASCII variant that is portable across all
|
||||||
@ -180,6 +244,7 @@ format or as the
|
|||||||
format.
|
format.
|
||||||
It stores the same numeric fields as the old binary format, but
|
It stores the same numeric fields as the old binary format, but
|
||||||
represents them as 6-character or 11-character octal values.
|
represents them as 6-character or 11-character octal values.
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct cpio_odc_header {
|
struct cpio_odc_header {
|
||||||
char c_magic[6];
|
char c_magic[6];
|
||||||
@ -196,9 +261,9 @@ struct cpio_odc_header {
|
|||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The fields are identical to those in the old binary format.
|
The fields are identical to those in the new binary format.
|
||||||
The name and file body follow the fixed header.
|
The name and file body follow the fixed header.
|
||||||
Unlike the old binary format, there is no additional padding
|
Unlike the binary formats, there is no additional padding
|
||||||
after the pathname or file contents.
|
after the pathname or file contents.
|
||||||
If the files being archived are themselves entirely ASCII, then
|
If the files being archived are themselves entirely ASCII, then
|
||||||
the resulting archive will be entirely ASCII, except for the
|
the resulting archive will be entirely ASCII, except for the
|
||||||
@ -207,6 +272,7 @@ NUL byte that terminates the name field.
|
|||||||
The "new" ASCII format uses 8-byte hexadecimal fields for
|
The "new" ASCII format uses 8-byte hexadecimal fields for
|
||||||
all numbers and separates device numbers into separate fields
|
all numbers and separates device numbers into separate fields
|
||||||
for major and minor numbers.
|
for major and minor numbers.
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct cpio_newc_header {
|
struct cpio_newc_header {
|
||||||
char c_magic[6];
|
char c_magic[6];
|
||||||
@ -227,7 +293,7 @@ struct cpio_newc_header {
|
|||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Except as specified below, the fields here match those specified
|
Except as specified below, the fields here match those specified
|
||||||
for the old binary format above.
|
for the new binary format above.
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Va magic
|
.It Va magic
|
||||||
The string
|
The string
|
||||||
@ -288,9 +354,9 @@ while working in AT&T's Unix Support Group.
|
|||||||
It appeared in 1977 as part of PWB/UNIX 1.0, the
|
It appeared in 1977 as part of PWB/UNIX 1.0, the
|
||||||
.Dq Programmer's Work Bench
|
.Dq Programmer's Work Bench
|
||||||
derived from
|
derived from
|
||||||
.At v6
|
.At 6th Edition UNIX
|
||||||
that was used internally at AT&T.
|
that was used internally at AT&T.
|
||||||
Both the old binary and old character formats were in use
|
Both the new binary and old character formats were in use
|
||||||
by 1980, according to the System III source released
|
by 1980, according to the System III source released
|
||||||
by SCO under their
|
by SCO under their
|
||||||
.Dq Ancient Unix
|
.Dq Ancient Unix
|
||||||
@ -304,9 +370,9 @@ The
|
|||||||
format is mis-named, as it uses a simple checksum and
|
format is mis-named, as it uses a simple checksum and
|
||||||
not a cyclic redundancy check.
|
not a cyclic redundancy check.
|
||||||
.Pp
|
.Pp
|
||||||
The old binary format is limited to 16 bits for user id,
|
The binary formats are limited to 16 bits for user id, group id,
|
||||||
group id, device, and inode numbers.
|
device, and inode numbers. They are limited to 16 megabyte and 2
|
||||||
It is limited to 4 gigabyte file sizes.
|
gigabyte file sizes for the older and newer variants, respectively.
|
||||||
.Pp
|
.Pp
|
||||||
The old ASCII format is limited to 18 bits for
|
The old ASCII format is limited to 18 bits for
|
||||||
the user id, group id, device, and inode numbers.
|
the user id, group id, device, and inode numbers.
|
||||||
|
@ -201,28 +201,27 @@ POSIX.1-2001 extended the ustar format to create the
|
|||||||
.Dq pax interchange
|
.Dq pax interchange
|
||||||
format.
|
format.
|
||||||
.Ss Cpio Formats
|
.Ss Cpio Formats
|
||||||
The libarchive library can read a number of common cpio variants and can write
|
The libarchive library can read and write a number of common cpio
|
||||||
.Dq odc
|
variants. A cpio archive stores each entry as a fixed-size header
|
||||||
and
|
followed by a variable-length filename and variable-length data.
|
||||||
.Dq newc
|
Unlike the tar format, the cpio format does only minimal padding of
|
||||||
format archives.
|
the header or file data. There are several cpio variants, which
|
||||||
A cpio archive stores each entry as a fixed-size header followed
|
differ primarily in how they store the initial header: some store the
|
||||||
by a variable-length filename and variable-length data.
|
values as octal or hexadecimal numbers in ASCII, others as binary
|
||||||
Unlike the tar format, the cpio format does only minimal padding
|
values of varying byte order and length.
|
||||||
of the header or file data.
|
|
||||||
There are several cpio variants, which differ primarily in
|
|
||||||
how they store the initial header: some store the values as
|
|
||||||
octal or hexadecimal numbers in ASCII, others as binary values of
|
|
||||||
varying byte order and length.
|
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Cm binary
|
.It Cm binary
|
||||||
The libarchive library transparently reads both big-endian and little-endian
|
The libarchive library transparently reads both big-endian and
|
||||||
variants of the original binary cpio format.
|
little-endian variants of the the two binary cpio formats; the
|
||||||
This format used 32-bit binary values for file size and mtime,
|
original one from PWB/UNIX, and the later, more widely used, variant.
|
||||||
and 16-bit binary values for the other fields.
|
This format used 32-bit binary values for file size and mtime, and
|
||||||
|
16-bit binary values for the other fields. The formats support only
|
||||||
|
the file types present in UNIX at the time of their creation. File
|
||||||
|
sizes are limited to 24 bits in the PWB format, because of the limits
|
||||||
|
of the file system, and to 31 bits in the newer binary format, where
|
||||||
|
signed 32 bit longs were used.
|
||||||
.It Cm odc
|
.It Cm odc
|
||||||
The libarchive library can both read and write this
|
This is the POSIX standardized format, which is officially known as the
|
||||||
POSIX-standard format, which is officially known as the
|
|
||||||
.Dq cpio interchange format
|
.Dq cpio interchange format
|
||||||
or the
|
or the
|
||||||
.Dq octet-oriented cpio archive format
|
.Dq octet-oriented cpio archive format
|
||||||
|
@ -105,7 +105,7 @@ POSIX
|
|||||||
.Dq pax interchange format
|
.Dq pax interchange format
|
||||||
archives,
|
archives,
|
||||||
.It
|
.It
|
||||||
POSIX octet-oriented cpio archives,
|
cpio archives,
|
||||||
.It
|
.It
|
||||||
Zip archive,
|
Zip archive,
|
||||||
.It
|
.It
|
||||||
|
@ -150,7 +150,11 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
|
|||||||
#if GCC_VERSION >= 409
|
#if GCC_VERSION >= 409
|
||||||
__attribute__((__no_sanitize_undefined__))
|
__attribute__((__no_sanitize_undefined__))
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
static __inline U32 A32(const void * x)
|
||||||
|
#else
|
||||||
static inline U32 A32(const void* x)
|
static inline U32 A32(const void* x)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return (((const U32_S *)(x))->v);
|
return (((const U32_S *)(x))->v);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user