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.
|
||||
|
||||
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
|
||||
as a build target much like a target defined by the
|
||||
: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,
|
||||
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`
|
||||
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
|
||||
an include directory so that the ``mysqrt.h`` header file can be found. The
|
||||
last few lines of the top-level ``CMakeLists.txt`` file should now look like:
|
||||
an include directory so that the ``MathFunctions.h`` header file can be found.
|
||||
The last few lines of the top-level ``CMakeLists.txt`` file should now look
|
||||
like:
|
||||
|
||||
.. code-block:: cmake
|
||||
:caption: CMakeLists.txt
|
||||
|
@ -11,8 +11,9 @@ work together in an example project can be very helpful.
|
||||
Steps
|
||||
=====
|
||||
|
||||
The tutorial documentation and source code for examples can be found in
|
||||
the ``Help/guide/tutorial`` directory of the CMake source code tree.
|
||||
.. include:: source.txt
|
||||
|
||||
|tutorial_source|
|
||||
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.
|
||||
|
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>
|
||||
|
||||
.. versionadded:: 3.21
|
||||
|
||||
where ``compiler_ids`` is a comma-separated list.
|
||||
``1`` if the CMake's compiler id of the HIP compiler matches any one
|
||||
of the entries in ``compiler_ids``, otherwise ``0``.
|
||||
@ -249,6 +251,8 @@ Variable Queries
|
||||
|
||||
.. genex:: $<HIP_COMPILER_VERSION:version>
|
||||
|
||||
.. versionadded:: 3.21
|
||||
|
||||
``1`` if the version of the HIP compiler matches ``version``, otherwise ``0``.
|
||||
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
|
||||
|
||||
@ -714,6 +718,8 @@ Variable Queries
|
||||
|
||||
.. genex:: $<HIP_COMPILER_ID>
|
||||
|
||||
.. versionadded:: 3.21
|
||||
|
||||
The CMake's compiler id of the HIP compiler used.
|
||||
See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
|
||||
|
||||
@ -760,6 +766,8 @@ Variable Queries
|
||||
|
||||
.. genex:: $<HIP_COMPILER_VERSION>
|
||||
|
||||
.. versionadded:: 3.21
|
||||
|
||||
The version of the HIP compiler used.
|
||||
See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
|
||||
|
||||
@ -1057,10 +1065,10 @@ which is just the string ``tgt``.
|
||||
.. versionadded:: 3.21
|
||||
|
||||
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
|
||||
transitive dependencies. Using this generator expression on targets other
|
||||
than executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error.
|
||||
On non-DLL platforms, it evaluates to an empty string.
|
||||
the locations of all the ``SHARED`` targets in the target's transitive
|
||||
dependencies. Using this generator expression on targets other than
|
||||
executables, ``SHARED`` libraries, and ``MODULE`` libraries is an error. On
|
||||
non-DLL platforms, it evaluates to an empty string.
|
||||
|
||||
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
|
||||
@ -1080,9 +1088,9 @@ which is just the string ``tgt``.
|
||||
.. note::
|
||||
|
||||
:ref:`Imported Targets` are supported only if they know the location
|
||||
of their ``.dll`` files. An imported ``SHARED`` or ``MODULE`` library
|
||||
must have :prop_tgt:`IMPORTED_LOCATION` set to its ``.dll`` file. See
|
||||
the :ref:`add_library imported libraries <add_library imported libraries>`
|
||||
of their ``.dll`` files. An imported ``SHARED`` library must have
|
||||
:prop_tgt:`IMPORTED_LOCATION` set to its ``.dll`` file. See the
|
||||
:ref:`add_library imported libraries <add_library imported libraries>`
|
||||
section for details. Many :ref:`Find Modules` produce imported targets
|
||||
with the ``UNKNOWN`` type and therefore will be ignored.
|
||||
|
||||
|
@ -185,6 +185,13 @@ CPack
|
||||
:variable:`CPACK_PRODUCTBUILD_IDENTIFIER`, used to customize the unique
|
||||
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
|
||||
:variable:`CPACK_IFW_ARCHIVE_FORMAT` and
|
||||
: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 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
|
||||
=============
|
||||
|
||||
@ -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
|
||||
properties added in CMake 3.23.0 are now read-only records of the header
|
||||
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 "optimization flag .* not supported" # Clang
|
||||
FAIL_REGEX "unknown argument ignored" # Clang (cl)
|
||||
FAIL_REGEX "warning: .* ignored" # Clang (linker)
|
||||
FAIL_REGEX "ignoring unknown option" # MSVC, Intel
|
||||
FAIL_REGEX "warning D9002" # MSVC, any lang
|
||||
FAIL_REGEX "option.*not supported" # Intel
|
||||
|
@ -177,9 +177,9 @@ macro.
|
||||
packages with no binaries.
|
||||
|
||||
.. versionadded:: 3.19
|
||||
``COMPATIBILITY_MODE`` ``AnyNewerVersion``, ``SameMajorVersion`` and
|
||||
``SameMinorVersion`` handle the version range if any is specified
|
||||
(see :command:`find_package` command for the details).
|
||||
The version file generated by ``AnyNewerVersion``, ``SameMajorVersion`` and
|
||||
``SameMinorVersion`` arguments of ``COMPATIBILITY`` handle the version range
|
||||
if any is specified (see :command:`find_package` command for the details).
|
||||
``ExactVersion`` mode is incompatible with version ranges and will display an
|
||||
author warning if one is specified.
|
||||
|
||||
|
@ -1380,7 +1380,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
|
||||
set(_Boost_TIMER_DEPENDENCIES chrono)
|
||||
set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic)
|
||||
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")
|
||||
endif()
|
||||
endif()
|
||||
@ -1653,6 +1653,7 @@ else()
|
||||
# _Boost_COMPONENT_HEADERS. See the instructions at the top of
|
||||
# _Boost_COMPONENT_DEPENDENCIES.
|
||||
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.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"
|
||||
|
@ -145,46 +145,41 @@ endif()
|
||||
|
||||
if (WIN32)
|
||||
set (_JNI_HINTS)
|
||||
execute_process(COMMAND REG QUERY HKLM\\SOFTWARE\\JavaSoft\\JDK
|
||||
RESULT_VARIABLE _JNI_RESULT
|
||||
OUTPUT_VARIABLE _JNI_VERSIONS
|
||||
ERROR_QUIET)
|
||||
if (NOT _JNI_RESULT)
|
||||
string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}")
|
||||
if (_JNI_VERSIONS)
|
||||
# sort versions. Most recent first
|
||||
## handle version 9 apart from other versions to get correct ordering
|
||||
set (_JNI_V9 ${_JNI_VERSIONS})
|
||||
list (FILTER _JNI_VERSIONS EXCLUDE REGEX "JDK\\\\9")
|
||||
list (SORT _JNI_VERSIONS)
|
||||
list (REVERSE _JNI_VERSIONS)
|
||||
list (FILTER _JNI_V9 INCLUDE REGEX "JDK\\\\9")
|
||||
list (SORT _JNI_V9)
|
||||
list (REVERSE _JNI_V9)
|
||||
list (APPEND _JNI_VERSIONS ${_JNI_V9})
|
||||
foreach (_JNI_HINT IN LISTS _JNI_VERSIONS)
|
||||
list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]")
|
||||
endforeach()
|
||||
macro (_JNI_GET_INSTALLED_VERSIONS _KIND)
|
||||
execute_process(COMMAND REG QUERY "HKLM\\SOFTWARE\\JavaSoft\\${_KIND}"
|
||||
RESULT_VARIABLE _JAVA_RESULT
|
||||
OUTPUT_VARIABLE _JAVA_VERSIONS
|
||||
ERROR_QUIET)
|
||||
if (NOT _JAVA_RESULT)
|
||||
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)
|
||||
# sort versions. Most recent first
|
||||
list (SORT _JNI_VERSIONS COMPARE NATURAL ORDER DESCENDING)
|
||||
foreach (_JNI_VERSION IN LISTS _JNI_VERSIONS)
|
||||
string(REPLACE "_" "." _JNI_CMAKE_VERSION "${_JNI_VERSION}")
|
||||
if (JNI_FIND_VERSION_EXACT
|
||||
AND NOT _JNI_CMAKE_VERSION MATCHES "^${JNI_FIND_VERSION}")
|
||||
continue()
|
||||
endif()
|
||||
if (DEFINED JNI_FIND_VERSION AND _JNI_CMAKE_VERSION VERSION_LESS JNI_FIND_VERSION)
|
||||
break()
|
||||
endif()
|
||||
list(APPEND _JNI_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JNI_VERSION};JavaHome]")
|
||||
endforeach()
|
||||
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)
|
||||
list(APPEND JAVA_AWT_LIBRARY_DIRECTORIES "${_JNI_HINT}/lib")
|
||||
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()
|
||||
|
||||
set(_JNI_JAVA_DIRECTORIES_BASE
|
||||
@ -268,16 +263,6 @@ if (WIN32)
|
||||
foreach (_JNI_HINT IN LISTS _JNI_HINTS)
|
||||
list(APPEND JAVA_AWT_INCLUDE_DIRECTORIES "${_JNI_HINT}/include")
|
||||
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()
|
||||
|
||||
JAVA_APPEND_LIBRARY_DIRECTORIES(JAVA_AWT_INCLUDE_DIRECTORIES
|
||||
|
@ -90,50 +90,35 @@ if(_JAVA_HOME)
|
||||
endif()
|
||||
if (WIN32)
|
||||
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
|
||||
OUTPUT_VARIABLE _JAVA_VERSIONS
|
||||
ERROR_QUIET)
|
||||
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)
|
||||
# sort versions. Most recent first
|
||||
## handle version 9 apart from other versions to get correct ordering
|
||||
set (_JAVA_V9 ${_JAVA_VERSIONS})
|
||||
list (FILTER _JAVA_VERSIONS EXCLUDE REGEX "${_KIND}\\\\9")
|
||||
list (SORT _JAVA_VERSIONS)
|
||||
list (REVERSE _JAVA_VERSIONS)
|
||||
list (FILTER _JAVA_V9 INCLUDE REGEX "${_KIND}\\\\9")
|
||||
list (SORT _JAVA_V9)
|
||||
list (REVERSE _JAVA_V9)
|
||||
list (APPEND _JAVA_VERSIONS ${_JAVA_V9})
|
||||
foreach (_JAVA_HINT IN LISTS _JAVA_VERSIONS)
|
||||
list(APPEND _JAVA_HINTS "[${_JAVA_HINT};JavaHome]/bin")
|
||||
list (SORT _JAVA_VERSIONS COMPARE NATURAL ORDER DESCENDING)
|
||||
foreach (_JAVA_VERSION IN LISTS _JAVA_VERSIONS)
|
||||
string(REPLACE "_" "." _JAVA_CMAKE_VERSION "${_JAVA_VERSION}")
|
||||
if (Java_FIND_VERSION_EXACT
|
||||
AND NOT _JAVA_CMAKE_VERSION MATCHES "^${Java_FIND_VERSION}")
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND _JAVA_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\${_KIND}\\${_JAVA_VERSION};JavaHome]/bin")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# search for installed versions for version 9 and upper
|
||||
# for version 9 and upper
|
||||
_JAVA_GET_INSTALLED_VERSIONS("JDK")
|
||||
_JAVA_GET_INSTALLED_VERSIONS("JRE")
|
||||
|
||||
list(APPEND _JAVA_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.9;JavaHome]/bin"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\1.8;JavaHome]/bin"
|
||||
"[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"
|
||||
)
|
||||
# for versions older than 9
|
||||
_JAVA_GET_INSTALLED_VERSIONS("Java Development Kit")
|
||||
_JAVA_GET_INSTALLED_VERSIONS("Java Runtime Environment")
|
||||
endif()
|
||||
|
||||
# Hard-coded guesses should still go in PATHS. This ensures that the user
|
||||
@ -336,13 +321,13 @@ else()
|
||||
find_package_handle_standard_args(Java
|
||||
REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
|
||||
Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
|
||||
VERSION_VAR Java_VERSION_STRING
|
||||
VERSION_VAR Java_VERSION
|
||||
)
|
||||
else()
|
||||
find_package_handle_standard_args(Java
|
||||
REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
|
||||
Java_JAVADOC_EXECUTABLE
|
||||
VERSION_VAR Java_VERSION_STRING
|
||||
VERSION_VAR Java_VERSION
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -429,7 +429,7 @@ macro(_pkg_set_path_internal)
|
||||
else()
|
||||
unset(_pkgconfig_allow_system_libs_old)
|
||||
endif()
|
||||
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 0)
|
||||
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 1)
|
||||
endmacro()
|
||||
|
||||
macro(_pkg_restore_path_internal)
|
||||
@ -440,6 +440,8 @@ macro(_pkg_restore_path_internal)
|
||||
if(DEFINED _pkgconfig_allow_system_libs_old)
|
||||
set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} "${_pkgconfig_allow_system_libs_old}")
|
||||
unset(_pkgconfig_allow_system_libs_old)
|
||||
else()
|
||||
unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS})
|
||||
endif()
|
||||
|
||||
unset(_extra_paths)
|
||||
|
@ -22,7 +22,7 @@ if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
|
||||
message (FATAL_ERROR "FindPython: INTERNAL ERROR")
|
||||
endif()
|
||||
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")
|
||||
set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
|
||||
else()
|
||||
@ -415,7 +415,6 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
|
||||
if (_PGN_WIN32)
|
||||
foreach (version IN LISTS _PGN_VERSION)
|
||||
string (REPLACE "." "" version_no_dots ${version})
|
||||
|
||||
set (name "python${version_no_dots}")
|
||||
if (_PGN_DEBUG)
|
||||
string (APPEND name "_d")
|
||||
@ -423,6 +422,13 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
|
||||
list (APPEND names "${name}")
|
||||
endforeach()
|
||||
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})
|
||||
endif()
|
||||
endif()
|
||||
@ -588,6 +594,11 @@ function (_PYTHON_GET_VERSION)
|
||||
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 "${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")
|
||||
set (version "${CMAKE_MATCH_1}")
|
||||
# try to pick-up a more precise version from the path
|
||||
@ -663,7 +674,7 @@ endfunction()
|
||||
function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME)
|
||||
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)
|
||||
OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER))
|
||||
|
@ -54,7 +54,7 @@ unset(_Python_NAMES)
|
||||
|
||||
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(_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_COUNT GREATER 1)
|
||||
|
@ -79,7 +79,7 @@ set(CMAKE_FIND_FRAMEWORK LAST)
|
||||
|
||||
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(_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_COUNT GREATER 1)
|
||||
|
@ -112,6 +112,9 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND
|
||||
CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
|
||||
target_compile_options(FortranCInterface PRIVATE "-fno-lto")
|
||||
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")
|
||||
endif()
|
||||
|
||||
|
@ -332,7 +332,9 @@ endfunction()
|
||||
function(_cpack_nuget_make_files_tag)
|
||||
set(_files)
|
||||
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()
|
||||
set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
@ -25,6 +25,15 @@ function(CMAKE_CHECK_LINKER_FLAG _lang _flag _var)
|
||||
set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
|
||||
|
||||
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}
|
||||
"${_lang_src}"
|
||||
${_var}
|
||||
|
@ -182,7 +182,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
|
||||
macro(__windows_compiler_clang_base lang)
|
||||
set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}")
|
||||
__windows_compiler_msvc(${lang})
|
||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc ")
|
||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc")
|
||||
endmacro()
|
||||
else()
|
||||
cmake_policy(GET CMP0091 __WINDOWS_CLANG_CMP0091)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# CMake version number components.
|
||||
set(CMake_VERSION_MAJOR 3)
|
||||
set(CMake_VERSION_MINOR 23)
|
||||
set(CMake_VERSION_PATCH 1)
|
||||
set(CMake_VERSION_PATCH 2)
|
||||
#set(CMake_VERSION_RC 0)
|
||||
set(CMake_VERSION_IS_DIRTY 0)
|
||||
|
||||
@ -21,7 +21,7 @@ endif()
|
||||
|
||||
if(NOT CMake_VERSION_NO_GIT)
|
||||
# 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.
|
||||
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()) {
|
||||
std::string srcName = cmSystemTools::GetFilenameName(this->Logo);
|
||||
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;
|
||||
cmsys::SystemTools::CopyFileIfDifferent(this->Logo, path);
|
||||
xout.Element("Logo", name);
|
||||
@ -461,7 +461,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
|
||||
std::string srcName =
|
||||
cmSystemTools::GetFilenameName(this->InstallerApplicationIcon);
|
||||
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;
|
||||
cmsys::SystemTools::CopyFileIfDifferent(this->InstallerApplicationIcon,
|
||||
path);
|
||||
@ -476,7 +476,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
|
||||
std::string srcName =
|
||||
cmSystemTools::GetFilenameName(this->InstallerWindowIcon);
|
||||
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;
|
||||
cmsys::SystemTools::CopyFileIfDifferent(this->InstallerWindowIcon, path);
|
||||
xout.Element("InstallerWindowIcon", name);
|
||||
|
@ -123,7 +123,9 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile,
|
||||
std::ostringstream xContents;
|
||||
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.Attribute("allow-external-scripts", "no");
|
||||
xout.Attribute("customize", "allow");
|
||||
@ -131,55 +133,69 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile,
|
||||
xout.Attribute("rootVolumeOnly", "false");
|
||||
}
|
||||
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
|
||||
// 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
|
||||
for (auto const& group : this->ComponentGroups) {
|
||||
if (group.second.ParentGroup == nullptr) {
|
||||
CreateChoiceOutline(group.second, xout);
|
||||
CreateChoiceOutline(group.second, xChoiceOut);
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the outline for the non-grouped components
|
||||
for (auto const& comp : this->Components) {
|
||||
if (!comp.second.Group) {
|
||||
xout.StartElement("line");
|
||||
xout.Attribute("choice", comp.first + "Choice");
|
||||
xout.Content(""); // Avoid self-closing tag.
|
||||
xout.EndElement();
|
||||
xChoiceOut.StartElement("line");
|
||||
xChoiceOut.Attribute("choice", comp.first + "Choice");
|
||||
xChoiceOut.Content(""); // Avoid self-closing tag.
|
||||
xChoiceOut.EndElement();
|
||||
}
|
||||
}
|
||||
if (!this->PostFlightComponent.Name.empty()) {
|
||||
xout.StartElement("line");
|
||||
xout.Attribute("choice", PostFlightComponent.Name + "Choice");
|
||||
xout.Content(""); // Avoid self-closing tag.
|
||||
xout.EndElement();
|
||||
xChoiceOut.StartElement("line");
|
||||
xChoiceOut.Attribute("choice", PostFlightComponent.Name + "Choice");
|
||||
xChoiceOut.Content(""); // Avoid self-closing tag.
|
||||
xChoiceOut.EndElement();
|
||||
}
|
||||
xout.EndElement(); // choices-outline>
|
||||
xChoiceOut.EndElement(); // choices-outline>
|
||||
|
||||
// Create the actual choices
|
||||
for (auto const& group : this->ComponentGroups) {
|
||||
CreateChoice(group.second, xout);
|
||||
CreateChoice(group.second, xChoiceOut);
|
||||
}
|
||||
for (auto const& comp : this->Components) {
|
||||
CreateChoice(comp.second, xout);
|
||||
CreateChoice(comp.second, xChoiceOut);
|
||||
}
|
||||
|
||||
if (!this->PostFlightComponent.Name.empty()) {
|
||||
CreateChoice(PostFlightComponent, xout);
|
||||
CreateChoice(PostFlightComponent, xChoiceOut);
|
||||
}
|
||||
|
||||
this->CreateDomains(xout);
|
||||
|
||||
// default background
|
||||
this->CreateBackground(nullptr, metapackageFile, genName, xout);
|
||||
// default background. These are not strictly part of the choices, but they
|
||||
// must be included in CPACK_PACKAGEMAKER_CHOICES to preserve backward
|
||||
// compatibility.
|
||||
this->CreateBackground(nullptr, metapackageFile, genName, xChoiceOut);
|
||||
// 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
|
||||
// into a distribution package.
|
||||
|
@ -35,11 +35,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
|
||||
: Args(std::move(args))
|
||||
, InitialWidth(initWidth)
|
||||
{
|
||||
this->HasNonStatusOutputs = false;
|
||||
this->NumberOfPages = 0;
|
||||
this->AdvancedMode = false;
|
||||
this->NumberOfVisibleEntries = 0;
|
||||
this->OkToGenerate = false;
|
||||
this->HelpMessage.emplace_back(
|
||||
"Welcome to ccmake, curses based user interface for CMake.");
|
||||
this->HelpMessage.emplace_back();
|
||||
@ -54,7 +49,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
|
||||
cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
|
||||
this->Args[0] = whereCMake;
|
||||
this->CMakeInstance->SetArgs(this->Args);
|
||||
this->SearchMode = false;
|
||||
}
|
||||
|
||||
cmCursesMainForm::~cmCursesMainForm()
|
||||
@ -99,13 +93,14 @@ void cmCursesMainForm::InitializeUI()
|
||||
|
||||
int entrywidth = this->InitialWidth - 35;
|
||||
|
||||
if (count == 0) {
|
||||
// If cache is empty, display a label saying so and a
|
||||
// dummy entry widget (does not respond to input)
|
||||
cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
|
||||
comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
|
||||
newEntries.emplace_back(std::move(comp));
|
||||
} else {
|
||||
// Add a label to display when cache is empty
|
||||
// dummy entry widget (does not respond to input)
|
||||
this->EmptyCacheEntry =
|
||||
cm::make_unique<cmCursesCacheEntryComposite>("EMPTY CACHE", 30, 30);
|
||||
this->EmptyCacheEntry->Entry =
|
||||
cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
|
||||
|
||||
if (count > 0) {
|
||||
// Create the composites.
|
||||
|
||||
// First add entries which are new
|
||||
@ -196,11 +191,11 @@ void cmCursesMainForm::RePost()
|
||||
this->Fields.push_back(entry.Entry->Field);
|
||||
}
|
||||
// if no cache entries there should still be one dummy field
|
||||
if (this->Fields.empty()) {
|
||||
const auto& front = this->Entries.front();
|
||||
this->Fields.push_back(front.Label->Field);
|
||||
this->Fields.push_back(front.IsNewLabel->Field);
|
||||
this->Fields.push_back(front.Entry->Field);
|
||||
this->IsEmpty = this->Fields.empty();
|
||||
if (this->IsEmpty) {
|
||||
this->Fields.push_back(this->EmptyCacheEntry->Label->Field);
|
||||
this->Fields.push_back(this->EmptyCacheEntry->IsNewLabel->Field);
|
||||
this->Fields.push_back(this->EmptyCacheEntry->Entry->Field);
|
||||
this->NumberOfVisibleEntries = 1;
|
||||
}
|
||||
// Has to be null terminated.
|
||||
@ -875,7 +870,7 @@ void cmCursesMainForm::HandleInput()
|
||||
}
|
||||
}
|
||||
// delete cache entry
|
||||
else if (key == 'd' && this->NumberOfVisibleEntries) {
|
||||
else if (key == 'd' && this->NumberOfVisibleEntries && !this->IsEmpty) {
|
||||
this->OkToGenerate = false;
|
||||
FIELD* cur = current_field(this->Form);
|
||||
size_t findex = field_index(cur);
|
||||
|
@ -138,7 +138,7 @@ protected:
|
||||
// Output produced by the last pass
|
||||
std::vector<std::string> Outputs;
|
||||
// Did the last pass produced outputs of interest (errors, warnings, ...)
|
||||
bool HasNonStatusOutputs;
|
||||
bool HasNonStatusOutputs = false;
|
||||
// Last progress bar
|
||||
std::string LastProgress;
|
||||
|
||||
@ -155,17 +155,19 @@ protected:
|
||||
// Fields displayed. Includes labels, new entry markers, entries
|
||||
std::vector<FIELD*> Fields;
|
||||
// Number of entries shown (depends on mode -normal or advanced-)
|
||||
size_t NumberOfVisibleEntries;
|
||||
bool AdvancedMode;
|
||||
size_t NumberOfVisibleEntries = 0;
|
||||
bool AdvancedMode = false;
|
||||
// Did the iteration converge (no new entries) ?
|
||||
bool OkToGenerate;
|
||||
bool OkToGenerate = false;
|
||||
// Number of pages displayed
|
||||
int NumberOfPages;
|
||||
int NumberOfPages = 0;
|
||||
bool IsEmpty = false;
|
||||
std::unique_ptr<cmCursesCacheEntryComposite> EmptyCacheEntry;
|
||||
|
||||
int InitialWidth;
|
||||
std::unique_ptr<cmake> CMakeInstance;
|
||||
|
||||
std::string SearchString;
|
||||
std::string OldSearchString;
|
||||
bool SearchMode;
|
||||
bool SearchMode = false;
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@ -15,7 +16,6 @@
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
@ -362,16 +362,93 @@ std::string cmExportBuildFileGenerator::InstallNameDir(
|
||||
return install_name_dir;
|
||||
}
|
||||
|
||||
std::string cmExportBuildFileGenerator::GetFileSetDirectories(
|
||||
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
|
||||
namespace {
|
||||
bool EntryIsContextSensitive(
|
||||
const std::unique_ptr<cmCompiledGeneratorExpression>& cge)
|
||||
{
|
||||
return cmOutputConverter::EscapeForCMake(
|
||||
cmJoin(fileSet->GetDirectoryEntries(), ";"));
|
||||
return cge->GetHadContextSensitiveCondition();
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmExportBuildFileGenerator::GetFileSetFiles(
|
||||
cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport* /*te*/)
|
||||
std::string cmExportBuildFileGenerator::GetFileSetDirectories(
|
||||
cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* /*te*/)
|
||||
{
|
||||
return cmOutputConverter::EscapeForCMake(
|
||||
cmJoin(fileSet->GetFileEntries(), ";"));
|
||||
std::vector<std::string> resultVector;
|
||||
|
||||
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.
|
||||
//
|
||||
// Always delete the temporary file. We never want it to stay around.
|
||||
cmSystemTools::RemoveFile(this->TempName);
|
||||
if (!this->TempName.empty()) {
|
||||
cmSystemTools::RemoveFile(this->TempName);
|
||||
}
|
||||
|
||||
return replaced;
|
||||
}
|
||||
|
@ -1208,8 +1208,10 @@ bool cmGeneratorTarget::IsInBuildSystem() const
|
||||
case cmStateEnums::GLOBAL_TARGET:
|
||||
return true;
|
||||
case cmStateEnums::INTERFACE_LIBRARY:
|
||||
// An INTERFACE library is in the build system if it has SOURCES.
|
||||
if (!this->SourceEntries.empty()) {
|
||||
// An INTERFACE library is in the build system if it has SOURCES or
|
||||
// HEADER_SETS.
|
||||
if (!this->SourceEntries.empty() ||
|
||||
!this->Target->GetHeaderSetsEntries().empty()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
@ -741,9 +741,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
[=](const cmInstallCommandFileSetArguments& fileSetArg)
|
||||
-> bool { return fileSetArg.GetFileSet() == name; });
|
||||
})) {
|
||||
status.SetError(cmStrCat(
|
||||
"TARGETS target ", target.GetName(),
|
||||
" is exported but not all of its file sets are installed"));
|
||||
status.SetError(cmStrCat("TARGETS target ", target.GetName(),
|
||||
" is exported but not all of its interface "
|
||||
"file sets are installed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -236,6 +236,7 @@ bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand(
|
||||
cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator();
|
||||
|
||||
// Add newer Visual Studio paths
|
||||
AddVisualStudioPath(paths, "Visual Studio 17 ", 17, gg);
|
||||
AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg);
|
||||
AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg);
|
||||
|
||||
|
@ -171,14 +171,15 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
|
||||
code.clear();
|
||||
}
|
||||
|
||||
if (arch.empty() && gencode.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a CodeGeneration field with [arch],[code] syntax in each entry.
|
||||
// CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
|
||||
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.
|
||||
if (!arch.empty()) {
|
||||
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]*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]*objc[^\n]*: Class [^\n]* One of the two will be used. Which one is undefined."
|
||||
"|[^\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 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_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
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}")
|
||||
endif ()
|
||||
assert_prop_eq(export::lib1 HEADER_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
|
||||
assert_prop_eq(export::lib1 HEADER_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
assert_prop_eq(export::lib1 HEADER_SET_c "$<1:dir/dir.h>")
|
||||
assert_prop_eq(export::lib1 HEADER_DIRS_c "$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>")
|
||||
assert_prop_eq(export::lib1 HEADER_SET_d "${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>/empty.h")
|
||||
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")
|
||||
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_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
else ()
|
||||
assert_prop_eq(export::lib1 HEADER_DIRS_b "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif ()
|
||||
assert_prop_eq(export::lib1 HEADER_SET_c "${CMAKE_CURRENT_SOURCE_DIR}/dir/dir.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}")
|
||||
endif ()
|
||||
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_DIRS_f "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
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}")
|
||||
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_DIRS_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2")
|
||||
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>")
|
||||
if (_multi_config)
|
||||
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 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
|
||||
|
@ -1,5 +1,5 @@
|
||||
^CMake Error at FileSetInstallMissingSetsInterface\.cmake:[0-9]+ \(install\):
|
||||
install TARGETS target lib1 is exported but not all of its file sets are
|
||||
installed
|
||||
install TARGETS target lib1 is exported but not all of its interface file
|
||||
sets are installed
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
||||
|
@ -43,6 +43,15 @@ if(APPLE)
|
||||
run_cmake(FileSetFramework)
|
||||
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)
|
||||
run_cmake(FileSetFileNoExist)
|
||||
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 subtree="Utilities/cmlibarchive"
|
||||
readonly repo="https://github.com/libarchive/libarchive.git"
|
||||
readonly tag="v3.5.1"
|
||||
readonly tag="v3.5.3"
|
||||
readonly shortlog=false
|
||||
readonly paths="
|
||||
CMakeLists.txt
|
||||
|
@ -68,7 +68,7 @@ if(SPHINX_HTML)
|
||||
|
||||
# we provide the path to the produced html output in the console
|
||||
# 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"
|
||||
)
|
||||
|
||||
@ -94,7 +94,7 @@ if(SPHINX_INFO)
|
||||
|
||||
# Sphinx texinfo builder supports .info, .txt, .html and .pdf output.
|
||||
# SPHINX_INFO controls the .info output.
|
||||
set(texinfo_extra_commands
|
||||
set(texinfo_post_commands
|
||||
COMMAND ${MAKEINFO_EXECUTABLE} --no-split -o
|
||||
${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.info
|
||||
${CMAKE_CURRENT_BINARY_DIR}/texinfo/cmake.texi
|
||||
@ -112,7 +112,7 @@ if(SPHINX_QTHELP)
|
||||
endif()
|
||||
list(APPEND doc_formats qthelp)
|
||||
|
||||
set(qthelp_extra_commands
|
||||
set(qthelp_post_commands
|
||||
# Workaround for assistant prior to
|
||||
# https://codereview.qt-project.org/#change,82250 in Qt 4.
|
||||
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)
|
||||
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
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qch"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/html/CMake.qch"
|
||||
@ -170,6 +174,7 @@ foreach(format ${doc_formats})
|
||||
# arguments in peculiar order
|
||||
add_custom_command(
|
||||
OUTPUT ${doc_format_output}
|
||||
${${format}_pre_commands}
|
||||
COMMAND ${SPHINX_EXECUTABLE}
|
||||
-M ${format}
|
||||
${CMake_SOURCE_DIR}/Help
|
||||
@ -179,7 +184,7 @@ foreach(format ${doc_formats})
|
||||
${sphinx_flags}
|
||||
${doc_${format}_opts}
|
||||
> ${doc_format_log} # log stdout, pass stderr
|
||||
${${format}_extra_commands}
|
||||
${${format}_post_commands}
|
||||
DEPENDS ${doc_format_last}
|
||||
COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
|
||||
VERBATIM
|
||||
@ -188,6 +193,7 @@ foreach(format ${doc_formats})
|
||||
# other formats use standard builder (-b) mode
|
||||
add_custom_command(
|
||||
OUTPUT ${doc_format_output}
|
||||
${${format}_pre_commands}
|
||||
COMMAND ${SPHINX_EXECUTABLE}
|
||||
-c ${CMAKE_CURRENT_BINARY_DIR}
|
||||
-d ${CMAKE_CURRENT_BINARY_DIR}/${doctrees}
|
||||
@ -197,7 +203,7 @@ foreach(format ${doc_formats})
|
||||
${CMake_SOURCE_DIR}/Help
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${format}
|
||||
> ${doc_format_log} # log stdout, pass stderr
|
||||
${${format}_extra_commands}
|
||||
${${format}_post_commands}
|
||||
DEPENDS ${doc_format_last}
|
||||
COMMENT "sphinx-build ${format}: see Utilities/Sphinx/${doc_format_log}"
|
||||
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_LIMITS_H 1)
|
||||
set(HAVE_LINK 0)
|
||||
set(HAVE_LINKAT 0)
|
||||
set(HAVE_LINUX_FIEMAP_H 0)
|
||||
set(HAVE_LINUX_FS_H 0)
|
||||
set(HAVE_LINUX_MAGIC_H 0)
|
||||
@ -184,6 +185,7 @@ if(WIN32)
|
||||
set(HAVE_STROPTS_H 0)
|
||||
set(HAVE__STRTOI64 1)
|
||||
set(HAVE_STRTOLL 1)
|
||||
set(HAVE_STRUCT_STATFS 0)
|
||||
set(HAVE_STRUCT_STATFS_F_NAMEMAX 0)
|
||||
set(HAVE_STRUCT_STAT_ST_BIRTHTIME 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 ??
|
||||
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.
|
||||
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")
|
||||
ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN)
|
||||
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".
|
||||
# The zlib and the bzip2 Setup program have installed programs and DLLs into
|
||||
# "C:/Program Files/GnuWin32" by default.
|
||||
@ -1044,7 +1044,7 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
|
||||
CMAKE_C_COMPILER_ID MATCHES "^Clang$")
|
||||
#
|
||||
# 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).
|
||||
#
|
||||
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(lchown HAVE_LCHOWN)
|
||||
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(lstat HAVE_LSTAT)
|
||||
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);}"
|
||||
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
|
||||
# older 2-argument version.
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
@ -1512,9 +1517,14 @@ CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff
|
||||
CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff
|
||||
"time.h" HAVE_STRUCT_TM___TM_GMTOFF)
|
||||
|
||||
IF(HAVE_STRUCT_STATFS)
|
||||
# Check for f_namemax in struct statfs
|
||||
CHECK_STRUCT_HAS_MEMBER("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_STRUCT_HAS_MEMBER("struct stat" st_birthtime
|
||||
|
@ -528,6 +528,9 @@
|
||||
/* Define to 1 if you have the `link' function. */
|
||||
#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. */
|
||||
#cmakedefine HAVE_LINUX_TYPES_H 1
|
||||
|
||||
|
@ -246,7 +246,7 @@ function hextoi(hex)
|
||||
# Exclusion code points specified by
|
||||
# http://unicode.org/Public/6.0.0/ucd/CompositionExclusions.txt
|
||||
##
|
||||
# 1. Script Specifices
|
||||
# 1. Script Specifics
|
||||
##
|
||||
\$1 ~/^095[89ABCDEF]\$/ {
|
||||
next
|
||||
|
@ -1 +1 @@
|
||||
3005001
|
||||
3005003
|
||||
|
@ -144,7 +144,9 @@ SET(libarchive_SOURCES
|
||||
archive_write_set_format_ar.c
|
||||
archive_write_set_format_by_name.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_odc.c
|
||||
archive_write_set_format_filter_by_ext.c
|
||||
archive_write_set_format_gnutar.c
|
||||
archive_write_set_format_iso9660.c
|
||||
|
@ -36,7 +36,7 @@
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* 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 <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.
|
||||
*/
|
||||
#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
|
||||
__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_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
||||
#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_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
||||
#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_svr4(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_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_iso9660(struct archive *);
|
||||
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
||||
|
@ -13,6 +13,8 @@
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -13,6 +13,8 @@
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include "archive_platform.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -319,7 +319,7 @@ translate_acl(struct archive_read_disk *a,
|
||||
|
||||
static int
|
||||
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 acl_type = 0;
|
||||
@ -364,6 +364,13 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
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);
|
||||
if (acl == (acl_t)NULL) {
|
||||
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
|
||||
/* 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
|
||||
{
|
||||
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) {
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& 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");
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& 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");
|
||||
|
||||
/* 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
|
||||
else if ((archive_acl_types(abstract_acl) &
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
|
@ -343,6 +343,11 @@ set_richacl(struct archive *a, int fd, const char *name,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
if (S_ISLNK(mode)) {
|
||||
/* Linux does not support RichACLs on symbolic links */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
richacl = richacl_alloc(entries);
|
||||
if (richacl == NULL) {
|
||||
archive_set_error(a, errno,
|
||||
@ -455,7 +460,7 @@ exit_free:
|
||||
#if ARCHIVE_ACL_LIBACL
|
||||
static int
|
||||
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 acl_type = 0;
|
||||
@ -488,6 +493,18 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
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);
|
||||
if (acl == (acl_t)NULL) {
|
||||
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) {
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& 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");
|
||||
if (ret != ARCHIVE_OK)
|
||||
return (ret);
|
||||
}
|
||||
if ((archive_acl_types(abstract_acl)
|
||||
& 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");
|
||||
}
|
||||
#endif /* ARCHIVE_ACL_LIBACL */
|
||||
|
@ -443,7 +443,7 @@ translate_acl(struct archive_read_disk *a,
|
||||
|
||||
static int
|
||||
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)
|
||||
{
|
||||
aclent_t *aclent;
|
||||
@ -467,7 +467,6 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
if (entries == 0)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
|
||||
switch (ae_requested_type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
||||
cmd = SETACL;
|
||||
@ -492,6 +491,12 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
if (S_ISLNK(mode)) {
|
||||
/* Skip ACLs on symbolic links */
|
||||
ret = ARCHIVE_OK;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
e = 0;
|
||||
|
||||
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)
|
||||
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||||
/* 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");
|
||||
|
||||
/* 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
|
||||
else if ((archive_acl_types(abstract_acl) &
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* 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
|
||||
|
@ -384,6 +384,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
|
||||
/* Empty pattern only matches the empty string. */
|
||||
if (p == NULL || *p == '\0')
|
||||
return (s == NULL || *s == '\0');
|
||||
else if (s == NULL)
|
||||
return (0);
|
||||
|
||||
/* Leading '^' anchors the start of the pattern. */
|
||||
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. */
|
||||
if (p == NULL || *p == L'\0')
|
||||
return (s == NULL || *s == L'\0');
|
||||
else if (s == NULL)
|
||||
return (0);
|
||||
|
||||
/* Leading '^' anchors the start of the pattern. */
|
||||
if (*p == L'^') {
|
||||
|
@ -46,6 +46,13 @@
|
||||
#define __LA_DEAD
|
||||
#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_READ_MAGIC (0xdeb0c5U)
|
||||
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
||||
|
@ -1522,8 +1522,40 @@ get_xfer_size(struct tree *t, int fd, const char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \
|
||||
&& !defined(ST_LOCAL)
|
||||
#if defined(HAVE_STATVFS)
|
||||
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.
|
||||
@ -1593,10 +1625,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
return (ARCHIVE_FAILED);
|
||||
} else if (xr == 1) {
|
||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||
t->current_filesystem->xfer_align = sfs.f_bsize;
|
||||
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;
|
||||
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
||||
}
|
||||
if (sfs.f_flags & MNT_LOCAL)
|
||||
t->current_filesystem->remote = 0;
|
||||
@ -1688,15 +1717,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
} else if (xr == 1) {
|
||||
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
||||
* for pathconf() function. */
|
||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
||||
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
|
||||
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||
}
|
||||
if (svfs.f_flag & ST_LOCAL)
|
||||
t->current_filesystem->remote = 0;
|
||||
@ -1803,15 +1824,9 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
} else if (xr == 1) {
|
||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||
#if defined(HAVE_STATVFS)
|
||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
||||
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;
|
||||
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||
#else
|
||||
t->current_filesystem->xfer_align = sfs.f_frsize;
|
||||
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;
|
||||
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
||||
#endif
|
||||
}
|
||||
switch (sfs.f_type) {
|
||||
@ -1918,10 +1933,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
return (ARCHIVE_FAILED);
|
||||
} else if (xr == 1) {
|
||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
||||
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;
|
||||
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||
}
|
||||
|
||||
#if defined(ST_NOATIME)
|
||||
|
@ -1844,7 +1844,7 @@ tree_next(struct tree *t)
|
||||
continue;
|
||||
return (r);
|
||||
} else {
|
||||
HANDLE h = FindFirstFileW(d, &t->_findData);
|
||||
HANDLE h = FindFirstFileW(t->stack->full_path.s, &t->_findData);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
la_dosmaperr(GetLastError());
|
||||
t->tree_errno = errno;
|
||||
|
@ -188,9 +188,18 @@ used when translating file names.
|
||||
.El
|
||||
.It Format cpio
|
||||
.Bl -tag -compact -width indent
|
||||
.It Cm compat-2x
|
||||
Libarchive 2.x incorrectly encoded Unicode filenames on
|
||||
some platforms.
|
||||
This option mimics the libarchive 2.x filename handling
|
||||
so that such archives can be read correctly.
|
||||
.It Cm hdrcharset
|
||||
The value is used as a character set name that will be
|
||||
used when translating 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
|
||||
.It Format iso9660
|
||||
.Bl -tag -compact -width indent
|
||||
|
@ -216,7 +216,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
|
||||
archive_set_error(
|
||||
&self->archive->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unrecoginized rpm header");
|
||||
"Unrecognized rpm header");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
rpm->state = ST_ARCHIVE;
|
||||
|
@ -248,7 +248,7 @@ bid_get_line(struct archive_read_filter *filter,
|
||||
*ravail = *avail;
|
||||
*b += 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);
|
||||
if (len >= 0)
|
||||
len += tested;
|
||||
|
@ -808,8 +808,12 @@ archive_read_format_7zip_read_data(struct archive_read *a,
|
||||
if (zip->end_of_entry)
|
||||
return (ARCHIVE_EOF);
|
||||
|
||||
bytes = read_stream(a, buff,
|
||||
(size_t)zip->entry_bytes_remaining, 0);
|
||||
const uint64_t max_read_size = 16 * 1024 * 1024; // Don't try to read more than 16 MB at a time
|
||||
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)
|
||||
return ((int)bytes);
|
||||
if (bytes == 0) {
|
||||
@ -1493,7 +1497,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
zip->ppmd7_stat = -1;
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Failed to initialize PPMd range decorder");
|
||||
"Failed to initialize PPMd range decoder");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
if (zip->ppstream.overconsumed) {
|
||||
@ -3031,10 +3035,10 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
|
||||
"Truncated 7-Zip file body");
|
||||
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;
|
||||
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;
|
||||
zip->folder_outbytes_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);
|
||||
if (ds->pos_tbl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
lzx_huffman_free(&(ds->mt));
|
||||
}
|
||||
|
||||
for (footer = 0; footer < 18; footer++)
|
||||
|
@ -185,6 +185,8 @@ struct cpio {
|
||||
struct archive_string_conv *opt_sconv;
|
||||
struct archive_string_conv *sconv_default;
|
||||
int init_default_conversion;
|
||||
|
||||
int option_pwb;
|
||||
};
|
||||
|
||||
static int64_t atol16(const char *, unsigned);
|
||||
@ -343,6 +345,10 @@ archive_read_format_cpio_options(struct archive_read *a,
|
||||
ret = ARCHIVE_FATAL;
|
||||
}
|
||||
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
|
||||
@ -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_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);
|
||||
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_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);
|
||||
@ -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_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]);
|
||||
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_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]);
|
||||
|
@ -408,7 +408,7 @@ next_line(struct archive_read *a,
|
||||
*ravail = *avail;
|
||||
*b += 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);
|
||||
if (len >= 0)
|
||||
len += tested;
|
||||
@ -1074,7 +1074,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
||||
continue;
|
||||
/* Non-printable characters are not allowed */
|
||||
for (s = p;s < p + len - 1; s++) {
|
||||
if (!isprint(*s)) {
|
||||
if (!isprint((unsigned char)*s)) {
|
||||
r = ARCHIVE_FATAL;
|
||||
break;
|
||||
}
|
||||
@ -2035,13 +2035,13 @@ mtree_atol(char **p, int base)
|
||||
|
||||
if (**p == '-') {
|
||||
limit = INT64_MIN / base;
|
||||
last_digit_limit = INT64_MIN % base;
|
||||
last_digit_limit = -(INT64_MIN % base);
|
||||
++(*p);
|
||||
|
||||
l = 0;
|
||||
digit = parsedigit(**p);
|
||||
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;
|
||||
l = (l * base) - digit;
|
||||
digit = parsedigit(*++(*p));
|
||||
|
@ -958,17 +958,17 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
||||
crc32_val = 0;
|
||||
while (skip > 0) {
|
||||
size_t to_read = skip;
|
||||
ssize_t did_read;
|
||||
if (to_read > 32 * 1024) {
|
||||
if (to_read > 32 * 1024)
|
||||
to_read = 32 * 1024;
|
||||
}
|
||||
if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
|
||||
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Bad RAR file");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
p = h;
|
||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
|
||||
__archive_read_consume(a, did_read);
|
||||
skip -= did_read;
|
||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
|
||||
__archive_read_consume(a, to_read);
|
||||
skip -= to_read;
|
||||
}
|
||||
if ((crc32_val & 0xffff) != crc32_expected) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
bits |= p[rar->bits.in_addr + 1] << 16;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
bits |= (int) p[rar->bits.in_addr + 1] << 8;
|
||||
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 */
|
||||
static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
|
||||
int* value)
|
||||
static int read_consume_bits(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, int n, int* value)
|
||||
{
|
||||
uint16_t v;
|
||||
int ret, num;
|
||||
@ -1051,7 +1069,7 @@ static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
ret = read_bits_16(rar, p, &v);
|
||||
ret = read_bits_16(a, rar, p, &v);
|
||||
if(ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
|
||||
@ -1712,14 +1730,29 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're currently switching volumes, ignore the new definition of
|
||||
* window_size. */
|
||||
if(rar->cstate.switch_multivolume == 0) {
|
||||
/* Values up to 64M should fit into ssize_t on every
|
||||
* architecture. */
|
||||
rar->cstate.window_size = (ssize_t) window_size;
|
||||
if(rar->cstate.window_size < (ssize_t) window_size &&
|
||||
rar->cstate.window_buf)
|
||||
{
|
||||
/* 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
|
||||
* architecture. */
|
||||
rar->cstate.window_size = (ssize_t) window_size;
|
||||
|
||||
if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
|
||||
/* Solid files have to have the same window_size across
|
||||
whole archive. Remember the window_size parameter
|
||||
@ -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,
|
||||
const uint8_t* p, uint16_t* num)
|
||||
{
|
||||
int i, bits, dist;
|
||||
int i, bits, dist, ret;
|
||||
uint16_t bitfield;
|
||||
uint32_t pos;
|
||||
struct rar5* rar = get_context(a);
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) {
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bitfield &= 0xfffe;
|
||||
@ -2537,14 +2570,6 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
||||
for(i = 0; i < HUFF_TABLE_SIZE;) {
|
||||
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);
|
||||
if(ret != ARCHIVE_OK) {
|
||||
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 */
|
||||
uint16_t n;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
|
||||
return ret;
|
||||
|
||||
if(num == 16) {
|
||||
n >>= 13;
|
||||
@ -2590,8 +2615,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
|
||||
/* other codes: fill with zeroes `n` times */
|
||||
uint16_t n;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &n))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
|
||||
return ret;
|
||||
|
||||
if(num == 18) {
|
||||
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. */
|
||||
static int parse_filter_data(struct rar5* rar, const uint8_t* p,
|
||||
uint32_t* filter_data)
|
||||
static int parse_filter_data(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, uint32_t* filter_data)
|
||||
{
|
||||
int i, bytes;
|
||||
int i, bytes, ret;
|
||||
uint32_t data = 0;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes)))
|
||||
return ret;
|
||||
|
||||
bytes++;
|
||||
|
||||
for(i = 0; i < bytes; i++) {
|
||||
uint16_t byte;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) {
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
struct filter_info* filt = NULL;
|
||||
struct rar5* rar = get_context(ar);
|
||||
int ret;
|
||||
|
||||
/* Read the parameters from the input stream. */
|
||||
if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start)))
|
||||
return ret;
|
||||
|
||||
if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length)))
|
||||
return ret;
|
||||
|
||||
if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type)))
|
||||
return ret;
|
||||
|
||||
filter_type >>= 13;
|
||||
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) {
|
||||
int channels;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels))
|
||||
return ARCHIVE_EOF;
|
||||
if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
|
||||
return ret;
|
||||
|
||||
filt->channels = channels + 1;
|
||||
}
|
||||
@ -2823,10 +2849,11 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
static int decode_code_length(struct rar5* rar, const uint8_t* p,
|
||||
uint16_t code)
|
||||
static int decode_code_length(struct archive_read* a, struct rar5* rar,
|
||||
const uint8_t* p, uint16_t code)
|
||||
{
|
||||
int lbits, length = 2;
|
||||
|
||||
if(code < 8) {
|
||||
lbits = 0;
|
||||
length += code;
|
||||
@ -2838,7 +2865,7 @@ static int decode_code_length(struct rar5* rar, const uint8_t* p,
|
||||
if(lbits > 0) {
|
||||
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;
|
||||
|
||||
length += add;
|
||||
@ -2933,7 +2960,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
continue;
|
||||
} else if(num >= 262) {
|
||||
uint16_t dist_slot;
|
||||
int len = decode_code_length(rar, p, num - 262),
|
||||
int len = decode_code_length(a, rar, p, num - 262),
|
||||
dbits,
|
||||
dist = 1;
|
||||
|
||||
@ -2975,12 +3002,12 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
uint16_t low_dist;
|
||||
|
||||
if(dbits > 4) {
|
||||
if(ARCHIVE_OK != read_bits_32(
|
||||
rar, p, &add)) {
|
||||
if(ARCHIVE_OK != (ret = read_bits_32(
|
||||
a, rar, p, &add))) {
|
||||
/* Return EOF if we
|
||||
* can't read more
|
||||
* data. */
|
||||
return ARCHIVE_EOF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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] */
|
||||
int add;
|
||||
|
||||
if(ARCHIVE_OK != read_consume_bits(rar,
|
||||
p, dbits, &add)) {
|
||||
if(ARCHIVE_OK != (ret = read_consume_bits(a, rar,
|
||||
p, dbits, &add))) {
|
||||
/* Return EOF if we can't read
|
||||
* more data. */
|
||||
return ARCHIVE_EOF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dist += add;
|
||||
@ -3076,7 +3103,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
/* We use while(1) here, but standard case allows for just 1
|
||||
* 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)) {
|
||||
archive_set_error(&ar->archive, ENOMEM,
|
||||
"Can't allocate rar5 filter buffer");
|
||||
free(rar);
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
|
@ -1906,7 +1906,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
||||
}
|
||||
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
|
||||
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,
|
||||
tar->sparse_offset, tar->sparse_numbytes)
|
||||
!= ARCHIVE_OK)
|
||||
@ -2643,14 +2643,14 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
||||
|
||||
maxval = INT64_MIN;
|
||||
limit = -(INT64_MIN / base);
|
||||
last_digit_limit = INT64_MIN % base;
|
||||
last_digit_limit = -(INT64_MIN % base);
|
||||
}
|
||||
|
||||
l = 0;
|
||||
if (char_cnt != 0) {
|
||||
digit = *p - '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. */
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
|
@ -142,6 +142,7 @@ struct zip {
|
||||
/* Structural information about the archive. */
|
||||
struct archive_string format_name;
|
||||
int64_t central_directory_offset;
|
||||
int64_t central_directory_offset_adjusted;
|
||||
size_t central_directory_entries_total;
|
||||
size_t central_directory_entries_on_this_disk;
|
||||
int has_encrypted_entries;
|
||||
@ -246,6 +247,17 @@ struct zip {
|
||||
/* Many systems define min or MIN, but not all. */
|
||||
#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
|
||||
* 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
|
||||
@ -899,81 +911,6 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
||||
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.
|
||||
*/
|
||||
@ -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;
|
||||
|
||||
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
|
||||
size_t linkname_full_length = linkname_length;
|
||||
if (zip->entry->compression != 0)
|
||||
{
|
||||
// symlink target string appeared to be compressed
|
||||
int status = ARCHIVE_FATAL;
|
||||
char *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;
|
||||
}
|
||||
const void *uncompressed_buffer;
|
||||
|
||||
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
|
||||
case 14: /* ZIPx LZMA compression. */
|
||||
/*(see zip file format specification, section 4.4.5)*/
|
||||
status = zipx_lzma_uncompress_buffer(p,
|
||||
linkname_length,
|
||||
uncompressed_buffer,
|
||||
(size_t)zip_entry->uncompressed_size);
|
||||
zip->entry_bytes_remaining = zip_entry->compressed_size;
|
||||
status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
|
||||
&linkname_full_length, NULL);
|
||||
break;
|
||||
#endif
|
||||
default: /* Unsupported compression. */
|
||||
@ -1280,8 +1211,6 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
if (status == ARCHIVE_OK)
|
||||
{
|
||||
p = uncompressed_buffer;
|
||||
linkname_full_length =
|
||||
(size_t)zip_entry->uncompressed_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1294,6 +1223,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
||||
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;
|
||||
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
|
||||
* 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
|
||||
* `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. */
|
||||
|
||||
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
|
||||
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. */
|
||||
|
||||
/* This must be the first volume. */
|
||||
if (archive_le16dec(p + 4) != 0)
|
||||
if (disk_num != 0)
|
||||
return 0;
|
||||
/* 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;
|
||||
/* All central directory entries must be on this volume. */
|
||||
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
|
||||
return 0;
|
||||
/* Central directory can't extend beyond start of EOCD record. */
|
||||
if (archive_le32dec(p + 16) + archive_le32dec(p + 12)
|
||||
> current_offset)
|
||||
if (cd_offset + cd_size > current_offset)
|
||||
return 0;
|
||||
|
||||
/* 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
|
||||
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. */
|
||||
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;
|
||||
}
|
||||
@ -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
|
||||
* 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;
|
||||
|
||||
found = 0;
|
||||
|
@ -482,6 +482,8 @@ archive_write_client_close(struct archive_write_filter *f)
|
||||
ssize_t block_length;
|
||||
ssize_t target_block_length;
|
||||
ssize_t bytes_written;
|
||||
size_t to_write;
|
||||
char *p;
|
||||
int ret = ARCHIVE_OK;
|
||||
|
||||
/* 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);
|
||||
block_length = target_block_length;
|
||||
}
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
a->client_data, state->buffer, block_length);
|
||||
ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
|
||||
p = state->buffer;
|
||||
to_write = block_length;
|
||||
while (to_write > 0) {
|
||||
bytes_written = (a->client_writer)(&a->archive,
|
||||
a->client_data, p, to_write);
|
||||
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)
|
||||
(*a->client_closer)(&a->archive, a->client_data);
|
||||
|
@ -173,6 +173,7 @@ struct fixup_entry {
|
||||
struct fixup_entry *next;
|
||||
struct archive_acl acl;
|
||||
mode_t mode;
|
||||
__LA_MODE_T filetype;
|
||||
int64_t atime;
|
||||
int64_t birthtime;
|
||||
int64_t mtime;
|
||||
@ -357,10 +358,11 @@ struct archive_write_disk {
|
||||
|
||||
static int la_opendirat(int, const char *);
|
||||
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 *,
|
||||
const char *);
|
||||
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
||||
int);
|
||||
int, int);
|
||||
static int check_symlinks(struct archive_write_disk *);
|
||||
static int create_filesystem_object(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
|
||||
}
|
||||
|
||||
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
|
||||
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));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->fixup |= TODO_MODE_BASE;
|
||||
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));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->mode = a->mode;
|
||||
fe->fixup |= TODO_TIMES;
|
||||
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));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->fixup |= TODO_ACLS;
|
||||
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));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->mac_metadata = malloc(metadata_size);
|
||||
if (fe->mac_metadata != NULL) {
|
||||
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));
|
||||
if (fe == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
fe->filetype = archive_entry_filetype(entry);
|
||||
fe->fixup |= TODO_FFLAGS;
|
||||
/* TODO: Complete this.. defer fflags from below. */
|
||||
}
|
||||
@ -2263,7 +2303,7 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
return (EPERM);
|
||||
}
|
||||
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
||||
&error_string, a->flags);
|
||||
&error_string, a->flags, 1);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
@ -2284,7 +2324,12 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
*/
|
||||
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
|
||||
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;
|
||||
#endif
|
||||
/*
|
||||
* New cpio and pax formats allow hardlink entries
|
||||
* 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 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_STATE_HEADER | ARCHIVE_STATE_DATA,
|
||||
@ -2469,10 +2516,70 @@ _archive_write_disk_close(struct archive *_a)
|
||||
while (p != NULL) {
|
||||
fd = -1;
|
||||
a->pst = NULL; /* Mark stat cache as out-of-date. */
|
||||
if (p->fixup &
|
||||
(TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
|
||||
fd = open(p->name,
|
||||
O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
|
||||
|
||||
/* We must strip trailing slashes from the path to avoid
|
||||
dereferencing symbolic links to directories */
|
||||
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) {
|
||||
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) {
|
||||
#ifdef HAVE_FCHMOD
|
||||
if (fd >= 0)
|
||||
fchmod(fd, p->mode);
|
||||
fchmod(fd, p->mode & 07777);
|
||||
else
|
||||
#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)
|
||||
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)
|
||||
set_mac_metadata(a, p->name, p->mac_metadata,
|
||||
p->mac_metadata_size);
|
||||
skip_fixup_entry:
|
||||
next = p->next;
|
||||
archive_acl_clear(&p->acl);
|
||||
free(p->mac_metadata);
|
||||
@ -2638,6 +2750,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
|
||||
fe->next = a->fixup_list;
|
||||
a->fixup_list = fe;
|
||||
fe->fixup = 0;
|
||||
fe->filetype = 0;
|
||||
fe->name = strdup(pathname);
|
||||
return (fe);
|
||||
}
|
||||
@ -2675,7 +2788,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
|
||||
*/
|
||||
static int
|
||||
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||
int flags)
|
||||
int flags, int checking_linkname)
|
||||
{
|
||||
#if !defined(HAVE_LSTAT) && \
|
||||
!(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_string; /* UNUSED */
|
||||
(void)flags; /* UNUSED */
|
||||
(void)checking_linkname; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
int res = ARCHIVE_OK;
|
||||
@ -2805,6 +2919,28 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||
head = tail + 1;
|
||||
}
|
||||
} 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) {
|
||||
/*
|
||||
* Last element is symlink; remove it
|
||||
@ -2971,7 +3107,7 @@ check_symlinks(struct archive_write_disk *a)
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
||||
a->flags);
|
||||
a->flags, 0);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s",
|
||||
error_string.s);
|
||||
@ -3737,6 +3873,7 @@ set_fflags(struct archive_write_disk *a)
|
||||
le = current_fixup(a, a->name);
|
||||
if (le == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
le->filetype = archive_entry_filetype(a->entry);
|
||||
le->fixup |= TODO_FFLAGS;
|
||||
le->fflags_set = set;
|
||||
/* 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 (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);
|
||||
}
|
||||
if (myfd < 0)
|
||||
|
@ -35,7 +35,10 @@
|
||||
.Nm archive_write_set_format_ar_svr4 ,
|
||||
.Nm archive_write_set_format_by_name ,
|
||||
.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_odc ,
|
||||
.Nm archive_write_set_format_cpio_pwb ,
|
||||
.Nm archive_write_set_format_filter_by_ext ,
|
||||
.Nm archive_write_set_format_filter_by_ext_def ,
|
||||
.Nm archive_write_set_format_gnutar ,
|
||||
@ -73,8 +76,14 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Ft int
|
||||
.Fn archive_write_set_format_cpio "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_write_set_format_cpio_bin "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_write_set_format_cpio_newc "struct archive *"
|
||||
.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"
|
||||
.Ft int
|
||||
.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
|
||||
Sets the corresponding format based on the common name.
|
||||
.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
|
||||
.Xc
|
||||
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
|
||||
.It Xo
|
||||
.Fn archive_write_set_format_7zip
|
||||
.Fn archive_write_set_format_ar_bsd ,
|
||||
.Fn archive_write_set_format_ar_svr4 ,
|
||||
.Fn archive_write_set_format_ar_bsd
|
||||
.Fn archive_write_set_format_ar_svr4
|
||||
.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_odc
|
||||
.Fn archive_write_set_format_cpio_pwb
|
||||
.Fn archive_write_set_format_gnutar
|
||||
.Fn archive_write_set_format_iso9660
|
||||
.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_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_ISO9660, archive_write_set_format_iso9660 },
|
||||
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
|
||||
|
@ -755,6 +755,10 @@ _7z_close(struct archive_write *a)
|
||||
*/
|
||||
#if HAVE_LZMA_H
|
||||
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.
|
||||
* This is the same way 7z command does. */
|
||||
if (zip->total_number_entry == 1)
|
||||
@ -762,7 +766,8 @@ _7z_close(struct archive_write *a)
|
||||
#else
|
||||
header_compression = _7Z_COPY;
|
||||
#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)
|
||||
return (r);
|
||||
zip->crc32flg = PRECODE_CRC32;
|
||||
|
@ -49,6 +49,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
|
||||
{ "arbsd", archive_write_set_format_ar_bsd },
|
||||
{ "argnu", 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 },
|
||||
{ "cd9660", archive_write_set_format_iso9660 },
|
||||
{ "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-classic", archive_write_set_format_mtree_classic },
|
||||
{ "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 },
|
||||
{ "pax", archive_write_set_format_pax },
|
||||
{ "paxr", archive_write_set_format_pax_restricted },
|
||||
{ "posix", archive_write_set_format_pax },
|
||||
{ "pwb", archive_write_set_format_cpio_pwb },
|
||||
{ "raw", archive_write_set_format_raw },
|
||||
{ "rpax", archive_write_set_format_pax_restricted },
|
||||
{ "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_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
|
||||
archive_write_set_format_cpio(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");
|
||||
|
||||
/* 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));
|
||||
return archive_write_set_format_cpio_odc(_a);
|
||||
}
|
||||
|
@ -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
|
||||
compression method.
|
||||
.El
|
||||
.It Format cpio
|
||||
.It Format bin
|
||||
.Bl -tag -compact -width indent
|
||||
.It Cm hdrcharset
|
||||
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
|
||||
used when translating file names.
|
||||
.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
|
||||
.Bl -tag -compact -width indent
|
||||
.It Cm hdrcharset
|
||||
|
@ -138,6 +138,7 @@
|
||||
#define HAVE_LIBZ 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_LINK 1
|
||||
#define HAVE_LINKAT 1
|
||||
#define HAVE_LOCALE_H 1
|
||||
#define HAVE_LOCALTIME_R 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
|
||||
.Dq TRAILER!!! .
|
||||
.Ss PWB format
|
||||
XXX Any documentation of the original PWB/UNIX 1.0 format? XXX
|
||||
.Ss Old Binary Format
|
||||
The old binary
|
||||
The PWB binary
|
||||
.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:
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
struct header_old_cpio {
|
||||
unsigned short c_magic;
|
||||
unsigned short c_dev;
|
||||
unsigned short c_ino;
|
||||
unsigned short c_mode;
|
||||
unsigned short c_uid;
|
||||
unsigned short c_gid;
|
||||
unsigned short c_nlink;
|
||||
unsigned short c_rdev;
|
||||
unsigned short c_mtime[2];
|
||||
unsigned short c_namesize;
|
||||
unsigned short c_filesize[2];
|
||||
struct header_pwb_cpio {
|
||||
short h_magic;
|
||||
short h_dev;
|
||||
short h_ino;
|
||||
short h_mode;
|
||||
short h_uid;
|
||||
short h_gid;
|
||||
short h_nlink;
|
||||
short h_majmin;
|
||||
long h_mtime;
|
||||
short h_namesize;
|
||||
long h_filesize;
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Va unsigned short
|
||||
fields here are 16-bit integer values; the
|
||||
.Va unsigned int
|
||||
fields are 32-bit integer values.
|
||||
The fields are as follows
|
||||
.Va short
|
||||
fields here are 16-bit integer values, while the
|
||||
.Va long
|
||||
fields are 32 bit integers. Since PWB UNIX, like the 6th Edition UNIX
|
||||
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
|
||||
.It Va magic
|
||||
.It Va h_magic
|
||||
The integer value octal 070707.
|
||||
This value can be used to determine whether this archive is
|
||||
written with little-endian or big-endian integers.
|
||||
.It Va dev , Va ino
|
||||
.It Va h_dev , Va h_ino
|
||||
The device and inode numbers from the disk.
|
||||
These are used by programs that read
|
||||
.Nm
|
||||
@ -97,9 +101,94 @@ archives to determine when two entries refer to the same file.
|
||||
Programs that synthesize
|
||||
.Nm
|
||||
archives should be careful to set these to distinct values for each entry.
|
||||
.It Va mode
|
||||
The mode specifies both the regular permissions and the file type.
|
||||
It consists of several bit fields as follows:
|
||||
.It Va h_mode
|
||||
The mode specifies both the regular permissions and the file type, and
|
||||
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
|
||||
.It 0170000
|
||||
This masks the file type bits.
|
||||
@ -124,51 +213,26 @@ SUID bit.
|
||||
SGID bit.
|
||||
.It 0001000
|
||||
Sticky bit.
|
||||
On some systems, this modifies the behavior of executables and/or directories.
|
||||
.It 0000777
|
||||
The lower 9 bits specify read/write/execute permissions
|
||||
for world, group, and user following standard POSIX conventions.
|
||||
.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
|
||||
The pathname immediately follows the fixed header.
|
||||
If the
|
||||
.Cm namesize
|
||||
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.
|
||||
Finally, the file size field now represents a signed 32 bit integer in
|
||||
the underlying file system, so the maximum file size has increased to
|
||||
2 gigabytes.
|
||||
.Pp
|
||||
Hardlinked files are not given special treatment;
|
||||
the full file contents are included with each copy of the
|
||||
file.
|
||||
Note that there is no obvious way to tell which of the two binary
|
||||
formats an archive uses, other than to see which one makes more
|
||||
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
|
||||
.St -susv2
|
||||
standardized an ASCII variant that is portable across all
|
||||
@ -180,6 +244,7 @@ format or as the
|
||||
format.
|
||||
It stores the same numeric fields as the old binary format, but
|
||||
represents them as 6-character or 11-character octal values.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
struct cpio_odc_header {
|
||||
char c_magic[6];
|
||||
@ -196,9 +261,9 @@ struct cpio_odc_header {
|
||||
};
|
||||
.Ed
|
||||
.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.
|
||||
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.
|
||||
If the files being archived are themselves entirely ASCII, then
|
||||
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
|
||||
all numbers and separates device numbers into separate fields
|
||||
for major and minor numbers.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
struct cpio_newc_header {
|
||||
char c_magic[6];
|
||||
@ -227,7 +293,7 @@ struct cpio_newc_header {
|
||||
.Ed
|
||||
.Pp
|
||||
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
|
||||
.It Va magic
|
||||
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
|
||||
.Dq Programmer's Work Bench
|
||||
derived from
|
||||
.At v6
|
||||
.At 6th Edition UNIX
|
||||
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 SCO under their
|
||||
.Dq Ancient Unix
|
||||
@ -304,9 +370,9 @@ The
|
||||
format is mis-named, as it uses a simple checksum and
|
||||
not a cyclic redundancy check.
|
||||
.Pp
|
||||
The old binary format is limited to 16 bits for user id,
|
||||
group id, device, and inode numbers.
|
||||
It is limited to 4 gigabyte file sizes.
|
||||
The binary formats are limited to 16 bits for user id, group id,
|
||||
device, and inode numbers. They are limited to 16 megabyte and 2
|
||||
gigabyte file sizes for the older and newer variants, respectively.
|
||||
.Pp
|
||||
The old ASCII format is limited to 18 bits for
|
||||
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
|
||||
format.
|
||||
.Ss Cpio Formats
|
||||
The libarchive library can read a number of common cpio variants and can write
|
||||
.Dq odc
|
||||
and
|
||||
.Dq newc
|
||||
format archives.
|
||||
A cpio archive stores each entry as a fixed-size header followed
|
||||
by a variable-length filename and variable-length data.
|
||||
Unlike the tar format, the cpio format does only minimal padding
|
||||
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.
|
||||
The libarchive library can read and write a number of common cpio
|
||||
variants. A cpio archive stores each entry as a fixed-size header
|
||||
followed by a variable-length filename and variable-length data.
|
||||
Unlike the tar format, the cpio format does only minimal padding 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
|
||||
.It Cm binary
|
||||
The libarchive library transparently reads both big-endian and little-endian
|
||||
variants of the original binary cpio format.
|
||||
This format used 32-bit binary values for file size and mtime,
|
||||
and 16-bit binary values for the other fields.
|
||||
The libarchive library transparently reads both big-endian and
|
||||
little-endian variants of the the two binary cpio formats; the
|
||||
original one from PWB/UNIX, and the later, more widely used, variant.
|
||||
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
|
||||
The libarchive library can both read and write this
|
||||
POSIX-standard format, which is officially known as the
|
||||
This is the POSIX standardized format, which is officially known as the
|
||||
.Dq cpio interchange format
|
||||
or the
|
||||
.Dq octet-oriented cpio archive format
|
||||
|
@ -105,7 +105,7 @@ POSIX
|
||||
.Dq pax interchange format
|
||||
archives,
|
||||
.It
|
||||
POSIX octet-oriented cpio archives,
|
||||
cpio archives,
|
||||
.It
|
||||
Zip archive,
|
||||
.It
|
||||
|
@ -150,7 +150,11 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
|
||||
#if GCC_VERSION >= 409
|
||||
__attribute__((__no_sanitize_undefined__))
|
||||
#endif
|
||||
static inline U32 A32(const void * x)
|
||||
#if defined(_MSC_VER)
|
||||
static __inline U32 A32(const void * x)
|
||||
#else
|
||||
static inline U32 A32(const void* x)
|
||||
#endif
|
||||
{
|
||||
return (((const U32_S *)(x))->v);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user