diff options
294 files changed, 8898 insertions, 4661 deletions
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index e219763..3c84c2b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -27,9 +27,12 @@ To contribute patches: #. Run `Utilities/SetupForDevelopment.sh`_ for local configuration. #. See the `CMake Source Code Guide`_ for coding guidelines. #. Base all new work on the upstream ``master`` branch. + Base work on the upstream ``release`` branch only if it fixes a + regression or bug in a feature new to that release. #. Create commits making incremental, distinct, logically complete changes. #. Push a topic branch to a personal repository fork on GitLab. -#. Create a GitLab Merge Request targeting the upstream ``master`` branch. +#. Create a GitLab Merge Request targeting the upstream ``master`` branch + (even if the change is intended for merge to the ``release`` branch). The merge request will enter the `CMake Review Process`_ for consideration. diff --git a/Help/dev/maint.rst b/Help/dev/maint.rst index 889e4e3..bdfb3d0 100644 --- a/Help/dev/maint.rst +++ b/Help/dev/maint.rst @@ -37,6 +37,48 @@ command to integrate a merge request. Please check at least the following: introduced. (Learn to tolerate spurious failures due to idiosyncrasies of various nightly builders.) +* Ensure that the MR targets the ``master`` branch. A MR intended for + the ``release`` branch should be based on ``release`` but still merged + to ``master`` first (via ``Do: merge``). A maintainer may then merge + the MR topic to ``release`` manually. + +Maintain Current Release +======================== + +The ``release`` branch is used to maintain the current release or release +candidate. The branch is published with no version number but maintained +using a local branch named ``release-$ver``, where ``$ver`` is the version +number of the current release in the form ``$major.$minor``. It is always +merged into ``master`` before publishing. + +To merge some ``$topic`` branch into ``release``, first create the local +branch: + +.. code-block:: shell + + git fetch origin + git checkout -b release-$ver origin/release + +Merge the ``$topic`` branch into the local ``release-$ver`` branch: + +.. code-block:: shell + + git merge --no-ff $topic + +Merge the ``release-$ver`` branch to ``master``: + +.. code-block:: shell + + git checkout master + git pull + git merge --no-ff release-$ver + +Publish both ``master`` and ``release`` simultaneously: + +.. code-block:: shell + + git push --atomic origin master release-$ver:release + .. _`CMake Review Process`: review.rst .. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 95f5b87..debaf23 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -266,7 +266,7 @@ The :command:`target_link_libraries` command has ``PRIVATE``, Because ``archive`` is a ``PUBLIC`` dependency of ``archiveExtras``, the usage requirements of it are propagated to ``consumer`` too. Because -``serialization`` is a ``PRIVATE`` dependency of ``archive``, the usage +``serialization`` is a ``PRIVATE`` dependency of ``archiveExtras``, the usage requirements of it are not propagated to ``consumer``. Generally, a dependency should be specified in a use of diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index eb9af27..c81ba59 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.10 .. toctree:: :maxdepth: 1 + CMP0071: Let AUTOMOC and AUTOUIC process GENERATED files. </policy/CMP0071> CMP0070: Define file(GENERATE) behavior for relative paths. </policy/CMP0070> Policies Introduced by CMake 3.9 diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index ba925e8..8aece23 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -262,6 +262,36 @@ Available commands are: 351abe79cd3800b38cdfb25d45015a15 file1.txt 052f86c15bbde68af55c7f7b340ab639 file2.txt +``sha1sum <file>...`` + Create SHA1 checksum of files in ``sha1sum`` compatible format:: + + 4bb7932a29e6f73c97bb9272f2bdc393122f86e0 file1.txt + 1df4c8f318665f9a5f2ed38f55adadb7ef9f559c file2.txt + +``sha224sum <file>...`` + Create SHA224 checksum of files in ``sha224sum`` compatible format:: + + b9b9346bc8437bbda630b0b7ddfc5ea9ca157546dbbf4c613192f930 file1.txt + 6dfbe55f4d2edc5fe5c9197bca51ceaaf824e48eba0cc453088aee24 file2.txt + +``sha256sum <file>...`` + Create SHA256 checksum of files in ``sha256sum`` compatible format:: + + 76713b23615d31680afeb0e9efe94d47d3d4229191198bb46d7485f9cb191acc file1.txt + 15b682ead6c12dedb1baf91231e1e89cfc7974b3787c1e2e01b986bffadae0ea file2.txt + +``sha384sum <file>...`` + Create SHA384 checksum of files in ``sha384sum`` compatible format:: + + acc049fedc091a22f5f2ce39a43b9057fd93c910e9afd76a6411a28a8f2b8a12c73d7129e292f94fc0329c309df49434 file1.txt + 668ddeb108710d271ee21c0f3acbd6a7517e2b78f9181c6a2ff3b8943af92b0195dcb7cce48aa3e17893173c0a39e23d file2.txt + +``sha512sum <file>...`` + Create SHA512 checksum of files in ``sha512sum`` compatible format:: + + 2a78d7a6c5328cfb1467c63beac8ff21794213901eaadafd48e7800289afbc08e5fb3e86aa31116c945ee3d7bf2a6194489ec6101051083d1108defc8e1dba89 file1.txt + 7a0b54896fe5e70cca6dd643ad6f672614b189bf26f8153061c4d219474b05dad08c4e729af9f4b009f1a1a280cb625454bf587c690f4617c27e3aebdf3b7a2d file2.txt + ``remove [-f] <file>...`` Remove the file(s). If any of the listed files already do not exist, the command returns a non-zero exit code, but no message diff --git a/Help/policy/CMP0071.rst b/Help/policy/CMP0071.rst new file mode 100644 index 0000000..61f14dc --- /dev/null +++ b/Help/policy/CMP0071.rst @@ -0,0 +1,34 @@ +CMP0071 +------- + +Let :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` process +:prop_sf:`GENERATED` files. + +CMake 3.10 and newer process regular *and* :prop_sf:`GENERATED` source files +in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. +In CMake 3.9 and lower, only regular source files were processed in +:prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`, +:prop_sf:`GENERATED` source files were ignored. + +This policy affects how :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` process +source files that are :prop_sf:`GENERATED`. + +The ``OLD`` behavior for this policy is to *ignore* :prop_sf:`GENERATED` +source files in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC`. + +The ``NEW`` behavior for this policy is to process :prop_sf:`GENERATED` +source files in :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` just like regular +source files. + +.. note:: + To exclude source files from :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` + processing, the boolean source file properties + :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC` and :prop_sf:`SKIP_AUTOGEN` + can be set accordingly. + +This policy was introduced in CMake version 3.10. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/autogen-generated-files.rst b/Help/release/dev/autogen-generated-files.rst new file mode 100644 index 0000000..da2fc4e --- /dev/null +++ b/Help/release/dev/autogen-generated-files.rst @@ -0,0 +1,8 @@ +autogen-generated-files +----------------------- + +* When using :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC`, + source files that are :prop_sf:`GENERATED` will be processed as well. + They were ignored by :prop_tgt:`AUTOMOC` and :prop_tgt:`AUTOUIC` + in earlier releases. + See policy :policy:`CMP0071`. diff --git a/Help/release/dev/cmake-command-mode-shasum.rst b/Help/release/dev/cmake-command-mode-shasum.rst new file mode 100644 index 0000000..681e0c0 --- /dev/null +++ b/Help/release/dev/cmake-command-mode-shasum.rst @@ -0,0 +1,5 @@ +cmake-command-mode-shasum +------------------------- + +* Added sha1sum, sha224sum, sha256sum, sha384sum and sha512sum + as an equivalent to existing md5sum to cmake command mode. diff --git a/Help/release/index.rst b/Help/release/index.rst index 7f481a3..6c68e65 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -1,3 +1,5 @@ +:orphan: + CMake Release Notes ******************* diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index 9aa096d..6572bb3 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -27,12 +27,18 @@ char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; @CMAKE_CXX_COMPILER_ID_PLATFORM_CONTENT@ @CMAKE_CXX_COMPILER_ID_ERROR_FOR_TEST@ +#if defined(_MSC_VER) && defined(_MSVC_LANG) +#define CXX_STD _MSVC_LANG +#else +#define CXX_STD __cplusplus +#endif + const char* info_language_dialect_default = "INFO" ":" "dialect_default[" -#if __cplusplus > 201402L +#if CXX_STD > 201402L "17" -#elif __cplusplus >= 201402L +#elif CXX_STD >= 201402L "14" -#elif __cplusplus >= 201103L +#elif CXX_STD >= 201103L "11" #else "98" diff --git a/Modules/CPack.STGZ_Header.sh.in b/Modules/CPack.STGZ_Header.sh.in index c615851..70f63d2 100755 --- a/Modules/CPack.STGZ_Header.sh.in +++ b/Modules/CPack.STGZ_Header.sh.in @@ -7,9 +7,11 @@ cpack_usage() Usage: $0 [options] Options: [defaults in brackets after descriptions] --help print this message + --version print cmake installer version --prefix=dir directory in which to install --include-subdir include the @CPACK_PACKAGE_FILE_NAME@ subdirectory --exclude-subdir exclude the @CPACK_PACKAGE_FILE_NAME@ subdirectory + --skip-license accept license EOF exit 1 } diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake index 354eea3..8552154 100644 --- a/Modules/CheckCXXSymbolExists.cmake +++ b/Modules/CheckCXXSymbolExists.cmake @@ -35,5 +35,5 @@ include(CheckSymbolExists) macro(CHECK_CXX_SYMBOL_EXISTS SYMBOL FILES VARIABLE) - _CHECK_SYMBOL_EXISTS("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) endmacro() diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index 6f1afcf..6d52d56 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -45,15 +45,15 @@ the way the check is run: macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE) if(CMAKE_C_COMPILER_LOADED) - _CHECK_SYMBOL_EXISTS("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) elseif(CMAKE_CXX_COMPILER_LOADED) - _CHECK_SYMBOL_EXISTS("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) else() message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled") endif() endmacro() -macro(_CHECK_SYMBOL_EXISTS SOURCEFILE SYMBOL FILES VARIABLE) +macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}") set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") set(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 9371301..f478b85 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -3,7 +3,25 @@ include(Compiler/CMakeCommonCompilerMacros) -if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) +if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.10.25017) + # VS 2015 Update 3 and above support language standard level flags, + # with the default and minimum level being C++14. + set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "") + set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std:c++14") + set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-std:c++14") + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.11.25505) + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std:c++17") + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std:c++17") + else() + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std:c++latest") + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std:c++latest") + endif() + + __compiler_check_default_language_standard(CXX 19.0 14) +elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) # MSVC has no specific options to set language standards, but set them as # empty strings anyways so the feature test infrastructure can at least check # to see if they are defined. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 2495736..d92eb5f 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -5,413 +5,860 @@ ExternalProject --------------- -Create custom targets to build projects in external trees +.. only:: html + + .. contents:: + +External Project Definition +^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. command:: ExternalProject_Add - The ``ExternalProject_Add`` function creates a custom target to drive + The ``ExternalProject_Add()`` function creates a custom target to drive download, update/patch, configure, build, install and test steps of an external project:: - ExternalProject_Add(<name> [<option>...]) - - General options are: - - ``DEPENDS <projects>...`` - Targets on which the project depends - ``PREFIX <dir>`` - Root dir for entire project - ``LIST_SEPARATOR <sep>`` - Sep to be replaced by ; in cmd lines - ``TMP_DIR <dir>`` - Directory to store temporary files - ``STAMP_DIR <dir>`` - Directory to store step timestamps - ``EXCLUDE_FROM_ALL 1`` - The "all" target does not depend on this - - Download step options are: - - ``DOWNLOAD_NAME <fname>`` - File name to store (if not end of URL) - ``DOWNLOAD_DIR <dir>`` - Directory to store downloaded files - ``DOWNLOAD_COMMAND <cmd>...`` - Command to download source tree - ``DOWNLOAD_NO_PROGRESS 1`` - Disable download progress reports - ``CVS_REPOSITORY <cvsroot>`` - CVSROOT of CVS repository - ``CVS_MODULE <mod>`` - Module to checkout from CVS repo - ``CVS_TAG <tag>`` - Tag to checkout from CVS repo - ``SVN_REPOSITORY <url>`` - URL of Subversion repo - ``SVN_REVISION -r<rev>`` - Revision to checkout from Subversion repo - ``SVN_USERNAME <username>`` - Username for Subversion checkout and update - ``SVN_PASSWORD <password>`` - Password for Subversion checkout and update - ``SVN_TRUST_CERT 1`` - Trust the Subversion server site certificate - ``GIT_REPOSITORY <url>`` - URL of git repo - ``GIT_TAG <tag>`` - Git branch name, commit id or tag - ``GIT_REMOTE_NAME <name>`` - The optional name of the remote, default to ``origin`` - ``GIT_SUBMODULES <module>...`` - Git submodules that shall be updated, all if empty - ``GIT_SHALLOW 1`` - Tell Git to clone with ``--depth 1``. Use when ``GIT_TAG`` is not - specified or when it names a branch in order to download only the - tip of the branch without the rest of its history. - ``GIT_PROGRESS 1`` - Tell Git to clone with ``--progress``. For large projects, the clone step - does not output anything which can make the build appear to have stalled. - This option forces Git to output progress information during the clone step - so that forward progress is indicated. - ``GIT_CONFIG <option>...`` - Tell Git to clone with ``--config <option>``. Use additional configuration - parameters when cloning the project (``key=value`` as expected by ``git - config``). - ``HG_REPOSITORY <url>`` - URL of mercurial repo - ``HG_TAG <tag>`` - Mercurial branch name, commit id or tag - ``URL /.../src.tgz [/.../src.tgz]...`` - Full path or URL(s) of source. Multiple URLs are allowed as mirrors. - ``URL_HASH ALGO=value`` - Hash of file at URL - ``URL_MD5 md5`` - Equivalent to URL_HASH MD5=md5 - ``HTTP_USERNAME <username>`` - Username for download operation - ``HTTP_PASSWORD <username>`` - Password for download operation - ``HTTP_HEADER <header>`` - HTTP header for download operation. Suboption can be repeated several times. - ``TLS_VERIFY <bool>`` - Should certificate for https be checked - ``TLS_CAINFO <file>`` - Path to a certificate authority file - ``TIMEOUT <seconds>`` - Time allowed for file download operations - ``DOWNLOAD_NO_EXTRACT 1`` - Just download the file and do not extract it; the full path to the - downloaded file is available as ``<DOWNLOADED_FILE>``. - - Update/Patch step options are: - - ``UPDATE_COMMAND <cmd>...`` - Source work-tree update command - ``UPDATE_DISCONNECTED 1`` - Never update automatically from the remote repository - ``PATCH_COMMAND <cmd>...`` - Command to patch downloaded source - - Configure step options are: - - ``SOURCE_DIR <dir>`` - Source dir to be used for build - ``SOURCE_SUBDIR <dir>`` - Path to source CMakeLists.txt relative to ``SOURCE_DIR`` - ``CONFIGURE_COMMAND <cmd>...`` - Build tree configuration command - ``CMAKE_COMMAND /.../cmake`` - Specify alternative cmake executable - ``CMAKE_GENERATOR <gen>`` - Specify generator for native build - ``CMAKE_GENERATOR_PLATFORM <platform>`` - Generator-specific platform name - ``CMAKE_GENERATOR_TOOLSET <toolset>`` - Generator-specific toolset name - ``CMAKE_ARGS <arg>...`` - Arguments to CMake command line. - These arguments are passed to CMake command line, and can contain - arguments other than cache values, see also - :manual:`CMake Options <cmake(1)>`. Arguments in the form - ``-Dvar:string=on`` are always passed to the command line, and - therefore cannot be changed by the user. - Arguments may use - :manual:`generator expressions <cmake-generator-expressions(7)>`. - ``CMAKE_CACHE_ARGS <arg>...`` - Initial cache arguments, of the form ``-Dvar:string=on``. - These arguments are written in a pre-load a script that populates - CMake cache, see also :manual:`cmake -C <cmake(1)>`. This allows one to - overcome command line length limits. - These arguments are :command:`set` using the ``FORCE`` argument, - and therefore cannot be changed by the user. - Arguments may use - :manual:`generator expressions <cmake-generator-expressions(7)>`. - ``CMAKE_CACHE_DEFAULT_ARGS <arg>...`` - Initial default cache arguments, of the form ``-Dvar:string=on``. - These arguments are written in a pre-load a script that populates - CMake cache, see also :manual:`cmake -C <cmake(1)>`. This allows one to - overcome command line length limits. - These arguments can be used as default value that will be set if no - previous value is found in the cache, and that the user can change - later. - Arguments may use - :manual:`generator expressions <cmake-generator-expressions(7)>`. - - Build step options are: - - ``BINARY_DIR <dir>`` - Specify build dir location - ``BUILD_COMMAND <cmd>...`` - Command to drive the native build - ``BUILD_IN_SOURCE 1`` - Use source dir for build dir - ``BUILD_ALWAYS 1`` - No stamp file, build step always runs - ``BUILD_BYPRODUCTS <file>...`` - Files that will be generated by the build command but may or may - not have their modification time updated by subsequent builds. - - Install step options are: - - ``INSTALL_DIR <dir>`` - Installation prefix to be placed in the ``<INSTALL_DIR>`` placeholder. - This does not actually configure the external project to install to - the given prefix. That must be done by passing appropriate arguments - to the external project configuration step, e.g. using ``<INSTALL_DIR>``. - ``INSTALL_COMMAND <cmd>...`` - Command to drive installation of the external project after it has been - built. This only happens at the *build* time of the calling project. - In order to install files from the external project alongside the - locally-built files, a separate local :command:`install` call must be - added to pick the files up from one of the external project trees. - - Test step options are: - - ``TEST_BEFORE_INSTALL 1`` - Add test step executed before install step - ``TEST_AFTER_INSTALL 1`` - Add test step executed after install step - ``TEST_EXCLUDE_FROM_MAIN 1`` - Main target does not depend on the test step - ``TEST_COMMAND <cmd>...`` - Command to drive test - - Output logging options are: - - ``LOG_DOWNLOAD 1`` - Wrap download in script to log output - ``LOG_UPDATE 1`` - Wrap update in script to log output - ``LOG_CONFIGURE 1`` - Wrap configure in script to log output - ``LOG_BUILD 1`` - Wrap build in script to log output - ``LOG_TEST 1`` - Wrap test in script to log output - ``LOG_INSTALL 1`` - Wrap install in script to log output - - Steps can be given direct access to the terminal if possible. With - the :generator:`Ninja` generator, this places the steps in the - ``console`` :prop_gbl:`pool <JOB_POOLS>`. Options are: - - ``USES_TERMINAL_DOWNLOAD 1`` - Give download terminal access. - ``USES_TERMINAL_UPDATE 1`` - Give update terminal access. - ``USES_TERMINAL_CONFIGURE 1`` - Give configure terminal access. - ``USES_TERMINAL_BUILD 1`` - Give build terminal access. - ``USES_TERMINAL_TEST 1`` - Give test terminal access. - ``USES_TERMINAL_INSTALL 1`` - Give install terminal access. - - Other options are: - - ``STEP_TARGETS <step-target>...`` - Generate custom targets for these steps - ``INDEPENDENT_STEP_TARGETS <step-target>...`` - Generate custom targets for these steps that do not depend on other - external projects even if a dependency is set - - The ``*_DIR`` options specify directories for the project, with default - directories computed as follows. If the ``PREFIX`` option is given to - ``ExternalProject_Add()`` or the ``EP_PREFIX`` directory property is set, - then an external project is built and installed under the specified prefix:: - - TMP_DIR = <prefix>/tmp - STAMP_DIR = <prefix>/src/<name>-stamp - DOWNLOAD_DIR = <prefix>/src - SOURCE_DIR = <prefix>/src/<name> - BINARY_DIR = <prefix>/src/<name>-build - INSTALL_DIR = <prefix> - - Otherwise, if the ``EP_BASE`` directory property is set then components - of an external project are stored under the specified base:: - - TMP_DIR = <base>/tmp/<name> - STAMP_DIR = <base>/Stamp/<name> - DOWNLOAD_DIR = <base>/Download/<name> - SOURCE_DIR = <base>/Source/<name> - BINARY_DIR = <base>/Build/<name> - INSTALL_DIR = <base>/Install/<name> - - If no ``PREFIX``, ``EP_PREFIX``, or ``EP_BASE`` is specified then the - default is to set ``PREFIX`` to ``<name>-prefix``. Relative paths are - interpreted with respect to the build directory corresponding to the - source directory in which ``ExternalProject_Add`` is invoked. - - If ``SOURCE_SUBDIR`` is set and no ``CONFIGURE_COMMAND`` is specified, the - configure command will run CMake using the ``CMakeLists.txt`` located in the - relative path specified by ``SOURCE_SUBDIR``, relative to the ``SOURCE_DIR``. - If no ``SOURCE_SUBDIR`` is given, ``SOURCE_DIR`` is used. - - If ``SOURCE_DIR`` is explicitly set to an existing directory the project - will be built from it. Otherwise a download step must be specified - using one of the ``DOWNLOAD_COMMAND``, ``CVS_*``, ``SVN_*``, or ``URL`` - options. The ``URL`` option may refer locally to a directory or source - tarball, or refer to a remote tarball (e.g. ``http://.../src.tgz``). - - If ``UPDATE_DISCONNECTED`` is set, the update step is not executed - automatically when building the main target. The update step can still - be added as a step target and called manually. This is useful if you - want to allow one to build the project when you are disconnected from the - network (you might still need the network for the download step). - This is disabled by default. - The directory property ``EP_UPDATE_DISCONNECTED`` can be used to change - the default value for all the external projects in the current - directory and its subdirectories. + ExternalProject_Add(<name> [<option>...]) + + The individual steps within the process can be driven independently if + required (e.g. for CDash submission) and extra custom steps can be defined, + along with the ability to control the step dependencies. The directory + structure used for the management of the external project can also be + customized. The function supports a large number of options which can be used + to tailor the external project behavior. + + **Directory Options:** + Most of the time, the default directory layout is sufficient. It is largely + an implementation detail that the main project usually doesn't need to + change. In some circumstances, however, control over the directory layout + can be useful or necessary. The directory options are potentially more + useful from the point of view that the main build can use the + :command:`ExternalProject_Get_Property` command to retrieve their values, + thereby allowing the main project to refer to build artifacts of the + external project. + + ``PREFIX <dir>`` + Root directory for the external project. Unless otherwise noted below, + all other directories associated with the external project will be + created under here. + + ``TMP_DIR <dir>`` + Directory in which to store temporary files. + + ``STAMP_DIR <dir>`` + Directory in which to store the timestamps of each step. Log files from + individual steps are also created in here (see *Logging Options* below). + + ``DOWNLOAD_DIR <dir>`` + Directory in which to store downloaded files before unpacking them. This + directory is only used by the URL download method, all other download + methods use ``SOURCE_DIR`` directly instead. + + ``SOURCE_DIR <dir>`` + Source directory into which downloaded contents will be unpacked, or for + non-URL download methods, the directory in which the repository should be + checked out, cloned, etc. If no download method is specified, this must + point to an existing directory where the external project has already + been unpacked or cloned/checked out. + + .. note:: + If a download method is specified, any existing contents of the source + directory may be deleted. Only the URL download method checks whether + this directory is either missing or empty before initiating the + download, stopping with an error if it is not empty. All other + download methods silently discard any previous contents of the source + directory. + + ``BINARY_DIR <dir>`` + Specify the build directory location. This option is ignored if + ``BUILD_IN_SOURCE`` is enabled. + + ``INSTALL_DIR <dir>`` + Installation prefix to be placed in the ``<INSTALL_DIR>`` placeholder. + This does not actually configure the external project to install to + the given prefix. That must be done by passing appropriate arguments + to the external project configuration step, e.g. using ``<INSTALL_DIR>``. + + If any of the above ``..._DIR`` options are not specified, their defaults + are computed as follows. If the ``PREFIX`` option is given or the + ``EP_PREFIX`` directory property is set, then an external project is built + and installed under the specified prefix:: + + TMP_DIR = <prefix>/tmp + STAMP_DIR = <prefix>/src/<name>-stamp + DOWNLOAD_DIR = <prefix>/src + SOURCE_DIR = <prefix>/src/<name> + BINARY_DIR = <prefix>/src/<name>-build + INSTALL_DIR = <prefix> + + Otherwise, if the ``EP_BASE`` directory property is set then components + of an external project are stored under the specified base:: + + TMP_DIR = <base>/tmp/<name> + STAMP_DIR = <base>/Stamp/<name> + DOWNLOAD_DIR = <base>/Download/<name> + SOURCE_DIR = <base>/Source/<name> + BINARY_DIR = <base>/Build/<name> + INSTALL_DIR = <base>/Install/<name> + + If no ``PREFIX``, ``EP_PREFIX``, or ``EP_BASE`` is specified, then the + default is to set ``PREFIX`` to ``<name>-prefix``. Relative paths are + interpreted with respect to :variable:`CMAKE_CURRENT_BINARY_DIR` at the + point where ``ExternalProject_Add()`` is called. + + **Download Step Options:** + A download method can be omitted if the ``SOURCE_DIR`` option is used to + point to an existing non-empty directory. Otherwise, one of the download + methods below must be specified (multiple download methods should not be + given) or a custom ``DOWNLOAD_COMMAND`` provided. + + ``DOWNLOAD_COMMAND <cmd>...`` + Overrides the command used for the download step + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). If this option is specified, all other download options will + be ignored. Providing an empty string for ``<cmd>`` effectively disables + the download step. + + *URL Download* + ``URL <url1> [<url2>...]`` + List of paths and/or URL(s) of the external project's source. When more + than one URL is given, they are tried in turn until one succeeds. A URL + may be an ordinary path in the local file system (in which case it + must be the only URL provided) or any downloadable URL supported by the + :command:`file(DOWNLOAD)` command. A local filesystem path may refer to + either an existing directory or to an archive file, whereas a URL is + expected to point to a file which can be treated as an archive. When an + archive is used, it will be unpacked automatically unless the + ``DOWNLOAD_NO_EXTRACT`` option is set to prevent it. The archive type + is determined by inspecting the actual content rather than using logic + based on the file extension. + + ``URL_HASH ALGO=<value>`` + Hash of the archive file to be downloaded. The ``<value>`` should be of + the form ``algo=hashValue`` where ``algo`` can be any of the hashing + algorithms supported by the :command:`file()` command. Specifying this + option is strongly recommended for URL downloads, as it ensures the + integrity of the downloaded content. It is also used as a check for a + previously downloaded file, allowing connection to the remote location + to be avoided altogether if the local directory already has a file from + an earlier download that matches the specified hash. + + ``URL_MD5 <md5>`` + Equivalent to ``URL_HASH MD5=<md5>``. + + ``DOWNLOAD_NAME <fname>`` + File name to use for the downloaded file. If not given, the end of the + URL is used to determine the file name. This option is rarely needed, + the default name is generally suitable and is not normally used outside + of code internal to the ``ExternalProject`` module. + + ``DOWNLOAD_NO_EXTRACT <bool>`` + Allows the extraction part of the download step to be disabled by + passing a boolean true value for this option. If this option is not + given, the downloaded contents will be unpacked automatically if + required. If extraction has been disabled, the full path to the + downloaded file is available as ``<DOWNLOADED_FILE>`` in subsequent + steps or as the property ``DOWNLOADED_FILE`` with the + :command:`ExternalProject_Get_Property` command. + + ``DOWNLOAD_NO_PROGRESS <bool>`` + Can be used to disable logging the download progress. If this option is + not given, download progress messages will be logged. + + ``TIMEOUT <seconds>`` + Maximum time allowed for file download operations. + + ``HTTP_USERNAME <username>`` + Username for the download operation if authentication is required. + + ``HTTP_PASSWORD <password>`` + Password for the download operation if authentication is required. + + ``HTTP_HEADER <header1> [<header2>...]`` + Provides an arbitrary list of HTTP headers for the download operation. + This can be useful for accessing content in systems like AWS, etc. + + ``TLS_VERIFY <bool>`` + Specifies whether certificate verification should be performed for + https URLs. If this option is not provided, the default behavior is + determined by the ``CMAKE_TLS_VERIFY`` variable (see + :command:`file(DOWNLOAD)`). If that is also not set, certificate + verification will not be performed. In situations where ``URL_HASH`` + cannot be provided, this option can be an alternative verification + measure. + + ``TLS_CAINFO <file>`` + Specify a custom certificate authority file to use if ``TLS_VERIFY`` + is enabled. If this option is not specified, the value of the + ``CMAKE_TLS_CAINFO`` variable will be used instead (see + :command:`file(DOWNLOAD)`) + + *Git* + NOTE: A git version of 1.6.5 or later is required if this download method + is used. + + ``GIT_REPOSITORY <url>`` + URL of the git repository. Any URL understood by the ``git`` command + may be used. + + ``GIT_TAG <tag>`` + Git branch name, tag or commit hash. Note that branch names and tags + should generally be specified as remote names (i.e. ``origin/myBranch`` + rather than simply ``myBranch``). This ensures that if the remote end + has its tag moved or branch rebased or history rewritten, the local + clone will still be updated correctly. In general, however, specifying + a commit hash should be preferred for a number of reasons: + + - If the local clone already has the commit corresponding to the hash, + no ``git fetch`` needs to be performed to check for changes each time + CMake is re-run. This can result in a significant speed up if many + external projects are being used. + - Using a specific git hash ensures that the main project's own history + is fully traceable to a specific point in the external project's + evolution. If a branch or tag name is used instead, then checking out + a specific commit of the main project doesn't necessarily pin the + whole build to a specific point in the life of the external project. + The lack of such deterministic behavior makes the main project lose + traceability and repeatability. + + ``GIT_REMOTE_NAME <name>`` + The optional name of the remote. If this option is not specified, it + defaults to ``origin``. + + ``GIT_SUBMODULES <module>...`` + Specific git submodules that should also be updated. If this option is + not provided, all git submodules will be updated. + + ``GIT_SHALLOW <bool>`` + When this option is enabled, the ``git clone`` operation will be given + the ``--depth 1`` option. This performs a shallow clone, which avoids + downloading the whole history and instead retrieves just the commit + denoted by the ``GIT_TAG`` option. + + ``GIT_PROGRESS <bool>`` + When enabled, this option instructs the ``git clone`` operation to + report its progress by passing it the ``--progress`` option. Without + this option, the clone step for large projects may appear to make the + build stall, since nothing will be logged until the clone operation + finishes. While this option can be used to provide progress to prevent + the appearance of the build having stalled, it may also make the build + overly noisy if lots of external projects are used. + + ``GIT_CONFIG <option1> [<option2>...]`` + Specify a list of config options to pass to ``git clone``. Each option + listed will be transformed into its own ``--config <option>`` on the + ``git clone`` command line, with each option required to be in the + form ``key=value``. + + *Subversion* + ``SVN_REPOSITORY <url>`` + URL of the Subversion repository. + + ``SVN_REVISION -r<rev>`` + Revision to checkout from the Subversion repository. + + ``SVN_USERNAME <username>`` + Username for the Subversion checkout and update. + + ``SVN_PASSWORD <password>`` + Password for the Subversion checkout and update. + + ``SVN_TRUST_CERT <bool>`` + Specifies whether to trust the Subversion server site certificate. If + enabled, the ``--trust-server-cert`` option is passed to the ``svn`` + checkout and update commands. + + *Mercurial* + ``HG_REPOSITORY <url>`` + URL of the mercurial repository. + + ``HG_TAG <tag>`` + Mercurial branch name, tag or commit id. + + *CVS* + ``CVS_REPOSITORY <cvsroot>`` + CVSROOT of the CVS repository. + + ``CVS_MODULE <mod>`` + Module to checkout from the CVS repository. + + ``CVS_TAG <tag>`` + Tag to checkout from the CVS repository. + + **Update/Patch Step Options:** + Whenever CMake is re-run, by default the external project's sources will be + updated if the download method supports updates (e.g. a git repository + would be checked if the ``GIT_TAG`` does not refer to a specific commit). + + ``UPDATE_COMMAND <cmd>...`` + Overrides the download method's update step with a custom command. + The command may use + :manual:`generator expressions <cmake-generator-expressions(7)>`. + + ``UPDATE_DISCONNECTED <bool>`` + When enabled, this option causes the update step to be skipped. It does + not, however, prevent the download step. The update step can still be + added as a step target (see :command:`ExternalProject_Add_StepTargets`) + and called manually. This is useful if you want to allow developers to + build the project when disconnected from the network (the network may + still be needed for the download step though). + + When this option is present, it is generally advisable to make the value + a cache variable under the developer's control rather than hard-coding + it. If this option is not present, the default value is taken from the + ``EP_UPDATE_DISCONNECTED`` directory property. If that is also not + defined, updates are performed as normal. The ``EP_UPDATE_DISCONNECTED`` + directory property is intended as a convenience for controlling the + ``UPDATE_DISCONNECTED`` behavior for an entire section of a project's + directory hierarchy and may be a more convenient method of giving + developers control over whether or not to perform updates (assuming the + project also provides a cache variable or some other convenient method + for setting the directory property). + + ``PATCH_COMMAND <cmd>...`` + Specifies a custom command to patch the sources after an update. By + default, no patch command is defined. Note that it can be quite difficult + to define an appropriate patch command that performs robustly, especially + for download methods such as git where changing the ``GIT_TAG`` will not + discard changes from a previous patch, but the patch command will be + called again after updating to the new tag. + + **Configure Step Options:** + The configure step is run after the download and update steps. By default, + the external project is assumed to be a CMake project, but this can be + overridden if required. + + ``CONFIGURE_COMMAND <cmd>...`` + The default configure command runs CMake with options based on the main + project. For non-CMake external projects, the ``CONFIGURE_COMMAND`` + option must be used to override this behavior + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). For projects that require no configure step, specify this + option with an empty string as the command to execute. + + ``CMAKE_COMMAND /.../cmake`` + Specify an alternative cmake executable for the configure step (use an + absolute path). This is generally not recommended, since it is + usually desirable to use the same CMake version throughout the whole + build. This option is ignored if a custom configure command has been + specified with ``CONFIGURE_COMMAND``. + + ``CMAKE_GENERATOR <gen>`` + Override the CMake generator used for the configure step. Without this + option, the same generator as the main build will be used. This option is + ignored if a custom configure command has been specified with the + ``CONFIGURE_COMMAND`` option. + + ``CMAKE_GENERATOR_PLATFORM <platform>`` + Pass a generator-specific platform name to the CMake command (see + :variable:`CMAKE_GENERATOR_PLATFORM`). It is an error to provide this + option without the ``CMAKE_GENERATOR`` option. + + ``CMAKE_GENERATOR_TOOLSET <toolset>`` + Pass a generator-specific toolset name to the CMake command (see + :variable:`CMAKE_GENERATOR_TOOLSET`). It is an error to provide this + option without the ``CMAKE_GENERATOR`` option. + + ``CMAKE_ARGS <arg>...`` + The specified arguments are passed to the ``cmake`` command line. They + can be any argument the ``cmake`` command understands, not just cache + values defined by ``-D...`` arguments (see also + :manual:`CMake Options <cmake(1)>`). In addition, arguments may use + :manual:`generator expressions <cmake-generator-expressions(7)>`. + + ``CMAKE_CACHE_ARGS <arg>...`` + This is an alternate way of specifying cache variables where command line + length issues may become a problem. The arguments are expected to be in + the form ``-Dvar:STRING=value``, which are then transformed into + CMake :command:`set` commands with the ``FORCE`` option used. These + ``set()`` commands are written to a pre-load script which is then applied + using the :manual:`cmake -C <cmake(1)>` command line option. Arguments + may use :manual:`generator expressions <cmake-generator-expressions(7)>`. + + ``CMAKE_CACHE_DEFAULT_ARGS <arg>...`` + This is the same as the ``CMAKE_CACHE_ARGS`` option except the ``set()`` + commands do not include the ``FORCE`` keyword. This means the values act + as initial defaults only and will not override any variables already set + from a previous run. Use this option with care, as it can lead to + different behavior depending on whether the build starts from a fresh + build directory or re-uses previous build contents. + + ``SOURCE_SUBDIR <dir>`` + When no ``CONFIGURE_COMMAND`` option is specified, the configure step + assumes the external project has a ``CMakeLists.txt`` file at the top of + its source tree (i.e. in ``SOURCE_DIR``). The ``SOURCE_SUBDIR`` option + can be used to point to an alternative directory within the source tree + to use as the top of the CMake source tree instead. This must be a + relative path and it will be interpreted as being relative to + ``SOURCE_DIR``. + + **Build Step Options:** + If the configure step assumed the external project uses CMake as its build + system, the build step will also. Otherwise, the build step will assume a + Makefile-based build and simply run ``make`` with no arguments as the + default build step. This can be overridden with custom build commands if + required. + + ``BUILD_COMMAND <cmd>...`` + Overrides the default build command + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). If this option is not given, the default build command will + be chosen to integrate with the main build in the most appropriate way + (e.g. using recursive ``make`` for Makefile generators or + ``cmake --build`` if the project uses a CMake build). This option can be + specified with an empty string as the command to make the build step do + nothing. + + ``BUILD_IN_SOURCE <bool>`` + When this option is enabled, the build will be done directly within the + external project's source tree. This should generally be avoided, the use + of a separate build directory is usually preferred, but it can be useful + when the external project assumes an in-source build. The ``BINARY_DIR`` + option should not be specified if building in-source. + + ``BUILD_ALWAYS <bool>`` + Enabling this option forces the build step to always be run. This can be + the easiest way to robustly ensure that the external project's own build + dependencies are evaluated rather than relying on the default + success timestamp-based method. This option is not normally needed unless + developers are expected to modify something the external project's build + depends on in a way that is not detectable via the step target + dependencies (e.g. ``SOURCE_DIR`` is used without a download method and + developers might modify the sources in ``SOURCE_DIR``). + + ``BUILD_BYPRODUCTS <file>...`` + Specifies files that will be generated by the build command but which + might or might not have their modification time updated by subsequent + builds. These ultimately get passed through as ``BYPRODUCTS`` to the + build step's own underlying call to :command:`add_custom_command`. + + **Install Step Options:** + If the configure step assumed the external project uses CMake as its build + system, the install step will also. Otherwise, the install step will assume + a Makefile-based build and simply run ``make install`` as the default build + step. This can be overridden with custom install commands if required. + + ``INSTALL_COMMAND <cmd>...`` + The external project's own install step is invoked as part of the main + project's *build*. It is done after the external project's build step + and may be before or after the external project's test step (see the + ``TEST_BEFORE_INSTALL`` option below). The external project's install + rules are not part of the main project's install rules, so if anything + from the external project should be installed as part of the main build, + these need to be specified in the main build as additional + :command:`install` commands. The default install step builds the + ``install`` target of the external project, but this can be overridden + with a custom command using this option + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). Passing an empty string as the ``<cmd>`` makes the install + step do nothing. + + **Test Step Options:** + The test step is only defined if at least one of the following ``TEST_...`` + options are provided. + + ``TEST_COMMAND <cmd>...`` + Overrides the default test command + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). If this option is not given, the default behavior of the test + step is to build the external project's own ``test`` target. This option + can be specified with ``<cmd>`` as an empty string, which allows the test + step to still be defined, but it will do nothing. Do not specify any of + the other ``TEST_...`` options if providing an empty string as the test + command, but prefer to omit all ``TEST_...`` options altogether if the + test step target is not needed. + + ``TEST_BEFORE_INSTALL <bool>`` + When this option is enabled, the test step will be executed before the + install step. The default behavior is for the test step to run after the + install step. + + ``TEST_AFTER_INSTALL <bool>`` + This option is mainly useful as a way to indicate that the test step is + desired but all default behavior is sufficient. Specifying this option + with a boolean true value ensures the test step is defined and that it + comes after the install step. If both ``TEST_BEFORE_INSTALL`` and + ``TEST_AFTER_INSTALL`` are enabled, the latter is silently ignored. + + ``TEST_EXCLUDE_FROM_MAIN <bool>`` + If enabled, the main build's default ALL target will not depend on the + test step. This can be a useful way of ensuring the test step is defined + but only gets invoked when manually requested. + + **Output Logging Options:** + Each of the following ``LOG_...`` options can be used to wrap the relevant + step in a script to capture its output to files. The log files will be + created in the ``STAMP_DIR`` directory with step-specific file names. + + ``LOG_DOWNLOAD <bool>`` + When enabled, the output of the download step is logged to files. + + ``LOG_UPDATE <bool>`` + When enabled, the output of the update step is logged to files. + + ``LOG_CONFIGURE <bool>`` + When enabled, the output of the configure step is logged to files. + + ``LOG_BUILD <bool>`` + When enabled, the output of the build step is logged to files. + + ``LOG_INSTALL <bool>`` + When enabled, the output of the install step is logged to files. + + ``LOG_TEST <bool>`` + When enabled, the output of the test step is logged to files. + + **Terminal Access Options:** + Steps can be given direct access to the terminal in some cases. Giving a + step access to the terminal may allow it to receive terminal input if + required, such as for authentication details not provided by other options. + With the :generator:`Ninja` generator, these options place the steps in the + ``console`` :prop_gbl:`job pool <JOB_POOLS>`. Each step can be given access + to the terminal individually via the following options: + + ``USES_TERMINAL_DOWNLOAD <bool>`` + Give the download step access to the terminal. + + ``USES_TERMINAL_UPDATE <bool>`` + Give the update step access to the terminal. + + ``USES_TERMINAL_CONFIGURE <bool>`` + Give the configure step access to the terminal. + + ``USES_TERMINAL_BUILD <bool>`` + Give the build step access to the terminal. + + ``USES_TERMINAL_INSTALL <bool>`` + Give the install step access to the terminal. + + ``USES_TERMINAL_TEST <bool>`` + Give the test step access to the terminal. + + **Target Options:** + ``DEPENDS <targets>...`` + Specify other targets on which the external project depends. The other + targets will be brought up to date before any of the external project's + steps are executed. Because the external project uses additional custom + targets internally for each step, the ``DEPENDS`` option is the most + convenient way to ensure all of those steps depend on the other targets. + Simply doing + :command:`add_dependencies(\<name\> \<targets\>) <add_dependencies>` will + not make any of the steps dependent on ``<targets>``. + + ``EXCLUDE_FROM_ALL <bool>`` + When enabled, this option excludes the external project from the default + ALL target of the main build. + + ``STEP_TARGETS <step-target>...`` + Generate custom targets for the specified steps. This is required if the + steps need to be triggered manually or if they need to be used as + dependencies of other targets. If this option is not specified, the + default value is taken from the ``EP_STEP_TARGETS`` directory property. + See :command:`ExternalProject_Add_Step` below for further discussion of + the effects of this option. + + ``INDEPENDENT_STEP_TARGETS <step-target>...`` + Generate custom targets for the specified steps and prevent these targets + from having the usual dependencies applied to them. If this option is not + specified, the default value is taken from the + ``EP_INDEPENDENT_STEP_TARGETS`` directory property. This option is mostly + useful for allowing individual steps to be driven independently, such as + for a CDash setup where each step should be initiated and reported + individually rather than as one whole build. See + :command:`ExternalProject_Add_Step` below for further discussion of the + effects of this option. + + **Miscellaneous Options:** + ``LIST_SEPARATOR <sep>`` + For any of the various ``..._COMMAND`` options, replace ``;`` with + ``<sep>`` in the specified command lines. This can be useful where list + variables may be given in commands where they should end up as + space-separated arguments (``<sep>`` would be a single space character + string in this case). + + ``COMMAND <cmd>...`` + Any of the other ``..._COMMAND`` options can have additional commands + appended to them by following them with as many ``COMMAND ...`` options + as needed + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). For example:: + + ExternalProject_Add(example + ... # Download options, etc. + BUILD_COMMAND ${CMAKE_COMMAND} -E echo "Starting $<CONFIG> build" + COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config $<CONFIG> + COMMAND ${CMAKE_COMMAND} -E echo "$<CONFIG> build complete" + ) + + It should also be noted that each build step is created via a call to + :command:`ExternalProject_Add_Step`. See that command's documentation for the + automatic substitutions that are supported for some options. + +Obtaining Project Properties +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: ExternalProject_Get_Property + + The ``ExternalProject_Get_Property()`` function retrieves external project + target properties:: + + ExternalProject_Get_Property(<name> <prop1> [<prop2>...]) + + The function stores property values in variables of the same name. Property + names correspond to the keyword argument names of ``ExternalProject_Add()``. + For example, the source directory might be retrieved like so: + + .. code-block:: cmake + + ExternalProject_Get_property(myExtProj SOURCE_DIR) + message("Source dir of myExtProj = ${SOURCE_DIR}") + +Explicit Step Management +^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``ExternalProject_Add()`` function on its own is often sufficient for +incorporating an external project into the main build. Certain scenarios +require additional work to implement desired behavior, such as adding in a +custom step or making steps available as manually triggerable targets. The +``ExternalProject_Add_Step()``, ``ExternalProject_Add_StepTargets()`` and +``ExternalProject_Add_StepDependencies`` functions provide the lower level +control needed to implement such step-level capabilities. .. command:: ExternalProject_Add_Step - The ``ExternalProject_Add_Step`` function adds a custom step to an - external project:: + The ``ExternalProject_Add_Step()`` function specifies an additional custom + step for an external project defined by an earlier call to + :command:`ExternalProject_Add`:: - ExternalProject_Add_Step(<name> <step> [<option>...]) + ExternalProject_Add_Step(<name> <step> [<option>...]) - Options are: + ``<name>`` is the same as the name passed to the original call to + :command:`ExternalProject_Add`. The specified ``<step>`` must not be one of + the pre-defined steps (``mkdir``, ``download``, ``update``, ``skip-update``, + ``patch``, ``configure``, ``build``, ``install`` or ``test``). The supported + options are: ``COMMAND <cmd>...`` - Command line invoked by this step + The command line to be executed by this custom step + (:manual:`generator expressions <cmake-generator-expressions(7)>` are + supported). This option can be repeated multiple times to specify multiple + commands to be executed in order. + ``COMMENT "<text>..."`` - Text printed when step executes + Text to be printed when the custom step executes. + ``DEPENDEES <step>...`` - Steps on which this step depends + Other steps (custom or pre-defined) on which this step depends. + ``DEPENDERS <step>...`` - Steps that depend on this step + Other steps (custom or pre-defined) that depend on this new custom step. + ``DEPENDS <file>...`` - Files on which this step depends + Files on which this custom step depends. + ``BYPRODUCTS <file>...`` - Files that will be generated by this step but may or may not - have their modification time updated by subsequent builds. - ``ALWAYS 1`` - No stamp file, step always runs - ``EXCLUDE_FROM_MAIN 1`` - Main target does not depend on this step + Files that will be generated by this custom step but which might or might + not have their modification time updated by subsequent builds. This list of + files will ultimately be passed through as the ``BYPRODUCTS`` option to the + :command:`add_custom_command` used to implement the custom step internally. + + ``ALWAYS <bool>`` + When enabled, this option specifies that the custom step should always be + run (i.e. that it is always considered out of date). + + ``EXCLUDE_FROM_MAIN <bool>`` + When enabled, this option specifies that the external project's main target + does not depend on the custom step. + ``WORKING_DIRECTORY <dir>`` - Working directory for command - ``LOG 1`` - Wrap step in script to log output - ``USES_TERMINAL 1`` - Give the step direct access to the terminal if possible. + Specifies the working directory to set before running the custom step's + command. If this option is not specified, the directory will be the value + of the :variable:`CMAKE_CURRENT_BINARY_DIR` at the point where + ``ExternalProject_Add_Step()`` was called. - The command line, comment, working directory, and byproducts of every - standard and custom step are processed to replace tokens ``<SOURCE_DIR>``, - ``<SOURCE_SUBDIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>``, and ``<TMP_DIR>`` - with corresponding property values. + ``LOG <bool>`` + If set, this causes the output from the custom step to be captured to files + in the external project's ``STAMP_DIR``. -Any builtin step that specifies a ``<step>_COMMAND cmd...`` or custom -step that specifies a ``COMMAND cmd...`` may specify additional command -lines using the form ``COMMAND cmd...``. At build time the commands -will be executed in order and aborted if any one fails. For example:: + ``USES_TERMINAL <bool>`` + If enabled, this gives the custom step direct access to the terminal if + possible. - ... BUILD_COMMAND make COMMAND echo done ... + The command line, comment, working directory and byproducts of every + standard and custom step are processed to replace the tokens + ``<SOURCE_DIR>``, ``<SOURCE_SUBDIR>``, ``<BINARY_DIR>``, ``<INSTALL_DIR>`` + and ``<TMP_DIR>`` with their corresponding property values defined in the + original call to :command:`ExternalProject_Add`. -specifies to run ``make`` and then ``echo done`` during the build step. -Whether the current working directory is preserved between commands is -not defined. Behavior of shell operators like ``&&`` is not defined. +.. command:: ExternalProject_Add_StepTargets -Arguments to ``<step>_COMMAND`` or ``COMMAND`` options may use -:manual:`generator expressions <cmake-generator-expressions(7)>`. + The ``ExternalProject_Add_StepTargets()`` function generates targets for the + steps listed. The name of each created target will be of the form + ``<name>-<step>``:: + + ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...]) + + Creating a target for a step allows it to be used as a dependency of another + target or to be triggered manually. Having targets for specific steps also + allows them to be driven independently of each other by specifying targets on + build command lines. For example, you may be submitting to a sub-project + based dashboard where you want to drive the configure portion of the build, + then submit to the dashboard, followed by the build portion, followed + by tests. If you invoke a custom target that depends on a step halfway + through the step dependency chain, then all the previous steps will also run + to ensure everything is up to date. + + If the ``NO_DEPENDS`` option is specified, the step target will not depend on + the dependencies of the external project (i.e. on any dependencies of the + ``<name>`` custom target created by :command:`ExternalProject_Add`). This is + usually safe for the ``download``, ``update`` and ``patch`` steps, since they + do not typically require that the dependencies are updated and built. Using + ``NO_DEPENDS`` for any of the other pre-defined steps, however, may break + parallel builds. Only use ``NO_DEPENDS`` where it is certain that the named + steps genuinely do not have dependencies. For custom steps, consider whether + or not the custom commands require the dependencies to be configured, built + and installed. + + Internally, :command:`ExternalProject_Add` calls + :command:`ExternalProject_Add_Step` to create each step. If any + ``STEP_TARGETS`` or ``INDEPENDENT_STEP_TARGETS`` were specified, then + ``ExternalProject_Add_StepTargets()`` will also be called after + :command:`ExternalProject_Add_Step`. ``INDEPENDENT_STEP_TARGETS`` have the + ``NO_DEPENDS`` option set, whereas ``STEP_TARGETS`` do not. Other than that, + the two options result in ``ExternalProject_Add_StepTargets()`` being called + in the same way. Even if a step is not mentioned in either of those two + options, ``ExternalProject_Add_StepTargets()`` can still be called later to + manually define a target for the step. + + The ``STEP_TARGETS`` and ``INDEPENDENT_STEP_TARGETS`` options for + :command:`ExternalProject_Add` are generally the easiest way to ensure + targets are created for specific steps of interest. For custom steps, + ``ExternalProject_Add_StepTargets()`` must be called explicitly if a target + should also be created for that custom step. An alternative to these two + options is to populate the ``EP_STEP_TARGETS`` and + ``EP_INDEPENDENT_STEP_TARGETS`` directory properties. These act as defaults + for the step target options and can save having to repeatedly specify the + same set of step targets when multiple external projects are being defined. -.. command:: ExternalProject_Get_Property +.. command:: ExternalProject_Add_StepDependencies - The ``ExternalProject_Get_Property`` function retrieves external project - target properties:: + The ``ExternalProject_Add_StepDependencies()`` function can be used to add + dependencies to a step. The dependencies added must be targets CMake already + knows about (these can be ordinary executable or library targets, custom + targets or even step targets of another external project):: - ExternalProject_Get_Property(<name> [prop1 [prop2 [...]]]) + ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...]) - It stores property values in variables of the same name. Property - names correspond to the keyword argument names of - ``ExternalProject_Add``. + This function takes care to set both target and file level dependencies and + will ensure that parallel builds will not break. It should be used instead of + :command:`add_dependencies` whenever adding a dependency for some of the step + targets generated by the ``ExternalProject`` module. -.. command:: ExternalProject_Add_StepTargets +Examples +^^^^^^^^ - The ``ExternalProject_Add_StepTargets`` function generates custom - targets for the steps listed:: - - ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] [step1 [step2 [...]]]) - -If ``NO_DEPENDS`` is set, the target will not depend on the -dependencies of the complete project. This is usually safe to use for -the download, update, and patch steps that do not require that all the -dependencies are updated and built. Using ``NO_DEPENDS`` for other -of the default steps might break parallel builds, so you should avoid, -it. For custom steps, you should consider whether or not the custom -commands requires that the dependencies are configured, built and -installed. - -If ``STEP_TARGETS`` or ``INDEPENDENT_STEP_TARGETS`` is set then -``ExternalProject_Add_StepTargets`` is automatically called at the end -of matching calls to ``ExternalProject_Add_Step``. Pass -``STEP_TARGETS`` or ``INDEPENDENT_STEP_TARGETS`` explicitly to -individual ``ExternalProject_Add`` calls, or implicitly to all -``ExternalProject_Add`` calls by setting the directory properties -``EP_STEP_TARGETS`` and ``EP_INDEPENDENT_STEP_TARGETS``. The -``INDEPENDENT`` version of the argument and of the property will call -``ExternalProject_Add_StepTargets`` with the ``NO_DEPENDS`` argument. - -If ``STEP_TARGETS`` and ``INDEPENDENT_STEP_TARGETS`` are not set, -clients may still manually call ``ExternalProject_Add_StepTargets`` -after calling ``ExternalProject_Add`` or ``ExternalProject_Add_Step``. - -This functionality is provided to make it easy to drive the steps -independently of each other by specifying targets on build command -lines. For example, you may be submitting to a sub-project based -dashboard, where you want to drive the configure portion of the build, -then submit to the dashboard, followed by the build portion, followed -by tests. If you invoke a custom target that depends on a step -halfway through the step dependency chain, then all the previous steps -will also run to ensure everything is up to date. - -For example, to drive configure, build and test steps independently -for each ``ExternalProject_Add`` call in your project, write the following -line prior to any ``ExternalProject_Add`` calls in your ``CMakeLists.txt`` -file:: - - set_property(DIRECTORY PROPERTY EP_STEP_TARGETS configure build test) +The following example shows how to download and build a hypothetical project +called *FooBar* from github: -.. command:: ExternalProject_Add_StepDependencies +.. code-block:: cmake + + include(ExternalProject) + ExternalProject_Add(foobar + GIT_REPOSITORY git@github.com:FooCo/FooBar.git + GIT_TAG origin/release/1.2.3 + ) + +For the sake of the example, also define a second hypothetical external project +called *SecretSauce*, which is downloaded from a web server. Two URLs are given +to take advantage of a faster internal network if available, with a fallback to +a slower external server. The project is a typical ``Makefile`` project with no +configure step, so some of the default commands are overridden. The build is +only required to build the *sauce* target: + +.. code-block:: cmake + + find_program(MAKE_EXE NAMES gmake nmake make) + ExternalProject_Add(secretsauce + URL http://intranet.somecompany.com/artifacts/sauce-2.7.tgz + https://www.somecompany.com/downloads/sauce-2.7.zip + URL_HASH MD5=d41d8cd98f00b204e9800998ecf8427e + CONFIGURE_COMMAND "" + BUILD_COMMAND ${MAKE_EXE} sauce + ) + +Suppose the build step of ``secretsauce`` requires that ``foobar`` must already +be built. This could be enforced like so: + +.. code-block:: cmake + + ExternalProject_Add_StepDependencies(secretsauce build foobar) + +Another alternative would be to create a custom target for ``foobar``'s build +step and make ``secretsauce`` depend on that rather than the whole ``foobar`` +project. This would mean ``foobar`` only needs to be built, it doesn't need to +run its install or test steps before ``secretsauce`` can be built. The +dependency can also be defined along with the ``secretsauce`` project: + +.. code-block:: cmake + + ExternalProject_Add_StepTargets(foobar build) + ExternalProject_Add(secretsauce + URL http://intranet.somecompany.com/artifacts/sauce-2.7.tgz + https://www.somecompany.com/downloads/sauce-2.7.zip + URL_HASH MD5=d41d8cd98f00b204e9800998ecf8427e + CONFIGURE_COMMAND "" + BUILD_COMMAND ${MAKE_EXE} sauce + DEPENDS foobar-build + ) + +Instead of calling :command:`ExternalProject_Add_StepTargets`, the target could +be defined along with the ``foobar`` project itself: + +.. code-block:: cmake + + ExternalProject_Add(foobar + GIT_REPOSITORY git@github.com:FooCo/FooBar.git + GIT_TAG origin/release/1.2.3 + STEP_TARGETS build + ) + +If many external projects should have the same set of step targets, setting a +directory property may be more convenient. The ``build`` step target could be +created automatically by setting the ``EP_STEP_TARGETS`` directory property +before creating the external projects with :command:`ExternalProject_Add`: + +.. code-block:: cmake + + set_property(DIRECTORY PROPERTY EP_STEP_TARGETS build) + +Lastly, suppose that ``secretsauce`` provides a script called ``makedoc`` which +can be used to generate its own documentation. Further suppose that the script +expects the output directory to be provided as the only parameter and that it +should be run from the ``secretsauce`` source directory. A custom step and a +custom target to trigger the script can be defined like so: + +.. code-block:: cmake + + ExternalProject_Add_Step(secretsauce docs + COMMAND <SOURCE_DIR>/makedoc <BINARY_DIR> + WORKING_DIRECTORY <SOURCE_DIR> + COMMENT "Building secretsauce docs" + ALWAYS TRUE + EXCLUDE_FROM_MAIN TRUE + ) + ExternalProject_Add_StepTargets(secretsauce docs) - The ``ExternalProject_Add_StepDependencies`` function add some - dependencies for some external project step:: +The custom step could then be triggered from the main build like so:: - ExternalProject_Add_StepDependencies(<name> <step> [target1 [target2 [...]]]) + cmake --build . --target secretsauce-docs - This function takes care to set both target and file level - dependencies, and will ensure that parallel builds will not break. - It should be used instead of :command:`add_dependencies()` when adding - a dependency for some of the step targets generated by - ``ExternalProject``. #]=======================================================================] # Pre-compute a regex to match documented keywords for each command. -math(EXPR _ep_documentation_line_count "${CMAKE_CURRENT_LIST_LINE} - 16") +math(EXPR _ep_documentation_line_count "${CMAKE_CURRENT_LIST_LINE} - 4") file(STRINGS "${CMAKE_CURRENT_LIST_FILE}" lines LIMIT_COUNT ${_ep_documentation_line_count} - REGEX "^\\.\\. command:: [A-Za-z0-9_]+|^ ``[A-Z0-9_]+ .*``$") + REGEX "^\\.\\. command:: [A-Za-z0-9_]+|^ +``[A-Z0-9_]+ [^`]*``$") foreach(line IN LISTS lines) if("${line}" MATCHES "^\\.\\. command:: ([A-Za-z0-9_]+)") if(_ep_func) @@ -421,7 +868,7 @@ foreach(line IN LISTS lines) #message("function [${_ep_func}]") set(_ep_keywords_${_ep_func} "^(") set(_ep_keyword_sep) - elseif("${line}" MATCHES "^ ``([A-Z0-9_]+) .*``$") + elseif("${line}" MATCHES "^ +``([A-Z0-9_]+) [^`]*``$") set(_ep_key "${CMAKE_MATCH_1}") #message(" keyword [${_ep_key}]") string(APPEND _ep_keywords_${_ep_func} @@ -504,7 +951,7 @@ define_property(DIRECTORY PROPERTY "EP_STEP_TARGETS" INHERITED BRIEF_DOCS "List of ExternalProject steps that automatically get corresponding targets" FULL_DOCS - "These targets will be dependent on the main target dependencies" + "These targets will be dependent on the main target dependencies. " "See documentation of the ExternalProject_Add_StepTargets() function in the " "ExternalProject module." ) @@ -513,7 +960,7 @@ define_property(DIRECTORY PROPERTY "EP_INDEPENDENT_STEP_TARGETS" INHERITED BRIEF_DOCS "List of ExternalProject steps that automatically get corresponding targets" FULL_DOCS - "These targets will not be dependent on the main target dependencies" + "These targets will not be dependent on the main target dependencies. " "See documentation of the ExternalProject_Add_StepTargets() function in the " "ExternalProject module." ) @@ -2012,12 +2459,12 @@ function(_ep_add_download_command name) " ${source_dir}\n" "is not an existing non-empty directory. Please specify one of:\n" " * SOURCE_DIR with an existing non-empty directory\n" + " * DOWNLOAD_COMMAND\n" " * URL\n" " * GIT_REPOSITORY\n" + " * SVN_REPOSITORY\n" " * HG_REPOSITORY\n" - " * CVS_REPOSITORY and CVS_MODULE\n" - " * SVN_REVISION\n" - " * DOWNLOAD_COMMAND" + " * CVS_REPOSITORY and CVS_MODULE" ) endif() endif() diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index cc273e0..b4abf75 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -244,6 +244,8 @@ if (NOT Boost_NO_BOOST_CMAKE) message("Found Boost components:") message(" ${Boost_FIND_COMPONENTS}") endif() + # Restore project's policies + cmake_policy(POP) return() endif() endif() diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index 3d32560..eb2242b 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -90,7 +90,7 @@ list(APPEND _JAVA_HINTS "[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\\2.6;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" @@ -143,7 +143,7 @@ if(Java_JAVA_EXECUTABLE) if(var MATCHES "java version \"([0-9]+\\.[0-9]+\\.[0-9_.]+.*)\"") # This is most likely Sun / OpenJDK, or maybe GCJ-java compat layer set(Java_VERSION_STRING "${CMAKE_MATCH_1}") - elseif(var MATCHES "openjdk version \"([0-9]+)-[a-z]+\"") + elseif(var MATCHES "openjdk version \"([0-9]+)-[A-Za-z]+\"") # OpenJDK 9 early access builds or locally built set(Java_VERSION_STRING "1.${CMAKE_MATCH_1}.0") elseif(var MATCHES "java full version \"kaffe-([0-9]+\\.[0-9]+\\.[0-9_]+)\"") diff --git a/Modules/FindLibXml2.cmake b/Modules/FindLibXml2.cmake index f68628d..8ac2980 100644 --- a/Modules/FindLibXml2.cmake +++ b/Modules/FindLibXml2.cmake @@ -50,6 +50,13 @@ find_path(LIBXML2_INCLUDE_DIR NAMES libxml/xpath.h PATH_SUFFIXES libxml2 ) +# CMake 3.9 and below used 'LIBXML2_LIBRARIES' as the name of +# the cache entry storing the find_library result. Use the +# value if it was set by the project or user. +if(DEFINED LIBXML2_LIBRARIES AND NOT DEFINED LIBXML2_LIBRARY) + set(LIBXML2_LIBRARY ${LIBXML2_LIBRARIES}) +endif() + find_library(LIBXML2_LIBRARY NAMES xml2 libxml2 HINTS ${PC_LIBXML_LIBDIR} diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 80bcda3..cd8246d 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -721,7 +721,7 @@ endfunction() # matlab_add_unit_test( # NAME <name> # UNITTEST_FILE matlab_file_containing_unittest.m -# [CUSTOM_MATLAB_COMMAND matlab_command_to_run_as_test] +# [CUSTOM_TEST_COMMAND matlab_command_to_run_as_test] # [UNITTEST_PRECOMMAND matlab_command_to_run] # [TIMEOUT timeout] # [ADDITIONAL_PATH path1 [path2 ...]] @@ -737,7 +737,7 @@ endfunction() # ``UNITTEST_FILE`` # the matlab unittest file. Its path will be automatically # added to the Matlab path. -# ``CUSTOM_MATLAB_COMMAND`` +# ``CUSTOM_TEST_COMMAND`` # Matlab script command to run as the test. # If this is not set, then the following is run: # ``runtests('matlab_file_name'), exit(max([ans(1,:).Failed]))`` diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake index 5faada3..80a8f41 100644 --- a/Modules/Platform/Android-Common.cmake +++ b/Modules/Platform/Android-Common.cmake @@ -160,13 +160,19 @@ macro(__android_compiler_common lang) # Do not do this for a standalone toolchain because it is already # tied to a specific API version. if(CMAKE_ANDROID_NDK) + if(CMAKE_SYSROOT_COMPILE) + set(_cmake_sysroot_compile "${CMAKE_SYSROOT_COMPILE}") + else() + set(_cmake_sysroot_compile "${CMAKE_SYSROOT}") + endif() if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES - "${CMAKE_SYSROOT_COMPILE}/usr/include" - "${CMAKE_SYSROOT_COMPILE}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}" + "${_cmake_sysroot_compile}/usr/include" + "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}" ) else() - list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${CMAKE_SYSROOT}/usr/include") + list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${_cmake_sysroot_compile}/usr/include") endif() + unset(_cmake_sysroot_compile) endif() endmacro() diff --git a/Modules/Platform/GHS-MULTI-Initialize.cmake b/Modules/Platform/GHS-MULTI-Initialize.cmake index fcda6f6..bf61d7b 100644 --- a/Modules/Platform/GHS-MULTI-Initialize.cmake +++ b/Modules/Platform/GHS-MULTI-Initialize.cmake @@ -10,7 +10,7 @@ if (NOT GHS_INT_DIRECTORY) if (EXISTS ${GHS_EXPECTED_ROOT}) FILE(GLOB GHS_CANDIDATE_INT_DIRS RELATIVE ${GHS_EXPECTED_ROOT} ${GHS_EXPECTED_ROOT}/*) - string(REGEX MATCHALL "int[0-9][0-9][0-9][0-9]" GHS_CANDIDATE_INT_DIRS + string(REGEX MATCHALL "int[0-9][0-9][0-9][0-9a-z]" GHS_CANDIDATE_INT_DIRS ${GHS_CANDIDATE_INT_DIRS}) if (GHS_CANDIDATE_INT_DIRS) list(SORT GHS_CANDIDATE_INT_DIRS) diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 456a6bd..c8b1cd7 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -121,8 +121,10 @@ macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile) endif() foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS}) - set(${outfiles} ${${outfiles}} - "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}${it}") + set(extra_file "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}${it}") + list(APPEND ${outfiles} ${extra_file}) + # Treat extra outputs as plain files regardless of language. + set_property(SOURCE "${extra_file}" PROPERTY LANGUAGE "") endforeach() endmacro() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index e556ca6..d35b7fb 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -1012,7 +1012,9 @@ target_link_libraries(cmake CMakeLib) if(CMake_ENABLE_SERVER_MODE) add_library(CMakeServerLib + cmConnection.h cmConnection.cxx cmFileMonitor.cxx cmFileMonitor.h + cmPipeConnection.cxx cmPipeConnection.h cmServer.cxx cmServer.h cmServerConnection.cxx cmServerConnection.h cmServerProtocol.cxx cmServerProtocol.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7a10ae1..45f7254 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 9) -set(CMake_VERSION_PATCH 20170717) +set(CMake_VERSION_PATCH 20170804) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 00d017e..0705460 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -6,6 +6,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" @@ -527,15 +528,13 @@ int cmCPackDebGenerator::createDeb() continue; } - char md5sum[33]; - if (!cmSystemTools::ComputeFileMD5(*fileIt, md5sum)) { + std::string output = + cmSystemTools::ComputeFileHash(*fileIt, cmCryptoHash::AlgoMD5); + if (output.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of " << *fileIt << std::endl); } - md5sum[32] = 0; - - std::string output(md5sum); output += " " + *fileIt + "\n"; // debian md5sums entries are like this: // 014f3604694729f3bf19263bac599765 usr/bin/ccmake diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 9864cf3..d4d2fdb 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -447,6 +447,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*"); mountpoint_regex.find(attach_output.c_str()); std::string const temp_mount = mountpoint_regex.match(1); + std::string const temp_mount_name = + temp_mount.substr(sizeof("/Volumes/") - 1); // Remove dummy padding file so we have enough space on RW image ... std::ostringstream dummy_padding; @@ -480,7 +482,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::ostringstream setup_script_command; setup_script_command << "osascript" << " \"" << cpack_dmg_ds_store_setup_script << "\"" - << " \"" << cpack_dmg_volume_name << "\""; + << " \"" << temp_mount_name << "\""; std::string error; if (!this->RunCommand(setup_script_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 8d62fa1..689668d 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -13,6 +13,7 @@ #include "cmCTest.h" #include "cmCTestCurl.h" #include "cmCTestScriptHandler.h" +#include "cmCryptoHash.h" #include "cmCurl.h" #include "cmGeneratedFileStream.h" #include "cmProcessOutput.h" @@ -428,10 +429,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) { upload_as += "bad_md5sum"; } else { - char md5[33]; - cmSystemTools::ComputeFileMD5(local_file, md5); - md5[32] = 0; - upload_as += md5; + upload_as += + cmSystemTools::ComputeFileHash(local_file, cmCryptoHash::AlgoMD5); } if (!cmSystemTools::FileExists(local_file.c_str())) { @@ -1058,9 +1057,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, } } - char md5sum[33]; - md5sum[32] = 0; - cmSystemTools::ComputeFileMD5(file, md5sum); + std::string md5sum = + cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5); // 1. request the buildid and check to see if the file // has already been uploaded // TODO I added support for subproject. You would need to add diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 8797204..ef0fac8 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1441,6 +1441,12 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) } xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "numeric/double"); + xml.Attribute("name", "Processors"); + xml.Element("Value", result->Properties->Processors); + xml.EndElement(); // NamedMeasurement + + xml.StartElement("NamedMeasurement"); xml.Attribute("type", "text/string"); xml.Attribute("name", "Completion Status"); xml.Element("Value", result->CompletionStatus); diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx new file mode 100644 index 0000000..00cf283 --- /dev/null +++ b/Source/cmConnection.cxx @@ -0,0 +1,158 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmConnection.h" + +#include "cmServer.h" +#include "cm_uv.h" + +#include <cassert> +#include <cstring> + +struct write_req_t +{ + uv_write_t req; + uv_buf_t buf; +}; + +void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) +{ + (void)(handle); + char* rawBuffer = new char[suggested_size]; + *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size)); +} + +void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread, + const uv_buf_t* buf) +{ + auto conn = reinterpret_cast<cmEventBasedConnection*>(stream->data); + if (conn) { + if (nread >= 0) { + conn->ReadData(std::string(buf->base, buf->base + nread)); + } else { + conn->OnDisconnect((int)nread); + } + } + + delete[](buf->base); +} + +void cmEventBasedConnection::on_close_delete(uv_handle_t* handle) +{ + delete handle; +} + +void cmEventBasedConnection::on_close(uv_handle_t* /*handle*/) +{ +} + +void cmEventBasedConnection::on_write(uv_write_t* req, int status) +{ + (void)(status); + + // Free req and buffer + write_req_t* wr = reinterpret_cast<write_req_t*>(req); + delete[](wr->buf.base); + delete wr; +} + +void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status) +{ + (void)(status); + auto conn = reinterpret_cast<cmEventBasedConnection*>(stream->data); + + if (conn) { + conn->Connect(stream); + } +} + +bool cmEventBasedConnection::IsOpen() const +{ + return this->WriteStream != CM_NULLPTR; +} + +void cmEventBasedConnection::WriteData(const std::string& data) +{ + assert(this->WriteStream); + + auto ds = data.size(); + + write_req_t* req = new write_req_t; + req->req.data = this; + req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds)); + memcpy(req->buf.base, data.c_str(), ds); + uv_write(reinterpret_cast<uv_write_t*>(req), + static_cast<uv_stream_t*>(this->WriteStream), &req->buf, 1, + on_write); +} + +void cmEventBasedConnection::ReadData(const std::string& data) +{ + this->RawReadBuffer += data; + if (BufferStrategy) { + std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer); + do { + ProcessRequest(packet); + packet = BufferStrategy->BufferMessage(this->RawReadBuffer); + } while (!packet.empty()); + + } else { + ProcessRequest(this->RawReadBuffer); + this->RawReadBuffer.clear(); + } +} + +cmEventBasedConnection::cmEventBasedConnection( + cmConnectionBufferStrategy* bufferStrategy) + : BufferStrategy(bufferStrategy) +{ +} + +void cmEventBasedConnection::Connect(uv_stream_t* server) +{ + (void)server; + Server->OnConnected(nullptr); +} + +void cmEventBasedConnection::OnDisconnect(int onerror) +{ + (void)onerror; + this->OnConnectionShuttingDown(); + this->Server->OnDisconnect(this); +} + +cmConnection::~cmConnection() +{ +} + +bool cmConnection::OnConnectionShuttingDown() +{ + return true; +} + +void cmConnection::SetServer(cmServerBase* s) +{ + Server = s; +} + +void cmConnection::ProcessRequest(const std::string& request) +{ + Server->ProcessRequest(this, request); +} + +bool cmConnection::OnServeStart(std::string* errString) +{ + (void)errString; + return true; +} + +bool cmEventBasedConnection::OnConnectionShuttingDown() +{ + this->WriteStream->data = nullptr; + this->ReadStream->data = nullptr; + + this->ReadStream = nullptr; + this->WriteStream = nullptr; + return true; +} diff --git a/Source/cmConnection.h b/Source/cmConnection.h new file mode 100644 index 0000000..4b8fcb3 --- /dev/null +++ b/Source/cmConnection.h @@ -0,0 +1,118 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#pragma once + +#include "cmConfigure.h" + +#include "cm_uv.h" + +#include <cstddef> +#include <memory> +#include <string> + +class cmServerBase; + +/*** + * Given a sequence of bytes with any kind of buffering, instances of this + * class arrange logical chunks according to whatever the use case is for + * the connection. + */ +class cmConnectionBufferStrategy +{ +public: + virtual ~cmConnectionBufferStrategy(); + + /*** + * Called whenever with an active raw buffer. If a logical chunk + * becomes available, that chunk is returned and that portion is + * removed from the rawBuffer + * + * @param rawBuffer in/out parameter. Receive buffer; the buffer strategy is + * free to manipulate this buffer anyway it needs to. + * + * @return Next chunk from the stream. Returns the empty string if a chunk + * isn't ready yet. Users of this interface should repeatedly call this + * function until an empty string is returned since its entirely possible + * multiple chunks come in a single raw buffer. + */ + virtual std::string BufferMessage(std::string& rawBuffer) = 0; + + /*** + * Resets the internal state of the buffering + */ + virtual void clear(); + + // TODO: There should be a callback / flag set for errors +}; + +class cmConnection +{ + CM_DISABLE_COPY(cmConnection) + +public: + cmConnection() {} + + virtual void WriteData(const std::string& data) = 0; + + virtual ~cmConnection(); + + virtual bool OnConnectionShuttingDown(); + + virtual bool IsOpen() const = 0; + + virtual void SetServer(cmServerBase* s); + + virtual void ProcessRequest(const std::string& request); + + virtual bool OnServeStart(std::string* pString); + +protected: + cmServerBase* Server = nullptr; +}; + +/*** + * Abstraction of a connection; ties in event callbacks from libuv and notifies + * the server when appropriate + */ +class cmEventBasedConnection : public cmConnection +{ + +public: + /*** + * @param bufferStrategy If no strategy is given, it will process the raw + * chunks as they come in. The connection + * owns the pointer given. + */ + cmEventBasedConnection(cmConnectionBufferStrategy* bufferStrategy = nullptr); + + virtual void Connect(uv_stream_t* server); + + virtual void ReadData(const std::string& data); + + bool IsOpen() const override; + + void WriteData(const std::string& data) override; + bool OnConnectionShuttingDown() override; + + virtual void OnDisconnect(int errorCode); + uv_stream_t* ReadStream = nullptr; + uv_stream_t* WriteStream = nullptr; + + static void on_close(uv_handle_t* handle); + static void on_close_delete(uv_handle_t* handle); + +protected: + std::string RawReadBuffer; + + std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy; + + static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); + + static void on_write(uv_write_t* req, int status); + + static void on_new_connection(uv_stream_t* stream, int status); + + static void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, + uv_buf_t* buf); +}; diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx index 8027535..c0401d7 100644 --- a/Source/cmFileMonitor.cxx +++ b/Source/cmFileMonitor.cxx @@ -171,7 +171,9 @@ public: { if (this->Handle) { uv_fs_event_stop(this->Handle); - uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close); + if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(this->Handle))) { + uv_close(reinterpret_cast<uv_handle_t*>(this->Handle), &on_fs_close); + } this->Handle = nullptr; } cmVirtualDirectoryWatcher::StopWatching(); diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index f291f9d..ca47535 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1090,6 +1090,9 @@ void cmFindPackageCommand::AppendSuccessInformation() void cmFindPackageCommand::ComputePrefixes() { if (!this->NoDefaultPath) { + if (!this->NoPackageRootPath) { + this->FillPrefixesPackageRoot(); + } if (!this->NoCMakePath) { this->FillPrefixesCMakeVariable(); } @@ -1117,6 +1120,23 @@ void cmFindPackageCommand::ComputePrefixes() this->ComputeFinalPaths(); } +void cmFindPackageCommand::FillPrefixesPackageRoot() +{ + cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot]; + + // Add package specific search prefixes + // NOTE: This should be using const_reverse_iterator but HP aCC and + // Oracle sunCC both currently have standard library issues + // with the reverse iterator APIs. + for (std::deque<std::string>::reverse_iterator pkg = + this->Makefile->FindPackageModuleStack.rbegin(); + pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) { + std::string varName = *pkg + "_ROOT"; + paths.AddCMakePath(varName); + paths.AddEnvPath(varName); + } +} + void cmFindPackageCommand::FillPrefixesCMakeEnvironment() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment]; diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 318b1dc..99b0059 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -100,6 +100,7 @@ private: void StoreVersionFound(); void ComputePrefixes(); + void FillPrefixesPackageRoot(); void FillPrefixesCMakeEnvironment(); void FillPrefixesCMakeVariable(); void FillPrefixesSystemEnvironment(); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1802da4..329c7a9 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1025,12 +1025,23 @@ cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources( std::string const key = cmSystemTools::UpperCase(config); KindedSourcesMapType::iterator it = this->KindedSourcesMap.find(key); if (it != this->KindedSourcesMap.end()) { + if (!it->second.Initialized) { + std::ostringstream e; + e << "The SOURCES of \"" << this->GetName() + << "\" use a generator expression that depends on the " + "SOURCES themselves."; + this->GlobalGenerator->GetCMakeInstance()->IssueMessage( + cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); + static KindedSources empty; + return empty; + } return it->second; } // Add an entry to the map for this configuration. KindedSources& files = this->KindedSourcesMap[key]; this->ComputeKindedSources(files, config); + files.Initialized = true; return files; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index c04d62b..52147e3 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -107,6 +107,11 @@ public: std::set<std::string> ExpectedResxHeaders; std::set<std::string> ExpectedXamlHeaders; std::set<std::string> ExpectedXamlSources; + bool Initialized; + KindedSources() + : Initialized(false) + { + } }; /** Get all sources needed for a configuration with kinds assigned. */ diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index e3835ff..4fff11a 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -757,6 +757,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) std::vector<std::string> cmd; cmd.push_back(this->GetMSBuildCommand()); cmd.push_back(vcxproj); + cmd.push_back("/p:Configuration=Debug"); cmd.push_back(std::string("/p:VisualStudioVersion=") + this->GetIDEVersion()); std::string out; diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx new file mode 100644 index 0000000..cc82438 --- /dev/null +++ b/Source/cmPipeConnection.cxx @@ -0,0 +1,80 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmPipeConnection.h" + +#include "cmConfigure.h" +#include "cmServer.h" + +cmPipeConnection::cmPipeConnection(const std::string& name, + cmConnectionBufferStrategy* bufferStrategy) + : cmEventBasedConnection(bufferStrategy) + , PipeName(name) +{ +} + +void cmPipeConnection::Connect(uv_stream_t* server) +{ + if (this->ClientPipe) { + // Accept and close all pipes but the first: + uv_pipe_t* rejectPipe = new uv_pipe_t(); + + uv_pipe_init(this->Server->GetLoop(), rejectPipe, 0); + uv_accept(server, reinterpret_cast<uv_stream_t*>(rejectPipe)); + uv_close(reinterpret_cast<uv_handle_t*>(rejectPipe), &on_close_delete); + return; + } + + this->ClientPipe = new uv_pipe_t(); + uv_pipe_init(this->Server->GetLoop(), this->ClientPipe, 0); + this->ClientPipe->data = static_cast<cmEventBasedConnection*>(this); + auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe); + if (uv_accept(server, client) != 0) { + uv_close(reinterpret_cast<uv_handle_t*>(client), &on_close_delete); + this->ClientPipe = CM_NULLPTR; + return; + } + this->ReadStream = client; + this->WriteStream = client; + + uv_read_start(this->ReadStream, on_alloc_buffer, on_read); + Server->OnConnected(this); +} + +bool cmPipeConnection::OnServeStart(std::string* errorMessage) +{ + this->ServerPipe = new uv_pipe_t(); + uv_pipe_init(this->Server->GetLoop(), this->ServerPipe, 0); + this->ServerPipe->data = static_cast<cmEventBasedConnection*>(this); + + int r; + if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) { + *errorMessage = std::string("Internal Error with ") + this->PipeName + + ": " + uv_err_name(r); + return false; + } + auto serverStream = reinterpret_cast<uv_stream_t*>(this->ServerPipe); + if ((r = uv_listen(serverStream, 1, on_new_connection)) != 0) { + *errorMessage = std::string("Internal Error listening on ") + + this->PipeName + ": " + uv_err_name(r); + return false; + } + + return cmConnection::OnServeStart(errorMessage); +} + +bool cmPipeConnection::OnConnectionShuttingDown() +{ + if (this->ClientPipe) { + uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe), + &on_close_delete); + this->WriteStream->data = nullptr; + } + uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe), &on_close_delete); + + this->ClientPipe = nullptr; + this->ServerPipe = nullptr; + this->WriteStream = nullptr; + this->ReadStream = nullptr; + + return cmConnection::OnConnectionShuttingDown(); +} diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h new file mode 100644 index 0000000..fea85b5 --- /dev/null +++ b/Source/cmPipeConnection.h @@ -0,0 +1,28 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#pragma once + +#include "cmConnection.h" + +#include "cm_uv.h" + +#include <string> + +class cmPipeConnection : public cmEventBasedConnection +{ +public: + cmPipeConnection(const std::string& name, + cmConnectionBufferStrategy* bufferStrategy = nullptr); + + bool OnServeStart(std::string* pString) override; + + bool OnConnectionShuttingDown() override; + + void Connect(uv_stream_t* server) override; + +private: + const std::string PipeName; + uv_pipe_t* ServerPipe = nullptr; + uv_pipe_t* ClientPipe = nullptr; +}; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 0a0178c..354011a 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -209,7 +209,9 @@ class cmMakefile; cmPolicies::WARN) \ SELECT(POLICY, CMP0070, \ "Define file(GENERATE) behavior for relative paths.", 3, 10, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0071, "Let AUTOMOC and AUTOUIC process GENERATED files.", \ + 3, 10, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index cecf165..108241a 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -11,6 +11,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" @@ -28,6 +29,7 @@ #include <algorithm> #include <map> #include <set> +#include <sstream> #include <string> #include <utility> #include <vector> @@ -290,6 +292,8 @@ static void AcquireScanFiles(cmGeneratorTarget const* target, { const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); + const cmPolicies::PolicyStatus CMP0071_status = + target->Makefile->GetPolicyStatus(cmPolicies::CMP0071); std::vector<cmSourceFile*> srcFiles; target->GetConfigCommonSourceFiles(srcFiles); @@ -298,24 +302,46 @@ static void AcquireScanFiles(cmGeneratorTarget const* target, cmSourceFile* sf = *fileIt; const cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { continue; } - if (PropertyEnabled(sf, "GENERATED") && - !target->GetPropertyAsBool("__UNDOCUMENTED_AUTOGEN_GENERATED_FILES")) { - // FIXME: Add a policy whose NEW behavior allows generated files. - // The implementation already works. We disable it here to avoid - // changing behavior for existing projects that do not expect it. - continue; - } + const std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); // Skip flags const bool skipAll = PropertyEnabled(sf, "SKIP_AUTOGEN"); const bool mocSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOMOC"); const bool uicSkip = skipAll || PropertyEnabled(sf, "SKIP_AUTOUIC"); + const bool accept = (mocTarget && !mocSkip) || (uicTarget && !uicSkip); + + // For GENERATED files check status of policy CMP0071 + if (accept && PropertyEnabled(sf, "GENERATED")) { + bool policyAccept = false; + switch (CMP0071_status) { + case cmPolicies::WARN: { + std::ostringstream ost; + ost << cmPolicies::GetPolicyWarning(cmPolicies::CMP0071) << "\n"; + ost << "AUTOMOC/AUTOUIC: Ignoring GENERATED source file:\n"; + ost << " " << cmQtAutoGeneratorCommon::Quoted(absFile) << "\n"; + target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, ost.str()); + } + CM_FALLTHROUGH; + case cmPolicies::OLD: + // Ignore GENERATED file + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Process GENERATED file + policyAccept = true; + break; + } + if (!policyAccept) { + continue; + } + } + // Add file name to skip lists. // Do this even when the file is not added to the sources/headers lists // because the file name may be extracted from an other file when @@ -327,7 +353,7 @@ static void AcquireScanFiles(cmGeneratorTarget const* target, uicSkipList.push_back(absFile); } - if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { + if (accept) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -719,7 +745,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( const std::string qtMajorVersion = GetQtMajorVersion(target); const std::string rccCommand = RccGetExecutable(target, qtMajorVersion); const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile); - std::vector<std::string> autogenDepends; + std::set<std::string> autogenDependsSet; std::vector<std::string> autogenProvides; // Remove build directories on cleanup @@ -811,7 +837,20 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // Initialize autogen target dependencies if (const char* deps = target->GetProperty("AUTOGEN_TARGET_DEPENDS")) { - cmSystemTools::ExpandListArgument(deps, autogenDepends); + std::vector<std::string> extraDepends; + cmSystemTools::ExpandListArgument(deps, extraDepends); + autogenDependsSet.insert(extraDepends.begin(), extraDepends.end()); + } + // Add other target dependencies autogen dependencies + { + const std::set<std::string>& utils = target->Target->GetUtilities(); + for (std::set<std::string>::const_iterator it = utils.begin(); + it != utils.end(); ++it) { + const std::string& targetName = *it; + if (makefile->FindTargetToUse(targetName) != CM_NULLPTR) { + autogenDependsSet.insert(targetName); + } + } } // Add link library targets to the autogen dependencies { @@ -821,7 +860,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( it != libVec.end(); ++it) { const std::string& libName = it->first; if (makefile->FindTargetToUse(libName) != CM_NULLPTR) { - autogenDepends.push_back(libName); + autogenDependsSet.insert(libName); } } } @@ -845,7 +884,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (PropertyEnabled(sf, "GENERATED")) { if ((mocEnabled && !PropertyEnabled(sf, "SKIP_AUTOMOC")) || (uicEnabled && !PropertyEnabled(sf, "SKIP_AUTOUIC"))) { - autogenDepends.push_back( + autogenDependsSet.insert( cmsys::SystemTools::GetRealPath(sf->GetFullPath())); #if defined(_WIN32) && !defined(__CYGWIN__) // Cannot use PRE_BUILD with generated files @@ -890,17 +929,22 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (PropertyEnabled(sf, "GENERATED")) { // Add generated qrc file to the dependencies - autogenDepends.push_back(absFile); + autogenDependsSet.insert(absFile); } else { // Run cmake again when .qrc file changes makefile->AddCMakeDependFile(absFile); - // Add the qrc input files to the dependencies - std::string error; - if (!cmQtAutoGeneratorCommon::RccListInputs( - qtMajorVersion, rccCommand, absFile, autogenDepends, - &error)) { - cmSystemTools::Error(error.c_str()); + { + std::string error; + std::vector<std::string> extraDepends; + if (cmQtAutoGeneratorCommon::RccListInputs( + qtMajorVersion, rccCommand, absFile, extraDepends, + &error)) { + autogenDependsSet.insert(extraDepends.begin(), + extraDepends.end()); + } else { + cmSystemTools::Error(error.c_str()); + } } } #if defined(_WIN32) && !defined(__CYGWIN__) @@ -914,10 +958,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } } + // Convert std::set to std::vector + const std::vector<std::string> autogenDepends(autogenDependsSet.begin(), + autogenDependsSet.end()); #if defined(_WIN32) && !defined(__CYGWIN__) if (usePRE_BUILD) { // If the autogen target depends on an other target don't use PRE_BUILD - for (std::vector<std::string>::iterator it = autogenDepends.begin(); + for (std::vector<std::string>::const_iterator it = autogenDepends.begin(); it != autogenDepends.end(); ++it) { if (makefile->FindTargetToUse(*it) != CM_NULLPTR) { usePRE_BUILD = false; diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 5283dfc..ccb9af6 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -2,7 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmServer.h" -#include "cmServerConnection.h" +#include "cmConnection.h" +#include "cmFileMonitor.h" #include "cmServerDictionary.h" #include "cmServerProtocol.h" #include "cmSystemTools.h" @@ -14,8 +15,23 @@ #include <algorithm> #include <cassert> #include <cstdint> +#include <memory> #include <utility> +void on_signal(uv_signal_t* signal, int signum) +{ + auto conn = reinterpret_cast<cmServerBase*>(signal->data); + conn->OnSignal(signum); +} + +static void on_walk_to_shutdown(uv_handle_t* handle, void* arg) +{ + (void)arg; + if (!uv_is_closing(handle)) { + uv_close(handle, &cmEventBasedConnection::on_close); + } +} + class cmServer::DebugInfo { public: @@ -30,11 +46,10 @@ public: uint64_t StartTime; }; -cmServer::cmServer(cmServerConnection* conn, bool supportExperimental) - : Connection(conn) +cmServer::cmServer(cmConnection* conn, bool supportExperimental) + : cmServerBase(conn) , SupportExperimental(supportExperimental) { - this->Connection->SetServer(this); // Register supported protocols: this->RegisterProtocol(new cmServerProtocol1); } @@ -48,23 +63,15 @@ cmServer::~cmServer() for (cmServerProtocol* p : this->SupportedProtocols) { delete p; } - - delete this->Connection; } -void cmServer::PopOne() +void cmServer::ProcessRequest(cmConnection* connection, + const std::string& input) { - if (this->Queue.empty()) { - return; - } - Json::Reader reader; Json::Value value; - const std::string input = this->Queue.front(); - this->Queue.erase(this->Queue.begin()); - if (!reader.parse(input, value)) { - this->WriteParseError("Failed to parse JSON input."); + this->WriteParseError(connection, "Failed to parse JSON input."); return; } @@ -76,13 +83,13 @@ void cmServer::PopOne() debug->PrintStatistics = debugValue["showStats"].asBool(); } - const cmServerRequest request(this, value[kTYPE_KEY].asString(), + const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(), value[kCOOKIE_KEY].asString(), value); if (request.Type == "") { cmServerResponse response(request); response.SetError("No type given in request."); - this->WriteResponse(response, nullptr); + this->WriteResponse(connection, response, nullptr); return; } @@ -91,9 +98,11 @@ void cmServer::PopOne() if (this->Protocol) { this->Protocol->CMakeInstance()->SetProgressCallback( reportProgress, const_cast<cmServerRequest*>(&request)); - this->WriteResponse(this->Protocol->Process(request), debug.get()); + this->WriteResponse(connection, this->Protocol->Process(request), + debug.get()); } else { - this->WriteResponse(this->SetProtocolVersion(request), debug.get()); + this->WriteResponse(connection, this->SetProtocolVersion(request), + debug.get()); } } @@ -115,7 +124,7 @@ void cmServer::RegisterProtocol(cmServerProtocol* protocol) } } -void cmServer::PrintHello() const +void cmServer::PrintHello(cmConnection* connection) const { Json::Value hello = Json::objectValue; hello[kTYPE_KEY] = "hello"; @@ -134,13 +143,7 @@ void cmServer::PrintHello() const protocolVersions.append(tmp); } - this->WriteJsonObject(hello, nullptr); -} - -void cmServer::QueueRequest(const std::string& request) -{ - this->Queue.push_back(request); - this->PopOne(); + this->WriteJsonObject(connection, hello, nullptr); } void cmServer::reportProgress(const char* msg, float progress, void* data) @@ -232,17 +235,26 @@ bool cmServer::Serve(std::string* errorMessage) } assert(!this->Protocol); - return Connection->ProcessEvents(errorMessage); + return cmServerBase::Serve(errorMessage); } cmFileMonitor* cmServer::FileMonitor() const { - return Connection->FileMonitor(); + return fileMonitor.get(); } void cmServer::WriteJsonObject(const Json::Value& jsonValue, const DebugInfo* debug) const { + for (auto& connection : this->Connections) { + WriteJsonObject(connection.get(), jsonValue, debug); + } +} + +void cmServer::WriteJsonObject(cmConnection* connection, + const Json::Value& jsonValue, + const DebugInfo* debug) const +{ Json::FastWriter writer; auto beforeJson = uv_hrtime(); @@ -272,7 +284,7 @@ void cmServer::WriteJsonObject(const Json::Value& jsonValue, } } - Connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") + + connection->WriteData(std::string("\n") + kSTART_MAGIC + std::string("\n") + result + kEND_MAGIC + std::string("\n")); } @@ -311,7 +323,7 @@ void cmServer::WriteProgress(const cmServerRequest& request, int min, obj[kPROGRESS_MAXIMUM_KEY] = max; obj[kPROGRESS_CURRENT_KEY] = current; - this->WriteJsonObject(obj, nullptr); + this->WriteJsonObject(request.Connection, obj, nullptr); } void cmServer::WriteMessage(const cmServerRequest& request, @@ -331,10 +343,11 @@ void cmServer::WriteMessage(const cmServerRequest& request, obj[kTITLE_KEY] = title; } - WriteJsonObject(obj, nullptr); + WriteJsonObject(request.Connection, obj, nullptr); } -void cmServer::WriteParseError(const std::string& message) const +void cmServer::WriteParseError(cmConnection* connection, + const std::string& message) const { Json::Value obj = Json::objectValue; obj[kTYPE_KEY] = kERROR_TYPE; @@ -342,7 +355,7 @@ void cmServer::WriteParseError(const std::string& message) const obj[kREPLY_TO_KEY] = ""; obj[kCOOKIE_KEY] = ""; - this->WriteJsonObject(obj, nullptr); + this->WriteJsonObject(connection, obj, nullptr); } void cmServer::WriteSignal(const std::string& name, @@ -358,7 +371,8 @@ void cmServer::WriteSignal(const std::string& name, WriteJsonObject(obj, nullptr); } -void cmServer::WriteResponse(const cmServerResponse& response, +void cmServer::WriteResponse(cmConnection* connection, + const cmServerResponse& response, const DebugInfo* debug) const { assert(response.IsComplete()); @@ -371,5 +385,161 @@ void cmServer::WriteResponse(const cmServerResponse& response, obj[kERROR_MESSAGE_KEY] = response.ErrorMessage(); } - this->WriteJsonObject(obj, debug); + this->WriteJsonObject(connection, obj, debug); +} + +void cmServer::OnConnected(cmConnection* connection) +{ + PrintHello(connection); +} + +void cmServer::OnServeStart() +{ + cmServerBase::OnServeStart(); + fileMonitor = std::make_shared<cmFileMonitor>(GetLoop()); +} + +void cmServer::StartShutDown() +{ + if (fileMonitor) { + fileMonitor->StopMonitoring(); + fileMonitor.reset(); + } + cmServerBase::StartShutDown(); +} + +static void __start_thread(void* arg) +{ + auto server = reinterpret_cast<cmServerBase*>(arg); + std::string error; + server->Serve(&error); +} + +bool cmServerBase::StartServeThread() +{ + ServeThreadRunning = true; + uv_thread_create(&ServeThread, __start_thread, this); + return true; +} + +bool cmServerBase::Serve(std::string* errorMessage) +{ + errorMessage->clear(); + + uv_signal_init(&Loop, &this->SIGINTHandler); + uv_signal_init(&Loop, &this->SIGHUPHandler); + + this->SIGINTHandler.data = this; + this->SIGHUPHandler.data = this; + + uv_signal_start(&this->SIGINTHandler, &on_signal, SIGINT); + uv_signal_start(&this->SIGHUPHandler, &on_signal, SIGHUP); + + OnServeStart(); + + for (auto& connection : Connections) { + if (!connection->OnServeStart(errorMessage)) { + return false; + } + } + + if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { + *errorMessage = "Internal Error: Event loop stopped in unclean state."; + StartShutDown(); + return false; + } + + ServeThreadRunning = false; + return true; +} + +void cmServerBase::OnConnected(cmConnection*) +{ +} + +void cmServerBase::OnDisconnect() +{ +} + +void cmServerBase::OnServeStart() +{ + uv_signal_start(&this->SIGINTHandler, &on_signal, SIGINT); + uv_signal_start(&this->SIGHUPHandler, &on_signal, SIGHUP); +} + +void cmServerBase::StartShutDown() +{ + if (!uv_is_closing((const uv_handle_t*)&this->SIGINTHandler)) { + uv_signal_stop(&this->SIGINTHandler); + } + + if (!uv_is_closing((const uv_handle_t*)&this->SIGHUPHandler)) { + uv_signal_stop(&this->SIGHUPHandler); + } + + for (auto& connection : Connections) { + connection->OnConnectionShuttingDown(); + } + Connections.clear(); + + uv_stop(&Loop); + + uv_walk(&Loop, on_walk_to_shutdown, CM_NULLPTR); + + uv_run(&Loop, UV_RUN_DEFAULT); +} + +bool cmServerBase::OnSignal(int signum) +{ + (void)signum; + StartShutDown(); + return true; +} + +cmServerBase::cmServerBase(cmConnection* connection) +{ + uv_loop_init(&Loop); + + uv_signal_init(&Loop, &this->SIGINTHandler); + uv_signal_init(&Loop, &this->SIGHUPHandler); + + this->SIGINTHandler.data = this; + this->SIGHUPHandler.data = this; + + AddNewConnection(connection); +} + +cmServerBase::~cmServerBase() +{ + + if (ServeThreadRunning) { + StartShutDown(); + uv_thread_join(&ServeThread); + } + + uv_loop_close(&Loop); +} + +void cmServerBase::AddNewConnection(cmConnection* ownedConnection) +{ + Connections.emplace_back(ownedConnection); + ownedConnection->SetServer(this); +} + +uv_loop_t* cmServerBase::GetLoop() +{ + return &Loop; +} + +void cmServerBase::OnDisconnect(cmConnection* pConnection) +{ + auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) { + return m.get() == pConnection; + }; + Connections.erase( + std::remove_if(Connections.begin(), Connections.end(), pred), + Connections.end()); + if (Connections.empty()) { + StartShutDown(); + } } diff --git a/Source/cmServer.h b/Source/cmServer.h index b814050..0000704 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -7,26 +7,83 @@ #include "cm_jsoncpp_value.h" #include "cm_uv.h" +#include <memory> // IWYU pragma: keep #include <string> #include <vector> +class cmConnection; class cmFileMonitor; -class cmServerConnection; class cmServerProtocol; class cmServerRequest; class cmServerResponse; -class cmServer +/*** + * This essentially hold and manages a libuv event queue and responds to + * messages + * on any of its connections. + */ +class cmServerBase +{ +public: + cmServerBase(cmConnection* connection); + virtual ~cmServerBase(); + + virtual void AddNewConnection(cmConnection* ownedConnection); + + /*** + * The main override responsible for tailoring behavior towards + * whatever the given server is supposed to do + * + * This should almost always be called by the given connections + * directly. + * + * @param connection The connectiont the request was received on + * @param request The actual request + */ + virtual void ProcessRequest(cmConnection* connection, + const std::string& request) = 0; + virtual void OnConnected(cmConnection* connection); + virtual void OnDisconnect(); + + /*** + * Start a dedicated thread. If this is used to start the server, it will + * join on the + * servers dtor. + */ + virtual bool StartServeThread(); + virtual bool Serve(std::string* errorMessage); + + virtual void OnServeStart(); + virtual void StartShutDown(); + + virtual bool OnSignal(int signum); + uv_loop_t* GetLoop(); + + void OnDisconnect(cmConnection* pConnection); + +protected: + std::vector<std::unique_ptr<cmConnection> > Connections; + + bool ServeThreadRunning = false; + uv_thread_t ServeThread; + + uv_loop_t Loop; + + uv_signal_t SIGINTHandler; + uv_signal_t SIGHUPHandler; +}; + +class cmServer : public cmServerBase { CM_DISABLE_COPY(cmServer) public: class DebugInfo; - cmServer(cmServerConnection* conn, bool supportExperimental); - ~cmServer(); + cmServer(cmConnection* conn, bool supportExperimental); + ~cmServer() override; - bool Serve(std::string* errorMessage); + bool Serve(std::string* errorMessage) override; cmFileMonitor* FileMonitor() const; @@ -34,9 +91,20 @@ private: void RegisterProtocol(cmServerProtocol* protocol); // Callbacks from cmServerConnection: - void PopOne(); - void QueueRequest(const std::string& request); + void ProcessRequest(cmConnection* connection, + const std::string& request) override; + std::shared_ptr<cmFileMonitor> fileMonitor; + +public: + void OnServeStart() override; + + void StartShutDown() override; + +public: + void OnConnected(cmConnection* connection) override; + +private: static void reportProgress(const char* msg, float progress, void* data); static void reportMessage(const char* msg, const char* title, bool& cancel, void* data); @@ -44,36 +112,37 @@ private: // Handle requests: cmServerResponse SetProtocolVersion(const cmServerRequest& request); - void PrintHello() const; + void PrintHello(cmConnection* connection) const; // Write responses: void WriteProgress(const cmServerRequest& request, int min, int current, int max, const std::string& message) const; void WriteMessage(const cmServerRequest& request, const std::string& message, const std::string& title) const; - void WriteResponse(const cmServerResponse& response, + void WriteResponse(cmConnection* connection, + const cmServerResponse& response, const DebugInfo* debug) const; - void WriteParseError(const std::string& message) const; + void WriteParseError(cmConnection* connection, + const std::string& message) const; void WriteSignal(const std::string& name, const Json::Value& obj) const; void WriteJsonObject(Json::Value const& jsonValue, const DebugInfo* debug) const; + void WriteJsonObject(cmConnection* connection, Json::Value const& jsonValue, + const DebugInfo* debug) const; + static cmServerProtocol* FindMatchingProtocol( const std::vector<cmServerProtocol*>& protocols, int major, int minor); - cmServerConnection* Connection = nullptr; const bool SupportExperimental; cmServerProtocol* Protocol = nullptr; std::vector<cmServerProtocol*> SupportedProtocols; - std::vector<std::string> Queue; std::string DataBuffer; std::string JsonData; - uv_loop_t* Loop = nullptr; - typedef union { uv_tty_t tty; @@ -87,7 +156,6 @@ private: mutable bool Writing = false; - friend class cmServerConnection; friend class cmServerProtocol; friend class cmServerRequest; }; diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx index 36312ed..4891131 100644 --- a/Source/cmServerConnection.cxx +++ b/Source/cmServerConnection.cxx @@ -2,376 +2,123 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmServerConnection.h" -#include "cmFileMonitor.h" #include "cmServer.h" #include "cmServerDictionary.h" -#include <assert.h> -#include <string.h> - -namespace { - -struct write_req_t +cmStdIoConnection::cmStdIoConnection( + cmConnectionBufferStrategy* bufferStrategy) + : cmEventBasedConnection(bufferStrategy) + , Input() + , Output() { - uv_write_t req; - uv_buf_t buf; -}; - -void on_alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) -{ - (void)(handle); - char* rawBuffer = new char[suggested_size]; - *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size)); -} - -void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) -{ - auto conn = reinterpret_cast<cmServerConnection*>(stream->data); - if (nread >= 0) { - conn->ReadData(std::string(buf->base, buf->base + nread)); - } else { - conn->TriggerShutdown(); - } - - delete[](buf->base); } -void on_write(uv_write_t* req, int status) +void cmStdIoConnection::SetServer(cmServerBase* s) { - (void)(status); - auto conn = reinterpret_cast<cmServerConnection*>(req->data); - - // Free req and buffer - write_req_t* wr = reinterpret_cast<write_req_t*>(req); - delete[](wr->buf.base); - delete wr; + cmConnection::SetServer(s); - conn->ProcessNextRequest(); -} + if (uv_guess_handle(1) == UV_TTY) { + usesTty = true; -void on_new_connection(uv_stream_t* stream, int status) -{ - (void)(status); - auto conn = reinterpret_cast<cmServerConnection*>(stream->data); - conn->Connect(stream); -} + this->Input.tty = new uv_tty_t(); + uv_tty_init(this->Server->GetLoop(), this->Input.tty, 0, 1); + uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL); + this->Input.tty->data = static_cast<cmEventBasedConnection*>(this); + this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty); -void on_signal(uv_signal_t* signal, int signum) -{ - auto conn = reinterpret_cast<cmServerConnection*>(signal->data); - (void)(signum); - conn->TriggerShutdown(); -} + this->Output.tty = new uv_tty_t(); + uv_tty_init(this->Server->GetLoop(), this->Output.tty, 1, 0); + uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL); + this->Output.tty->data = static_cast<cmEventBasedConnection*>(this); + this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty); + } else { + usesTty = false; -void on_signal_close(uv_handle_t* handle) -{ - delete reinterpret_cast<uv_signal_t*>(handle); -} + this->Input.pipe = new uv_pipe_t(); + uv_pipe_init(this->Server->GetLoop(), this->Input.pipe, 0); + uv_pipe_open(this->Input.pipe, 0); + this->Input.pipe->data = static_cast<cmEventBasedConnection*>(this); + this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe); -void on_pipe_close(uv_handle_t* handle) -{ - delete reinterpret_cast<uv_pipe_t*>(handle); + this->Output.pipe = new uv_pipe_t(); + uv_pipe_init(this->Server->GetLoop(), this->Output.pipe, 0); + uv_pipe_open(this->Output.pipe, 1); + this->Output.pipe->data = static_cast<cmEventBasedConnection*>(this); + this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe); + } } -void on_tty_close(uv_handle_t* handle) +bool cmStdIoConnection::OnServeStart(std::string* pString) { - delete reinterpret_cast<uv_tty_t*>(handle); + uv_read_start(this->ReadStream, on_alloc_buffer, on_read); + Server->OnConnected(this); + return cmConnection::OnServeStart(pString); } -} // namespace - -class LoopGuard +bool cmStdIoConnection::OnConnectionShuttingDown() { -public: - LoopGuard(cmServerConnection* connection) - : Connection(connection) - { - this->Connection->mLoop = uv_default_loop(); - if (!this->Connection->mLoop) { - return; - } - this->Connection->mFileMonitor = - new cmFileMonitor(this->Connection->mLoop); - } - - ~LoopGuard() - { - if (!this->Connection->mLoop) { - return; - } + cmEventBasedConnection::OnConnectionShuttingDown(); - if (this->Connection->mFileMonitor) { - delete this->Connection->mFileMonitor; - } - uv_loop_close(this->Connection->mLoop); - this->Connection->mLoop = nullptr; + if (usesTty) { + uv_read_stop(reinterpret_cast<uv_stream_t*>(this->Input.tty)); + uv_close(reinterpret_cast<uv_handle_t*>(this->Input.tty), + &on_close_delete); + uv_close(reinterpret_cast<uv_handle_t*>(this->Output.tty), + &on_close_delete); + } else { + uv_close(reinterpret_cast<uv_handle_t*>(this->Input.pipe), + &on_close_delete); + uv_close(reinterpret_cast<uv_handle_t*>(this->Output.pipe), + &on_close_delete); } -private: - cmServerConnection* Connection; -}; + return true; +} -cmServerConnection::cmServerConnection() +cmServerPipeConnection::cmServerPipeConnection(const std::string& name) + : cmPipeConnection(name, new cmServerBufferStrategy) { } -cmServerConnection::~cmServerConnection() +cmServerStdIoConnection::cmServerStdIoConnection() + : cmStdIoConnection(new cmServerBufferStrategy) { } -void cmServerConnection::SetServer(cmServer* s) +cmConnectionBufferStrategy::~cmConnectionBufferStrategy() { - this->Server = s; } -bool cmServerConnection::ProcessEvents(std::string* errorMessage) +void cmConnectionBufferStrategy::clear() { - assert(this->Server); - errorMessage->clear(); - - this->RawReadBuffer.clear(); - this->RequestBuffer.clear(); - - LoopGuard guard(this); - (void)(guard); - if (!this->mLoop) { - *errorMessage = "Internal Error: Failed to create event loop."; - return false; - } - - this->SIGINTHandler = new uv_signal_t; - uv_signal_init(this->mLoop, this->SIGINTHandler); - this->SIGINTHandler->data = static_cast<void*>(this); - uv_signal_start(this->SIGINTHandler, &on_signal, SIGINT); - - this->SIGHUPHandler = new uv_signal_t; - uv_signal_init(this->mLoop, this->SIGHUPHandler); - this->SIGHUPHandler->data = static_cast<void*>(this); - uv_signal_start(this->SIGHUPHandler, &on_signal, SIGHUP); - - if (!DoSetup(errorMessage)) { - return false; - } - - if (uv_run(this->mLoop, UV_RUN_DEFAULT) != 0) { - *errorMessage = "Internal Error: Event loop stopped in unclean state."; - return false; - } - - // These need to be cleaned up by now: - assert(!this->ReadStream); - assert(!this->WriteStream); - - this->RawReadBuffer.clear(); - this->RequestBuffer.clear(); - - return true; } -void cmServerConnection::ReadData(const std::string& data) +std::string cmServerBufferStrategy::BufferMessage(std::string& RawReadBuffer) { - this->RawReadBuffer += data; - for (;;) { - auto needle = this->RawReadBuffer.find('\n'); + auto needle = RawReadBuffer.find('\n'); if (needle == std::string::npos) { - return; + return ""; } - std::string line = this->RawReadBuffer.substr(0, needle); + std::string line = RawReadBuffer.substr(0, needle); const auto ls = line.size(); if (ls > 1 && line.at(ls - 1) == '\r') { line.erase(ls - 1, 1); } - this->RawReadBuffer.erase(this->RawReadBuffer.begin(), - this->RawReadBuffer.begin() + - static_cast<long>(needle) + 1); + RawReadBuffer.erase(RawReadBuffer.begin(), + RawReadBuffer.begin() + static_cast<long>(needle) + 1); if (line == kSTART_MAGIC) { - this->RequestBuffer.clear(); + RequestBuffer.clear(); continue; } if (line == kEND_MAGIC) { - this->Server->QueueRequest(this->RequestBuffer); - this->RequestBuffer.clear(); - } else { - this->RequestBuffer += line; - this->RequestBuffer += "\n"; + std::string rtn; + rtn.swap(this->RequestBuffer); + return rtn; } - } -} -void cmServerConnection::TriggerShutdown() -{ - this->FileMonitor()->StopMonitoring(); - - uv_signal_stop(this->SIGINTHandler); - uv_signal_stop(this->SIGHUPHandler); - - uv_close(reinterpret_cast<uv_handle_t*>(this->SIGINTHandler), - &on_signal_close); // delete handle - uv_close(reinterpret_cast<uv_handle_t*>(this->SIGHUPHandler), - &on_signal_close); // delete handle - - this->SIGINTHandler = nullptr; - this->SIGHUPHandler = nullptr; - - this->TearDown(); -} - -void cmServerConnection::WriteData(const std::string& data) -{ - assert(this->WriteStream); - - auto ds = data.size(); - - write_req_t* req = new write_req_t; - req->req.data = this; - req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds)); - memcpy(req->buf.base, data.c_str(), ds); - - uv_write(reinterpret_cast<uv_write_t*>(req), - static_cast<uv_stream_t*>(this->WriteStream), &req->buf, 1, - on_write); -} - -void cmServerConnection::ProcessNextRequest() -{ - Server->PopOne(); -} - -void cmServerConnection::SendGreetings() -{ - Server->PrintHello(); -} - -cmServerStdIoConnection::cmServerStdIoConnection() -{ - this->Input.tty = nullptr; - this->Output.tty = nullptr; -} - -bool cmServerStdIoConnection::DoSetup(std::string* errorMessage) -{ - (void)(errorMessage); - - if (uv_guess_handle(1) == UV_TTY) { - usesTty = true; - this->Input.tty = new uv_tty_t; - uv_tty_init(this->Loop(), this->Input.tty, 0, 1); - uv_tty_set_mode(this->Input.tty, UV_TTY_MODE_NORMAL); - Input.tty->data = this; - this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.tty); - - this->Output.tty = new uv_tty_t; - uv_tty_init(this->Loop(), this->Output.tty, 1, 0); - uv_tty_set_mode(this->Output.tty, UV_TTY_MODE_NORMAL); - Output.tty->data = this; - this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.tty); - } else { - usesTty = false; - this->Input.pipe = new uv_pipe_t; - uv_pipe_init(this->Loop(), this->Input.pipe, 0); - uv_pipe_open(this->Input.pipe, 0); - Input.pipe->data = this; - this->ReadStream = reinterpret_cast<uv_stream_t*>(this->Input.pipe); - - this->Output.pipe = new uv_pipe_t; - uv_pipe_init(this->Loop(), this->Output.pipe, 0); - uv_pipe_open(this->Output.pipe, 1); - Output.pipe->data = this; - this->WriteStream = reinterpret_cast<uv_stream_t*>(this->Output.pipe); + this->RequestBuffer += line; + this->RequestBuffer += "\n"; } - - SendGreetings(); - uv_read_start(this->ReadStream, on_alloc_buffer, on_read); - - return true; -} - -void cmServerStdIoConnection::TearDown() -{ - if (usesTty) { - uv_close(reinterpret_cast<uv_handle_t*>(this->Input.tty), &on_tty_close); - uv_close(reinterpret_cast<uv_handle_t*>(this->Output.tty), &on_tty_close); - this->Input.tty = nullptr; - this->Output.tty = nullptr; - } else { - uv_close(reinterpret_cast<uv_handle_t*>(this->Input.pipe), &on_pipe_close); - uv_close(reinterpret_cast<uv_handle_t*>(this->Output.pipe), - &on_pipe_close); - this->Input.pipe = nullptr; - this->Input.pipe = nullptr; - } - this->ReadStream = nullptr; - this->WriteStream = nullptr; -} - -cmServerPipeConnection::cmServerPipeConnection(const std::string& name) - : PipeName(name) -{ -} - -bool cmServerPipeConnection::DoSetup(std::string* errorMessage) -{ - this->ServerPipe = new uv_pipe_t; - uv_pipe_init(this->Loop(), this->ServerPipe, 0); - this->ServerPipe->data = this; - - int r; - if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) { - *errorMessage = std::string("Internal Error with ") + this->PipeName + - ": " + uv_err_name(r); - return false; - } - auto serverStream = reinterpret_cast<uv_stream_t*>(this->ServerPipe); - if ((r = uv_listen(serverStream, 1, on_new_connection)) != 0) { - *errorMessage = std::string("Internal Error listening on ") + - this->PipeName + ": " + uv_err_name(r); - return false; - } - - return true; -} - -void cmServerPipeConnection::TearDown() -{ - if (this->ClientPipe) { - uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe), &on_pipe_close); - this->WriteStream->data = nullptr; - } - uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe), &on_pipe_close); - - this->ClientPipe = nullptr; - this->ServerPipe = nullptr; - this->WriteStream = nullptr; - this->ReadStream = nullptr; -} - -void cmServerPipeConnection::Connect(uv_stream_t* server) -{ - if (this->ClientPipe) { - // Accept and close all pipes but the first: - uv_pipe_t* rejectPipe = new uv_pipe_t; - - uv_pipe_init(this->Loop(), rejectPipe, 0); - auto rejecter = reinterpret_cast<uv_stream_t*>(rejectPipe); - uv_accept(server, rejecter); - uv_close(reinterpret_cast<uv_handle_t*>(rejecter), &on_pipe_close); - return; - } - - this->ClientPipe = new uv_pipe_t; - uv_pipe_init(this->Loop(), this->ClientPipe, 0); - this->ClientPipe->data = this; - auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe); - if (uv_accept(server, client) != 0) { - uv_close(reinterpret_cast<uv_handle_t*>(client), nullptr); - return; - } - this->ReadStream = client; - this->WriteStream = client; - - uv_read_start(this->ReadStream, on_alloc_buffer, on_read); - - this->SendGreetings(); } diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h index b96bf3c..0804f0e 100644 --- a/Source/cmServerConnection.h +++ b/Source/cmServerConnection.h @@ -2,68 +2,46 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once -#include "cmConfigure.h" +#include "cmConnection.h" +#include "cmPipeConnection.h" #include "cm_uv.h" #include <string> -class cmFileMonitor; -class cmServer; +class cmServerBase; -class cmServerConnection +/*** + * This connection buffer strategy accepts messages in the form of + * [== "CMake Server" ==[ +{ + ... some JSON message ... +} +]== "CMake Server" ==] + * and only passes on the core json; it discards the envelope. + */ +class cmServerBufferStrategy : public cmConnectionBufferStrategy { - CM_DISABLE_COPY(cmServerConnection) - public: - cmServerConnection(); - virtual ~cmServerConnection(); - - void SetServer(cmServer* s); - - bool ProcessEvents(std::string* errorMessage); - - void ReadData(const std::string& data); - void TriggerShutdown(); - void WriteData(const std::string& data); - void ProcessNextRequest(); - - virtual void Connect(uv_stream_t* server) { (void)(server); } - - cmFileMonitor* FileMonitor() const { return this->mFileMonitor; } - -protected: - virtual bool DoSetup(std::string* errorMessage) = 0; - virtual void TearDown() = 0; - - void SendGreetings(); - - uv_loop_t* Loop() const { return mLoop; } - -protected: - std::string RawReadBuffer; - std::string RequestBuffer; - - uv_stream_t* ReadStream = nullptr; - uv_stream_t* WriteStream = nullptr; + std::string BufferMessage(std::string& rawBuffer) override; private: - uv_loop_t* mLoop = nullptr; - cmFileMonitor* mFileMonitor = nullptr; - cmServer* Server = nullptr; - uv_signal_t* SIGINTHandler = nullptr; - uv_signal_t* SIGHUPHandler = nullptr; - - friend class LoopGuard; + std::string RequestBuffer; }; -class cmServerStdIoConnection : public cmServerConnection +/*** + * Generic connection over std io interfaces -- tty + */ +class cmStdIoConnection : public cmEventBasedConnection { public: - cmServerStdIoConnection(); - bool DoSetup(std::string* errorMessage) override; + cmStdIoConnection(cmConnectionBufferStrategy* bufferStrategy); + + void SetServer(cmServerBase* s) override; + + bool OnConnectionShuttingDown() override; - void TearDown() override; + bool OnServeStart(std::string* pString) override; private: typedef union @@ -78,18 +56,18 @@ private: InOutUnion Output; }; -class cmServerPipeConnection : public cmServerConnection +/*** + * These specific connections use the cmake server + * buffering strategy. + */ +class cmServerStdIoConnection : public cmStdIoConnection { public: - cmServerPipeConnection(const std::string& name); - bool DoSetup(std::string* errorMessage) override; - - void TearDown() override; - - void Connect(uv_stream_t* server) override; + cmServerStdIoConnection(); +}; -private: - const std::string PipeName; - uv_pipe_t* ServerPipe = nullptr; - uv_pipe_t* ClientPipe = nullptr; +class cmServerPipeConnection : public cmPipeConnection +{ +public: + cmServerPipeConnection(const std::string& name); }; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 21b69cf..7a841a8 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -128,11 +128,13 @@ void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir, } // namespace -cmServerRequest::cmServerRequest(cmServer* server, const std::string& t, - const std::string& c, const Json::Value& d) +cmServerRequest::cmServerRequest(cmServer* server, cmConnection* connection, + const std::string& t, const std::string& c, + const Json::Value& d) : Type(t) , Cookie(c) , Data(d) + , Connection(connection) , m_Server(server) { } @@ -287,7 +289,9 @@ static bool testValue(cmState* state, const std::string& key, std::string& value, const std::string& keyDescription, std::string* errorMessage) { - const std::string cachedValue = std::string(state->GetCacheEntryValue(key)); + const char* entry = state->GetCacheEntryValue(key); + const std::string cachedValue = + entry == nullptr ? std::string() : std::string(entry); if (!cachedValue.empty() && !value.empty() && cachedValue != value) { setErrorMessage(errorMessage, std::string("\"") + key + "\" is set but incompatible with configured " + diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 4e57bb6..145708c 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -11,6 +11,7 @@ #include <string> #include <utility> +class cmConnection; class cmFileMonitor; class cmServer; class cmServerRequest; @@ -52,9 +53,11 @@ public: const std::string Type; const std::string Cookie; const Json::Value Data; + cmConnection* Connection; private: - cmServerRequest(cmServer* server, const std::string& t, const std::string& c, + cmServerRequest(cmServer* server, cmConnection* connection, + const std::string& t, const std::string& c, const Json::Value& d); void ReportProgress(int min, int current, int max, diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 7a097ba..5a6cf48 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -309,6 +309,7 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args) std::string output; const char* p = input.c_str(); while (re.find(p)) { + this->Makefile->ClearMatches(); this->Makefile->StoreMatches(re); std::string::size_type l = re.start(); std::string::size_type r = re.end(); @@ -391,6 +392,7 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args) std::string output; std::string::size_type base = 0; while (re.find(input.c_str() + base)) { + this->Makefile->ClearMatches(); this->Makefile->StoreMatches(re); std::string::size_type l2 = re.start(); std::string::size_type r = re.end(); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index f7192e0..9f214c3 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -934,19 +934,17 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname) #endif } -bool cmSystemTools::ComputeFileMD5(const std::string& source, char* md5out) +std::string cmSystemTools::ComputeFileHash(const std::string& source, + cmCryptoHash::Algo algo) { #if defined(CMAKE_BUILD_WITH_CMAKE) - cmCryptoHash md5(cmCryptoHash::AlgoMD5); - std::string const str = md5.HashFile(source); - strncpy(md5out, str.c_str(), 32); - return !str.empty(); + cmCryptoHash hash(algo); + return hash.HashFile(source); #else (void)source; - (void)md5out; - cmSystemTools::Message("md5sum not supported in bootstrapping mode", + cmSystemTools::Message("hashsum not supported in bootstrapping mode", "Error"); - return false; + return std::string(); #endif } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 9de7967..e163c91 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" +#include "cmCryptoHash.h" #include "cmProcessOutput.h" #include "cmsys/Process.h" #include "cmsys/SystemTools.hxx" // IWYU pragma: export @@ -179,8 +180,9 @@ public: if possible). */ static bool RenameFile(const char* oldname, const char* newname); - ///! Compute the md5sum of a file - static bool ComputeFileMD5(const std::string& source, char* md5out); + ///! Compute the hash of a file + static std::string ComputeFileHash(const std::string& source, + cmCryptoHash::Algo algo); /** Compute the md5sum of a string. */ static std::string ComputeStringMD5(const std::string& input); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index d5b0861..c546c7e 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -44,6 +44,8 @@ #include <stdlib.h> #include <time.h> +class cmConnection; + int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, std::vector<std::string>::const_iterator argEnd); int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, @@ -88,6 +90,11 @@ void CMakeCommandUsage(const char* program) << " environment - display the current environment\n" << " make_directory <dir>... - create parent and <dir> directories\n" << " md5sum <file>... - create MD5 checksum of files\n" + << " sha1sum <file>... - create SHA1 checksum of files\n" + << " sha224sum <file>... - create SHA224 checksum of files\n" + << " sha256sum <file>... - create SHA256 checksum of files\n" + << " sha384sum <file>... - create SHA384 checksum of files\n" + << " sha512sum <file>... - create SHA512 checksum of files\n" << " remove [-f] <file>... - remove the file(s), use -f to force " "it\n" << " remove_directory dir - remove a directory and its contents\n" @@ -641,24 +648,28 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // Command to calculate the md5sum of a file if (args[1] == "md5sum" && args.size() >= 3) { - char md5out[32]; - int retval = 0; - for (std::string::size_type cc = 2; cc < args.size(); cc++) { - const char* filename = args[cc].c_str(); - // Cannot compute md5sum of a directory - if (cmSystemTools::FileIsDirectory(filename)) { - std::cerr << "Error: " << filename << " is a directory" << std::endl; - retval++; - } else if (!cmSystemTools::ComputeFileMD5(filename, md5out)) { - // To mimic md5sum behavior in a shell: - std::cerr << filename << ": No such file or directory" << std::endl; - retval++; - } else { - std::cout << std::string(md5out, 32) << " " << filename - << std::endl; - } - } - return retval; + return HashSumFile(args, cmCryptoHash::AlgoMD5); + } + + // Command to calculate the sha1sum of a file + if (args[1] == "sha1sum" && args.size() >= 3) { + return HashSumFile(args, cmCryptoHash::AlgoSHA1); + } + + if (args[1] == "sha224sum" && args.size() >= 3) { + return HashSumFile(args, cmCryptoHash::AlgoSHA224); + } + + if (args[1] == "sha256sum" && args.size() >= 3) { + return HashSumFile(args, cmCryptoHash::AlgoSHA256); + } + + if (args[1] == "sha384sum" && args.size() >= 3) { + return HashSumFile(args, cmCryptoHash::AlgoSHA384); + } + + if (args[1] == "sha512sum" && args.size() >= 3) { + return HashSumFile(args, cmCryptoHash::AlgoSHA512); } // Command to change directory and run a program. @@ -1013,7 +1024,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) } } #if defined(HAVE_SERVER_MODE) && HAVE_SERVER_MODE - cmServerConnection* conn; + cmConnection* conn; if (isDebug) { conn = new cmServerStdIoConnection; } else { @@ -1074,6 +1085,33 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) return 1; } +int cmcmd::HashSumFile(std::vector<std::string>& args, cmCryptoHash::Algo algo) +{ + if (args.size() < 3) { + return -1; + } + int retval = 0; + + for (std::string::size_type cc = 2; cc < args.size(); cc++) { + const char* filename = args[cc].c_str(); + // Cannot compute sum of a directory + if (cmSystemTools::FileIsDirectory(filename)) { + std::cerr << "Error: " << filename << " is a directory" << std::endl; + retval++; + } else { + std::string value = cmSystemTools::ComputeFileHash(filename, algo); + if (value.empty()) { + // To mimic "md5sum/shasum" behavior in a shell: + std::cerr << filename << ": No such file or directory" << std::endl; + retval++; + } else { + std::cout << value << " " << filename << std::endl; + } + } + } + return retval; +} + int cmcmd::SymlinkLibrary(std::vector<std::string>& args) { int result = 0; diff --git a/Source/cmcmd.h b/Source/cmcmd.h index 929f1ae..faac1d2 100644 --- a/Source/cmcmd.h +++ b/Source/cmcmd.h @@ -4,6 +4,7 @@ #define cmcmd_h #include "cmConfigure.h" // IWYU pragma: keep +#include "cmCryptoHash.h" #include <string> #include <vector> @@ -18,6 +19,8 @@ public: static int ExecuteCMakeCommand(std::vector<std::string>&); protected: + static int HashSumFile(std::vector<std::string>& args, + cmCryptoHash::Algo algo); static int SymlinkLibrary(std::vector<std::string>& args); static int SymlinkExecutable(std::vector<std::string>& args); static bool SymlinkInternal(std::string const& file, diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 34418c5..13d796e 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1285,12 +1285,28 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt5Autogen" --force-new-ctest-process --build-options ${build_options} - -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DQT_TEST_VERSION=5 + -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + -DQT_TEST_VERSION=5 ${QtAutogen_BUILD_OPTIONS} --test-command ${run_autogen_test} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt5Autogen") + add_test(NAME Qt5AutogenRerun COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/QtAutogenRerun" + "${CMake_BINARY_DIR}/Tests/Qt5AutogenRerun" + ${build_generator_args} + --build-project QtAutogenRerun + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt5AutogenRerun" + --force-new-ctest-process + --build-options ${build_options} + -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + -DQT_TEST_VERSION=5 + ${QtAutogen_BUILD_OPTIONS} + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt5AutogenRerun") + add_test(Qt5AutoUicInterface ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/QtAutoUicInterface" @@ -1315,12 +1331,28 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4Autogen" --force-new-ctest-process --build-options ${build_options} - -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DQT_TEST_VERSION=4 + -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + -DQT_TEST_VERSION=4 ${QtAutogen_BUILD_OPTIONS} --test-command ${run_autogen_test} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Autogen") + add_test(NAME Qt4AutogenRerun COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/QtAutogenRerun" + "${CMake_BINARY_DIR}/Tests/Qt4AutogenRerun" + ${build_generator_args} + --build-project QtAutogenRerun + --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4AutogenRerun" + --force-new-ctest-process + --build-options ${build_options} + -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + -DQT_TEST_VERSION=4 + ${QtAutogen_BUILD_OPTIONS} + ) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4AutogenRerun") + add_test(Qt4AutoUicInterface ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/QtAutoUicInterface" @@ -1330,7 +1362,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4AutoUicInterface" --force-new-ctest-process --build-options ${build_options} - -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} -DQT_TEST_VERSION=4 + -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + -DQT_TEST_VERSION=4 --test-command ${run_autouic_test} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4AutoUicInterface") diff --git a/Tests/CompileFeatures/default_dialect.cpp b/Tests/CompileFeatures/default_dialect.cpp index 9b65b42..0de1125 100644 --- a/Tests/CompileFeatures/default_dialect.cpp +++ b/Tests/CompileFeatures/default_dialect.cpp @@ -2,25 +2,30 @@ template <long l> struct Outputter; +#if defined(_MSC_VER) && defined(_MSVC_LANG) +#define CXX_STD _MSVC_LANG +#else +#define CXX_STD __cplusplus +#endif + #if DEFAULT_CXX17 -#if __cplusplus <= 201402L -Outputter<__cplusplus> o; +#if CXX_STD <= 201402L +Outputter<CXX_STD> o; #endif #elif DEFAULT_CXX14 -#if __cplusplus != 201402L -Outputter<__cplusplus> o; +#if CXX_STD != 201402L +Outputter<CXX_STD> o; #endif #elif DEFAULT_CXX11 -#if __cplusplus != 201103L -Outputter<__cplusplus> o; +#if CXX_STD != 201103L +Outputter<CXX_STD> o; #endif #else #if !DEFAULT_CXX98 #error Buildsystem error #endif -#if __cplusplus != 199711L && __cplusplus != 1 && \ - !defined(__GXX_EXPERIMENTAL_CXX0X__) -Outputter<__cplusplus> o; +#if CXX_STD != 199711L && CXX_STD != 1 && !defined(__GXX_EXPERIMENTAL_CXX0X__) +Outputter<CXX_STD> o; #endif #endif diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 89d2b80..5064d26 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -1,14 +1,7 @@ -cmake_minimum_required(VERSION 3.7) - +cmake_minimum_required(VERSION 3.9) +cmake_policy(SET CMP0071 NEW) project(QtAutogen) -# Tell find_package(Qt5) where to find Qt. -if(QT_QMAKE_EXECUTABLE) - get_filename_component(Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) - get_filename_component(Qt_PREFIX_DIR "${Qt_BIN_DIR}" PATH) - set(CMAKE_PREFIX_PATH ${Qt_PREFIX_DIR}) -endif() - if (QT_TEST_VERSION STREQUAL 4) find_package(Qt4 REQUIRED) @@ -22,6 +15,9 @@ if (QT_TEST_VERSION STREQUAL 4) macro(qtx_wrap_cpp) qt4_wrap_cpp(${ARGN}) endmacro() + macro(qtx_generate_moc) + qt4_generate_moc(${ARGN}) + endmacro() else() if (NOT QT_TEST_VERSION STREQUAL 5) @@ -41,6 +37,9 @@ else() macro(qtx_wrap_cpp) qt5_wrap_cpp(${ARGN}) endmacro() + macro(qtx_generate_moc) + qt5_generate_moc(${ARGN}) + endmacro() endif() @@ -102,132 +101,6 @@ set_target_properties(no_link_language PROPERTIES AUTOMOC TRUE) target_compile_features(no_link_language PRIVATE ${QT_COMPILE_FEATURES}) target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES}) -# -- Test -# When a file listed in a .qrc file changes the target must be rebuilt -set(timeformat "%Y%j%H%M%S") -set(RCC_DEPENDS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/rccDepends") -set(RCC_DEPENDS_BIN "${CMAKE_CURRENT_BINARY_DIR}/rccDepends") -configure_file(${RCC_DEPENDS_SRC}/res1a.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY) -configure_file(${RCC_DEPENDS_SRC}/res2a.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY) -try_compile(RCC_DEPENDS - "${RCC_DEPENDS_BIN}" - "${RCC_DEPENDS_SRC}" - rccDepends - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" - "-DQT_TEST_VERSION=${QT_TEST_VERSION}" - "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" - OUTPUT_VARIABLE output -) -if (NOT RCC_DEPENDS) - message(SEND_ERROR "Initial build of rccDepends failed. Output: ${output}") -endif() -# Get name and timestamp of the output binary -file(STRINGS "${RCC_DEPENDS_BIN}/target.txt" targetList ENCODING UTF-8) -list(GET targetList 0 rccDependsBin) -file(TIMESTAMP "${rccDependsBin}" timeBegin "${timeformat}") -# Sleep, touch regular qrc input file, rebuild and compare timestamp -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/input.txt") -execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) -if (result) - message(SEND_ERROR "Second build of rccDepends failed.") -endif() -file(TIMESTAMP "${rccDependsBin}" timeStep1 "${timeformat}") -if (NOT timeStep1 GREATER timeBegin) - message(SEND_ERROR "File (${rccDependsBin}) should have changed in the first step!") -endif() -# Sleep, update regular qrc file, rebuild and compare timestamp -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -configure_file(${RCC_DEPENDS_SRC}/res1b.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY) -execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) -if (result) - message(SEND_ERROR "Third build of rccDepends failed.") -endif() -file(TIMESTAMP "${rccDependsBin}" timeStep2 "${timeformat}") -if (NOT timeStep2 GREATER timeStep1) - message(SEND_ERROR "File (${rccDependsBin}) should have changed in the second step!") -endif() -# Sleep, touch regular qrc newly added input file, rebuild and compare timestamp -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/inputAdded.txt") -execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) -if (result) - message(SEND_ERROR "Fourth build of rccDepends failed.") -endif() -file(TIMESTAMP "${rccDependsBin}" timeStep3 "${timeformat}") -if (NOT timeStep3 GREATER timeStep2) - message(SEND_ERROR "File (${rccDependsBin}) should have changed in the third step!") -endif() -# Sleep, touch generated qrc input file, rebuild and compare timestamp -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/input.txt") -execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) -if (result) - message(SEND_ERROR "Fifth build of rccDepends failed.") -endif() -file(TIMESTAMP "${rccDependsBin}" timeStep4 "${timeformat}") -if (NOT timeStep4 GREATER timeStep3) - message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fourth step!") -endif() -# Sleep, update generated qrc file, rebuild and compare timestamp -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -configure_file(${RCC_DEPENDS_SRC}/res2b.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY) -execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) -if (result) - message(SEND_ERROR "Sixth build of rccDepends failed.") -endif() -file(TIMESTAMP "${rccDependsBin}" timeStep5 "${timeformat}") -if (NOT timeStep5 GREATER timeStep4) - message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fitfh step!") -endif() -# Sleep, touch generated qrc newly added input file, rebuild and compare timestamp -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. -execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/inputAdded.txt") -execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) -if (result) - message(SEND_ERROR "Seventh build of rccDepends failed.") -endif() -file(TIMESTAMP "${rccDependsBin}" timeStep6 "${timeformat}") -if (NOT timeStep6 GREATER timeStep5) - message(SEND_ERROR "File (${rccDependsBin}) should have changed in the sixth step!") -endif() - - -# -- Test -# Ensure a repeated build succeeds when a header containing a QObject changes -set(timeformat "%Y%j%H%M%S") -configure_file(mocRerun/test1a.h.in mocRerun/test1.h COPYONLY) -try_compile(MOC_RERUN - "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" - "${CMAKE_CURRENT_SOURCE_DIR}/mocRerun" - mocRerun - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" - "-DQT_TEST_VERSION=${QT_TEST_VERSION}" - "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" - OUTPUT_VARIABLE output -) -if (NOT MOC_RERUN) - message(SEND_ERROR "Initial build of mocRerun failed. Output: ${output}") -endif() -# Get name and timestamp of the output binary -file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/mocRerun/target1.txt" target1List ENCODING UTF-8) -list(GET target1List 0 binFile) -file(TIMESTAMP "${binFile}" timeBegin "${timeformat}") -# Change file content and rebuild -execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) -configure_file(mocRerun/test1b.h.in mocRerun/test1.h COPYONLY) -execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" - RESULT_VARIABLE mocRerun_result - ) -if (mocRerun_result) - message(SEND_ERROR "Second build of mocRerun failed.") -endif() -# Compare timestamps -file(TIMESTAMP "${binFile}" timeStep1 "${timeformat}") -if (NOT timeStep1 GREATER timeBegin) - message(SEND_ERROR "File (${binFile}) should have changed in the first step!") -endif() # -- Test # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target @@ -304,80 +177,15 @@ add_subdirectory(mocDepends) # -- Test # Tests various include moc patterns -add_subdirectory(mocIncludeStrict) - -# -- Test -# Tests various include moc patterns -add_subdirectory(mocIncludeRelaxed) +if(ALLOW_WRAP_CPP) + add_subdirectory(mocIncludeStrict) + add_subdirectory(mocIncludeRelaxed) +endif() # -- Test -# Tests Q_PLUGIN_METADATA json file change detection -if (NOT QT_TEST_VERSION STREQUAL 4) - try_compile(MOC_PLUGIN - "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" - "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin" - mocPlugin - CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" - "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" - OUTPUT_VARIABLE output - ) - if (NOT MOC_PLUGIN) - message(SEND_ERROR "Initial build of mocPlugin failed. Output: ${output}") - endif() - - set(timeformat "%Y%j%H%M%S") - set(mocPlugSrcDir "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin") - set(mocPlugBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") - find_library(plAFile "PlugA" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) - find_library(plBFile "PlugB" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) - find_library(plCFile "PlugC" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) - find_library(plDFile "PlugD" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) - - file(TIMESTAMP "${plAFile}" plABefore "${timeformat}") - file(TIMESTAMP "${plBFile}" plBBefore "${timeformat}") - file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") - file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") - - # Ensure that the timestamp will change and change the json files - execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) - configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC.json") - configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD.json") - execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}") - - file(TIMESTAMP "${plAFile}" plAAfter "${timeformat}") - file(TIMESTAMP "${plBFile}" plBAfter "${timeformat}") - file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") - file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") - - if (plAAfter GREATER plABefore) - message(SEND_ERROR "file (${plAFile}) should not have changed!") - endif() - if (plBAfter GREATER plBBefore) - message(SEND_ERROR "file (${plBFile}) should not have changed!") - endif() - if (NOT plCAfter GREATER plCBefore) - message(SEND_ERROR "file (${plCFile}) should have changed!") - endif() - if (NOT plDAfter GREATER plDBefore) - message(SEND_ERROR "file (${plDFile}) should have changed!") - endif() - - # Test custom macro - file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") - file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") - execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) - configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC_Custom.json") - configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD_Custom.json") - execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}") - file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") - file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") - if (NOT plCAfter GREATER plCBefore) - message(SEND_ERROR "file (${plCFile}) should have changed!") - endif() - if (NOT plDAfter GREATER plDBefore) - message(SEND_ERROR "file (${plDFile}) should have changed!") - endif() - +# Tests policy 0071 +if(ALLOW_WRAP_CPP) + add_subdirectory(mocCMP0071) endif() # -- Test diff --git a/Tests/QtAutogen/complex/CMakeLists.txt b/Tests/QtAutogen/complex/CMakeLists.txt index d48f6cc..2043ccf 100644 --- a/Tests/QtAutogen/complex/CMakeLists.txt +++ b/Tests/QtAutogen/complex/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.9) # -- Test: AUTOMOC AUTORCC AUTOUIC add_definitions(-DFOO -DSomeDefine="Barx") diff --git a/Tests/QtAutogen/mocCMP0071/CMakeLists.txt b/Tests/QtAutogen/mocCMP0071/CMakeLists.txt new file mode 100644 index 0000000..003fa08 --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.9) +project(mocCMP0071 CXX) +add_subdirectory(OLD) +add_subdirectory(NEW) diff --git a/Tests/QtAutogen/mocCMP0071/NEW/CMakeLists.txt b/Tests/QtAutogen/mocCMP0071/NEW/CMakeLists.txt new file mode 100644 index 0000000..0237afc --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/NEW/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.9) +cmake_policy(SET CMP0071 NEW) + +# *Generate* files +set(CSD ${CMAKE_CURRENT_SOURCE_DIR}) +set(CBD ${CMAKE_CURRENT_BINARY_DIR}) +add_custom_command( + OUTPUT ${CBD}/Obj_p.h ${CBD}/Obj.hpp ${CBD}/Obj.cpp ${CBD}/main.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../Obj_p.h ${CBD}/Obj_p.h + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../Obj.hpp ${CBD}/Obj.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../Obj.cpp ${CBD}/Obj.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../main.cpp ${CBD}/main.cpp) + +add_executable(mocCMP0071New ${CBD}/Obj.cpp ${CBD}/main.cpp) +target_link_libraries(mocCMP0071New ${QT_LIBRARIES}) +set_target_properties(mocCMP0071New PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocCMP0071/OLD/CMakeLists.txt b/Tests/QtAutogen/mocCMP0071/OLD/CMakeLists.txt new file mode 100644 index 0000000..5699433 --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/OLD/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.9) +cmake_policy(SET CMP0071 OLD) + +# *Generate* files +set(CSD ${CMAKE_CURRENT_SOURCE_DIR}) +set(CBD ${CMAKE_CURRENT_BINARY_DIR}) +add_custom_command( + OUTPUT ${CBD}/Obj_p.h ${CBD}/Obj.hpp ${CBD}/Obj.cpp ${CBD}/main.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../Obj_p.h ${CBD}/Obj_p.h + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../Obj.hpp ${CBD}/Obj.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../Obj.cpp ${CBD}/Obj.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CSD}/../main.cpp ${CBD}/main.cpp) + +# Generate moc files externally +qtx_wrap_cpp(mocCMP0071OldMoc ${CBD}/Obj.hpp ${CBD}/Obj_p.h) +add_executable(mocCMP0071Old ${CBD}/Obj.cpp ${CBD}/main.cpp ${mocCMP0071OldMoc}) +target_link_libraries(mocCMP0071Old ${QT_LIBRARIES}) +set_target_properties(mocCMP0071Old PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocCMP0071/Obj.cpp b/Tests/QtAutogen/mocCMP0071/Obj.cpp new file mode 100644 index 0000000..1ae50ed --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/Obj.cpp @@ -0,0 +1,20 @@ +#include "Obj.hpp" +#include "Obj_p.h" + +ObjPrivate::ObjPrivate() +{ +} + +ObjPrivate::~ObjPrivate() +{ +} + +Obj::Obj() + : d(new ObjPrivate) +{ +} + +Obj::~Obj() +{ + delete d; +} diff --git a/Tests/QtAutogen/mocCMP0071/Obj.hpp b/Tests/QtAutogen/mocCMP0071/Obj.hpp new file mode 100644 index 0000000..f064e47 --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/Obj.hpp @@ -0,0 +1,19 @@ +#ifndef OBJ_HPP +#define OBJ_HPP + +#include <QObject> + +// Object source comes without any _moc/.moc includes +class ObjPrivate; +class Obj : public QObject +{ + Q_OBJECT +public: + Obj(); + ~Obj(); + +private: + ObjPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocCMP0071/Obj_p.h b/Tests/QtAutogen/mocCMP0071/Obj_p.h new file mode 100644 index 0000000..cb1e5df --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/Obj_p.h @@ -0,0 +1,14 @@ +#ifndef OBJ_P_HPP +#define OBJ_P_HPP + +#include <QObject> + +class ObjPrivate : public QObject +{ + Q_OBJECT +public: + ObjPrivate(); + ~ObjPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocCMP0071/main.cpp b/Tests/QtAutogen/mocCMP0071/main.cpp new file mode 100644 index 0000000..3887840 --- /dev/null +++ b/Tests/QtAutogen/mocCMP0071/main.cpp @@ -0,0 +1,7 @@ +#include "Obj.hpp" + +int main(int argv, char** args) +{ + Obj obj; + return 0; +} diff --git a/Tests/QtAutogen/mocDepends/CMakeLists.txt b/Tests/QtAutogen/mocDepends/CMakeLists.txt index a67dcfe..d71d740 100644 --- a/Tests/QtAutogen/mocDepends/CMakeLists.txt +++ b/Tests/QtAutogen/mocDepends/CMakeLists.txt @@ -1,5 +1,6 @@ -cmake_minimum_required(VERSION 3.7) -project(mocDepends) +cmake_minimum_required(VERSION 3.9) +cmake_policy(SET CMP0071 NEW) +project(mocDepends CXX) if (QT_TEST_VERSION STREQUAL 4) find_package(Qt4 REQUIRED) @@ -15,33 +16,80 @@ endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) -# -- Test 1 using generated header -# This tests the dependency of AUTOMOC of mocDepends1 to the generated object.hpp -add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/object.hpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp - COMMAND ${CMAKE_COMMAND} -E sleep 3 - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/object.hpp - ) - -add_executable(mocDepends1 test1.cpp - ${CMAKE_CURRENT_BINARY_DIR}/object.hpp -) +# -- Test 1: Depend on generated header +# The ORIGIN_autogen target must depend on the same *GENERATED* source files as +# the ORIGIN target. This is a requirement to ensure that all files for the +# ORIGIN target are generated before the ORIGIN_autogen target is built. +# +# This tests the dependency of the mocDepends1_autogen target of mocDepends1 +# to the source file test1_object.hpp, which is *GENERATED* by a custom command. +# If mocDepends1_autogen gets built *before* or in *parallel* to the +# custom command, the build will fail. That's because test1_object.hpp, +# which is required by mocDepends1_autogen, is only valid after the +# custom command has been completed. +# +# The sleep seconds artificially increase the build time of the custom command +# to simulate a slow file generation process that takes longer to run than +# the build of the mocDepends1_autogen target. +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp) + +add_executable(mocDepends1 test1.cpp ${CMAKE_CURRENT_BINARY_DIR}/test1_object.hpp) target_link_libraries(mocDepends1 ${QT_CORE_TARGET}) set_target_properties(mocDepends1 PROPERTIES AUTOMOC TRUE) -set_property(TARGET mocDepends1 PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1) - -# -- Test 2 using generated library -# This tests the dependency of AUTOMOC of mocDepends2 to the -# generated simpleLib.hpp which belongs to a linked library of mocDepends2 -add_custom_command(OUTPUT simpleLib.hpp simpleLib.cpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp - COMMAND ${CMAKE_COMMAND} -E sleep 3 - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp - ) -add_library(SimpleLib STATIC simpleLib.hpp simpleLib.cpp) - -add_executable(mocDepends2 test2.cpp ) -target_link_libraries(mocDepends2 SimpleLib ${QT_CORE_TARGET}) + +# -- Test 2: Depend on header generating target +# The ORIGIN_autogen target must depend on the same user defined targets +# as the ORIGIN target. This is a requirement to ensure that all files for the +# ORIGIN target are generated before the ORIGIN_autogen target is built. +# +# This tests the dependency of the mocDepends2_autogen target of mocDepends2 +# to the utility target mocDepends2Object. If mocDepends2_autogen gets built +# *before* or in *parallel* to mocDepends2Object, the build will fail. That's +# because test2_object.hpp, which is required by mocDepends2_autogen, +# is only valid after the mocDepends2Object build has been completed. +# +# The sleep seconds artificially increase the build time of mocDepends2Object +# to simulate a slow utility target build that takes longer to run than +# the build of the mocDepends2_autogen target. +add_custom_target(mocDepends2Object + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/object.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/test2_object.hpp) + +add_executable(mocDepends2 test2.cpp) +target_link_libraries(mocDepends2 ${QT_CORE_TARGET}) set_target_properties(mocDepends2 PROPERTIES AUTOMOC TRUE) -set_property(TARGET mocDepends2 PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1) +add_dependencies(mocDepends2 mocDepends2Object) + +# -- Test 3: Depend on generated linked library +# The ORIGIN_autogen target must depend on the same linked libraries +# as the ORIGIN target. This is a requirement to ensure that all files for the +# ORIGIN target are generated before the ORIGIN_autogen target is built. +# +# This tests the dependency of the mocDepends3_autogen target of mocDepends3 +# to the user generated library SimpleLib, which mocDepends3 links to. +# If mocDepends3_autogen gets built *before* or in *parallel* to SimpleLib, +# the build will fail. That's because simpleLib.hpp, which is required by +# mocDepends3_autogen, is only valid after the SimpleLib build has been +# completed. +# +# The sleep seconds artificially increase the build time of SimpleLib +# to simulate a slow utility library build that takes longer to run than +# the build of the mocDepends3_autogen target. +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/invalid.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E sleep 3 + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/simpleLib.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp) +add_library(SimpleLib STATIC ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.hpp ${CMAKE_CURRENT_BINARY_DIR}/simpleLib.cpp) +target_link_libraries(SimpleLib ${QT_CORE_TARGET}) + +add_executable(mocDepends3 test3.cpp) +target_link_libraries(mocDepends3 SimpleLib ${QT_CORE_TARGET}) +set_target_properties(mocDepends3 PROPERTIES AUTOMOC TRUE) diff --git a/Tests/QtAutogen/mocDepends/simpleLib.hpp.in b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in index 758f1f6..b65b0cb 100644 --- a/Tests/QtAutogen/mocDepends/simpleLib.hpp.in +++ b/Tests/QtAutogen/mocDepends/simpleLib.hpp.in @@ -1,8 +1,11 @@ #ifndef SIMPLE_LIB_H #define SIMPLE_LIB_H -class SimpleLib +#include <QObject> + +class SimpleLib : public QObject { + Q_OBJECT public: SimpleLib(); ~SimpleLib(); diff --git a/Tests/QtAutogen/mocDepends/test1.cpp b/Tests/QtAutogen/mocDepends/test1.cpp index 92c259c..002dfd8 100644 --- a/Tests/QtAutogen/mocDepends/test1.cpp +++ b/Tests/QtAutogen/mocDepends/test1.cpp @@ -1,9 +1,8 @@ -#include "object.hpp" +#include "test1_object.hpp" int main() { Object obj; - return 0; } diff --git a/Tests/QtAutogen/mocDepends/test2.cpp b/Tests/QtAutogen/mocDepends/test2.cpp index 155b19b..3fd845e 100644 --- a/Tests/QtAutogen/mocDepends/test2.cpp +++ b/Tests/QtAutogen/mocDepends/test2.cpp @@ -1,10 +1,9 @@ -#include "test2.hpp" +#include "moc_test2_object.cpp" +#include "test2_object.hpp" int main() { - SimpleLib obj; - LObject lobject; - + Object obj; return 0; } diff --git a/Tests/QtAutogen/mocDepends/test3.cpp b/Tests/QtAutogen/mocDepends/test3.cpp new file mode 100644 index 0000000..a009598 --- /dev/null +++ b/Tests/QtAutogen/mocDepends/test3.cpp @@ -0,0 +1,12 @@ + +#include "test3.hpp" + +int main() +{ + SimpleLib libObject; + LObject lobject; + return 0; +} + +// AUTOMOC the SimpleLib header simpleLib.hpp +#include "moc_simpleLib.cpp" diff --git a/Tests/QtAutogen/mocDepends/test2.hpp b/Tests/QtAutogen/mocDepends/test3.hpp index 0125f07..408335b 100644 --- a/Tests/QtAutogen/mocDepends/test2.hpp +++ b/Tests/QtAutogen/mocDepends/test3.hpp @@ -1,5 +1,5 @@ -#ifndef TEST2_HPP -#define TEST2_HPP +#ifndef TEST3_HPP +#define TEST3_HPP #include "simpleLib.hpp" #include <QObject> diff --git a/Tests/QtAutogen/mocInclude/EObjA.cpp b/Tests/QtAutogen/mocInclude/EObjA.cpp new file mode 100644 index 0000000..ca713b2 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjA.cpp @@ -0,0 +1,43 @@ +#include "EObjA.hpp" +#include "EObjAExtra.hpp" +#include "EObjA_p.hpp" + +class EObjALocal : public QObject +{ + Q_OBJECT +public: + EObjALocal(); + ~EObjALocal(); +}; + +EObjALocal::EObjALocal() +{ +} + +EObjALocal::~EObjALocal() +{ +} + +EObjAPrivate::EObjAPrivate() +{ + EObjALocal localObj; + EObjAExtra extraObj; +} + +EObjAPrivate::~EObjAPrivate() +{ +} + +EObjA::EObjA() + : d(new EObjAPrivate) +{ +} + +EObjA::~EObjA() +{ +} + +// For EObjALocal +#include "EObjA.moc" +// - Not the own header +#include "moc_EObjAExtra.cpp" diff --git a/Tests/QtAutogen/mocInclude/EObjA.hpp b/Tests/QtAutogen/mocInclude/EObjA.hpp new file mode 100644 index 0000000..0939ab6 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjA.hpp @@ -0,0 +1,19 @@ +#ifndef EOBJA_HPP +#define EOBJA_HPP + +#include <QObject> + +// Sources includes a moc_ includes of an extra object +class EObjAPrivate; +class EObjA : public QObject +{ + Q_OBJECT +public: + EObjA(); + ~EObjA(); + +private: + EObjAPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/EObjAExtra.cpp b/Tests/QtAutogen/mocInclude/EObjAExtra.cpp new file mode 100644 index 0000000..369ca8f --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjAExtra.cpp @@ -0,0 +1,20 @@ +#include "EObjAExtra.hpp" +#include "EObjAExtra_p.hpp" + +EObjAExtraPrivate::EObjAExtraPrivate() +{ +} + +EObjAExtraPrivate::~EObjAExtraPrivate() +{ +} + +EObjAExtra::EObjAExtra() + : d(new EObjAExtraPrivate) +{ +} + +EObjAExtra::~EObjAExtra() +{ + delete d; +} diff --git a/Tests/QtAutogen/mocInclude/EObjAExtra.hpp b/Tests/QtAutogen/mocInclude/EObjAExtra.hpp new file mode 100644 index 0000000..b10681d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjAExtra.hpp @@ -0,0 +1,18 @@ +#ifndef EOBJAEXTRA_HPP +#define EOBJAEXTRA_HPP + +#include <QObject> + +class EObjAExtraPrivate; +class EObjAExtra : public QObject +{ + Q_OBJECT +public: + EObjAExtra(); + ~EObjAExtra(); + +private: + EObjAExtraPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/EObjAExtra_p.hpp b/Tests/QtAutogen/mocInclude/EObjAExtra_p.hpp new file mode 100644 index 0000000..dea6cb5 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjAExtra_p.hpp @@ -0,0 +1,12 @@ +#ifndef EOBJAEXTRA_P_HPP +#define EOBJAEXTRA_P_HPP + +class EObjAExtraPrivate : public QObject +{ + Q_OBJECT +public: + EObjAExtraPrivate(); + ~EObjAExtraPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/EObjA_p.hpp b/Tests/QtAutogen/mocInclude/EObjA_p.hpp new file mode 100644 index 0000000..1e0d7e1 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjA_p.hpp @@ -0,0 +1,12 @@ +#ifndef EOBJA_P_HPP +#define EOBJA_P_HPP + +class EObjAPrivate : public QObject +{ + Q_OBJECT +public: + EObjAPrivate(); + ~EObjAPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/EObjB.cpp b/Tests/QtAutogen/mocInclude/EObjB.cpp new file mode 100644 index 0000000..d19fbfa --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjB.cpp @@ -0,0 +1,44 @@ +#include "EObjB.hpp" +#include "EObjB_p.hpp" +#include "subExtra/EObjBExtra.hpp" + +class EObjBLocal : public QObject +{ + Q_OBJECT +public: + EObjBLocal(); + ~EObjBLocal(); +}; + +EObjBLocal::EObjBLocal() +{ +} + +EObjBLocal::~EObjBLocal() +{ +} + +EObjBPrivate::EObjBPrivate() +{ + EObjBLocal localObj; + EObjBExtra extraObj; +} + +EObjBPrivate::~EObjBPrivate() +{ +} + +EObjB::EObjB() + : d(new EObjBPrivate) +{ +} + +EObjB::~EObjB() +{ +} + +// For EObjBLocal +#include "EObjB.moc" +// - Not the own header +// - in a subdirectory +#include "subExtra/moc_EObjBExtra.cpp" diff --git a/Tests/QtAutogen/mocInclude/EObjB.hpp b/Tests/QtAutogen/mocInclude/EObjB.hpp new file mode 100644 index 0000000..6632bdb --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjB.hpp @@ -0,0 +1,19 @@ +#ifndef EOBJB_HPP +#define EOBJB_HPP + +#include <QObject> + +// Sources includes a moc_ includes of an extra object in a subdirectory +class EObjBPrivate; +class EObjB : public QObject +{ + Q_OBJECT +public: + EObjB(); + ~EObjB(); + +private: + EObjBPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/EObjB_p.hpp b/Tests/QtAutogen/mocInclude/EObjB_p.hpp new file mode 100644 index 0000000..2905f28 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/EObjB_p.hpp @@ -0,0 +1,12 @@ +#ifndef EOBJB_P_HPP +#define EOBJB_P_HPP + +class EObjBPrivate : public QObject +{ + Q_OBJECT +public: + EObjBPrivate(); + ~EObjBPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/LObjA.cpp b/Tests/QtAutogen/mocInclude/LObjA.cpp new file mode 100644 index 0000000..9aae991 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/LObjA.cpp @@ -0,0 +1,39 @@ +#include "LObjA.hpp" +#include "LObjA_p.h" + +class LObjALocal : public QObject +{ + Q_OBJECT +public: + LObjALocal(); + ~LObjALocal(); +}; + +LObjALocal::LObjALocal() +{ +} + +LObjALocal::~LObjALocal() +{ +} + +LObjAPrivate::LObjAPrivate() +{ + LObjALocal localObj; +} + +LObjAPrivate::~LObjAPrivate() +{ +} + +LObjA::LObjA() + : d(new LObjAPrivate) +{ +} + +LObjA::~LObjA() +{ + delete d; +} + +#include "LObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/LObjA.hpp b/Tests/QtAutogen/mocInclude/LObjA.hpp new file mode 100644 index 0000000..aac670c --- /dev/null +++ b/Tests/QtAutogen/mocInclude/LObjA.hpp @@ -0,0 +1,19 @@ +#ifndef LOBJA_HPP +#define LOBJA_HPP + +#include <QObject> + +// Object source comes with a .moc include +class LObjAPrivate; +class LObjA : public QObject +{ + Q_OBJECT +public: + LObjA(); + ~LObjA(); + +private: + LObjAPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/LObjA_p.h b/Tests/QtAutogen/mocInclude/LObjA_p.h new file mode 100644 index 0000000..ebe8395 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/LObjA_p.h @@ -0,0 +1,12 @@ +#ifndef LOBJA_P_HPP +#define LOBJA_P_HPP + +class LObjAPrivate : public QObject +{ + Q_OBJECT +public: + LObjAPrivate(); + ~LObjAPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/LObjB.cpp b/Tests/QtAutogen/mocInclude/LObjB.cpp new file mode 100644 index 0000000..7485d8f --- /dev/null +++ b/Tests/QtAutogen/mocInclude/LObjB.cpp @@ -0,0 +1,40 @@ +#include "LObjB.hpp" +#include "LObjB_p.h" + +class LObjBLocal : public QObject +{ + Q_OBJECT +public: + LObjBLocal(); + ~LObjBLocal(); +}; + +LObjBLocal::LObjBLocal() +{ +} + +LObjBLocal::~LObjBLocal() +{ +} + +LObjBPrivate::LObjBPrivate() +{ + LObjBLocal localObj; +} + +LObjBPrivate::~LObjBPrivate() +{ +} + +LObjB::LObjB() + : d(new LObjBPrivate) +{ +} + +LObjB::~LObjB() +{ + delete d; +} + +#include "LObjB.moc" +#include "moc_LObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/LObjB.hpp b/Tests/QtAutogen/mocInclude/LObjB.hpp new file mode 100644 index 0000000..eb4e58d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/LObjB.hpp @@ -0,0 +1,19 @@ +#ifndef LLObjB_HPP +#define LLObjB_HPP + +#include <QObject> + +// Object source comes with a .moc and a _moc include +class LObjBPrivate; +class LObjB : public QObject +{ + Q_OBJECT +public: + LObjB(); + ~LObjB(); + +private: + LObjBPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/LObjB_p.h b/Tests/QtAutogen/mocInclude/LObjB_p.h new file mode 100644 index 0000000..b871f2d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/LObjB_p.h @@ -0,0 +1,12 @@ +#ifndef LOBJB_P_HPP +#define LOBJB_P_HPP + +class LObjBPrivate : public QObject +{ + Q_OBJECT +public: + LObjBPrivate(); + ~LObjBPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp index 1b0311d..6f6b90e 100644 --- a/Tests/QtAutogen/mocInclude/ObjA.cpp +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -1,24 +1,20 @@ #include "ObjA.hpp" +#include "ObjA_p.h" -class SubObjA : public QObject +ObjAPrivate::ObjAPrivate() { - Q_OBJECT - -public: - SubObjA() {} - ~SubObjA() {} - - Q_SLOT - void aSlot(); -}; +} -void SubObjA::aSlot() +ObjAPrivate::~ObjAPrivate() { } -void ObjA::go() +ObjA::ObjA() + : d(new ObjAPrivate) { - SubObjA subObj; } -#include "ObjA.moc" +ObjA::~ObjA() +{ + delete d; +} diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp index 281e90d..f16c924 100644 --- a/Tests/QtAutogen/mocInclude/ObjA.hpp +++ b/Tests/QtAutogen/mocInclude/ObjA.hpp @@ -3,11 +3,17 @@ #include <QObject> +// Object source comes without any _moc/.moc includes +class ObjAPrivate; class ObjA : public QObject { Q_OBJECT - Q_SLOT - void go(); +public: + ObjA(); + ~ObjA(); + +private: + ObjAPrivate* const d; }; #endif diff --git a/Tests/QtAutogen/mocInclude/ObjA_p.h b/Tests/QtAutogen/mocInclude/ObjA_p.h new file mode 100644 index 0000000..eb60c98 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA_p.h @@ -0,0 +1,12 @@ +#ifndef OBJA_P_HPP +#define OBJA_P_HPP + +class ObjAPrivate : public QObject +{ + Q_OBJECT +public: + ObjAPrivate(); + ~ObjAPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp index 5ff315d..a6f2509 100644 --- a/Tests/QtAutogen/mocInclude/ObjB.cpp +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -1,25 +1,22 @@ #include "ObjB.hpp" +#include "ObjB_p.h" -class SubObjB : public QObject +ObjBPrivate::ObjBPrivate() { - Q_OBJECT - -public: - SubObjB() {} - ~SubObjB() {} +} - Q_SLOT - void aSlot(); -}; +ObjBPrivate::~ObjBPrivate() +{ +} -void SubObjB::aSlot() +ObjB::ObjB() + : d(new ObjBPrivate) { } -void ObjB::go() +ObjB::~ObjB() { - SubObjB subObj; + delete d; } -#include "ObjB.moc" #include "moc_ObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp index 94f3d49..2ac8d17 100644 --- a/Tests/QtAutogen/mocInclude/ObjB.hpp +++ b/Tests/QtAutogen/mocInclude/ObjB.hpp @@ -1,13 +1,19 @@ -#ifndef OBJB_HPP -#define OBJB_HPP +#ifndef ObjB_HPP +#define ObjB_HPP #include <QObject> +// Object source comes with a _moc include +class ObjBPrivate; class ObjB : public QObject { Q_OBJECT - Q_SLOT - void go(); +public: + ObjB(); + ~ObjB(); + +private: + ObjBPrivate* const d; }; #endif diff --git a/Tests/QtAutogen/mocInclude/ObjB_p.h b/Tests/QtAutogen/mocInclude/ObjB_p.h new file mode 100644 index 0000000..418da65 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB_p.h @@ -0,0 +1,12 @@ +#ifndef OBJB_P_HPP +#define OBJB_P_HPP + +class ObjBPrivate : public QObject +{ + Q_OBJECT +public: + ObjBPrivate(); + ~ObjBPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp deleted file mode 100644 index 8ca34cb..0000000 --- a/Tests/QtAutogen/mocInclude/ObjC.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ObjC.hpp" - -class SubObjC : public QObject -{ - Q_OBJECT - -public: - SubObjC() {} - ~SubObjC() {} - - Q_SLOT - void aSlot(); -}; - -void SubObjC::aSlot() -{ -} - -void ObjC::go() -{ - SubObjC subObj; -} - -#include "ObjC.moc" -// Not the own header -#include "moc_ObjD.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjC.hpp b/Tests/QtAutogen/mocInclude/ObjC.hpp deleted file mode 100644 index a8e98eb..0000000 --- a/Tests/QtAutogen/mocInclude/ObjC.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef OBJC_HPP -#define OBJC_HPP - -#include <QObject> - -class ObjC : public QObject -{ - Q_OBJECT - Q_SLOT - void go(); -}; - -#endif diff --git a/Tests/QtAutogen/mocInclude/ObjD.cpp b/Tests/QtAutogen/mocInclude/ObjD.cpp deleted file mode 100644 index c18aec1..0000000 --- a/Tests/QtAutogen/mocInclude/ObjD.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ObjD.hpp" - -class SubObjD : public QObject -{ - Q_OBJECT - -public: - SubObjD() {} - ~SubObjD() {} - - Q_SLOT - void aSlot(); -}; - -void SubObjD::aSlot() -{ -} - -void ObjD::go() -{ - SubObjD subObj; -} - -#include "ObjD.moc" -// Header in subdirectory -#include "subA/moc_SubObjA.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjD.hpp b/Tests/QtAutogen/mocInclude/ObjD.hpp deleted file mode 100644 index b6ee098..0000000 --- a/Tests/QtAutogen/mocInclude/ObjD.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef OBJD_HPP -#define OBJD_HPP - -#include <QObject> - -class ObjD : public QObject -{ - Q_OBJECT - Q_SLOT - void go(); -}; - -#endif diff --git a/Tests/QtAutogen/mocInclude/SObjA.cpp b/Tests/QtAutogen/mocInclude/SObjA.cpp new file mode 100644 index 0000000..7e75bf9 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjA.cpp @@ -0,0 +1,11 @@ +#include "SObjA.hpp" + +SObjA::SObjA() +{ +} + +SObjA::~SObjA() +{ +} + +#include "SObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/SObjA.hpp b/Tests/QtAutogen/mocInclude/SObjA.hpp new file mode 100644 index 0000000..1436abc --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjA.hpp @@ -0,0 +1,15 @@ +#ifndef SOBJA_HPP +#define SOBJA_HPP + +#include <QObject> + +// Object source includes externally generated .moc file +class SObjA : public QObject +{ + Q_OBJECT +public: + SObjA(); + ~SObjA(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/SObjB.cpp.in b/Tests/QtAutogen/mocInclude/SObjB.cpp.in new file mode 100644 index 0000000..b1cc12a --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjB.cpp.in @@ -0,0 +1,11 @@ +#include "SObjB.hpp" + +SObjB::SObjB() +{ +} + +SObjB::~SObjB() +{ +} + +#include "SObjB.moc" diff --git a/Tests/QtAutogen/mocInclude/SObjB.hpp.in b/Tests/QtAutogen/mocInclude/SObjB.hpp.in new file mode 100644 index 0000000..5e396ae --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjB.hpp.in @@ -0,0 +1,15 @@ +#ifndef SOBJB_HPP +#define SOBJB_HPP + +#include <QObject> + +// Object source includes externally generated .moc file +class SObjB : public QObject +{ + Q_OBJECT +public: + SObjB(); + ~SObjB(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/SObjC.cpp b/Tests/QtAutogen/mocInclude/SObjC.cpp new file mode 100644 index 0000000..1e8d397 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjC.cpp @@ -0,0 +1,35 @@ +#include "SObjC.hpp" + +void SObjCLocalFunction(); + +class SObjCLocal : public QObject +{ + Q_OBJECT + +public: + SObjCLocal(); + ~SObjCLocal(); +}; + +SObjCLocal::SObjCLocal() +{ +} + +SObjCLocal::~SObjCLocal() +{ +} + +SObjC::SObjC() +{ + SObjCLocal localObject; + SObjCLocalFunction(); +} + +SObjC::~SObjC() +{ +} + +#include "SObjC.moc" +#include "moc_SObjC.cpp" +// Include moc_ file for which the header is SKIP_AUTOMOC enabled +#include "moc_SObjCExtra.cpp" diff --git a/Tests/QtAutogen/mocInclude/SObjC.hpp b/Tests/QtAutogen/mocInclude/SObjC.hpp new file mode 100644 index 0000000..def0f9d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjC.hpp @@ -0,0 +1,15 @@ +#ifndef SOBJC_HPP +#define SOBJC_HPP + +#include <QObject> + +// Object source includes externally generated .moc file +class SObjC : public QObject +{ + Q_OBJECT +public: + SObjC(); + ~SObjC(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/SObjCExtra.cpp b/Tests/QtAutogen/mocInclude/SObjCExtra.cpp new file mode 100644 index 0000000..55dd1c3 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjCExtra.cpp @@ -0,0 +1,31 @@ +#include "SObjCExtra.hpp" + +class SObjCLocalExtra : public QObject +{ + Q_OBJECT + +public: + SObjCLocalExtra(); + ~SObjCLocalExtra(); +}; + +SObjCLocalExtra::SObjCLocalExtra() +{ +} + +SObjCLocalExtra::~SObjCLocalExtra() +{ +} + +SObjCExtra::SObjCExtra() +{ +} + +SObjCExtra::~SObjCExtra() +{ +} + +// Externally generated header moc +#include "SObjCExtra_extMoc.cpp" +// AUTOMOC generated source moc +#include "SObjCExtra.moc" diff --git a/Tests/QtAutogen/mocInclude/SObjCExtra.hpp b/Tests/QtAutogen/mocInclude/SObjCExtra.hpp new file mode 100644 index 0000000..08545ac --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjCExtra.hpp @@ -0,0 +1,15 @@ +#ifndef SOBJCEXTRA_HPP +#define SOBJCEXTRA_HPP + +#include <QObject> + +// Object source includes externally generated .moc file +class SObjCExtra : public QObject +{ + Q_OBJECT +public: + SObjCExtra(); + ~SObjCExtra(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/SObjCExtra.moc.in b/Tests/QtAutogen/mocInclude/SObjCExtra.moc.in new file mode 100644 index 0000000..00fc4aa --- /dev/null +++ b/Tests/QtAutogen/mocInclude/SObjCExtra.moc.in @@ -0,0 +1,4 @@ + +void SObjCLocalFunction() +{ +} diff --git a/Tests/QtAutogen/mocInclude/shared.cmake b/Tests/QtAutogen/mocInclude/shared.cmake new file mode 100644 index 0000000..c426050 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/shared.cmake @@ -0,0 +1,69 @@ +# Test moc include patterns +include_directories("../mocInclude") +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Generate .moc file externally and enabled SKIP_AUTOMOC on the file +qtx_generate_moc( + ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjA.hpp + ${CMAKE_CURRENT_BINARY_DIR}/SObjA.moc) +set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjA.cpp PROPERTY SKIP_AUTOMOC ON) + +# Generate .moc file externally from generated source file +# and enabled SKIP_AUTOMOC on the source file +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/SObjB.hpp + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjB.hpp.in + ${CMAKE_CURRENT_BINARY_DIR}/SObjB.hpp) +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/SObjB.cpp + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjB.cpp.in + ${CMAKE_CURRENT_BINARY_DIR}/SObjB.cpp) +qtx_generate_moc( + ${CMAKE_CURRENT_BINARY_DIR}/SObjB.hpp + ${CMAKE_CURRENT_BINARY_DIR}/SObjB.moc) +set_property(SOURCE ${CMAKE_CURRENT_BINARY_DIR}/SObjB.cpp PROPERTY SKIP_AUTOMOC ON) + +# Generate moc file externally and enabled SKIP_AUTOMOC on the header +qtx_generate_moc( + ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjCExtra.hpp + ${CMAKE_CURRENT_BINARY_DIR}/SObjCExtra_extMoc.cpp) +set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjCExtra.hpp PROPERTY SKIP_AUTOMOC ON) +# Custom target to depend on +set(SOBJC_MOC ${CMAKE_CURRENT_BINARY_DIR}/${MOC_INCLUDE_NAME}_autogen/include/moc_SObjCExtra.cpp) +add_custom_target("${MOC_INCLUDE_NAME}_SOBJC" + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/SObjCExtra_extMoc.cpp + BYPRODUCTS ${SOBJC_MOC} + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/SObjCExtra.moc.in + ${SOBJC_MOC}) + +# MOC_INCLUDE_NAME must be defined by the includer +add_executable(${MOC_INCLUDE_NAME} + # Common sources + ../mocInclude/ObjA.cpp + ../mocInclude/ObjB.cpp + + ../mocInclude/LObjA.cpp + ../mocInclude/LObjB.cpp + + ../mocInclude/EObjA.cpp + ../mocInclude/EObjAExtra.cpp + ../mocInclude/EObjB.cpp + ../mocInclude/subExtra/EObjBExtra.cpp + + ../mocInclude/SObjA.cpp + ${CMAKE_CURRENT_BINARY_DIR}/SObjA.moc + ${CMAKE_CURRENT_BINARY_DIR}/SObjB.cpp + ${CMAKE_CURRENT_BINARY_DIR}/SObjB.moc + ../mocInclude/SObjC.cpp + ../mocInclude/SObjCExtra.hpp + ../mocInclude/SObjCExtra.cpp + + ../mocInclude/subGlobal/GObj.cpp + main.cpp +) +add_dependencies(${MOC_INCLUDE_NAME} "${MOC_INCLUDE_NAME}_SOBJC") +target_link_libraries(${MOC_INCLUDE_NAME} ${QT_LIBRARIES}) +set_target_properties(${MOC_INCLUDE_NAME} PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp deleted file mode 100644 index a05f6e3..0000000 --- a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "SubObjA.hpp" - -namespace subA { - -class SubObjA : public QObject -{ - Q_OBJECT - -public: - SubObjA() {} - ~SubObjA() {} - - Q_SLOT - void aSlot(); -}; - -void SubObjA::aSlot() -{ -} - -void ObjA::go() -{ - SubObjA subObj; -} -} - -#include "SubObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp deleted file mode 100644 index 31a18b6..0000000 --- a/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SUBOBJA_HPP -#define SUBOBJA_HPP - -#include <QObject> - -namespace subA { - -class ObjA : public QObject -{ - Q_OBJECT - Q_SLOT - void go(); -}; -} - -#endif diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp deleted file mode 100644 index 1e77639..0000000 --- a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "SubObjB.hpp" - -namespace subB { - -class SubObjB : public QObject -{ - Q_OBJECT - -public: - SubObjB() {} - ~SubObjB() {} - - Q_SLOT - void aSlot(); -}; - -void SubObjB::aSlot() -{ -} - -void ObjB::go() -{ - SubObjB subObj; -} -} - -#include "SubObjB.moc" diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp deleted file mode 100644 index 3f29fa2..0000000 --- a/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SUBOBJB_HPP -#define SUBOBJB_HPP - -#include <QObject> - -namespace subB { - -class ObjB : public QObject -{ - Q_OBJECT - Q_SLOT - void go(); -}; -} - -#endif diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp deleted file mode 100644 index c2d94ef..0000000 --- a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "SubObjC.hpp" - -namespace subC { - -class SubObjC : public QObject -{ - Q_OBJECT - -public: - SubObjC() {} - ~SubObjC() {} - - Q_SLOT - void aSlot(); -}; - -void SubObjC::aSlot() -{ -} - -void ObjC::go() -{ - SubObjC subObj; -} -} - -#include "SubObjC.moc" diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp deleted file mode 100644 index dc251fd..0000000 --- a/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SUBOBJC_HPP -#define SUBOBJC_HPP - -#include <QObject> - -namespace subC { - -class ObjC : public QObject -{ - Q_OBJECT - Q_SLOT - void go(); -}; -} - -#endif diff --git a/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra.cpp b/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra.cpp new file mode 100644 index 0000000..c697866 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra.cpp @@ -0,0 +1,20 @@ +#include "EObjBExtra.hpp" +#include "EObjBExtra_p.hpp" + +EObjBExtraPrivate::EObjBExtraPrivate() +{ +} + +EObjBExtraPrivate::~EObjBExtraPrivate() +{ +} + +EObjBExtra::EObjBExtra() + : d(new EObjBExtraPrivate) +{ +} + +EObjBExtra::~EObjBExtra() +{ + delete d; +} diff --git a/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra.hpp b/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra.hpp new file mode 100644 index 0000000..3798d7f --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra.hpp @@ -0,0 +1,18 @@ +#ifndef EOBJBEXTRA_HPP +#define EOBJBEXTRA_HPP + +#include <QObject> + +class EObjBExtraPrivate; +class EObjBExtra : public QObject +{ + Q_OBJECT +public: + EObjBExtra(); + ~EObjBExtra(); + +private: + EObjBExtraPrivate* const d; +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra_p.hpp b/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra_p.hpp new file mode 100644 index 0000000..db8a096 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subExtra/EObjBExtra_p.hpp @@ -0,0 +1,12 @@ +#ifndef EOBJBEXTRA_P_HPP +#define EOBJBEXTRA_P_HPP + +class EObjBExtraPrivate : public QObject +{ + Q_OBJECT +public: + EObjBExtraPrivate(); + ~EObjBExtraPrivate(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subGlobal/GObj.cpp b/Tests/QtAutogen/mocInclude/subGlobal/GObj.cpp new file mode 100644 index 0000000..6b92f21 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subGlobal/GObj.cpp @@ -0,0 +1,41 @@ +#include "GObj.hpp" +#include "GObj_p.hpp" + +namespace subGlobal { + +class GObjLocal : public QObject +{ + Q_OBJECT +public: + GObjLocal(); + ~GObjLocal(); +}; + +GObjLocal::GObjLocal() +{ +} + +GObjLocal::~GObjLocal() +{ +} + +GObjPrivate::GObjPrivate() +{ +} + +GObjPrivate::~GObjPrivate() +{ +} + +GObj::GObj() +{ + GObjLocal localObj; +} + +GObj::~GObj() +{ +} +} + +// For the local QObject +#include "GObj.moc" diff --git a/Tests/QtAutogen/mocInclude/subGlobal/GObj.hpp b/Tests/QtAutogen/mocInclude/subGlobal/GObj.hpp new file mode 100644 index 0000000..2f9ee82 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subGlobal/GObj.hpp @@ -0,0 +1,17 @@ +#ifndef GOBJ_HPP +#define GOBJ_HPP + +#include <QObject> + +namespace subGlobal { + +class GObj : public QObject +{ + Q_OBJECT +public: + GObj(); + ~GObj(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocInclude/subGlobal/GObj_p.hpp b/Tests/QtAutogen/mocInclude/subGlobal/GObj_p.hpp new file mode 100644 index 0000000..7b37dfd --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subGlobal/GObj_p.hpp @@ -0,0 +1,15 @@ +#ifndef GOBJ_P_HPP +#define GOBJ_P_HPP + +namespace subGlobal { + +class GObjPrivate : public QObject +{ + Q_OBJECT +public: + GObjPrivate(); + ~GObjPrivate(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt index 6a0829d..97ba1df 100644 --- a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt +++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt @@ -2,17 +2,16 @@ set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) -include_directories("../mocInclude") +# Shared executable +set(MOC_INCLUDE_NAME "mocIncludeRelaxed") +include(${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/shared.cmake) -add_executable(mocIncludeRelaxed - ../mocInclude/ObjA.cpp - ../mocInclude/ObjB.cpp - ../mocInclude/ObjC.cpp - ../mocInclude/ObjD.cpp - ../mocInclude/subA/SubObjA.cpp - ../mocInclude/subB/SubObjB.cpp - ../mocInclude/subC/SubObjC.cpp - main.cpp +# Relaxed ony executable +add_executable(mocIncludeRelaxedOnly + RObjA.cpp + RObjB.cpp + RObjC.cpp + RMain.cpp ) -target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES}) -set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON) +target_link_libraries(mocIncludeRelaxedOnly ${QT_LIBRARIES}) +set_target_properties(mocIncludeRelaxedOnly PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RMain.cpp b/Tests/QtAutogen/mocIncludeRelaxed/RMain.cpp new file mode 100644 index 0000000..5b2c070 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RMain.cpp @@ -0,0 +1,12 @@ +// Relaxed AUTOMOC objects +#include "RObjA.hpp" +#include "RObjB.hpp" +#include "RObjC.hpp" + +int main(int argv, char** args) +{ + RObjA rObjA; + RObjB rObjB; + RObjC rObjC; + return 0; +} diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjA.cpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjA.cpp new file mode 100644 index 0000000..2e2cf6a --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjA.cpp @@ -0,0 +1,12 @@ +#include "RObjA.hpp" + +RObjA::RObjA() +{ +} + +RObjA::~RObjA() +{ +} + +// Relaxed include should moc the header instead +#include "RObjA.moc" diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjA.hpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjA.hpp new file mode 100644 index 0000000..5974187 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjA.hpp @@ -0,0 +1,14 @@ +#ifndef ROBJA_HPP +#define ROBJA_HPP + +#include <QObject> + +class RObjA : public QObject +{ + Q_OBJECT +public: + RObjA(); + ~RObjA(); +}; + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjB.cpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjB.cpp new file mode 100644 index 0000000..c56d10f --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjB.cpp @@ -0,0 +1,22 @@ +#include "RObjB.hpp" +#include "RObjBExtra.hpp" + +RObjBExtra::RObjBExtra() +{ +} + +RObjBExtra::~RObjBExtra() +{ +} + +RObjB::RObjB() +{ + RObjBExtra extraObject; +} + +RObjB::~RObjB() +{ +} + +// Relaxed mode should run moc on RObjBExtra.hpp instead +#include "RObjBExtra.moc" diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjB.hpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjB.hpp new file mode 100644 index 0000000..d6d0474 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjB.hpp @@ -0,0 +1,14 @@ +#ifndef ROBJB_HPP +#define ROBJB_HPP + +#include <QObject> + +class RObjB : public QObject +{ + Q_OBJECT +public: + RObjB(); + ~RObjB(); +}; + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjBExtra.hpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjBExtra.hpp new file mode 100644 index 0000000..5d6be75 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjBExtra.hpp @@ -0,0 +1,14 @@ +#ifndef ROBJBEXTRA_HPP +#define ROBJBEXTRA_HPP + +#include <QObject> + +class RObjBExtra : public QObject +{ + Q_OBJECT +public: + RObjBExtra(); + ~RObjBExtra(); +}; + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjC.cpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjC.cpp new file mode 100644 index 0000000..4ba32f5 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjC.cpp @@ -0,0 +1,30 @@ +#include "RObjC.hpp" +#include <QObject> + +class RObjCPrivate : public QObject +{ + Q_OBJECT +public: + RObjCPrivate(); + ~RObjCPrivate(); +}; + +RObjCPrivate::RObjCPrivate() +{ +} + +RObjCPrivate::~RObjCPrivate() +{ +} + +RObjC::RObjC() +{ + RObjCPrivate privateObject; +} + +RObjC::~RObjC() +{ +} + +// Relaxed include should moc this source instead of the header +#include "moc_RObjC.cpp" diff --git a/Tests/QtAutogen/mocIncludeRelaxed/RObjC.hpp b/Tests/QtAutogen/mocIncludeRelaxed/RObjC.hpp new file mode 100644 index 0000000..5552ede --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/RObjC.hpp @@ -0,0 +1,14 @@ +#ifndef ROBJC_HPP +#define ROBJC_HPP + +#include <QObject> + +class RObjC : public QObject +{ + Q_OBJECT +public: + RObjC(); + ~RObjC(); +}; + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp index 142d59e..5a3148d 100644 --- a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp +++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp @@ -1,14 +1,26 @@ +#include "EObjA.hpp" +#include "EObjB.hpp" +#include "LObjA.hpp" +#include "LObjB.hpp" #include "ObjA.hpp" #include "ObjB.hpp" -#include "ObjC.hpp" +#include "SObjA.hpp" +#include "SObjB.hpp" +#include "subGlobal/GObj.hpp" int main(int argv, char** args) { + subGlobal::GObj gObj; ObjA objA; ObjB objB; - ObjC objC; + LObjA lObjA; + LObjB lObjB; + EObjA eObjA; + EObjB eObjB; + SObjA sObjA; + SObjB sObjB; return 0; } // Header in global subdirectory -#include "subB/moc_SubObjB.cpp" +#include "subGlobal/moc_GObj.cpp" diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt index 22e93a8..789354a 100644 --- a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt +++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt @@ -1,18 +1,6 @@ # Test moc include patterns set(CMAKE_AUTOMOC_RELAXED_MODE FALSE) +set(MOC_INCLUDE_NAME "mocIncludeStrict") -include_directories("../mocInclude") - -add_executable(mocIncludeStrict - ../mocInclude/ObjA.cpp - ../mocInclude/ObjB.cpp - ../mocInclude/ObjC.cpp - ../mocInclude/ObjD.cpp - ../mocInclude/subA/SubObjA.cpp - ../mocInclude/subB/SubObjB.cpp - ../mocInclude/subC/SubObjC.cpp - main.cpp -) -target_link_libraries(mocIncludeStrict ${QT_LIBRARIES}) -set_target_properties(mocIncludeStrict PROPERTIES AUTOMOC ON) +include(${CMAKE_CURRENT_SOURCE_DIR}/../mocInclude/shared.cmake) diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp index 142d59e..5a3148d 100644 --- a/Tests/QtAutogen/mocIncludeStrict/main.cpp +++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp @@ -1,14 +1,26 @@ +#include "EObjA.hpp" +#include "EObjB.hpp" +#include "LObjA.hpp" +#include "LObjB.hpp" #include "ObjA.hpp" #include "ObjB.hpp" -#include "ObjC.hpp" +#include "SObjA.hpp" +#include "SObjB.hpp" +#include "subGlobal/GObj.hpp" int main(int argv, char** args) { + subGlobal::GObj gObj; ObjA objA; ObjB objB; - ObjC objC; + LObjA lObjA; + LObjB lObjB; + EObjA eObjA; + EObjB eObjB; + SObjA sObjA; + SObjB sObjB; return 0; } // Header in global subdirectory -#include "subB/moc_SubObjB.cpp" +#include "subGlobal/moc_GObj.cpp" diff --git a/Tests/QtAutogenRerun/CMakeLists.txt b/Tests/QtAutogenRerun/CMakeLists.txt new file mode 100644 index 0000000..088025f --- /dev/null +++ b/Tests/QtAutogenRerun/CMakeLists.txt @@ -0,0 +1,239 @@ +cmake_minimum_required(VERSION 3.9) +cmake_policy(SET CMP0071 NEW) +project(QtAutogenRerun) + +# Tell find_package(Qt5) where to find Qt. +if(QT_QMAKE_EXECUTABLE) + get_filename_component(Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) + get_filename_component(Qt_PREFIX_DIR "${Qt_BIN_DIR}" PATH) + set(CMAKE_PREFIX_PATH ${Qt_PREFIX_DIR}) +endif() + +if (QT_TEST_VERSION STREQUAL 4) + find_package(Qt4 REQUIRED) + + # Include this directory before using the UseQt4 file. + add_subdirectory(defines_test) + + include(UseQt4) + + set(QT_QTCORE_TARGET Qt4::QtCore) + +else() + if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") + endif() + find_package(Qt5Widgets REQUIRED) + + set(QT_QTCORE_TARGET Qt5::Core) + + include_directories(${Qt5Widgets_INCLUDE_DIRS}) + set(QT_LIBRARIES Qt5::Widgets) + + if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) + endif() + +endif() + +# -- Test +# Dummy test to generate clean target +add_executable(dummy dummy.cpp) + +# -- Test +# When a file listed in a .qrc file changes the target must be rebuilt +set(timeformat "%Y%j%H%M%S") +set(RCC_DEPENDS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/rccDepends") +set(RCC_DEPENDS_BIN "${CMAKE_CURRENT_BINARY_DIR}/rccDepends") +configure_file(${RCC_DEPENDS_SRC}/res1a.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY) +configure_file(${RCC_DEPENDS_SRC}/res2a.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY) +try_compile(RCC_DEPENDS + "${RCC_DEPENDS_BIN}" + "${RCC_DEPENDS_SRC}" + rccDepends + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" + OUTPUT_VARIABLE output +) +if (NOT RCC_DEPENDS) + message(SEND_ERROR "Initial build of rccDepends failed. Output: ${output}") +endif() +# Get name and timestamp of the output binary +file(STRINGS "${RCC_DEPENDS_BIN}/target.txt" targetList ENCODING UTF-8) +list(GET targetList 0 rccDependsBin) +file(TIMESTAMP "${rccDependsBin}" timeBegin "${timeformat}") +# Sleep, touch regular qrc input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/input.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Second build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep1 "${timeformat}") +if (NOT timeStep1 GREATER timeBegin) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the first step!") +endif() +# Sleep, update regular qrc file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +configure_file(${RCC_DEPENDS_SRC}/res1b.qrc.in ${RCC_DEPENDS_BIN}/res1.qrc COPYONLY) +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Third build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep2 "${timeformat}") +if (NOT timeStep2 GREATER timeStep1) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the second step!") +endif() +# Sleep, touch regular qrc newly added input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res1/inputAdded.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Fourth build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep3 "${timeformat}") +if (NOT timeStep3 GREATER timeStep2) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the third step!") +endif() +# Sleep, touch generated qrc input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/input.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Fifth build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep4 "${timeformat}") +if (NOT timeStep4 GREATER timeStep3) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fourth step!") +endif() +# Sleep, update generated qrc file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +configure_file(${RCC_DEPENDS_SRC}/res2b.qrc.in ${RCC_DEPENDS_BIN}/res2.qrc.in COPYONLY) +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Sixth build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep5 "${timeformat}") +if (NOT timeStep5 GREATER timeStep4) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the fitfh step!") +endif() +# Sleep, touch generated qrc newly added input file, rebuild and compare timestamp +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the timestamp will change. +execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${RCC_DEPENDS_BIN}/res2/inputAdded.txt") +execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${RCC_DEPENDS_BIN}" RESULT_VARIABLE result) +if (result) + message(SEND_ERROR "Seventh build of rccDepends failed.") +endif() +file(TIMESTAMP "${rccDependsBin}" timeStep6 "${timeformat}") +if (NOT timeStep6 GREATER timeStep5) + message(SEND_ERROR "File (${rccDependsBin}) should have changed in the sixth step!") +endif() + + +# -- Test +# Ensure a repeated build succeeds when a header containing a QObject changes +set(timeformat "%Y%j%H%M%S") +configure_file(mocRerun/test1a.h.in mocRerun/test1.h COPYONLY) +try_compile(MOC_RERUN + "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" + "${CMAKE_CURRENT_SOURCE_DIR}/mocRerun" + mocRerun + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" + OUTPUT_VARIABLE output +) +if (NOT MOC_RERUN) + message(SEND_ERROR "Initial build of mocRerun failed. Output: ${output}") +endif() +# Get name and timestamp of the output binary +file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/mocRerun/target1.txt" target1List ENCODING UTF-8) +list(GET target1List 0 binFile) +file(TIMESTAMP "${binFile}" timeBegin "${timeformat}") +# Change file content and rebuild +execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) +configure_file(mocRerun/test1b.h.in mocRerun/test1.h COPYONLY) +execute_process(COMMAND "${CMAKE_COMMAND}" --build . + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocRerun" + RESULT_VARIABLE mocRerun_result + ) +if (mocRerun_result) + message(SEND_ERROR "Second build of mocRerun failed.") +endif() +# Compare timestamps +file(TIMESTAMP "${binFile}" timeStep1 "${timeformat}") +if (NOT timeStep1 GREATER timeBegin) + message(SEND_ERROR "File (${binFile}) should have changed in the first step!") +endif() + + +# -- Test +# Tests Q_PLUGIN_METADATA json file change detection +if (NOT QT_TEST_VERSION STREQUAL 4) + try_compile(MOC_PLUGIN + "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" + "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin" + mocPlugin + CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" + OUTPUT_VARIABLE output + ) + if (NOT MOC_PLUGIN) + message(SEND_ERROR "Initial build of mocPlugin failed. Output: ${output}") + endif() + + set(timeformat "%Y%j%H%M%S") + set(mocPlugSrcDir "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin") + set(mocPlugBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(plAFile "PlugA" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plBFile "PlugB" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plCFile "PlugC" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plDFile "PlugD" PATHS "${mocPlugBinDir}/Debug" "${mocPlugBinDir}" NO_DEFAULT_PATH) + + file(TIMESTAMP "${plAFile}" plABefore "${timeformat}") + file(TIMESTAMP "${plBFile}" plBBefore "${timeformat}") + file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") + file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") + + # Ensure that the timestamp will change and change the json files + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC.json") + configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD.json") + execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}") + + file(TIMESTAMP "${plAFile}" plAAfter "${timeformat}") + file(TIMESTAMP "${plBFile}" plBAfter "${timeformat}") + file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") + file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") + + if (plAAfter GREATER plABefore) + message(SEND_ERROR "file (${plAFile}) should not have changed!") + endif() + if (plBAfter GREATER plBBefore) + message(SEND_ERROR "file (${plBFile}) should not have changed!") + endif() + if (NOT plCAfter GREATER plCBefore) + message(SEND_ERROR "file (${plCFile}) should have changed!") + endif() + if (NOT plDAfter GREATER plDBefore) + message(SEND_ERROR "file (${plDFile}) should have changed!") + endif() + + # Test custom macro + file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") + file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + configure_file("${mocPlugSrcDir}/jsonIn/StyleD.json" "${mocPlugBinDir}/jsonFiles/StyleC_Custom.json") + configure_file("${mocPlugSrcDir}/jsonIn/StyleC.json" "${mocPlugBinDir}/jsonFiles/sub/StyleD_Custom.json") + execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPlugBinDir}") + file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") + file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") + if (NOT plCAfter GREATER plCBefore) + message(SEND_ERROR "file (${plCFile}) should have changed!") + endif() + if (NOT plDAfter GREATER plDBefore) + message(SEND_ERROR "file (${plDFile}) should have changed!") + endif() + +endif() diff --git a/Tests/QtAutogenRerun/defines_test/CMakeLists.txt b/Tests/QtAutogenRerun/defines_test/CMakeLists.txt new file mode 100644 index 0000000..9ee9a22 --- /dev/null +++ b/Tests/QtAutogenRerun/defines_test/CMakeLists.txt @@ -0,0 +1,4 @@ + +add_executable(defines_test defines_test.cpp) +set_target_properties(defines_test PROPERTIES AUTOMOC TRUE) +target_link_libraries(defines_test Qt4::QtGui) diff --git a/Tests/QtAutogenRerun/defines_test/defines_test.cpp b/Tests/QtAutogenRerun/defines_test/defines_test.cpp new file mode 100644 index 0000000..cf4e9cb --- /dev/null +++ b/Tests/QtAutogenRerun/defines_test/defines_test.cpp @@ -0,0 +1,38 @@ + +#include <QObject> + +#ifdef QT_GUI_LIB +#include <QTextDocument> + +class SomeDocument : public QTextDocument +{ + Q_OBJECT + +Q_SIGNALS: + void someSig(); +}; +#endif + +#ifdef QT_CORE_LIB +class SomeObject : public QObject +{ + Q_OBJECT + +Q_SIGNALS: + void someSig(); +}; +#endif + +int main(int argc, char** argv) +{ +#ifdef QT_CORE_LIB + QMetaObject sosmo = SomeObject::staticMetaObject; +#endif +#ifdef QT_GUI_LIB + QMetaObject sdsmo = SomeDocument::staticMetaObject; +#endif + + return 0; +} + +#include "defines_test.moc" diff --git a/Tests/QtAutogenRerun/dummy.cpp b/Tests/QtAutogenRerun/dummy.cpp new file mode 100644 index 0000000..4837a76 --- /dev/null +++ b/Tests/QtAutogenRerun/dummy.cpp @@ -0,0 +1,5 @@ + +int main(int argv, char** args) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogenRerun/mocPlugin/CMakeLists.txt index f80aa29..9b224fb 100644 --- a/Tests/QtAutogen/mocPlugin/CMakeLists.txt +++ b/Tests/QtAutogenRerun/mocPlugin/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.9) project(mocPlugin CXX) set(CMAKE_AUTOMOC_DEPEND_FILTERS diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogenRerun/mocPlugin/StyleA.cpp index b5e8753..b5e8753 100644 --- a/Tests/QtAutogen/mocPlugin/StyleA.cpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleA.cpp diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogenRerun/mocPlugin/StyleA.hpp index 1b6154d..1b6154d 100644 --- a/Tests/QtAutogen/mocPlugin/StyleA.hpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleA.hpp diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogenRerun/mocPlugin/StyleA.json index cc33953..cc33953 100644 --- a/Tests/QtAutogen/mocPlugin/StyleA.json +++ b/Tests/QtAutogenRerun/mocPlugin/StyleA.json diff --git a/Tests/QtAutogen/mocPlugin/StyleA_Custom.json b/Tests/QtAutogenRerun/mocPlugin/StyleA_Custom.json index cc33953..cc33953 100644 --- a/Tests/QtAutogen/mocPlugin/StyleA_Custom.json +++ b/Tests/QtAutogenRerun/mocPlugin/StyleA_Custom.json diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogenRerun/mocPlugin/StyleB.cpp index 17d4400..17d4400 100644 --- a/Tests/QtAutogen/mocPlugin/StyleB.cpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleB.cpp diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogenRerun/mocPlugin/StyleB.hpp index 163c9b2..163c9b2 100644 --- a/Tests/QtAutogen/mocPlugin/StyleB.hpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleB.hpp diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogenRerun/mocPlugin/StyleC.cpp index 37e7564..37e7564 100644 --- a/Tests/QtAutogen/mocPlugin/StyleC.cpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleC.cpp diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogenRerun/mocPlugin/StyleC.hpp index 52a887a..52a887a 100644 --- a/Tests/QtAutogen/mocPlugin/StyleC.hpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleC.hpp diff --git a/Tests/QtAutogen/mocPlugin/StyleCommon.hpp b/Tests/QtAutogenRerun/mocPlugin/StyleCommon.hpp index f1a7ec6..f1a7ec6 100644 --- a/Tests/QtAutogen/mocPlugin/StyleCommon.hpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleCommon.hpp diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogenRerun/mocPlugin/StyleD.cpp index 7e4b121..7e4b121 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.cpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleD.cpp diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogenRerun/mocPlugin/StyleD.hpp index df8a439..df8a439 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.hpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleD.hpp diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogenRerun/mocPlugin/StyleE.cpp index 8fc9a7f..8fc9a7f 100644 --- a/Tests/QtAutogen/mocPlugin/StyleE.cpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleE.cpp diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogenRerun/mocPlugin/StyleE.hpp index e7915a8..e7915a8 100644 --- a/Tests/QtAutogen/mocPlugin/StyleE.hpp +++ b/Tests/QtAutogenRerun/mocPlugin/StyleE.hpp diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleB.json index 129cac4..129cac4 100644 --- a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json +++ b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleB.json diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleB_Custom.json index 129cac4..129cac4 100644 --- a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json +++ b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleB_Custom.json diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleC.json index 119aaa4..119aaa4 100644 --- a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json +++ b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleC.json diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleD.json index 732c547..732c547 100644 --- a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json +++ b/Tests/QtAutogenRerun/mocPlugin/jsonIn/StyleD.json diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogenRerun/mocPlugin/main.cpp index 3ba2ddc..3ba2ddc 100644 --- a/Tests/QtAutogen/mocPlugin/main.cpp +++ b/Tests/QtAutogenRerun/mocPlugin/main.cpp diff --git a/Tests/QtAutogen/mocRerun/CMakeLists.txt b/Tests/QtAutogenRerun/mocRerun/CMakeLists.txt index 14b077b..7380bdd 100644 --- a/Tests/QtAutogen/mocRerun/CMakeLists.txt +++ b/Tests/QtAutogenRerun/mocRerun/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.9) +cmake_policy(SET CMP0071 NEW) project(mocRerun CXX) if (QT_TEST_VERSION STREQUAL 4) @@ -27,7 +28,6 @@ add_executable(mocRerun ${CMAKE_CURRENT_BINARY_DIR}/main.cpp res1.qrc ) -set_property(TARGET mocRerun PROPERTY __UNDOCUMENTED_AUTOGEN_GENERATED_FILES 1) target_include_directories(mocRerun PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(mocRerun ${QT_CORE_TARGET}) # Write target name to text file diff --git a/Tests/QtAutogen/mocRerun/input.txt b/Tests/QtAutogenRerun/mocRerun/input.txt index da62762..da62762 100644 --- a/Tests/QtAutogen/mocRerun/input.txt +++ b/Tests/QtAutogenRerun/mocRerun/input.txt diff --git a/Tests/QtAutogen/mocRerun/main.cpp.in b/Tests/QtAutogenRerun/mocRerun/main.cpp.in index b37ff61..b37ff61 100644 --- a/Tests/QtAutogen/mocRerun/main.cpp.in +++ b/Tests/QtAutogenRerun/mocRerun/main.cpp.in diff --git a/Tests/QtAutogen/mocRerun/res1.qrc b/Tests/QtAutogenRerun/mocRerun/res1.qrc index fb804b5..fb804b5 100644 --- a/Tests/QtAutogen/mocRerun/res1.qrc +++ b/Tests/QtAutogenRerun/mocRerun/res1.qrc diff --git a/Tests/QtAutogen/mocRerun/test1a.h.in b/Tests/QtAutogenRerun/mocRerun/test1a.h.in index a335046..a335046 100644 --- a/Tests/QtAutogen/mocRerun/test1a.h.in +++ b/Tests/QtAutogenRerun/mocRerun/test1a.h.in diff --git a/Tests/QtAutogen/mocRerun/test1b.h.in b/Tests/QtAutogenRerun/mocRerun/test1b.h.in index 6128eeb..6128eeb 100644 --- a/Tests/QtAutogen/mocRerun/test1b.h.in +++ b/Tests/QtAutogenRerun/mocRerun/test1b.h.in diff --git a/Tests/QtAutogen/rccDepends/CMakeLists.txt b/Tests/QtAutogenRerun/rccDepends/CMakeLists.txt index 878ae5d..edc0ac3 100644 --- a/Tests/QtAutogen/rccDepends/CMakeLists.txt +++ b/Tests/QtAutogenRerun/rccDepends/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.7) -project(rccDepends) +cmake_minimum_required(VERSION 3.9) +project(rccDepends CXX) set(CMAKE_AUTORCC ON) diff --git a/Tests/QtAutogen/rccDepends/main.cpp b/Tests/QtAutogenRerun/rccDepends/main.cpp index 766b775..766b775 100644 --- a/Tests/QtAutogen/rccDepends/main.cpp +++ b/Tests/QtAutogenRerun/rccDepends/main.cpp diff --git a/Tests/QtAutogen/rccDepends/res/input1.txt.in b/Tests/QtAutogenRerun/rccDepends/res/input1.txt.in index da62762..da62762 100644 --- a/Tests/QtAutogen/rccDepends/res/input1.txt.in +++ b/Tests/QtAutogenRerun/rccDepends/res/input1.txt.in diff --git a/Tests/QtAutogen/rccDepends/res/input2.txt.in b/Tests/QtAutogenRerun/rccDepends/res/input2.txt.in index 08e14b7..08e14b7 100644 --- a/Tests/QtAutogen/rccDepends/res/input2.txt.in +++ b/Tests/QtAutogenRerun/rccDepends/res/input2.txt.in diff --git a/Tests/QtAutogen/rccDepends/res1a.qrc.in b/Tests/QtAutogenRerun/rccDepends/res1a.qrc.in index d111ffb..d111ffb 100644 --- a/Tests/QtAutogen/rccDepends/res1a.qrc.in +++ b/Tests/QtAutogenRerun/rccDepends/res1a.qrc.in diff --git a/Tests/QtAutogen/rccDepends/res1b.qrc.in b/Tests/QtAutogenRerun/rccDepends/res1b.qrc.in index 4cb3f04..4cb3f04 100644 --- a/Tests/QtAutogen/rccDepends/res1b.qrc.in +++ b/Tests/QtAutogenRerun/rccDepends/res1b.qrc.in diff --git a/Tests/QtAutogen/rccDepends/res2a.qrc.in b/Tests/QtAutogenRerun/rccDepends/res2a.qrc.in index 19f34ac..19f34ac 100644 --- a/Tests/QtAutogen/rccDepends/res2a.qrc.in +++ b/Tests/QtAutogenRerun/rccDepends/res2a.qrc.in diff --git a/Tests/QtAutogen/rccDepends/res2b.qrc.in b/Tests/QtAutogenRerun/rccDepends/res2b.qrc.in index 19e8ba1..19e8ba1 100644 --- a/Tests/QtAutogen/rccDepends/res2b.qrc.in +++ b/Tests/QtAutogenRerun/rccDepends/res2b.qrc.in diff --git a/Tests/RunCMake/CommandLine/E_md5sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt new file mode 100644 index 0000000..061fd64 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-dir-stderr.txt @@ -0,0 +1 @@ +Error: . is a directory diff --git a/Tests/RunCMake/CommandLine/E_md5sum-mixed-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-mixed-result.txt new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-mixed-result.txt @@ -0,0 +1 @@ +2 diff --git a/Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt new file mode 100644 index 0000000..b6b84c3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stderr.txt @@ -0,0 +1,2 @@ +Error: . is a directory +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt new file mode 100644 index 0000000..18e49be --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-mixed-stdout.txt @@ -0,0 +1 @@ +275876e34cf609db118f3d84b799a790 ../dummy diff --git a/Tests/RunCMake/CommandLine/E_md5sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-no-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-no-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt new file mode 100644 index 0000000..732e8c4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-no-file-stderr.txt @@ -0,0 +1 @@ +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_md5sum-result.txt b/Tests/RunCMake/CommandLine/E_md5sum-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_md5sum-stdout.txt b/Tests/RunCMake/CommandLine/E_md5sum-stdout.txt new file mode 100644 index 0000000..18e49be --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_md5sum-stdout.txt @@ -0,0 +1 @@ +275876e34cf609db118f3d84b799a790 ../dummy diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha1sum-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha1sum-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt new file mode 100644 index 0000000..061fd64 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha1sum-dir-stderr.txt @@ -0,0 +1 @@ +Error: . is a directory diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt new file mode 100644 index 0000000..732e8c4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha1sum-no-file-stderr.txt @@ -0,0 +1 @@ +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-result.txt b/Tests/RunCMake/CommandLine/E_sha1sum-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha1sum-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt new file mode 100644 index 0000000..689b85b --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha1sum-stdout.txt @@ -0,0 +1 @@ +829c3804401b0727f70f73d4415e162400cbe57b ../dummy diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha224sum-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha224sum-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt new file mode 100644 index 0000000..061fd64 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha224sum-dir-stderr.txt @@ -0,0 +1 @@ +Error: . is a directory diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt new file mode 100644 index 0000000..732e8c4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha224sum-no-file-stderr.txt @@ -0,0 +1 @@ +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-result.txt b/Tests/RunCMake/CommandLine/E_sha224sum-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha224sum-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt new file mode 100644 index 0000000..5b3e217 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha224sum-stdout.txt @@ -0,0 +1 @@ +37d32c6dbabed711cb1d4620b64090fef0ef63ab16a4a51d668259e6 ../dummy diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha256sum-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha256sum-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt new file mode 100644 index 0000000..061fd64 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha256sum-dir-stderr.txt @@ -0,0 +1 @@ +Error: . is a directory diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt new file mode 100644 index 0000000..732e8c4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha256sum-no-file-stderr.txt @@ -0,0 +1 @@ +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-result.txt b/Tests/RunCMake/CommandLine/E_sha256sum-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha256sum-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt new file mode 100644 index 0000000..9a18770 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha256sum-stdout.txt @@ -0,0 +1 @@ +b5a2c96250612366ea272ffac6d9744aaf4b45aacd96aa7cfcb931ee3b558259 ../dummy diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha384sum-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha384sum-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt new file mode 100644 index 0000000..061fd64 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha384sum-dir-stderr.txt @@ -0,0 +1 @@ +Error: . is a directory diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt new file mode 100644 index 0000000..732e8c4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha384sum-no-file-stderr.txt @@ -0,0 +1 @@ +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-result.txt b/Tests/RunCMake/CommandLine/E_sha384sum-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha384sum-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt new file mode 100644 index 0000000..b706ac5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha384sum-stdout.txt @@ -0,0 +1 @@ +43c1835ceba2e29596f05e3859d4fe2b6d124a181ed670f68e914bd3ed251b02b4be609608a13f23ec3d98da6c4eb8cd ../dummy diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-dir-result.txt b/Tests/RunCMake/CommandLine/E_sha512sum-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha512sum-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt b/Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt new file mode 100644 index 0000000..061fd64 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha512sum-dir-stderr.txt @@ -0,0 +1 @@ +Error: . is a directory diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-no-file-result.txt b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt new file mode 100644 index 0000000..732e8c4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha512sum-no-file-stderr.txt @@ -0,0 +1 @@ +nonexisting: No such file or directory diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-result.txt b/Tests/RunCMake/CommandLine/E_sha512sum-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha512sum-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt b/Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt new file mode 100644 index 0000000..4305383 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_sha512sum-stdout.txt @@ -0,0 +1 @@ +1692526aab84461a8aebcefddcba2b33fb5897ab180c53e8b345ae125484d0aaa35baf60487050be21ed8909a48eace93851bf139087ce1f7a87d97b6120a651 ../dummy diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index f94b10a..6efcc12 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -172,6 +172,30 @@ run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1) run_cmake_command(E_env-set ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake) run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake) +run_cmake_command(E_md5sum-dir ${CMAKE_COMMAND} -E md5sum .) +run_cmake_command(E_sha1sum-dir ${CMAKE_COMMAND} -E sha1sum .) +run_cmake_command(E_sha224sum-dir ${CMAKE_COMMAND} -E sha224sum .) +run_cmake_command(E_sha256sum-dir ${CMAKE_COMMAND} -E sha256sum .) +run_cmake_command(E_sha384sum-dir ${CMAKE_COMMAND} -E sha384sum .) +run_cmake_command(E_sha512sum-dir ${CMAKE_COMMAND} -E sha512sum .) + +run_cmake_command(E_md5sum-no-file ${CMAKE_COMMAND} -E md5sum nonexisting) +run_cmake_command(E_sha1sum-no-file ${CMAKE_COMMAND} -E sha1sum nonexisting) +run_cmake_command(E_sha224sum-no-file ${CMAKE_COMMAND} -E sha224sum nonexisting) +run_cmake_command(E_sha256sum-no-file ${CMAKE_COMMAND} -E sha256sum nonexisting) +run_cmake_command(E_sha384sum-no-file ${CMAKE_COMMAND} -E sha384sum nonexisting) +run_cmake_command(E_sha512sum-no-file ${CMAKE_COMMAND} -E sha512sum nonexisting) + +file(WRITE "${RunCMake_BINARY_DIR}/dummy" "dummy") +run_cmake_command(E_md5sum ${CMAKE_COMMAND} -E md5sum ../dummy) +run_cmake_command(E_md5sum-mixed ${CMAKE_COMMAND} -E md5sum . ../dummy nonexisting) +run_cmake_command(E_sha1sum ${CMAKE_COMMAND} -E sha1sum ../dummy) +run_cmake_command(E_sha224sum ${CMAKE_COMMAND} -E sha224sum ../dummy) +run_cmake_command(E_sha256sum ${CMAKE_COMMAND} -E sha256sum ../dummy) +run_cmake_command(E_sha384sum ${CMAKE_COMMAND} -E sha384sum ../dummy) +run_cmake_command(E_sha512sum ${CMAKE_COMMAND} -E sha512sum ../dummy) +file(REMOVE "${RunCMake_BINARY_DIR}/dummy") + set(RunCMake_DEFAULT_stderr ".") run_cmake_command(E_sleep-no-args ${CMAKE_COMMAND} -E sleep) unset(RunCMake_DEFAULT_stderr) diff --git a/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt b/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt index 12a76c5..2fc7d29 100644 --- a/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt +++ b/Tests/RunCMake/ExternalProject/NoOptions-stderr.txt @@ -6,12 +6,12 @@ is not an existing non-empty directory. Please specify one of: \* SOURCE_DIR with an existing non-empty directory + \* DOWNLOAD_COMMAND \* URL \* GIT_REPOSITORY + \* SVN_REPOSITORY \* HG_REPOSITORY \* CVS_REPOSITORY and CVS_MODULE - \* SVN_REVISION - \* DOWNLOAD_COMMAND Call Stack \(most recent call first\): .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\) NoOptions.cmake:[0-9]+ \(ExternalProject_Add\) diff --git a/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt b/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt index 58a343c..07c6e87 100644 --- a/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt +++ b/Tests/RunCMake/ExternalProject/SourceEmpty-stderr.txt @@ -6,12 +6,12 @@ is not an existing non-empty directory. Please specify one of: \* SOURCE_DIR with an existing non-empty directory + \* DOWNLOAD_COMMAND \* URL \* GIT_REPOSITORY + \* SVN_REPOSITORY \* HG_REPOSITORY \* CVS_REPOSITORY and CVS_MODULE - \* SVN_REVISION - \* DOWNLOAD_COMMAND Call Stack \(most recent call first\): .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\) SourceEmpty.cmake:[0-9]+ \(ExternalProject_Add\) diff --git a/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt b/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt index e62f7cf..373f6e3 100644 --- a/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt +++ b/Tests/RunCMake/ExternalProject/SourceMissing-stderr.txt @@ -6,12 +6,12 @@ is not an existing non-empty directory. Please specify one of: \* SOURCE_DIR with an existing non-empty directory + \* DOWNLOAD_COMMAND \* URL \* GIT_REPOSITORY + \* SVN_REPOSITORY \* HG_REPOSITORY \* CVS_REPOSITORY and CVS_MODULE - \* SVN_REVISION - \* DOWNLOAD_COMMAND Call Stack \(most recent call first\): .*/Modules/ExternalProject.cmake:[0-9]+ \(_ep_add_download_command\) SourceMissing.cmake:[0-9]+ \(ExternalProject_Add\) diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/OwnSources-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt new file mode 100644 index 0000000..40d650e --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/OwnSources-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at OwnSources.cmake:[0-9]+ \(add_library\): + The SOURCES of "A" use a generator expression that depends on the SOURCES + themselves. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/ObjectLibrary/OwnSources.cmake b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake new file mode 100644 index 0000000..e7bdf8d --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/OwnSources.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +target_sources(A PRIVATE $<TARGET_OBJECTS:A>) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index fe708ce..b8eed73 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -19,6 +19,7 @@ run_cmake(LinkObjRHS1) run_cmake(LinkObjRHS2) run_cmake(MissingSource) run_cmake(ObjWithObj) +run_cmake(OwnSources) run_cmake(PostBuild) run_cmake(PreBuild) run_cmake(PreLink) diff --git a/Tests/RunCMake/find_package/PackageRoot-stderr.txt b/Tests/RunCMake/find_package/PackageRoot-stderr.txt index 409fa89..d97c029 100644 --- a/Tests/RunCMake/find_package/PackageRoot-stderr.txt +++ b/Tests/RunCMake/find_package/PackageRoot-stderr.txt @@ -1,383 +1,43 @@ +---------- Foo_ROOT : ENV{Foo_ROOT} : + +find_package\(Foo\) FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND -Foo_ROOT : -ENV{Foo_ROOT} : -Bar_ROOT : -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND -BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND -BAR_TEST_FILE_BAR :BAR_TEST_FILE_BAR-NOTFOUND -BAR_TEST_FILE_ZOT :BAR_TEST_FILE_ZOT-NOTFOUND -BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND -BAR_TEST_PATH_BAR :BAR_TEST_PATH_BAR-NOTFOUND -BAR_TEST_PATH_ZOT :BAR_TEST_PATH_ZOT-NOTFOUND -BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND -BAR_TEST_PROG_BAR :BAR_TEST_PROG_BAR-NOTFOUND - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : -Bar_ROOT : -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe - -Foo_ROOT : -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe - -Foo_ROOT : -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT : -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/foo/env_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/foo/env_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/foo/env_root/bin/bar.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT : -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe - -Foo_ROOT : -ENV{Foo_ROOT} : -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND - -Foo_ROOT : -ENV{Foo_ROOT} : -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND -BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe - -Foo_ROOT : -ENV{Foo_ROOT} : -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND - -Foo_ROOT : -ENV{Foo_ROOT} : -Bar_ROOT : -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND -BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe - -Foo_ROOT : -ENV{Foo_ROOT} : -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND - -Foo_ROOT : -ENV{Foo_ROOT} : -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND -FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND -FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND -BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe - +---------- Foo_ROOT :.*/PackageRoot/foo/cmake_root ENV{Foo_ROOT} : -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe - -Foo_ROOT : -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe - -Foo_ROOT : -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : +find_package\(Foo\) FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : -Bar_ROOT : -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe - +---------- Foo_ROOT : ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -Foo_ROOT : -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT : -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root +find_package\(Foo\) FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/env_root/include/zot/zot.h FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/env_root/include/zot FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT : -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +---------- Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} : -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe - -Foo_ROOT : -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe - -Foo_ROOT : ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/env_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/env_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/env_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root +find_package\(Foo\) FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe - -Foo_ROOT :.*/PackageRoot/foo/cmake_root -ENV{Foo_ROOT} :.*/PackageRoot/foo/env_root -Bar_ROOT :.*/PackageRoot/bar/cmake_root -ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root -FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h -BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h -BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h -BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include -BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include -BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot -BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe -BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe diff --git a/Tests/RunCMake/find_package/PackageRoot.cmake b/Tests/RunCMake/find_package/PackageRoot.cmake index 421c243..39551c4 100644 --- a/Tests/RunCMake/find_package/PackageRoot.cmake +++ b/Tests/RunCMake/find_package/PackageRoot.cmake @@ -5,73 +5,33 @@ set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) macro(CleanUpPackageRootTest) unset(Foo_ROOT) unset(ENV{Foo_ROOT}) - unset(Bar_ROOT) - unset(ENV{Bar_ROOT}) unset(FOO_TEST_FILE_FOO) + unset(FOO_TEST_FILE_ZOT) unset(FOO_TEST_PATH_FOO) + unset(FOO_TEST_PATH_ZOT) unset(FOO_TEST_PROG_FOO) - unset(BAR_TEST_FILE_FOO) - unset(BAR_TEST_FILE_BAR) - unset(BAR_TEST_PATH_FOO) - unset(BAR_TEST_PATH_BAR) - unset(BAR_TEST_PROG_FOO) - unset(BAR_TEST_PROG_BAR) unset(FOO_TEST_FILE_FOO CACHE) + unset(FOO_TEST_FILE_ZOT CACHE) unset(FOO_TEST_PATH_FOO CACHE) + unset(FOO_TEST_PATH_ZOT CACHE) unset(FOO_TEST_PROG_FOO CACHE) - unset(BAR_TEST_FILE_FOO CACHE) - unset(BAR_TEST_FILE_BAR CACHE) - unset(BAR_TEST_PATH_FOO CACHE) - unset(BAR_TEST_PATH_BAR CACHE) - unset(BAR_TEST_PROG_FOO CACHE) - unset(BAR_TEST_PROG_BAR CACHE) endmacro() macro(RunPackageRootTest) - set(orig_foo_cmake_root ${Foo_ROOT}) - set(orig_foo_env_root $ENV{Foo_ROOT}) - set(orig_bar_cmake_root ${Bar_ROOT}) - set(orig_bar_env_root $ENV{Bar_ROOT}) - - find_package(Foo) + message("----------") message("Foo_ROOT :${Foo_ROOT}") message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}") - message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}") - message("FOO_TEST_FILE_ZOT :${FOO_TEST_FILE_ZOT}") - message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}") - message("FOO_TEST_PATH_ZOT :${FOO_TEST_PATH_ZOT}") - message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}") - CleanUpPackageRootTest() message("") - set(Foo_ROOT ${orig_foo_cmake_root}) - set(ENV{Foo_ROOT} ${orig_foo_env_root}) - set(Bar_ROOT ${orig_bar_cmake_root}) - set(ENV{Bar_ROOT} ${orig_bar_env_root}) - - find_package(Foo COMPONENTS Bar) - message("Foo_ROOT :${Foo_ROOT}") - message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}") - message("Bar_ROOT :${Bar_ROOT}") - message("ENV{Bar_ROOT} :$ENV{Bar_ROOT}") + find_package(Foo) + message("find_package(Foo)") message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}") + message("FOO_TEST_FILE_ZOT :${FOO_TEST_FILE_ZOT}") message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}") + message("FOO_TEST_PATH_ZOT :${FOO_TEST_PATH_ZOT}") message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}") - message("BAR_TEST_FILE_FOO :${BAR_TEST_FILE_FOO}") - message("BAR_TEST_FILE_BAR :${BAR_TEST_FILE_BAR}") - message("BAR_TEST_FILE_ZOT :${BAR_TEST_FILE_ZOT}") - message("BAR_TEST_PATH_FOO :${BAR_TEST_PATH_FOO}") - message("BAR_TEST_PATH_BAR :${BAR_TEST_PATH_BAR}") - message("BAR_TEST_PATH_ZOT :${BAR_TEST_PATH_ZOT}") - message("BAR_TEST_PROG_FOO :${BAR_TEST_PROG_FOO}") - message("BAR_TEST_PROG_BAR :${BAR_TEST_PROG_BAR}") CleanUpPackageRootTest() message("") - - unset(orig_foo_cmake_root) - unset(orig_foo_env_root) - unset(orig_bar_cmake_root) - unset(orig_bar_env_root) endmacro() RunPackageRootTest() @@ -85,63 +45,3 @@ RunPackageRootTest() set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) RunPackageRootTest() - -## - -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -RunPackageRootTest() - -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -## - -set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -RunPackageRootTest() - -set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -RunPackageRootTest() - -set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) -set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -RunPackageRootTest() - -## - -set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) -set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -## - -set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() - -set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) -set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root) -set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) -set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) -RunPackageRootTest() diff --git a/Tests/RunCMake/find_package/PackageRoot/BarConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/BarConfig.cmake new file mode 100644 index 0000000..9eaf386 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot/BarConfig.cmake @@ -0,0 +1,9 @@ +set(BAR_CMAKE_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE FILEPATH "") +find_file(BAR_TEST_FILE_FOO foo.h) +find_file(BAR_TEST_FILE_BAR bar.h) +find_file(BAR_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot) +find_path(BAR_TEST_PATH_FOO foo.h) +find_path(BAR_TEST_PATH_BAR bar.h) +find_path(BAR_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot) +find_program(BAR_TEST_PROG_FOO foo.exe) +find_program(BAR_TEST_PROG_BAR bar.exe) diff --git a/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake b/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake index 72774a7..9eaf386 100644 --- a/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake +++ b/Tests/RunCMake/find_package/PackageRoot/FindBar.cmake @@ -1,3 +1,4 @@ +set(BAR_CMAKE_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE FILEPATH "") find_file(BAR_TEST_FILE_FOO foo.h) find_file(BAR_TEST_FILE_BAR bar.h) find_file(BAR_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot) diff --git a/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake b/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake index e160a1d..b929c2a 100644 --- a/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake +++ b/Tests/RunCMake/find_package/PackageRoot/FindFoo.cmake @@ -4,6 +4,8 @@ find_path(FOO_TEST_PATH_FOO foo.h) find_path(FOO_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot) find_program(FOO_TEST_PROG_FOO foo.exe) -if ("Bar" IN_LIST Foo_FIND_COMPONENTS) +if ("BarModule" IN_LIST Foo_FIND_COMPONENTS) find_package(Bar) +elseif ("BarConfig" IN_LIST Foo_FIND_COMPONENTS) + find_package(Bar CONFIG) endif () diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake new file mode 100644 index 0000000..9eaf386 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake @@ -0,0 +1,9 @@ +set(BAR_CMAKE_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE FILEPATH "") +find_file(BAR_TEST_FILE_FOO foo.h) +find_file(BAR_TEST_FILE_BAR bar.h) +find_file(BAR_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot) +find_path(BAR_TEST_PATH_FOO foo.h) +find_path(BAR_TEST_PATH_BAR bar.h) +find_path(BAR_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot) +find_program(BAR_TEST_PROG_FOO foo.exe) +find_program(BAR_TEST_PROG_BAR bar.exe) diff --git a/Tests/RunCMake/find_package/PackageRoot/foo/env_root/cmake/BarConfig.cmake b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/cmake/BarConfig.cmake new file mode 100644 index 0000000..9eaf386 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRoot/foo/env_root/cmake/BarConfig.cmake @@ -0,0 +1,9 @@ +set(BAR_CMAKE_FILE ${CMAKE_CURRENT_LIST_FILE} CACHE FILEPATH "") +find_file(BAR_TEST_FILE_FOO foo.h) +find_file(BAR_TEST_FILE_BAR bar.h) +find_file(BAR_TEST_FILE_ZOT zot.h PATH_SUFFIXES zot) +find_path(BAR_TEST_PATH_FOO foo.h) +find_path(BAR_TEST_PATH_BAR bar.h) +find_path(BAR_TEST_PATH_ZOT zot.h PATH_SUFFIXES zot) +find_program(BAR_TEST_PROG_FOO foo.exe) +find_program(BAR_TEST_PROG_BAR bar.exe) diff --git a/Tests/RunCMake/find_package/PackageRootNestedConfig-stderr.txt b/Tests/RunCMake/find_package/PackageRootNestedConfig-stderr.txt new file mode 100644 index 0000000..79266c3 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRootNestedConfig-stderr.txt @@ -0,0 +1,298 @@ +---------- +Foo_ROOT : +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND +BAR_CMAKE_FILE : +BAR_TEST_FILE_FOO : +BAR_TEST_FILE_BAR : +BAR_TEST_FILE_ZOT : +BAR_TEST_PATH_FOO : +BAR_TEST_PATH_BAR : +BAR_TEST_PATH_ZOT : +BAR_TEST_PROG_FOO : +BAR_TEST_PROG_BAR : + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/env_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/env_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/env_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/env_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/env_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/env_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarConfig\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/foo/cmake_root/cmake/BarConfig.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe diff --git a/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake b/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake new file mode 100644 index 0000000..571739d --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake @@ -0,0 +1,135 @@ +cmake_policy(SET CMP0057 NEW) +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) +set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) + +macro(CleanUpPackageRootTest) + unset(Foo_ROOT) + unset(ENV{Foo_ROOT}) + unset(Bar_DIR) + unset(BAR_CMAKE_FILE) + unset(Bar_ROOT) + unset(ENV{Bar_ROOT}) + unset(FOO_TEST_FILE_FOO) + unset(FOO_TEST_FILE_ZOT) + unset(FOO_TEST_PATH_FOO) + unset(FOO_TEST_PATH_ZOT) + unset(FOO_TEST_PROG_FOO) + unset(BAR_TEST_FILE_FOO) + unset(BAR_TEST_FILE_BAR) + unset(BAR_TEST_FILE_ZOT) + unset(BAR_TEST_PATH_FOO) + unset(BAR_TEST_PATH_BAR) + unset(BAR_TEST_PATH_ZOT) + unset(BAR_TEST_PROG_FOO) + unset(BAR_TEST_PROG_BAR) + unset(Bar_DIR CACHE) + unset(BAR_CMAKE_FILE CACHE) + unset(FOO_TEST_FILE_FOO CACHE) + unset(FOO_TEST_FILE_ZOT CACHE) + unset(FOO_TEST_PATH_FOO CACHE) + unset(FOO_TEST_PATH_ZOT CACHE) + unset(FOO_TEST_PROG_FOO CACHE) + unset(BAR_TEST_FILE_FOO CACHE) + unset(BAR_TEST_FILE_BAR CACHE) + unset(BAR_TEST_FILE_ZOT CACHE) + unset(BAR_TEST_PATH_FOO CACHE) + unset(BAR_TEST_PATH_BAR CACHE) + unset(BAR_TEST_PATH_ZOT CACHE) + unset(BAR_TEST_PROG_FOO CACHE) + unset(BAR_TEST_PROG_BAR CACHE) +endmacro() + +macro(RunPackageRootTest) + message("----------") + message("Foo_ROOT :${Foo_ROOT}") + message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}") + message("Bar_DIR :${Bar_DIR}") + message("Bar_ROOT :${Bar_ROOT}") + message("ENV{Bar_ROOT} :$ENV{Bar_ROOT}") + message("") + + find_package(Foo COMPONENTS BarConfig) + message("find_package(Foo COMPONENTS BarConfig)") + message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}") + message("FOO_TEST_FILE_ZOT :${FOO_TEST_FILE_ZOT}") + message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}") + message("FOO_TEST_PATH_ZOT :${FOO_TEST_PATH_ZOT}") + message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}") + message("BAR_CMAKE_FILE :${BAR_CMAKE_FILE}") + message("BAR_TEST_FILE_FOO :${BAR_TEST_FILE_FOO}") + message("BAR_TEST_FILE_BAR :${BAR_TEST_FILE_BAR}") + message("BAR_TEST_FILE_ZOT :${BAR_TEST_FILE_ZOT}") + message("BAR_TEST_PATH_FOO :${BAR_TEST_PATH_FOO}") + message("BAR_TEST_PATH_BAR :${BAR_TEST_PATH_BAR}") + message("BAR_TEST_PATH_ZOT :${BAR_TEST_PATH_ZOT}") + message("BAR_TEST_PROG_FOO :${BAR_TEST_PROG_FOO}") + message("BAR_TEST_PROG_BAR :${BAR_TEST_PROG_BAR}") + CleanUpPackageRootTest() + message("") +endmacro() + +# + +RunPackageRootTest() + +# + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +# + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +# + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() diff --git a/Tests/RunCMake/find_package/PackageRootNestedModule-stderr.txt b/Tests/RunCMake/find_package/PackageRootNestedModule-stderr.txt new file mode 100644 index 0000000..57cab60 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRootNestedModule-stderr.txt @@ -0,0 +1,298 @@ +---------- +Foo_ROOT : +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :BAR_TEST_FILE_FOO-NOTFOUND +BAR_TEST_FILE_BAR :BAR_TEST_FILE_BAR-NOTFOUND +BAR_TEST_FILE_ZOT :BAR_TEST_FILE_ZOT-NOTFOUND +BAR_TEST_PATH_FOO :BAR_TEST_PATH_FOO-NOTFOUND +BAR_TEST_PATH_BAR :BAR_TEST_PATH_BAR-NOTFOUND +BAR_TEST_PATH_ZOT :BAR_TEST_PATH_ZOT-NOTFOUND +BAR_TEST_PROG_FOO :BAR_TEST_PROG_FOO-NOTFOUND +BAR_TEST_PROG_BAR :BAR_TEST_PROG_BAR-NOTFOUND + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/env_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/env_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} : +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/env_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/env_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/foo/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/foo/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} : + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT : +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/env_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/env_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/env_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/env_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/env_root/bin/bar.exe + +---------- +Foo_ROOT :.*/PackageRoot/foo/cmake_root +ENV{Foo_ROOT} :.*/PackageRoot/foo/cmake_root +Bar_DIR : +Bar_ROOT :.*/PackageRoot/bar/cmake_root +ENV{Bar_ROOT} :.*/PackageRoot/bar/env_root + +find_package\(Foo COMPONENTS BarModule\) +FOO_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT :.*/PackageRoot/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +FOO_TEST_PATH_ZOT :.*/PackageRoot/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_CMAKE_FILE :.*/PackageRoot/FindBar.cmake +BAR_TEST_FILE_FOO :.*/PackageRoot/foo/cmake_root/include/foo.h +BAR_TEST_FILE_BAR :.*/PackageRoot/bar/cmake_root/include/bar.h +BAR_TEST_FILE_ZOT :.*/PackageRoot/bar/cmake_root/include/zot/zot.h +BAR_TEST_PATH_FOO :.*/PackageRoot/foo/cmake_root/include +BAR_TEST_PATH_BAR :.*/PackageRoot/bar/cmake_root/include +BAR_TEST_PATH_ZOT :.*/PackageRoot/bar/cmake_root/include/zot +BAR_TEST_PROG_FOO :.*/PackageRoot/foo/cmake_root/bin/foo.exe +BAR_TEST_PROG_BAR :.*/PackageRoot/bar/cmake_root/bin/bar.exe diff --git a/Tests/RunCMake/find_package/PackageRootNestedModule.cmake b/Tests/RunCMake/find_package/PackageRootNestedModule.cmake new file mode 100644 index 0000000..f99db59 --- /dev/null +++ b/Tests/RunCMake/find_package/PackageRootNestedModule.cmake @@ -0,0 +1,135 @@ +cmake_policy(SET CMP0057 NEW) +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) +set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) + +macro(CleanUpPackageRootTest) + unset(Foo_ROOT) + unset(ENV{Foo_ROOT}) + unset(Bar_DIR) + unset(BAR_CMAKE_FILE) + unset(Bar_ROOT) + unset(ENV{Bar_ROOT}) + unset(FOO_TEST_FILE_FOO) + unset(FOO_TEST_FILE_ZOT) + unset(FOO_TEST_PATH_FOO) + unset(FOO_TEST_PATH_ZOT) + unset(FOO_TEST_PROG_FOO) + unset(BAR_TEST_FILE_FOO) + unset(BAR_TEST_FILE_BAR) + unset(BAR_TEST_FILE_ZOT) + unset(BAR_TEST_PATH_FOO) + unset(BAR_TEST_PATH_BAR) + unset(BAR_TEST_PATH_ZOT) + unset(BAR_TEST_PROG_FOO) + unset(BAR_TEST_PROG_BAR) + unset(Bar_DIR CACHE) + unset(BAR_CMAKE_FILE CACHE) + unset(FOO_TEST_FILE_FOO CACHE) + unset(FOO_TEST_FILE_ZOT CACHE) + unset(FOO_TEST_PATH_FOO CACHE) + unset(FOO_TEST_PATH_ZOT CACHE) + unset(FOO_TEST_PROG_FOO CACHE) + unset(BAR_TEST_FILE_FOO CACHE) + unset(BAR_TEST_FILE_BAR CACHE) + unset(BAR_TEST_FILE_ZOT CACHE) + unset(BAR_TEST_PATH_FOO CACHE) + unset(BAR_TEST_PATH_BAR CACHE) + unset(BAR_TEST_PATH_ZOT CACHE) + unset(BAR_TEST_PROG_FOO CACHE) + unset(BAR_TEST_PROG_BAR CACHE) +endmacro() + +macro(RunPackageRootTest) + message("----------") + message("Foo_ROOT :${Foo_ROOT}") + message("ENV{Foo_ROOT} :$ENV{Foo_ROOT}") + message("Bar_DIR :${Bar_DIR}") + message("Bar_ROOT :${Bar_ROOT}") + message("ENV{Bar_ROOT} :$ENV{Bar_ROOT}") + message("") + + find_package(Foo COMPONENTS BarModule) + message("find_package(Foo COMPONENTS BarModule)") + message("FOO_TEST_FILE_FOO :${FOO_TEST_FILE_FOO}") + message("FOO_TEST_FILE_ZOT :${FOO_TEST_FILE_ZOT}") + message("FOO_TEST_PATH_FOO :${FOO_TEST_PATH_FOO}") + message("FOO_TEST_PATH_ZOT :${FOO_TEST_PATH_ZOT}") + message("FOO_TEST_PROG_FOO :${FOO_TEST_PROG_FOO}") + message("BAR_CMAKE_FILE :${BAR_CMAKE_FILE}") + message("BAR_TEST_FILE_FOO :${BAR_TEST_FILE_FOO}") + message("BAR_TEST_FILE_BAR :${BAR_TEST_FILE_BAR}") + message("BAR_TEST_FILE_ZOT :${BAR_TEST_FILE_ZOT}") + message("BAR_TEST_PATH_FOO :${BAR_TEST_PATH_FOO}") + message("BAR_TEST_PATH_BAR :${BAR_TEST_PATH_BAR}") + message("BAR_TEST_PATH_ZOT :${BAR_TEST_PATH_ZOT}") + message("BAR_TEST_PROG_FOO :${BAR_TEST_PROG_FOO}") + message("BAR_TEST_PROG_BAR :${BAR_TEST_PROG_BAR}") + CleanUpPackageRootTest() + message("") +endmacro() + +# + +RunPackageRootTest() + +# + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +# + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +# + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() + +set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/cmake_root) +set(Bar_ROOT ${PackageRoot_BASE}/bar/cmake_root) +set(ENV{Bar_ROOT} ${PackageRoot_BASE}/bar/env_root) +RunPackageRootTest() diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index 7875db6..d548da0 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -14,6 +14,8 @@ run_cmake(MissingConfigRequired) run_cmake(MissingConfigVersion) run_cmake(MixedModeOptions) run_cmake(PackageRoot) +run_cmake(PackageRootNestedConfig) +run_cmake(PackageRootNestedModule) run_cmake(PolicyPush) run_cmake(PolicyPop) run_cmake(SetFoundFALSE) diff --git a/Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt b/Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt new file mode 100644 index 0000000..4360d79 --- /dev/null +++ b/Tests/RunCMake/string/RegexMultiMatchClear-stderr.txt @@ -0,0 +1,12 @@ +^matches: Some::;Scope +results from: string\(REGEX MATCHALL\) +CMAKE_MATCH_0: -->Scope<-- +CMAKE_MATCH_1: -->Scope<-- +CMAKE_MATCH_2: --><-- +CMAKE_MATCH_COUNT: -->1<-- +replace: \[Some\]\[Scope\] +results from: string\(REGEX REPLACE\) +CMAKE_MATCH_0: -->Scope<-- +CMAKE_MATCH_1: -->Scope<-- +CMAKE_MATCH_2: --><-- +CMAKE_MATCH_COUNT: -->1<--$ diff --git a/Tests/RunCMake/string/RegexMultiMatchClear.cmake b/Tests/RunCMake/string/RegexMultiMatchClear.cmake new file mode 100644 index 0000000..80b6b3c --- /dev/null +++ b/Tests/RunCMake/string/RegexMultiMatchClear.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required (VERSION 3.0) +project (RegexClear NONE) + +function (output_results msg) + message("results from: ${msg}") + message("CMAKE_MATCH_0: -->${CMAKE_MATCH_0}<--") + message("CMAKE_MATCH_1: -->${CMAKE_MATCH_1}<--") + message("CMAKE_MATCH_2: -->${CMAKE_MATCH_2}<--") + message("CMAKE_MATCH_COUNT: -->${CMAKE_MATCH_COUNT}<--") +endfunction () + +set(haystack "Some::Scope") + +string(REGEX MATCHALL "^([^:]+)(::)?" matches "${haystack}") +message("matches: ${matches}") +output_results("string(REGEX MATCHALL)") + +string(REGEX REPLACE "^([^:]+)(::)?" "[\\1]" replace "${haystack}") +message("replace: ${replace}") +output_results("string(REGEX REPLACE)") diff --git a/Tests/RunCMake/string/RunCMakeTest.cmake b/Tests/RunCMake/string/RunCMakeTest.cmake index 38a77b0..32b61b5 100644 --- a/Tests/RunCMake/string/RunCMakeTest.cmake +++ b/Tests/RunCMake/string/RunCMakeTest.cmake @@ -20,6 +20,7 @@ run_cmake(UuidMissingTypeValue) run_cmake(UuidBadType) run_cmake(RegexClear) +run_cmake(RegexMultiMatchClear) run_cmake(UTF-16BE) run_cmake(UTF-16LE) diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py index 62d9008..5621111 100644 --- a/Tests/Server/server-test.py +++ b/Tests/Server/server-test.py @@ -117,4 +117,4 @@ except: proc.terminate() raise -sys.exit(0) +sys.exit(proc.returncode) diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index fe0f7df..23ca091 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -21,6 +21,7 @@ { include: [ "<wctype.h>", public, "<cwctype>", public ] }, # HACK: check whether this can be removed with next iwyu release. + { include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] }, { include: [ "<bits/std_function.h>", private, "<functional>", public ] }, { include: [ "<bits/time.h>", private, "<time.h>", public ] }, { include: [ "<bits/types/clock_t.h>", private, "<time.h>", public ] }, diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash index 41c6a66..7534f94 100755 --- a/Utilities/Scripts/update-libarchive.bash +++ b/Utilities/Scripts/update-libarchive.bash @@ -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.3.1" +readonly tag="v3.3.2" readonly shortlog=false readonly paths=" CMakeLists.txt diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 6f273f9..cfda2d4 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -46,7 +46,20 @@ from sphinx.directives import ObjectDescription from sphinx.domains import Domain, ObjType from sphinx.roles import XRefRole from sphinx.util.nodes import make_refnode -from sphinx import addnodes, version_info +from sphinx import addnodes + +# Needed for checking if Sphinx version is >= 1.4. +# See https://github.com/sphinx-doc/sphinx/issues/2673 +old_sphinx = False + +try: + from sphinx import version_info + if version_info < (1, 4): + old_sphinx = True +except ImportError: + # The `sphinx.version_info` tuple was added in Sphinx v1.2: + old_sphinx = True + class CMakeModule(Directive): required_arguments = 1 @@ -124,7 +137,7 @@ class _cmake_index_entry: def __call__(self, title, targetid, main = 'main'): # See https://github.com/sphinx-doc/sphinx/issues/2673 - if version_info < (1, 4): + if old_sphinx: return ('pair', u'%s ; %s' % (self.desc, title), targetid, main) else: return ('pair', u'%s ; %s' % (self.desc, title), targetid, main, None) diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index bfe6b13..206f3c6 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -422,6 +422,7 @@ int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS) LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H) +LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H) LA_CHECK_INCLUDE_FILE("memory.h" HAVE_MEMORY_H) LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H) LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H) @@ -439,11 +440,13 @@ LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H) LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H) LA_CHECK_INCLUDE_FILE("sys/acl.h" HAVE_SYS_ACL_H) LA_CHECK_INCLUDE_FILE("sys/cdefs.h" HAVE_SYS_CDEFS_H) +LA_CHECK_INCLUDE_FILE("sys/extattr.h" HAVE_SYS_EXTATTR_H) LA_CHECK_INCLUDE_FILE("sys/ioctl.h" HAVE_SYS_IOCTL_H) LA_CHECK_INCLUDE_FILE("sys/mkdev.h" HAVE_SYS_MKDEV_H) LA_CHECK_INCLUDE_FILE("sys/mount.h" HAVE_SYS_MOUNT_H) LA_CHECK_INCLUDE_FILE("sys/param.h" HAVE_SYS_PARAM_H) LA_CHECK_INCLUDE_FILE("sys/poll.h" HAVE_SYS_POLL_H) +LA_CHECK_INCLUDE_FILE("sys/richacl.h" HAVE_SYS_RICHACL_H) LA_CHECK_INCLUDE_FILE("sys/select.h" HAVE_SYS_SELECT_H) LA_CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H) LA_CHECK_INCLUDE_FILE("sys/statfs.h" HAVE_SYS_STATFS_H) @@ -453,6 +456,7 @@ LA_CHECK_INCLUDE_FILE("sys/utime.h" HAVE_SYS_UTIME_H) LA_CHECK_INCLUDE_FILE("sys/utsname.h" HAVE_SYS_UTSNAME_H) LA_CHECK_INCLUDE_FILE("sys/vfs.h" HAVE_SYS_VFS_H) LA_CHECK_INCLUDE_FILE("sys/wait.h" HAVE_SYS_WAIT_H) +LA_CHECK_INCLUDE_FILE("sys/xattr.h" HAVE_SYS_XATTR_H) LA_CHECK_INCLUDE_FILE("time.h" HAVE_TIME_H) LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H) LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H) @@ -461,6 +465,9 @@ LA_CHECK_INCLUDE_FILE("wctype.h" HAVE_WCTYPE_H) LA_CHECK_INCLUDE_FILE("windows.h" HAVE_WINDOWS_H) IF(ENABLE_CNG) LA_CHECK_INCLUDE_FILE("Bcrypt.h" HAVE_BCRYPT_H) + IF(HAVE_BCRYPT_H) + LIST(APPEND ADDITIONAL_LIBS "Bcrypt") + ENDIF(HAVE_BCRYPT_H) ELSE(ENABLE_CNG) UNSET(HAVE_BCRYPT_H CACHE) ENDIF(ENABLE_CNG) @@ -924,7 +931,6 @@ CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS) CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN) CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT) CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R) -CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD) CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR) CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS) CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD) @@ -1024,6 +1030,10 @@ CHECK_C_SOURCE_COMPILES( "#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}" HAVE_READDIR_R) +# dirfd can be either a function or a macro. +CHECK_C_SOURCE_COMPILES( + "#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); return dirfd(d);}" + HAVE_DIRFD) # Only detect readlinkat() if we also have AT_FDCWD in unistd.h. # NOTE: linux requires fcntl.h for AT_FDCWD. @@ -1256,60 +1266,105 @@ CHECK_FILE_OFFSET_BITS() # Check for Extended Attribute libraries, headers, and functions # IF(ENABLE_XATTR) - LA_CHECK_INCLUDE_FILE(attr/xattr.h HAVE_ATTR_XATTR_H) - LA_CHECK_INCLUDE_FILE(sys/xattr.h HAVE_SYS_XATTR_H) - LA_CHECK_INCLUDE_FILE(sys/extattr.h HAVE_SYS_EXTATTR_H) CHECK_LIBRARY_EXISTS(attr "setxattr" "" HAVE_LIBATTR) IF(HAVE_LIBATTR) SET(CMAKE_REQUIRED_LIBRARIES "attr") ENDIF(HAVE_LIBATTR) CHECK_SYMBOL_EXISTS(EXTATTR_NAMESPACE_USER "sys/types.h;sys/extattr.h" HAVE_DECL_EXTATTR_NAMESPACE_USER) - CHECK_FUNCTION_EXISTS_GLIBC(extattr_get_file HAVE_EXTATTR_GET_FILE) - CHECK_FUNCTION_EXISTS_GLIBC(extattr_list_file HAVE_EXTATTR_LIST_FILE) - CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_fd HAVE_EXTATTR_SET_FD) - CHECK_FUNCTION_EXISTS_GLIBC(extattr_set_file HAVE_EXTATTR_SET_FILE) - CHECK_FUNCTION_EXISTS_GLIBC(fgetxattr HAVE_FGETXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(flistxattr HAVE_FLISTXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR) - CHECK_FUNCTION_EXISTS_GLIBC(fgetea HAVE_FGETEA) - CHECK_FUNCTION_EXISTS_GLIBC(flistea HAVE_FLISTEA) - CHECK_FUNCTION_EXISTS_GLIBC(fsetea HAVE_FSETEA) - CHECK_FUNCTION_EXISTS_GLIBC(getea HAVE_GETEA) - CHECK_FUNCTION_EXISTS_GLIBC(lgetea HAVE_LGETEA) - CHECK_FUNCTION_EXISTS_GLIBC(listea HAVE_LISTEA) - CHECK_FUNCTION_EXISTS_GLIBC(llistea HAVE_LLISTEA) - CHECK_FUNCTION_EXISTS_GLIBC(lsetea HAVE_LSETEA) + CHECK_SYMBOL_EXISTS(XATTR_NOFOLLOW "sys/xattr.h" HAVE_DECL_XATTR_NOFOLLOW) + IF(HAVE_SYS_XATTR_H AND HAVE_DECL_XATTR_NOFOLLOW) + CHECK_FUNCTION_EXISTS(fgetxattr HAVE_FGETXATTR) + CHECK_FUNCTION_EXISTS(flistxattr HAVE_FLISTXATTR) + CHECK_FUNCTION_EXISTS(fsetxattr HAVE_FSETXATTR) + CHECK_FUNCTION_EXISTS(getxattr HAVE_GETXATTR) + CHECK_FUNCTION_EXISTS(listxattr HAVE_LISTXATTR) + CHECK_FUNCTION_EXISTS(setxattr HAVE_SETXATTR) + IF(HAVE_FGETXATTR AND + HAVE_FLISTXATTR AND + HAVE_FSETXATTR AND + HAVE_GETXATTR AND + HAVE_LISTXATTR AND + HAVE_SETXATTR) + SET(ARCHIVE_XATTR_DARWIN TRUE) + ENDIF() + ELSEIF(HAVE_SYS_EXTATTR_H AND HAVE_DECL_EXTATTR_NAMESPACE_USER) + # FreeBSD xattr support + CHECK_FUNCTION_EXISTS(extattr_get_fd HAVE_EXTATTR_GET_FD) + CHECK_FUNCTION_EXISTS(extattr_get_file HAVE_EXTATTR_GET_FILE) + CHECK_FUNCTION_EXISTS(extattr_get_link HAVE_EXTATTR_GET_LINK) + CHECK_FUNCTION_EXISTS(extattr_list_fd HAVE_EXTATTR_LIST_FD) + CHECK_FUNCTION_EXISTS(extattr_list_file HAVE_EXTATTR_LIST_FILE) + CHECK_FUNCTION_EXISTS(extattr_list_link HAVE_EXTATTR_LIST_LINK) + CHECK_FUNCTION_EXISTS(extattr_set_fd HAVE_EXTATTR_SET_FD) + CHECK_FUNCTION_EXISTS(extattr_set_link HAVE_EXTATTR_SET_LINK) + IF(HAVE_EXTATTR_GET_FD AND + HAVE_EXTATTR_GET_FILE AND + HAVE_EXTATTR_GET_LINK AND + HAVE_EXTATTR_LIST_FD AND + HAVE_EXTATTR_LIST_FILE AND + HAVE_EXTATTR_LIST_LINK AND + HAVE_EXTATTR_SET_FD AND + HAVE_EXTATTR_SET_LINK) + SET(ARCHIVE_XATTR_FREEBSD TRUE) + ENDIF() + ELSEIF(HAVE_SYS_XATTR_H OR HAVE_ATTR_XATTR_H) + # Linux xattr support + CHECK_FUNCTION_EXISTS_GLIBC(fgetxattr HAVE_FGETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(flistxattr HAVE_FLISTXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(fsetxattr HAVE_FSETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(getxattr HAVE_GETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(lgetxattr HAVE_LGETXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(listxattr HAVE_LISTXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(llistxattr HAVE_LLISTXATTR) + CHECK_FUNCTION_EXISTS_GLIBC(lsetxattr HAVE_LSETXATTR) + IF(HAVE_FGETXATTR AND + HAVE_FLISTXATTR AND + HAVE_FSETXATTR AND + HAVE_GETXATTR AND + HAVE_LGETXATTR AND + HAVE_LISTXATTR AND + HAVE_LLISTXATTR AND + HAVE_LSETXATTR) + SET(ARCHIVE_XATTR_LINUX TRUE) + ENDIF() + ELSEIF(HAVE_SYS_EA_H) + # AIX xattr support + CHECK_FUNCTION_EXISTS(fgetea HAVE_FGETEA) + CHECK_FUNCTION_EXISTS(flistea HAVE_FLISTEA) + CHECK_FUNCTION_EXISTS(fsetea HAVE_FSETEA) + CHECK_FUNCTION_EXISTS(getea HAVE_GETEA) + CHECK_FUNCTION_EXISTS(lgetea HAVE_LGETEA) + CHECK_FUNCTION_EXISTS(listea HAVE_LISTEA) + CHECK_FUNCTION_EXISTS(llistea HAVE_LLISTEA) + CHECK_FUNCTION_EXISTS(lsetea HAVE_LSETEA) + IF(HAVE_FGETEA AND + HAVE_FLISTEA AND + HAVE_FSETEA AND + HAVE_GETEA AND + HAVE_LGETEA AND + HAVE_LISTEA AND + HAVE_LLISTEA AND + HAVE_LSETEA) + SET(ARCHIVE_XATTR_AIX TRUE) + ENDIF() + ENDIF() + + IF(ARCHIVE_XATTR_DARWIN) + MESSAGE(STATUS "Extended attributes support: Darwin") + ELSEIF(ARCHIVE_XATTR_FREEBSD) + MESSAGE(STATUS "Extended attributes support: FreeBSD") + ELSEIF(ARCHIVE_XATTR_LINUX) + MESSAGE(STATUS "Extended attributes support: Linux") + ELSEIF(ARCHIVE_XATTR_AIX) + MESSAGE(STATUS "Extended attributes support: AIX") + ELSE() + MESSAGE(STATUS "Extended attributes support: none") + ENDIF() ELSE(ENABLE_XATTR) - SET(HAVE_ATTR_LIB FALSE) - SET(HAVE_ATTR_XATTR_H FALSE) - SET(HAVE_DECL_EXTATTR_NAMESPACE_USER FALSE) - SET(HAVE_EXTATTR_GET_FILE FALSE) - SET(HAVE_EXTATTR_LIST_FILE FALSE) - SET(HAVE_EXTATTR_SET_FD FALSE) - SET(HAVE_EXTATTR_SET_FILE FALSE) - SET(HAVE_FGETEA FALSE) - SET(HAVE_FGETXATTR FALSE) - SET(HAVE_FLISTEA FALSE) - SET(HAVE_FLISTXATTR FALSE) - SET(HAVE_FSETEA FALSE) - SET(HAVE_FSETXATTR FALSE) - SET(HAVE_GETEA FALSE) - SET(HAVE_GETXATTR FALSE) - SET(HAVE_LGETEA FALSE) - SET(HAVE_LGETXATTR FALSE) - SET(HAVE_LISTEA FALSE) - SET(HAVE_LISTXATTR FALSE) - SET(HAVE_LLISTEA FALSE) - SET(HAVE_LLISTXATTR FALSE) - SET(HAVE_LSETEA FALSE) - SET(HAVE_LSETXATTR FALSE) - SET(HAVE_SYS_EXTATTR_H FALSE) - SET(HAVE_SYS_XATTR_H FALSE) + SET(ARCHIVE_XATTR_DARWIN FALSE) + SET(ARCHIVE_XATTR_FREEBSD FALSE) + SET(ARCHIVE_XATTR_LINUX FALSE) + SET(ARCHIVE_XATTR_AIX FALSE) ENDIF(ENABLE_XATTR) # @@ -1321,78 +1376,212 @@ ENDIF(ENABLE_XATTR) # which makes the following checks rather more complex than I would like. # IF(ENABLE_ACL) + # Solaris and derivates ACLs + CHECK_FUNCTION_EXISTS(acl HAVE_ACL) + CHECK_FUNCTION_EXISTS(facl HAVE_FACL) + + # Libacl CHECK_LIBRARY_EXISTS(acl "acl_get_file" "" HAVE_LIBACL) IF(HAVE_LIBACL) SET(CMAKE_REQUIRED_LIBRARIES "acl") FIND_LIBRARY(ACL_LIBRARY NAMES acl) LIST(APPEND ADDITIONAL_LIBS ${ACL_LIBRARY}) ENDIF(HAVE_LIBACL) - # - CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY) - CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT) - CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD) - CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd_np HAVE_ACL_SET_FD_NP) - CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE) - CHECK_TYPE_EXISTS(acl_permset_t "${INCLUDES}" HAVE_ACL_PERMSET_T) - - # The "acl_get_perm()" function was omitted from the POSIX draft. - # (It's a pretty obvious oversight; otherwise, there's no way to - # test for specific permissions in a permset.) Linux uses the obvious - # name, FreeBSD adds _np to mark it as "non-Posix extension." - # Test for both as a double-check that we really have POSIX-style ACL support. - CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP) - CHECK_FUNCTION_EXISTS(acl_get_perm HAVE_ACL_GET_PERM) - CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP) - CHECK_FUNCTION_EXISTS(acl_get_link HAVE_ACL_GET_LINK) - CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) - CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) - CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) - CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "${INCLUDES}" HAVE_ACL_TYPE_NFS4) - - # MacOS has an acl.h that isn't POSIX. It can be detected by - # checking for ACL_USER - CHECK_SYMBOL_EXISTS(ACL_USER "${INCLUDES}" HAVE_ACL_USER) - CHECK_C_SOURCE_COMPILES("#include <sys/types.h> + + CHECK_TYPE_EXISTS(acl_t "sys/types.h;sys/acl.h" HAVE_ACL_T) + CHECK_TYPE_EXISTS(acl_entry_t "sys/types.h;sys/acl.h" HAVE_ACL_ENTRY_T) + CHECK_TYPE_EXISTS(acl_permset_t "sys/types.h;sys/acl.h" HAVE_ACL_PERMSET_T) + CHECK_TYPE_EXISTS(acl_tag_t "sys/types.h;sys/acl.h" HAVE_ACL_TAG_T) + + IF(HAVE_ACL AND HAVE_FACL) + CHECK_TYPE_EXISTS(aclent_t "sys/acl.h" HAVE_ACLENT_T) + IF(HAVE_ACLENT_T) + CHECK_SYMBOL_EXISTS(GETACL "sys/acl.h" HAVE_DECL_GETACL) + CHECK_SYMBOL_EXISTS(GETACLCNT "sys/acl.h" HAVE_DECL_GETACLCNT) + CHECK_SYMBOL_EXISTS(SETACL "sys/acl.h" HAVE_DECL_SETACL) + IF(HAVE_DECL_GETACL AND + HAVE_DECL_GETACLCNT AND + HAVE_DECL_SETACL) + SET(ARCHIVE_ACL_SUNOS TRUE) + ENDIF() + CHECK_TYPE_EXISTS(ace_t "sys/acl.h" HAVE_ACE_T) + IF(HAVE_ACE_T) + CHECK_SYMBOL_EXISTS(ACE_GETACL "sys/acl.h" HAVE_DECL_ACE_GETACL) + CHECK_SYMBOL_EXISTS(ACE_GETACLCNT "sys/acl.h" HAVE_DECL_ACE_GETACLCNT) + CHECK_SYMBOL_EXISTS(ACE_SETACL "sys/acl.h" HAVE_DECL_ACE_SETACL) + IF(HAVE_DECL_ACE_GETACL AND + HAVE_DECL_ACE_GETACLCNT AND + HAVE_DECL_ACE_SETACL) + SET(ARCHIVE_ACL_SUNOS_NFS4 TRUE) + ENDIF() + ENDIF(HAVE_ACE_T) + ENDIF(HAVE_ACLENT_T) + ENDIF(HAVE_ACL AND HAVE_FACL) + + IF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND HAVE_ACL_TAG_T) + CHECK_FUNCTION_EXISTS_GLIBC(acl_add_perm HAVE_ACL_ADD_PERM) + CHECK_FUNCTION_EXISTS_GLIBC(acl_clear_perms HAVE_ACL_CLEAR_PERMS) + CHECK_FUNCTION_EXISTS_GLIBC(acl_create_entry HAVE_ACL_CREATE_ENTRY) + CHECK_FUNCTION_EXISTS_GLIBC(acl_delete_def_file HAVE_ACL_DELETE_DEF_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_free HAVE_ACL_FREE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_entry HAVE_ACL_GET_ENTRY) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_fd HAVE_ACL_GET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_file HAVE_ACL_GET_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_permset HAVE_ACL_GET_PERMSET) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_qualifier HAVE_ACL_GET_QUALIFIER) + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_tag_type HAVE_ACL_GET_TAG_TYPE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_init HAVE_ACL_INIT) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_fd HAVE_ACL_SET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_file HAVE_ACL_SET_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_qualifier HAVE_ACL_SET_QUALIFIER) + CHECK_FUNCTION_EXISTS_GLIBC(acl_set_tag_type HAVE_ACL_SET_TAG_TYPE) + IF(HAVE_ACL_ADD_PERM AND + HAVE_ACL_CLEAR_PERMS AND + HAVE_ACL_CREATE_ENTRY AND + HAVE_ACL_DELETE_DEF_FILE AND + HAVE_ACL_FREE AND + HAVE_ACL_GET_ENTRY AND + HAVE_ACL_GET_FD AND + HAVE_ACL_GET_FILE AND + HAVE_ACL_GET_PERMSET AND + HAVE_ACL_GET_QUALIFIER AND + HAVE_ACL_GET_TAG_TYPE AND + HAVE_ACL_INIT AND + HAVE_ACL_SET_FD AND + HAVE_ACL_SET_FILE AND + HAVE_ACL_SET_QUALIFIER AND + HAVE_ACL_SET_TAG_TYPE) + SET(HAVE_POSIX_ACL_FUNCS 1) + ENDIF() + + CHECK_FUNCTION_EXISTS_GLIBC(acl_get_perm HAVE_ACL_GET_PERM) + + IF(HAVE_POSIX_ACL_FUNCS AND HAVE_ACL_LIBACL_H AND HAVE_LIBACL AND + HAVE_ACL_GET_PERM) + SET(ARCHIVE_ACL_LIBACL TRUE) + ELSE() + CHECK_FUNCTION_EXISTS(acl_add_flag_np HAVE_ACL_ADD_FLAG_NP) + CHECK_FUNCTION_EXISTS(acl_clear_flags_np HAVE_ACL_CLEAR_FLAGS_NP) + CHECK_FUNCTION_EXISTS(acl_get_brand_np HAVE_ACL_GET_BRAND_NP) + CHECK_FUNCTION_EXISTS(acl_get_entry_type_np HAVE_ACL_GET_ENTRY_TYPE_NP) + CHECK_FUNCTION_EXISTS(acl_get_flag_np HAVE_ACL_GET_FLAG_NP) + CHECK_FUNCTION_EXISTS(acl_get_flagset_np HAVE_ACL_GET_FLAGSET_NP) + CHECK_FUNCTION_EXISTS(acl_get_fd_np HAVE_ACL_GET_FD_NP) + CHECK_FUNCTION_EXISTS(acl_get_link_np HAVE_ACL_GET_LINK_NP) + CHECK_FUNCTION_EXISTS(acl_get_perm_np HAVE_ACL_GET_PERM_NP) + CHECK_FUNCTION_EXISTS(acl_is_trivial_np HAVE_ACL_IS_TRIVIAL_NP) + CHECK_FUNCTION_EXISTS(acl_set_entry_type_np HAVE_ACL_SET_ENTRY_TYPE_NP) + CHECK_FUNCTION_EXISTS(acl_set_fd_np HAVE_ACL_SET_FD_NP) + CHECK_FUNCTION_EXISTS(acl_set_link_np HAVE_ACL_SET_LINK_NP) + CHECK_FUNCTION_EXISTS(mbr_gid_to_uuid HAVE_MBR_GID_TO_UUID) + CHECK_FUNCTION_EXISTS(mbr_uid_to_uuid HAVE_MBR_UID_TO_UUID) + CHECK_FUNCTION_EXISTS(mbr_uuid_to_id HAVE_MBR_UUID_TO_ID) + + CHECK_C_SOURCE_COMPILES("#include <sys/types.h> #include <sys/acl.h> -int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED) +int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_DECL_ACL_TYPE_EXTENDED) + CHECK_C_SOURCE_COMPILES("#include <sys/types.h> +#include <sys/acl.h> +int main(void) { return ACL_SYNCHRONIZE; }" HAVE_DECL_ACL_SYNCHRONIZE) + CHECK_SYMBOL_EXISTS(ACL_TYPE_NFS4 "sys/acl.h" HAVE_DECL_ACL_TYPE_NFS4) + CHECK_SYMBOL_EXISTS(ACL_USER "sys/acl.h" HAVE_DECL_ACL_USER) + + IF(HAVE_POSIX_ACL_FUNCS AND + HAVE_ACL_GET_FD_NP AND + HAVE_ACL_GET_PERM_NP AND + NOT HAVE_ACL_GET_PERM AND + HAVE_ACL_SET_FD_NP) + IF(HAVE_DECL_ACL_USER) + SET(ARCHIVE_ACL_FREEBSD TRUE) + IF(HAVE_DECL_ACL_TYPE_NFS4 AND + HAVE_ACL_ADD_FLAG_NP AND + HAVE_ACL_CLEAR_FLAGS_NP AND + HAVE_ACL_GET_BRAND_NP AND + HAVE_ACL_GET_ENTRY_TYPE_NP AND + HAVE_ACL_GET_FLAGSET_NP AND + HAVE_ACL_SET_ENTRY_TYPE_NP) + SET(ARCHIVE_ACL_FREEBSD_NFS4 TRUE) + ENDIF() + ELSEIF(HAVE_DECL_ACL_TYPE_EXTENDED AND + HAVE_MEMBERSHIP_H AND + HAVE_ACL_ADD_FLAG_NP AND + HAVE_ACL_CLEAR_FLAGS_NP AND + HAVE_ACL_GET_FLAGSET_NP AND + HAVE_ACL_GET_LINK_NP AND + HAVE_ACL_SET_LINK_NP AND + HAVE_MBR_UID_TO_UUID AND + HAVE_MBR_GID_TO_UUID AND + HAVE_MBR_UUID_TO_ID) + SET(ARCHIVE_ACL_DARWIN TRUE) + ENDIF() + ENDIF() + ENDIF() + ENDIF(HAVE_ACL_T AND HAVE_ACL_ENTRY_T AND HAVE_ACL_PERMSET_T AND + HAVE_ACL_TAG_T) + + # Richacl + CHECK_LIBRARY_EXISTS(richacl "richacl_get_file" "" HAVE_LIBRICHACL) + IF(HAVE_LIBRICHACL) + SET(CMAKE_REQUIRED_LIBRARIES "richacl") + FIND_LIBRARY(RICHACL_LIBRARY NAMES richacl) + LIST(APPEND ADDITIONAL_LIBS ${RICHACL_LIBRARY}) + ENDIF(HAVE_LIBRICHACL) + + CHECK_STRUCT_HAS_MEMBER("struct richace" e_type "sys/richacl.h" + HAVE_STRUCT_RICHACE) + CHECK_STRUCT_HAS_MEMBER("struct richacl" a_flags "sys/richacl.h" + HAVE_STRUCT_RICHACL) + + IF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_alloc HAVE_RICHACL_ALLOC) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_equiv_mode HAVE_RICHACL_EQUIV_MODE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_free HAVE_RICHACL_FREE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_fd HAVE_RICHACL_GET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_get_file HAVE_RICHACL_GET_FILE) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_fd HAVE_RICHACL_SET_FD) + CHECK_FUNCTION_EXISTS_GLIBC(richacl_set_file HAVE_RICHACL_SET_FILE) + IF(HAVE_RICHACL_ALLOC AND + HAVE_RICHACL_EQUIV_MODE AND + HAVE_RICHACL_FREE AND + HAVE_RICHACL_GET_FD AND + HAVE_RICHACL_GET_FILE AND + HAVE_RICHACL_SET_FD AND + HAVE_RICHACL_SET_FILE) + SET(ARCHIVE_ACL_LIBRICHACL TRUE) + ENDIF() + ENDIF(HAVE_LIBRICHACL AND HAVE_STRUCT_RICHACL AND HAVE_STRUCT_RICHACE) + + IF(ARCHIVE_ACL_DARWIN) + MESSAGE(STATUS "ACL support: Darwin (limited NFSv4)") + ELSEIF(ARCHIVE_ACL_FREEBSD_NFS4) + MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e and NFSv4)") + ELSEIF(ARCHIVE_ACL_FREEBSD) + MESSAGE(STATUS "ACL support: FreeBSD (POSIX.1e)") + ELSEIF(ARCHIVE_ACL_LIBACL OR ARCHIVE_ACL_LIBRICHACL) + IF(ARCHIVE_ACL_LIBACL AND ARCHIVE_ACL_LIBRICHACL) + MESSAGE(STATUS "ACL support: libacl (POSIX.1e) + librichacl (NFSv4)") + ELSEIF(ARCHIVE_ACL_LIBRICHACL) + MESSAGE(STATUS "ACL support: librichacl (NFSv4)") + ELSE() + MESSAGE(STATUS "ACL support: libacl (POSIX.1e)") + ENDIF() + ELSEIF(ARCHIVE_ACL_SUNOS_NFS4) + MESSAGE(STATUS "ACL support: Solaris (POSIX.1e and NFSv4)") + ELSEIF(ARCHIVE_ACL_SUNOS) + MESSAGE(STATUS "ACL support: Solaris (POSIX.1e)") + ELSE() + MESSAGE(STATUS "ACL support: none") + ENDIF() - # Solaris and derivates ACLs - CHECK_LIBRARY_EXISTS(sec "acl_get" "" HAVE_LIBSEC) - IF(HAVE_LIBSEC) - SET(CMAKE_REQUIRED_LIBRARIES "sec") - FIND_LIBRARY(SEC_LIBRARY NAMES sec) - LIST(APPEND ADDITIONAL_LIBS ${SEC_LIBRARY}) - ENDIF(HAVE_LIBSEC) - # - CHECK_TYPE_EXISTS(aclent_t "${INCLUDES}" HAVE_ACLENT_T) - CHECK_TYPE_EXISTS(ace_t "${INCLUDES}" HAVE_ACE_T) - CHECK_FUNCTION_EXISTS(acl_get HAVE_FACL_GET) - CHECK_FUNCTION_EXISTS(facl_get HAVE_FACL_GET) - CHECK_FUNCTION_EXISTS(acl_set HAVE_FACL_SET) - CHECK_FUNCTION_EXISTS(facl_set HAVE_FACL_SET) ELSE(ENABLE_ACL) # If someone runs cmake, then disables ACL support, we need # to forcibly override the cached values for these. - SET(HAVE_ACL_CREATE_ENTRY FALSE) - SET(HAVE_ACL_GET_LINK FALSE) - SET(HAVE_ACL_GET_LINK_NP FALSE) - SET(HAVE_ACL_GET_PERM FALSE) - SET(HAVE_ACL_GET_PERM_NP FALSE) - SET(HAVE_ACL_INIT FALSE) - SET(HAVE_ACL_LIB FALSE) - SET(HAVE_ACL_PERMSET_T FALSE) - SET(HAVE_ACL_SET_FD FALSE) - SET(HAVE_ACL_SET_FD_NP FALSE) - SET(HAVE_ACL_SET_FILE FALSE) - SET(HAVE_ACL_TYPE_NFS4 FALSE) - SET(HAVE_ACL_USER FALSE) - SET(HAVE_ACL_TYPE_EXTENDED FALSE) - SET(HAVE_ACL_GET FALSE) - SET(HAVE_ACLENT_T FALSE) - SET(HAVE_ACE_T FALSE) - SET(HAVE_FACL_GET FALSE) - SET(HAVE_ACL_SET FALSE) - SET(HAVE_FACL_SET FALSE) + SET(ARCHIVE_ACL_DARWIN FALSE) + SET(ARCHIVE_ACL_FREEBSD FALSE) + SET(ARCHIVE_ACL_FREEBSD_NFS4 FALSE) + SET(ARCHIVE_ACL_LIBACL FALSE) + SET(ARCHIVE_ACL_SUNOS FALSE) + SET(ARCHIVE_ACL_SUNOS_NFS4 FALSE) ENDIF(ENABLE_ACL) # diff --git a/Utilities/cmlibarchive/build/cmake/config.h.in b/Utilities/cmlibarchive/build/cmake/config.h.in index 55e04b9..368a451 100644 --- a/Utilities/cmlibarchive/build/cmake/config.h.in +++ b/Utilities/cmlibarchive/build/cmake/config.h.in @@ -182,6 +182,27 @@ typedef uint64_t uintmax_t; /* Define ZLIB_WINAPI if zlib was built on Visual Studio. */ #cmakedefine ZLIB_WINAPI 1 +/* Darwin ACL support */ +#cmakedefine ARCHIVE_ACL_DARWIN 1 + +/* FreeBSD ACL support */ +#cmakedefine ARCHIVE_ACL_FREEBSD 1 + +/* FreeBSD NFSv4 ACL support */ +#cmakedefine ARCHIVE_ACL_FREEBSD_NFS4 1 + +/* Linux POSIX.1e ACL support via libacl */ +#cmakedefine ARCHIVE_ACL_LIBACL 1 + +/* Linux NFSv4 ACL support via librichacl */ +#cmakedefine ARCHIVE_ACL_LIBRICHACL 1 + +/* Solaris ACL support */ +#cmakedefine ARCHIVE_ACL_SUNOS 1 + +/* Solaris NFSv4 ACL support */ +#cmakedefine ARCHIVE_ACL_SUNOS_NFS4 1 + /* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */ #cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1 @@ -284,6 +305,18 @@ typedef uint64_t uintmax_t; /* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */ #cmakedefine ARCHIVE_CRYPTO_SHA512_WIN 1 +/* AIX xattr support */ +#cmakedefine ARCHIVE_XATTR_AIX 1 + +/* Darwin xattr support */ +#cmakedefine ARCHIVE_XATTR_DARWIN 1 + +/* FreeBSD xattr support */ +#cmakedefine ARCHIVE_XATTR_FREEBSD 1 + +/* Linux xattr support */ +#cmakedefine ARCHIVE_XATTR_LINUX 1 + /* Version number of bsdcpio */ #cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}" @@ -329,15 +362,6 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `acl_set_file' function. */ #cmakedefine HAVE_ACL_SET_FILE 1 -/* True for FreeBSD with NFSv4 ACL support */ -#cmakedefine HAVE_ACL_TYPE_NFS4 1 - -/* True for MacOS ACL support */ -#cmakedefine HAVE_ACL_TYPE_EXTENDED 1 - -/* True for systems with POSIX ACL support */ -#cmakedefine HAVE_ACL_USER 1 - /* Define to 1 if you have the `arc4random_buf' function. */ #cmakedefine HAVE_ARC4RANDOM_BUF 1 @@ -374,6 +398,34 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `cygwin_conv_path' function. */ #cmakedefine HAVE_CYGWIN_CONV_PATH 1 +/* Define to 1 if you have the declaration of `ACE_GETACL', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_GETACL 1 + +/* Define to 1 if you have the declaration of `ACE_GETACLCNT', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_GETACLCNT 1 + +/* Define to 1 if you have the declaration of `ACE_SETACL', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACE_SETACL 1 + +/* Define to 1 if you have the declaration of `ACL_SYNCHRONIZE', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_ACL_SYNCHRONIZE 1 + +/* Define to 1 if you have the declaration of `ACL_TYPE_EXTENDED', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_ACL_TYPE_EXTENDED 1 + +/* Define to 1 if you have the declaration of `ACL_TYPE_NFS4', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACL_TYPE_NFS4 1 + +/* Define to 1 if you have the declaration of `ACL_USER', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_ACL_USER 1 + /* Define to 1 if you have the declaration of `INT32_MAX', and to 0 if you don't. */ #cmakedefine HAVE_DECL_INT32_MAX 1 @@ -398,6 +450,10 @@ typedef uint64_t uintmax_t; don't. */ #cmakedefine HAVE_DECL_INTMAX_MIN 1 +/* Define to 1 if you have the declaration of `SETACL', and to 0 if you don't. + */ +#cmakedefine HAVE_DECL_SETACL 1 + /* Define to 1 if you have the declaration of `SIZE_MAX', and to 0 if you don't. */ #cmakedefine HAVE_DECL_SIZE_MAX 1 @@ -422,6 +478,10 @@ typedef uint64_t uintmax_t; don't. */ #cmakedefine HAVE_DECL_UINTMAX_MAX 1 +/* Define to 1 if you have the declaration of `XATTR_NOFOLLOW', and to 0 if + you don't. */ +#cmakedefine HAVE_DECL_XATTR_NOFOLLOW 1 + /* Define to 1 if you have the <direct.h> header file. */ #cmakedefine HAVE_DIRECT_H 1 @@ -471,6 +531,14 @@ typedef uint64_t uintmax_t; /* Define to 1 if EXTATTR_NAMESPACE_USER is defined in sys/extattr.h. */ #cmakedefine HAVE_DECL_EXTATTR_NAMESPACE_USER 1 +/* Define to 1 if you have the declaration of `GETACL', and to 0 if you don't. + */ +#cmakedefine HAVE_DECL_GETACL 1 + +/* Define to 1 if you have the declaration of `GETACLCNT', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_GETACLCNT 1 + /* Define to 1 if you have the `fchdir' function. */ #cmakedefine HAVE_FCHDIR 1 @@ -748,6 +816,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `mbrtowc' function. */ #cmakedefine HAVE_MBRTOWC 1 +/* Define to 1 if you have the <membership.h> header file. */ +#cmakedefine HAVE_MEMBERSHIP_H 1 + /* Define to 1 if you have the `memmove' function. */ #cmakedefine HAVE_MEMMOVE 1 @@ -985,6 +1056,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <sys/poll.h> header file. */ #cmakedefine HAVE_SYS_POLL_H 1 +/* Define to 1 if you have the <sys/richacl.h> header file. */ +#cmakedefine HAVE_SYS_RICHACL_H 1 + /* Define to 1 if you have the <sys/select.h> header file. */ #cmakedefine HAVE_SYS_SELECT_H 1 diff --git a/Utilities/cmlibarchive/build/version b/Utilities/cmlibarchive/build/version index ef83457..2dd0839 100644 --- a/Utilities/cmlibarchive/build/version +++ b/Utilities/cmlibarchive/build/version @@ -1 +1 @@ -3003001 +3003002 diff --git a/Utilities/cmlibarchive/libarchive/CMakeLists.txt b/Utilities/cmlibarchive/libarchive/CMakeLists.txt index d412c80..b02ae82 100644 --- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt @@ -14,6 +14,7 @@ SET(include_HEADERS # Sources and private headers SET(libarchive_SOURCES archive_acl.c + archive_acl_private.h archive_check_magic.c archive_cmdline.c archive_cmdline_private.h @@ -47,6 +48,8 @@ SET(libarchive_SOURCES archive_pathmatch.c archive_pathmatch.h archive_platform.h + archive_platform_acl.h + archive_platform_xattr.h archive_ppmd_private.h archive_ppmd7.c archive_ppmd7_private.h @@ -106,9 +109,9 @@ SET(libarchive_SOURCES archive_string_composition.h archive_string_sprintf.c archive_util.c + archive_version_details.c archive_virtual.c archive_write.c - archive_write_disk_acl.c archive_write_disk_posix.c archive_write_disk_private.h archive_write_disk_set_standard_lookup.c @@ -210,6 +213,16 @@ IF(WIN32 AND NOT CYGWIN) LIST(APPEND libarchive_SOURCES filter_fork_windows.c) ENDIF(WIN32 AND NOT CYGWIN) +IF(ARCHIVE_ACL_DARWIN) + LIST(APPEND libarchive_SOURCES archive_disk_acl_darwin.c) +ELSEIF(ARCHIVE_ACL_FREEBSD) + LIST(APPEND libarchive_SOURCES archive_disk_acl_freebsd.c) +ELSEIF(ARCHIVE_ACL_LIBACL) + LIST(APPEND libarchive_SOURCES archive_disk_acl_linux.c) +ELSEIF(ARCHIVE_ACL_SUNOS) + LIST(APPEND libarchive_SOURCES archive_disk_acl_sunos.c) +ENDIF() + # CMake needs just one static "cmlibarchive" library. ADD_LIBRARY(cmlibarchive STATIC ${libarchive_SOURCES} ${include_HEADERS}) TARGET_LINK_LIBRARIES(cmlibarchive ${ADDITIONAL_LIBS}) diff --git a/Utilities/cmlibarchive/libarchive/archive.h b/Utilities/cmlibarchive/libarchive/archive.h index cfb5c48..0f94d2e 100644 --- a/Utilities/cmlibarchive/libarchive/archive.h +++ b/Utilities/cmlibarchive/libarchive/archive.h @@ -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 3003001 +#define ARCHIVE_VERSION_NUMBER 3003002 #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.3.1" +#define ARCHIVE_VERSION_ONLY_STRING "3.3.2" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); diff --git a/Utilities/cmlibarchive/libarchive/archive_check_magic.c b/Utilities/cmlibarchive/libarchive/archive_check_magic.c index c695e58..288ce23 100644 --- a/Utilities/cmlibarchive/libarchive/archive_check_magic.c +++ b/Utilities/cmlibarchive/libarchive/archive_check_magic.c @@ -62,7 +62,7 @@ errmsg(const char *m) } } -static void +static __LA_DEAD void diediedie(void) { #if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) diff --git a/Utilities/cmlibarchive/libarchive/archive_disk_acl_darwin.c b/Utilities/cmlibarchive/libarchive/archive_disk_acl_darwin.c new file mode 100644 index 0000000..48ad016 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_disk_acl_darwin.c @@ -0,0 +1,559 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * 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" + +#if ARCHIVE_ACL_DARWIN + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_MEMBERSHIP_H +#include <membership.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include <sys/acl.h> +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, +#if HAVE_DECL_ACL_SYNCHRONIZE + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +#endif +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} +}; + +static const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); + +static int translate_guid(struct archive *a, acl_entry_t acl_entry, + int *ae_id, int *ae_tag, const char **ae_name) +{ + void *q; + uid_t ugid; + int r, idtype; + + q = acl_get_qualifier(acl_entry); + if (q == NULL) + return (1); + r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); + if (r != 0) { + acl_free(q); + return (1); + } + if (idtype == ID_TYPE_UID) { + *ae_tag = ARCHIVE_ENTRY_ACL_USER; + *ae_id = ugid; + *ae_name = archive_read_disk_uname(a, *ae_id); + } else if (idtype == ID_TYPE_GID) { + *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + *ae_id = ugid; + *ae_name = archive_read_disk_gname(a, *ae_id); + } else + r = 1; + + acl_free(q); + return (r); +} + +static void +add_trivial_nfs4_acl(struct archive_entry *entry) +{ + mode_t mode; + int i; + const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; + const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | + ARCHIVE_ENTRY_ACL_APPEND_DATA; + const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; + const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_READ_ACL | + ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | + ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | + ARCHIVE_ENTRY_ACL_WRITE_ACL | + ARCHIVE_ENTRY_ACL_WRITE_OWNER; + + struct { + const int type; + const int tag; + int permset; + } tacl_entry[] = { + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, + {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} + }; + + mode = archive_entry_mode(entry); + + /* Permissions for everyone@ */ + if (mode & 0004) + tacl_entry[5].permset |= rperm; + if (mode & 0002) + tacl_entry[5].permset |= wperm; + if (mode & 0001) + tacl_entry[5].permset |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tacl_entry[4].permset |= rperm; + else if (mode & 0004) + tacl_entry[2].permset |= rperm; + if (mode & 0020) + tacl_entry[4].permset |= wperm; + else if (mode & 0002) + tacl_entry[2].permset |= wperm; + if (mode & 0010) + tacl_entry[4].permset |= eperm; + else if (mode & 0001) + tacl_entry[2].permset |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tacl_entry[3].permset |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tacl_entry[0].permset |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tacl_entry[1].permset |= rperm; + if (mode & 0200) { + tacl_entry[3].permset |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tacl_entry[0].permset |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tacl_entry[1].permset |= wperm; + if (mode & 0100) { + tacl_entry[3].permset |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tacl_entry[0].permset |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tacl_entry[1].permset |= eperm; + + for (i = 0; i < 6; i++) { + if (tacl_entry[i].permset != 0) { + archive_entry_acl_add_entry(entry, + tacl_entry[i].type, tacl_entry[i].permset, + tacl_entry[i].tag, -1, NULL); + } + } + + return; +} + +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl) +{ + acl_tag_t acl_tag; + acl_flagset_t acl_flagset; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type; + int r, s, ae_id, ae_tag, ae_perm; + const char *ae_name; + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + + while (s == 0) { + ae_id = -1; + ae_name = NULL; + ae_perm = 0; + + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } + switch (acl_tag) { + case ACL_EXTENDED_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + r = translate_guid(&a->archive, acl_entry, + &ae_id, &ae_tag, &ae_name); + break; + case ACL_EXTENDED_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + r = translate_guid(&a->archive, acl_entry, + &ae_id, &ae_tag, &ae_name); + break; + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + /* Skip if translate_guid() above failed */ + if (r != 0) { + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + /* + * Libarchive stores "flag" (NFSv4 inheritance bits) + * in the ae_perm bitmap. + * + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get flagset from a NFSv4 ACL entry"); + return (ARCHIVE_WARN); + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + r = acl_get_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check flag in a NFSv4 " + "ACL flagset"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + /* + * acl_get_perm() is spelled differently on different + * platforms; see above. + */ + r = acl_get_perm_np(acl_permset, + acl_nfs4_perm_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL " + "permission set"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_nfs4_perm_map[i].a_perm; + } + +#if !HAVE_DECL_ACL_SYNCHRONIZE + /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */ + ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; +#endif + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); + + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + } + return (ARCHIVE_OK); +} + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + acl_t acl; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + acl_flagset_t acl_flagset; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + uuid_t ae_uuid; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + /* + * Mac OS doesn't support NFSv4 ACLs for + * owner@, group@ and everyone@. + * We skip any of these ACLs found. + */ + if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ || + ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ || + ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE) + continue; + + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY); + break; + default: + /* We don't support any other types on MacOS */ + continue; + } + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + if (mbr_uid_to_uuid(ae_uid, ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + if (mbr_gid_to_uuid(ae_gid, ae_uuid) != 0) + continue; + if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) + continue; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if (ae_permset & acl_nfs4_perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + acl_nfs4_perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + + /* + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to get flagset from an NFSv4 ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_flags_np(acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to clear flags from an NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + if (acl_add_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add flag to " + "NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + } + + if (fd >= 0) { + if (acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (acl_set_link_np(name, ACL_TYPE_EXTENDED, acl) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + acl_free(acl); + return (ret); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + acl_t acl; + int r; + + accpath = NULL; + + if (*fd < 0) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + + acl = NULL; + + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_EXTENDED); + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_EXTENDED); + else + acl = acl_get_file(accpath, ACL_TYPE_EXTENDED); + + if (acl != NULL) { + r = translate_acl(a, entry, acl); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + /* + * Because Mac OS doesn't support owner@, group@ and everyone@ + * ACLs we need to add NFSv4 ACLs mirroring the file mode to + * the archive entry. Otherwise extraction on non-Mac platforms + * would lead to an invalid file mode. + */ + if ((archive_entry_acl_types(entry) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + add_trivial_nfs4_acl(entry); + + return (r); + } + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + + (void)mode; /* UNUSED */ + + if ((archive_acl_types(abstract_acl) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_acl(a, fd, name, abstract_acl, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } + return (ret); +} +#endif /* ARCHIVE_ACL_DARWIN */ diff --git a/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c b/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c new file mode 100644 index 0000000..07d08ff --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_disk_acl_freebsd.c @@ -0,0 +1,700 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2017 Martin Matuska + * 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" + +#if ARCHIVE_ACL_FREEBSD + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include <sys/acl.h> +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +static const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, +}; + +static const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); + +#if ARCHIVE_ACL_FREEBSD_NFS4 +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} +}; + +static const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); +#endif /* ARCHIVE_ACL_FREEBSD_NFS4 */ + +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl, int default_entry_acl_type) +{ +#if ARCHIVE_ACL_FREEBSD_NFS4 + int brand; + acl_flagset_t acl_flagset; + acl_entry_type_t acl_type; +#endif + acl_tag_t acl_tag; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type, perm_map_size; + const acl_perm_map_t *perm_map; + int r, s, ae_id, ae_tag, ae_perm; + void *q; + const char *ae_name; + +#if ARCHIVE_ACL_FREEBSD_NFS4 + // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 + // Make sure the "brand" on this ACL is consistent + // with the default_entry_acl_type bits provided. + if (acl_get_brand_np(acl, &brand) != 0) { + archive_set_error(&a->archive, errno, + "Failed to read ACL brand"); + return (ARCHIVE_WARN); + } + switch (brand) { + case ACL_BRAND_POSIX: + switch (default_entry_acl_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for POSIX.1e ACL"); + return (ARCHIVE_WARN); + } + break; + case ACL_BRAND_NFS4: + if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for NFSv4 ACL"); + return (ARCHIVE_WARN); + } + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown ACL brand"); + return (ARCHIVE_WARN); + } +#endif + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + + while (s == 1) { + ae_id = -1; + ae_name = NULL; + ae_perm = 0; + + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } + switch (acl_tag) { + case ACL_USER: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(uid_t *)q; + acl_free(q); + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case ACL_GROUP: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(gid_t *)q; + acl_free(q); + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case ACL_MASK: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case ACL_USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case ACL_GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case ACL_OTHER: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; +#if ARCHIVE_ACL_FREEBSD_NFS4 + case ACL_EVERYONE: + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; +#endif + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + // XXX acl_type maps to allow/deny/audit/YYYY bits + entry_acl_type = default_entry_acl_type; + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* + * acl_get_entry_type_np() fails with non-NFSv4 ACLs + */ + if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { + archive_set_error(&a->archive, errno, "Failed " + "to get ACL type from a NFSv4 ACL entry"); + return (ARCHIVE_WARN); + } + switch (acl_type) { + case ACL_ENTRY_TYPE_ALLOW: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACL_ENTRY_TYPE_DENY: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACL_ENTRY_TYPE_AUDIT: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + break; + case ACL_ENTRY_TYPE_ALARM: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + default: + archive_set_error(&a->archive, errno, + "Invalid NFSv4 ACL entry type"); + return (ARCHIVE_WARN); + } + + /* + * Libarchive stores "flag" (NFSv4 inheritance bits) + * in the ae_perm bitmap. + * + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get flagset from a NFSv4 " + "ACL entry"); + return (ARCHIVE_WARN); + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + r = acl_get_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check flag in a NFSv4 " + "ACL flagset"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + } +#endif + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + perm_map_size = acl_nfs4_perm_map_size; + perm_map = acl_nfs4_perm_map; + } else { +#endif + perm_map_size = acl_posix_perm_map_size; + perm_map = acl_posix_perm_map; +#if ARCHIVE_ACL_FREEBSD_NFS4 + } +#endif + + for (i = 0; i < perm_map_size; ++i) { + r = acl_get_perm_np(acl_permset, perm_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL " + "permission set"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= perm_map[i].a_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); + + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get next ACL entry"); + return (ARCHIVE_WARN); + } + } + return (ARCHIVE_OK); +} + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + int acl_type = 0; + acl_t acl; + acl_entry_t acl_entry; + acl_permset_t acl_permset; +#if ARCHIVE_ACL_FREEBSD_NFS4 + acl_flagset_t acl_flagset; + int r; +#endif + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + int perm_map_size; + const acl_perm_map_t *perm_map; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + acl_type = ACL_TYPE_ACCESS; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + acl_type = ACL_TYPE_DEFAULT; + break; +#if ARCHIVE_ACL_FREEBSD_NFS4 + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + acl_type = ACL_TYPE_NFS4; + break; +#endif + default: + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_USER); + acl_set_qualifier(acl_entry, &ae_uid); + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_GROUP); + acl_set_qualifier(acl_entry, &ae_gid); + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + acl_set_tag_type(acl_entry, ACL_USER_OBJ); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); + break; + case ARCHIVE_ENTRY_ACL_MASK: + acl_set_tag_type(acl_entry, ACL_MASK); + break; + case ARCHIVE_ENTRY_ACL_OTHER: + acl_set_tag_type(acl_entry, ACL_OTHER); + break; +#if ARCHIVE_ACL_FREEBSD_NFS4 + case ARCHIVE_ENTRY_ACL_EVERYONE: + acl_set_tag_type(acl_entry, ACL_EVERYONE); + break; +#endif + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + r = 0; + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_ALLOW); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_DENY); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_AUDIT); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + r = acl_set_entry_type_np(acl_entry, + ACL_ENTRY_TYPE_ALARM); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + // These don't translate directly into the system ACL. + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (r != 0) { + archive_set_error(a, errno, + "Failed to set ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#endif + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + perm_map_size = acl_nfs4_perm_map_size; + perm_map = acl_nfs4_perm_map; + } else { +#endif + perm_map_size = acl_posix_perm_map_size; + perm_map = acl_posix_perm_map; +#if ARCHIVE_ACL_FREEBSD_NFS4 + } +#endif + + for (i = 0; i < perm_map_size; ++i) { + if (ae_permset & perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + +#if ARCHIVE_ACL_FREEBSD_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* + * acl_get_flagset_np() fails with non-NFSv4 ACLs + */ + if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to get flagset from an NFSv4 " + "ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_flags_np(acl_flagset) != 0) { + archive_set_error(a, errno, + "Failed to clear flags from an NFSv4 " + "ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + if (acl_add_flag_np(acl_flagset, + acl_nfs4_flag_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add flag to " + "NFSv4 ACL flagset"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + } +#endif + } + + /* Try restoring the ACL through 'fd' if we can. */ + if (fd >= 0) { + if (acl_set_fd_np(fd, acl, acl_type) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } +#if HAVE_ACL_SET_LINK_NP + 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) +#endif + { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + acl_free(acl); + return (ret); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + acl_t acl; + int r; + + accpath = NULL; + + if (*fd < 0) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + + acl = NULL; + +#if ARCHIVE_ACL_FREEBSD_NFS4 + /* Try NFSv4 ACL first. */ + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4); + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_NFS4); + else + acl = acl_get_file(accpath, ACL_TYPE_NFS4); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { + acl_free(acl); + acl = NULL; + return (ARCHIVE_OK); + } + + if (acl != NULL) { + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + return (r); + } +#endif + + /* Retrieve access ACL from file. */ + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS); +#if HAVE_ACL_GET_LINK_NP + else if (!a->follow_symlinks) + acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); +#else + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + acl = NULL; +#endif + else + acl = acl_get_file(accpath, ACL_TYPE_ACCESS); + +#if HAVE_ACL_IS_TRIVIAL_NP + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) { + acl_free(acl); + acl = NULL; + } +#endif + + if (acl != NULL) { + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + /* Only directories can have default ACLs. */ + if (S_ISDIR(archive_entry_mode(entry))) { + if (*fd >= 0) + acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); + else + acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); + if (acl != NULL) { + r = translate_acl(a, entry, acl, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + acl_free(acl); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate default ACLs"); + return (r); + } + } + } + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + + (void)mode; /* UNUSED */ + + if ((archive_acl_types(abstract_acl) + & 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, + 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, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); + + /* Simultaneous POSIX.1e and NFSv4 is not supported */ + return (ret); + } +#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, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } +#endif + return (ret); +} +#endif /* ARCHIVE_ACL_FREEBSD */ diff --git a/Utilities/cmlibarchive/libarchive/archive_disk_acl_linux.c b/Utilities/cmlibarchive/libarchive/archive_disk_acl_linux.c new file mode 100644 index 0000000..3928f3d --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_disk_acl_linux.c @@ -0,0 +1,743 @@ +/*- + * Copyright (c) 2003-2009 Tim Kientzle + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2017 Martin Matuska + * 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" + +#if ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#if HAVE_ACL_LIBACL_H +#include <acl/libacl.h> +#endif +#ifdef HAVE_SYS_ACL_H +#include <sys/acl.h> +#endif +#ifdef HAVE_SYS_RICHACL_H +#include <sys/richacl.h> +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +#if ARCHIVE_ACL_LIBACL +static const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, + {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, + {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, +}; + +static const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); +#endif /* ARCHIVE_ACL_LIBACL */ + +#if ARCHIVE_ACL_LIBRICHACL +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, RICHACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, RICHACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, RICHACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, RICHACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, RICHACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, RICHACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, RICHACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, RICHACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, RICHACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, RICHACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, RICHACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, RICHACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, RICHACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, RICHACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, RICHACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, RICHACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, RICHACE_SYNCHRONIZE} +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, RICHACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, RICHACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, RICHACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, RICHACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, RICHACE_INHERITED_ACE} +}; + +static const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBACL +/* + * Translate POSIX.1e ACLs into libarchive internal structure + */ +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, acl_t acl, int default_entry_acl_type) +{ + acl_tag_t acl_tag; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + int i, entry_acl_type; + int r, s, ae_id, ae_tag, ae_perm; + void *q; + const char *ae_name; + + s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get first ACL entry"); + return (ARCHIVE_WARN); + } + + while (s == 1) { + ae_id = -1; + ae_name = NULL; + ae_perm = 0; + + if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL tag type"); + return (ARCHIVE_WARN); + } + switch (acl_tag) { + case ACL_USER: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(uid_t *)q; + acl_free(q); + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case ACL_GROUP: + q = acl_get_qualifier(acl_entry); + if (q != NULL) { + ae_id = (int)*(gid_t *)q; + acl_free(q); + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case ACL_MASK: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case ACL_USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case ACL_GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case ACL_OTHER: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + default: + /* Skip types that libarchive can't support. */ + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + continue; + } + + // XXX acl_type maps to allow/deny/audit/YYYY bits + entry_acl_type = default_entry_acl_type; + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(&a->archive, errno, + "Failed to get ACL permission set"); + return (ARCHIVE_WARN); + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + r = acl_get_perm(acl_permset, + acl_posix_perm_map[i].p_perm); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to check permission in an ACL " + "permission set"); + return (ARCHIVE_WARN); + } else if (r) + ae_perm |= acl_posix_perm_map[i].a_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, + ae_id, ae_name); + + s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get next ACL entry"); + return (ARCHIVE_WARN); + } + } + return (ARCHIVE_OK); +} +#endif /* ARCHIVE_ACL_LIBACL */ + +#if ARCHIVE_ACL_LIBRICHACL +/* + * Translate RichACL into libarchive internal ACL + */ +static int +translate_richacl(struct archive_read_disk *a, struct archive_entry *entry, + struct richacl *richacl) +{ + int ae_id, ae_tag, ae_perm; + int entry_acl_type, i; + const char *ae_name; + + struct richace *richace; + + richacl_for_each_entry(richace, richacl) { + ae_name = NULL; + ae_tag = 0; + ae_perm = 0; + ae_id = -1; + + switch (richace->e_type) { + case RICHACE_ACCESS_ALLOWED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case RICHACE_ACCESS_DENIED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + default: /* Unknown entry type, skip */ + continue; + } + + /* Unsupported */ + if (richace->e_flags & RICHACE_UNMAPPED_WHO) + continue; + + if (richace->e_flags & RICHACE_SPECIAL_WHO) { + switch (richace->e_id) { + case RICHACE_OWNER_SPECIAL_ID: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case RICHACE_GROUP_SPECIAL_ID: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case RICHACE_EVERYONE_SPECIAL_ID: + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; + default: /* Unknown special ID type */ + continue; + } + } else { + ae_id = richace->e_id; + if (richace->e_flags & RICHACE_IDENTIFIER_GROUP) { + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + ae_name = archive_read_disk_gname(&a->archive, + (gid_t)(richace->e_id)); + } else { + ae_tag = ARCHIVE_ENTRY_ACL_USER; + ae_name = archive_read_disk_uname(&a->archive, + (uid_t)(richace->e_id)); + } + } + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if ((richace->e_flags & + acl_nfs4_flag_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if ((richace->e_mask & + acl_nfs4_perm_map[i].p_perm) != 0) + ae_perm |= + acl_nfs4_perm_map[i].a_perm; + } + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, ae_id, ae_name); + } + return (ARCHIVE_OK); +} +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBRICHACL +static int +_richacl_mode_to_mask(short mode) +{ + int mask = 0; + + if (mode & S_IROTH) + mask |= RICHACE_POSIX_MODE_READ; + if (mode & S_IWOTH) + mask |= RICHACE_POSIX_MODE_WRITE; + if (mode & S_IXOTH) + mask |= RICHACE_POSIX_MODE_EXEC; + + return (mask); +} + +static void +_richacl_mode_to_masks(struct richacl *richacl, __LA_MODE_T mode) +{ + richacl->a_owner_mask = _richacl_mode_to_mask((mode & 0700) >> 6); + richacl->a_group_mask = _richacl_mode_to_mask((mode & 0070) >> 3); + richacl->a_other_mask = _richacl_mode_to_mask(mode & 0007); +} +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBRICHACL +static int +set_richacl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode, + int ae_requested_type, const char *tname) +{ + int ae_type, ae_permset, ae_tag, ae_id; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + int ret; + int e = 0; + struct richacl *richacl = NULL; + struct richace *richace; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + if (ae_requested_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + richacl = richacl_alloc(entries); + if (richacl == NULL) { + archive_set_error(a, errno, + "Failed to initialize RichACL working storage"); + return (ARCHIVE_FAILED); + } + + e = 0; + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + richace = &(richacl->a_entries[e]); + + richace->e_flags = 0; + richace->e_mask = 0; + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + richace->e_id = ae_uid; + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + richace->e_id = ae_gid; + richace->e_flags |= RICHACE_IDENTIFIER_GROUP; + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + richace->e_flags |= RICHACE_SPECIAL_WHO; + richace->e_id = RICHACE_OWNER_SPECIAL_ID; + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + richace->e_flags |= RICHACE_SPECIAL_WHO; + richace->e_id = RICHACE_GROUP_SPECIAL_ID; + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + richace->e_flags |= RICHACE_SPECIAL_WHO; + richace->e_id = RICHACE_EVERYONE_SPECIAL_ID; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + switch (ae_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + richace->e_type = + RICHACE_ACCESS_ALLOWED_ACE_TYPE; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + richace->e_type = + RICHACE_ACCESS_DENIED_ACE_TYPE; + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if (ae_permset & acl_nfs4_perm_map[i].a_perm) + richace->e_mask |= acl_nfs4_perm_map[i].p_perm; + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & + acl_nfs4_flag_map[i].a_perm) + richace->e_flags |= acl_nfs4_flag_map[i].p_perm; + } + e++; + } + + /* Fill RichACL masks */ + _richacl_mode_to_masks(richacl, mode); + + if (fd >= 0) { + if (richacl_set_fd(fd, richacl) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set richacl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (richacl_set_file(name, richacl) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set richacl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + richacl_free(richacl); + return (ret); +} +#endif /* ARCHIVE_ACL_RICHACL */ + +#if ARCHIVE_ACL_LIBACL +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + int acl_type = 0; + int ae_type, ae_permset, ae_tag, ae_id; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + int ret; + acl_t acl = NULL; + acl_entry_t acl_entry; + acl_permset_t acl_permset; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + acl_type = ACL_TYPE_ACCESS; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + acl_type = ACL_TYPE_DEFAULT; + break; + default: + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + acl = acl_init(entries); + if (acl == (acl_t)NULL) { + archive_set_error(a, errno, + "Failed to initialize ACL working storage"); + return (ARCHIVE_FAILED); + } + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + + if (acl_create_entry(&acl, &acl_entry) != 0) { + archive_set_error(a, errno, + "Failed to create a new ACL entry"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_USER); + acl_set_qualifier(acl_entry, &ae_uid); + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + acl_set_tag_type(acl_entry, ACL_GROUP); + acl_set_qualifier(acl_entry, &ae_gid); + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + acl_set_tag_type(acl_entry, ACL_USER_OBJ); + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); + break; + case ARCHIVE_ENTRY_ACL_MASK: + acl_set_tag_type(acl_entry, ACL_MASK); + break; + case ARCHIVE_ENTRY_ACL_OTHER: + acl_set_tag_type(acl_entry, ACL_OTHER); + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (acl_get_permset(acl_entry, &acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to get ACL permission set"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + if (acl_clear_perms(acl_permset) != 0) { + archive_set_error(a, errno, + "Failed to clear ACL permissions"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + if (ae_permset & acl_posix_perm_map[i].a_perm) { + if (acl_add_perm(acl_permset, + acl_posix_perm_map[i].p_perm) != 0) { + archive_set_error(a, errno, + "Failed to add ACL permission"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + } + } + + } + + if (fd >= 0 && ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + if (acl_set_fd(fd, acl) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (acl_set_file(name, acl_type, acl) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + acl_free(acl); + return (ret); +} +#endif /* ARCHIVE_ACL_LIBACL */ + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + int r; +#if ARCHIVE_ACL_LIBACL + acl_t acl; +#endif +#if ARCHIVE_ACL_LIBRICHACL + struct richacl *richacl; + mode_t mode; +#endif + + accpath = NULL; + r = ARCHIVE_OK; + + /* For default ACLs we need reachable accpath */ + if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + +#if ARCHIVE_ACL_LIBACL + acl = NULL; +#endif +#if ARCHIVE_ACL_LIBRICHACL + richacl = NULL; +#endif + +#if ARCHIVE_ACL_LIBRICHACL + /* Try NFSv4 ACL first. */ + if (*fd >= 0) + richacl = richacl_get_fd(*fd); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one */ + richacl = NULL; + else + richacl = richacl_get_file(accpath); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (richacl != NULL) { + mode = archive_entry_mode(entry); + if (richacl_equiv_mode(richacl, &mode) == 0) { + richacl_free(richacl); + richacl = NULL; + return (ARCHIVE_OK); + } + } + + if (richacl != NULL) { + r = translate_richacl(a, entry, richacl); + richacl_free(richacl); + richacl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + + return (r); + } +#endif /* ARCHIVE_ACL_LIBRICHACL */ + +#if ARCHIVE_ACL_LIBACL + /* Retrieve access ACL from file. */ + if (*fd >= 0) + acl = acl_get_fd(*fd); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + acl = NULL; + else + acl = acl_get_file(accpath, ACL_TYPE_ACCESS); + + if (acl != NULL) { + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + acl_free(acl); + acl = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + /* Only directories can have default ACLs. */ + if (S_ISDIR(archive_entry_mode(entry))) { + acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); + if (acl != NULL) { + r = translate_acl(a, entry, acl, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + acl_free(acl); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate default ACLs"); + return (r); + } + } + } +#endif /* ARCHIVE_ACL_LIBACL */ + return (r); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + +#if !ARCHIVE_ACL_LIBRICHACL + (void)mode; /* UNUSED */ +#endif + +#if ARCHIVE_ACL_LIBRICHACL + if ((archive_acl_types(abstract_acl) + & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = set_richacl(a, fd, name, abstract_acl, mode, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } +#if ARCHIVE_ACL_LIBACL + else +#endif +#endif /* ARCHIVE_ACL_LIBRICHACL */ +#if ARCHIVE_ACL_LIBACL + if ((archive_acl_types(abstract_acl) + & 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, + 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, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); + } +#endif /* ARCHIVE_ACL_LIBACL */ + return (ret); +} +#endif /* ARCHIVE_ACL_LIBACL || ARCHIVE_ACL_LIBRICHACL */ diff --git a/Utilities/cmlibarchive/libarchive/archive_disk_acl_sunos.c b/Utilities/cmlibarchive/libarchive/archive_disk_acl_sunos.c new file mode 100644 index 0000000..bc84fd6 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_disk_acl_sunos.c @@ -0,0 +1,821 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * 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" + +#if ARCHIVE_ACL_SUNOS + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_ACL_H +#define _ACL_PRIVATE /* For debugging */ +#include <sys/acl.h> +#endif + +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_read_disk_private.h" +#include "archive_write_disk_private.h" + +typedef struct { + const int a_perm; /* Libarchive permission or flag */ + const int p_perm; /* Platform permission or flag */ +} acl_perm_map_t; + +static const acl_perm_map_t acl_posix_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH }, + {ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH }, + {ARCHIVE_ENTRY_ACL_READ, S_IROTH } +}; + +static const int acl_posix_perm_map_size = + (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0])); + +#if ARCHIVE_ACL_SUNOS_NFS4 +static const acl_perm_map_t acl_nfs4_perm_map[] = { + {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, + {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, + {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, + {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, + {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, + {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, + {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, + {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, + {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, + {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, + {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, + {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, + {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} +}; + +static const int acl_nfs4_perm_map_size = + (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0])); + +static const acl_perm_map_t acl_nfs4_flag_map[] = { + {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, + {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, + {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, +#ifdef ACE_INHERITED_ACE + {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} +#endif +}; + +const int acl_nfs4_flag_map_size = + (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0])); + +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + +static void * +sunacl_get(int cmd, int *aclcnt, int fd, const char *path) +{ + int cnt, cntcmd; + size_t size; + void *aclp; + + if (cmd == GETACL) { + cntcmd = GETACLCNT; + size = sizeof(aclent_t); + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else if (cmd == ACE_GETACL) { + cntcmd = ACE_GETACLCNT; + size = sizeof(ace_t); + } +#endif + else { + errno = EINVAL; + *aclcnt = -1; + return (NULL); + } + + aclp = NULL; + cnt = -2; + + while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { + if (path != NULL) + cnt = acl(path, cntcmd, 0, NULL); + else + cnt = facl(fd, cntcmd, 0, NULL); + + if (cnt > 0) { + if (aclp == NULL) + aclp = malloc(cnt * size); + else + aclp = realloc(NULL, cnt * size); + if (aclp != NULL) { + if (path != NULL) + cnt = acl(path, cmd, cnt, aclp); + else + cnt = facl(fd, cmd, cnt, aclp); + } + } else { + if (aclp != NULL) { + free(aclp); + aclp = NULL; + } + break; + } + } + + *aclcnt = cnt; + return (aclp); +} + +/* + * Check if acl is trivial + * This is a FreeBSD acl_is_trivial_np() implementation for Solaris + */ +static int +sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4, + int is_dir, int *trivialp) +{ +#if ARCHIVE_ACL_SUNOS_NFS4 + int i, p; + const uint32_t rperm = ACE_READ_DATA; + const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; + const uint32_t eperm = ACE_EXECUTE; + const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_READ_ACL | ACE_SYNCHRONIZE; + const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | + ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; + + ace_t *ace; + ace_t tace[6]; +#endif + + if (aclp == NULL || trivialp == NULL) + return (-1); + + *trivialp = 0; + + /* + * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with + * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, + * including mask. + */ + if (!is_nfs4) { + if (aclcnt == 4) + *trivialp = 1; + return (0); + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + /* + * Continue with checking NFSv4 ACLs + * + * Create list of trivial ace's to be compared + */ + + /* owner@ allow pre */ + tace[0].a_flags = ACE_OWNER; + tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[0].a_access_mask = 0; + + /* owner@ deny */ + tace[1].a_flags = ACE_OWNER; + tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[1].a_access_mask = 0; + + /* group@ deny */ + tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; + tace[2].a_access_mask = 0; + + /* owner@ allow */ + tace[3].a_flags = ACE_OWNER; + tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[3].a_access_mask = ownset; + + /* group@ allow */ + tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; + tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[4].a_access_mask = pubset; + + /* everyone@ allow */ + tace[5].a_flags = ACE_EVERYONE; + tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + tace[5].a_access_mask = pubset; + + /* Permissions for everyone@ */ + if (mode & 0004) + tace[5].a_access_mask |= rperm; + if (mode & 0002) + tace[5].a_access_mask |= wperm; + if (mode & 0001) + tace[5].a_access_mask |= eperm; + + /* Permissions for group@ */ + if (mode & 0040) + tace[4].a_access_mask |= rperm; + else if (mode & 0004) + tace[2].a_access_mask |= rperm; + if (mode & 0020) + tace[4].a_access_mask |= wperm; + else if (mode & 0002) + tace[2].a_access_mask |= wperm; + if (mode & 0010) + tace[4].a_access_mask |= eperm; + else if (mode & 0001) + tace[2].a_access_mask |= eperm; + + /* Permissions for owner@ */ + if (mode & 0400) { + tace[3].a_access_mask |= rperm; + if (!(mode & 0040) && (mode & 0004)) + tace[0].a_access_mask |= rperm; + } else if ((mode & 0040) || (mode & 0004)) + tace[1].a_access_mask |= rperm; + if (mode & 0200) { + tace[3].a_access_mask |= wperm; + if (!(mode & 0020) && (mode & 0002)) + tace[0].a_access_mask |= wperm; + } else if ((mode & 0020) || (mode & 0002)) + tace[1].a_access_mask |= wperm; + if (mode & 0100) { + tace[3].a_access_mask |= eperm; + if (!(mode & 0010) && (mode & 0001)) + tace[0].a_access_mask |= eperm; + } else if ((mode & 0010) || (mode & 0001)) + tace[1].a_access_mask |= eperm; + + /* Check if the acl count matches */ + p = 3; + for (i = 0; i < 3; i++) { + if (tace[i].a_access_mask != 0) + p++; + } + if (aclcnt != p) + return (0); + + p = 0; + for (i = 0; i < 6; i++) { + if (tace[i].a_access_mask != 0) { + ace = &((ace_t *)aclp)[p]; + /* + * Illumos added ACE_DELETE_CHILD to write perms for + * directories. We have to check against that, too. + */ + if (ace->a_flags != tace[i].a_flags || + ace->a_type != tace[i].a_type || + (ace->a_access_mask != tace[i].a_access_mask && + (!is_dir || (tace[i].a_access_mask & wperm) == 0 || + ace->a_access_mask != + (tace[i].a_access_mask | ACE_DELETE_CHILD)))) + return (0); + p++; + } + } + + *trivialp = 1; +#else /* !ARCHIVE_ACL_SUNOS_NFS4 */ + (void)is_dir; /* UNUSED */ + (void)aclp; /* UNUSED */ +#endif /* !ARCHIVE_ACL_SUNOS_NFS4 */ + return (0); +} + +/* + * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL + */ +static int +translate_acl(struct archive_read_disk *a, + struct archive_entry *entry, void *aclp, int aclcnt, + int default_entry_acl_type) +{ + int e, i; + int ae_id, ae_tag, ae_perm; + int entry_acl_type; + const char *ae_name; + aclent_t *aclent; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace_t *ace; +#endif + + if (aclcnt <= 0) + return (ARCHIVE_OK); + + for (e = 0; e < aclcnt; e++) { + ae_name = NULL; + ae_tag = 0; + ae_perm = 0; + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + ace = &((ace_t *)aclp)[e]; + ae_id = ace->a_who; + + switch(ace->a_type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + break; + default: + /* Unknown entry type, skip */ + continue; + } + + if ((ace->a_flags & ACE_OWNER) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if ((ace->a_flags & ACE_GROUP) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + else if ((ace->a_flags & ACE_EVERYONE) != 0) + ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; + else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + } else { + ae_tag = ARCHIVE_ENTRY_ACL_USER; + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + } + + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if ((ace->a_flags & + acl_nfs4_flag_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_flag_map[i].a_perm; + } + + for (i = 0; i < acl_nfs4_perm_map_size; ++i) { + if ((ace->a_access_mask & + acl_nfs4_perm_map[i].p_perm) != 0) + ae_perm |= acl_nfs4_perm_map[i].a_perm; + } + } else +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + aclent = &((aclent_t *)aclp)[e]; + if ((aclent->a_type & ACL_DEFAULT) != 0) + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + else + entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + ae_id = aclent->a_id; + + switch(aclent->a_type) { + case DEF_USER: + case USER: + ae_name = archive_read_disk_uname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_USER; + break; + case DEF_GROUP: + case GROUP: + ae_name = archive_read_disk_gname(&a->archive, + ae_id); + ae_tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case DEF_CLASS_OBJ: + case CLASS_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_MASK; + break; + case DEF_USER_OBJ: + case USER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case DEF_GROUP_OBJ: + case GROUP_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case DEF_OTHER_OBJ: + case OTHER_OBJ: + ae_tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + default: + /* Unknown tag type, skip */ + continue; + } + + for (i = 0; i < acl_posix_perm_map_size; ++i) { + if ((aclent->a_perm & + acl_posix_perm_map[i].p_perm) != 0) + ae_perm |= acl_posix_perm_map[i].a_perm; + } + } else + return (ARCHIVE_WARN); + + archive_entry_acl_add_entry(entry, entry_acl_type, + ae_perm, ae_tag, ae_id, ae_name); + } + return (ARCHIVE_OK); +} + +static int +set_acl(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, + int ae_requested_type, const char *tname) +{ + aclent_t *aclent; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace_t *ace; +#endif + int cmd, e, r; + void *aclp; + int ret; + int ae_type, ae_permset, ae_tag, ae_id; + int perm_map_size; + const acl_perm_map_t *perm_map; + uid_t ae_uid; + gid_t ae_gid; + const char *ae_name; + int entries; + int i; + + ret = ARCHIVE_OK; + entries = archive_acl_reset(abstract_acl, ae_requested_type); + if (entries == 0) + return (ARCHIVE_OK); + + + switch (ae_requested_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + cmd = SETACL; + aclp = malloc(entries * sizeof(aclent_t)); + break; +#if ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + cmd = ACE_SETACL; + aclp = malloc(entries * sizeof(ace_t)); + + break; +#endif + default: + errno = ENOENT; + archive_set_error(a, errno, "Unsupported ACL type"); + return (ARCHIVE_FAILED); + } + + if (aclp == NULL) { + archive_set_error(a, errno, + "Can't allocate memory for acl buffer"); + return (ARCHIVE_FAILED); + } + + e = 0; + + while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, + &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { + aclent = NULL; +#if ARCHIVE_ACL_SUNOS_NFS4 + ace = NULL; +#endif + if (cmd == SETACL) { + aclent = &((aclent_t *)aclp)[e]; + aclent->a_id = -1; + aclent->a_type = 0; + aclent->a_perm = 0; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { /* cmd == ACE_SETACL */ + ace = &((ace_t *)aclp)[e]; + ace->a_who = -1; + ace->a_access_mask = 0; + ace->a_flags = 0; + } +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + + switch (ae_tag) { + case ARCHIVE_ENTRY_ACL_USER: + ae_uid = archive_write_disk_uid(a, ae_name, ae_id); + if (aclent != NULL) { + aclent->a_id = ae_uid; + aclent->a_type |= USER; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_who = ae_uid; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_GROUP: + ae_gid = archive_write_disk_gid(a, ae_name, ae_id); + if (aclent != NULL) { + aclent->a_id = ae_gid; + aclent->a_type |= GROUP; + } +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_who = ae_gid; + ace->a_flags |= ACE_IDENTIFIER_GROUP; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (aclent != NULL) + aclent->a_type |= USER_OBJ; +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_flags |= ACE_OWNER; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (aclent != NULL) + aclent->a_type |= GROUP_OBJ; +#if ARCHIVE_ACL_SUNOS_NFS4 + else { + ace->a_flags |= ACE_GROUP; + ace->a_flags |= ACE_IDENTIFIER_GROUP; + } +#endif + break; + case ARCHIVE_ENTRY_ACL_MASK: + if (aclent != NULL) + aclent->a_type |= CLASS_OBJ; + break; + case ARCHIVE_ENTRY_ACL_OTHER: + if (aclent != NULL) + aclent->a_type |= OTHER_OBJ; + break; +#if ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_EVERYONE: + if (ace != NULL) + ace->a_flags |= ACE_EVERYONE; + break; +#endif + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + r = 0; + switch (ae_type) { +#if ARCHIVE_ACL_SUNOS_NFS4 + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + if (ace != NULL) + ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + if (ace != NULL) + ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + if (ace != NULL) + ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; + else + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + if (ace != NULL) + ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; + else + r = -1; + break; +#endif + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + if (aclent == NULL) + r = -1; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + if (aclent != NULL) + aclent->a_type |= ACL_DEFAULT; + else + r = -1; + break; + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unsupported ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + + if (r != 0) { + errno = EINVAL; + archive_set_error(a, errno, + "Failed to set ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + perm_map_size = acl_nfs4_perm_map_size; + perm_map = acl_nfs4_perm_map; + } else { +#endif + perm_map_size = acl_posix_perm_map_size; + perm_map = acl_posix_perm_map; +#if ARCHIVE_ACL_SUNOS_NFS4 + } +#endif + for (i = 0; i < perm_map_size; ++i) { + if (ae_permset & perm_map[i].a_perm) { +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == + ARCHIVE_ENTRY_ACL_TYPE_NFS4) + ace->a_access_mask |= + perm_map[i].p_perm; + else +#endif + aclent->a_perm |= perm_map[i].p_perm; + } + } + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + for (i = 0; i < acl_nfs4_flag_map_size; ++i) { + if (ae_permset & acl_nfs4_flag_map[i].a_perm) { + ace->a_flags |= + acl_nfs4_flag_map[i].p_perm; + } + } + } +#endif + e++; + } + + /* Try restoring the ACL through 'fd' if we can. */ + if (fd >= 0) { + if (facl(fd, cmd, entries, aclp) == 0) + ret = ARCHIVE_OK; + else { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, + "Failed to set acl on fd: %s", tname); + ret = ARCHIVE_WARN; + } + } + } else if (acl(name, cmd, entries, aclp) != 0) { + if (errno == EOPNOTSUPP) { + /* Filesystem doesn't support ACLs */ + ret = ARCHIVE_OK; + } else { + archive_set_error(a, errno, "Failed to set acl: %s", + tname); + ret = ARCHIVE_WARN; + } + } +exit_free: + free(aclp); + return (ret); +} + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *accpath; + void *aclp; + int aclcnt; + int r; + + accpath = NULL; + + if (*fd < 0) { + accpath = archive_read_disk_entry_setup_path(a, entry, fd); + if (accpath == NULL) + return (ARCHIVE_WARN); + } + + archive_entry_acl_clear(entry); + + aclp = NULL; + +#if ARCHIVE_ACL_SUNOS_NFS4 + if (*fd >= 0) + aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + aclp = NULL; + else + aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath); + + if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, + archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)), + &r) == 0 && r == 1) { + free(aclp); + aclp = NULL; + return (ARCHIVE_OK); + } + + if (aclp != NULL) { + r = translate_acl(a, entry, aclp, aclcnt, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + free(aclp); + aclp = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate NFSv4 ACLs"); + } + return (r); + } +#endif /* ARCHIVE_ACL_SUNOS_NFS4 */ + + /* Retrieve POSIX.1e ACLs from file. */ + if (*fd >= 0) + aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL); + else if ((!a->follow_symlinks) + && (archive_entry_filetype(entry) == AE_IFLNK)) + /* We can't get the ACL of a symlink, so we assume it can't + have one. */ + aclp = NULL; + else + aclp = sunacl_get(GETACL, &aclcnt, 0, accpath); + + /* Ignore "trivial" ACLs that just mirror the file mode. */ + if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt, + archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)), + &r) == 0 && r == 1) { + free(aclp); + aclp = NULL; + } + + if (aclp != NULL) + { + r = translate_acl(a, entry, aclp, aclcnt, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + free(aclp); + aclp = NULL; + + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, errno, + "Couldn't translate access ACLs"); + return (r); + } + } + + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + int ret = ARCHIVE_OK; + + (void)mode; /* UNUSED */ + + 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, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e"); + + /* Simultaneous POSIX.1e and NFSv4 is not supported */ + return (ret); + } +#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, + ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); + } +#endif + return (ret); +} +#endif /* ARCHIVE_ACL_SUNOS */ diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.3 b/Utilities/cmlibarchive/libarchive/archive_entry.3 index f5e22af..f75916c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd Feburary 2, 2012 +.Dd February 2, 2012 .Dt ARCHIVE_ENTRY 3 .Os .Sh NAME diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.c b/Utilities/cmlibarchive/libarchive/archive_entry.c index 10eff11..30fb456 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry.c @@ -401,7 +401,7 @@ archive_entry_fflags_text(struct archive_entry *entry) return (NULL); } -int64_t +la_int64_t archive_entry_gid(struct archive_entry *entry) { return (entry->ae_stat.aest_gid); @@ -502,7 +502,7 @@ _archive_entry_hardlink_l(struct archive_entry *entry, return (archive_mstring_get_mbs_l(&entry->ae_hardlink, p, len, sc)); } -int64_t +la_int64_t archive_entry_ino(struct archive_entry *entry) { return (entry->ae_stat.aest_ino); @@ -514,7 +514,7 @@ archive_entry_ino_is_set(struct archive_entry *entry) return (entry->ae_set & AE_SET_INO); } -int64_t +la_int64_t archive_entry_ino64(struct archive_entry *entry) { return (entry->ae_stat.aest_ino); @@ -627,7 +627,7 @@ archive_entry_rdevminor(struct archive_entry *entry) return minor(entry->ae_stat.aest_rdev); } -int64_t +la_int64_t archive_entry_size(struct archive_entry *entry) { return (entry->ae_stat.aest_size); @@ -715,7 +715,7 @@ _archive_entry_symlink_l(struct archive_entry *entry, return (archive_mstring_get_mbs_l( &entry->ae_symlink, p, len, sc)); } -int64_t +la_int64_t archive_entry_uid(struct archive_entry *entry) { return (entry->ae_stat.aest_uid); @@ -819,7 +819,7 @@ archive_entry_copy_fflags_text_w(struct archive_entry *entry, } void -archive_entry_set_gid(struct archive_entry *entry, int64_t g) +archive_entry_set_gid(struct archive_entry *entry, la_int64_t g) { entry->stat_valid = 0; entry->ae_stat.aest_gid = g; @@ -868,7 +868,7 @@ _archive_entry_copy_gname_l(struct archive_entry *entry, } void -archive_entry_set_ino(struct archive_entry *entry, int64_t ino) +archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino) { entry->stat_valid = 0; entry->ae_set |= AE_SET_INO; @@ -876,7 +876,7 @@ archive_entry_set_ino(struct archive_entry *entry, int64_t ino) } void -archive_entry_set_ino64(struct archive_entry *entry, int64_t ino) +archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino) { entry->stat_valid = 0; entry->ae_set |= AE_SET_INO; @@ -1209,7 +1209,7 @@ archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) } void -archive_entry_set_size(struct archive_entry *entry, int64_t s) +archive_entry_set_size(struct archive_entry *entry, la_int64_t s) { entry->stat_valid = 0; entry->ae_stat.aest_size = s; @@ -1306,7 +1306,7 @@ _archive_entry_copy_symlink_l(struct archive_entry *entry, } void -archive_entry_set_uid(struct archive_entry *entry, int64_t u) +archive_entry_set_uid(struct archive_entry *entry, la_int64_t u) { entry->stat_valid = 0; entry->ae_stat.aest_uid = u; @@ -1638,7 +1638,7 @@ _archive_entry_acl_text_l(struct archive_entry *entry, int flags, * SUCH DAMAGE. */ -static struct flag { +static const struct flag { const char *name; const wchar_t *wname; unsigned long set; @@ -1708,6 +1708,9 @@ static struct flag { #ifdef UF_COMPRESSED { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 }, #endif +#ifdef UF_HIDDEN + { "nohidden", L"nohidden", UF_HIDDEN, 0 }, +#endif #if defined(FS_UNRM_FL) { "nouunlink", L"nouunlink", FS_UNRM_FL, 0}, #elif defined(EXT2_UNRM_FL) @@ -1840,7 +1843,7 @@ ae_fflagstostr(unsigned long bitset, unsigned long bitclear) char *string, *dp; const char *sp; unsigned long bits; - struct flag *flag; + const struct flag *flag; size_t length; bits = bitset | bitclear; @@ -1892,7 +1895,7 @@ static const char * ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp) { const char *start, *end; - struct flag *flag; + const struct flag *flag; unsigned long set, clear; const char *failed; @@ -1960,7 +1963,7 @@ static const wchar_t * ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) { const wchar_t *start, *end; - struct flag *flag; + const struct flag *flag; unsigned long set, clear; const wchar_t *failed; diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index 6e0225b..8c8e75a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -30,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3003001 +#define ARCHIVE_VERSION_NUMBER 3003002 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 index c5115f7..534dbfa 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_acl.3 @@ -32,7 +32,7 @@ .Nm archive_entry_acl_clear , .Nm archive_entry_acl_count , .Nm archive_entry_acl_from_text , -.Nm archive_entry_acl_from_text_w, +.Nm archive_entry_acl_from_text_w , .Nm archive_entry_acl_next , .Nm archive_entry_acl_next_w , .Nm archive_entry_acl_reset , @@ -267,7 +267,7 @@ Only inherit, do not apply the permission on the directory itself. .It Dv ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT ( Sy n ) Do not propagate inherit flags. Only first-level entries inherit ACLs. .It Dv ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS ( Sy S ) -Trigger alarm or audit on succesful access. +Trigger alarm or audit on successful access. .It Dv ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS ( Sy F ) Trigger alarm or audit on failed access. .It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERITED ( Sy I ) @@ -279,7 +279,7 @@ and .Fn archive_entry_acl_add_entry_w add a single ACL entry. For the access ACL and non-extended principals, the classic Unix permissions -are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL +are updated. An archive entry cannot contain both POSIX.1e and NFSv4 ACL entries. .Pp .Fn archive_entry_acl_clear @@ -303,7 +303,7 @@ for POSIX.1e ACLs and for NFSv4 ACLs. For POSIX.1e ACLs if .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS is included and at least one extended ACL entry is found, -the three non-extened ACLs are added. +the three non-extended ACLs are added. .Pp .Fn archive_entry_acl_from_text and @@ -367,7 +367,7 @@ and .Fn archive_entry_acl_to_text_w convert the ACL entries for the given type into a .Pq wide -string of ACL entries separated by newline. If the the pointer +string of ACL entries separated by newline. If the pointer .Fa len_p is not NULL, then the function shall return the length of the string .Pq not including the NULL terminator diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 b/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 index fd22cf7..f647212 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_paths.3 @@ -31,25 +31,25 @@ .Nm archive_entry_set_hardlink , .Nm archive_entry_copy_hardlink , .Nm archive_entry_copy_hardlink_w , -.Nm archve_entry_update_hardlink_utf8 , +.Nm archive_entry_update_hardlink_utf8 , .Nm archive_entry_set_link , .Nm archive_entry_copy_link , .Nm archive_entry_copy_link_w , -.Nm archve_entry_update_link_utf8 , +.Nm archive_entry_update_link_utf8 , .Nm archive_entry_pathname , .Nm archive_entry_pathname_w , .Nm archive_entry_set_pathname , .Nm archive_entry_copy_pathname , .Nm archive_entry_copy_pathname_w , -.Nm archve_entry_update_pathname_utf8 , +.Nm archive_entry_update_pathname_utf8 , .Nm archive_entry_sourcepath , .Nm archive_entry_copy_sourcepath , -.Nm archive_entry_symlink, -.Nm archive_entry_symlink_w, +.Nm archive_entry_symlink , +.Nm archive_entry_symlink_w , .Nm archive_entry_set_symlink , .Nm archive_entry_copy_symlink , .Nm archive_entry_copy_symlink_w , -.Nm archve_entry_update_symlink_utf8 +.Nm archive_entry_update_symlink_utf8 .Nd functions for manipulating path names in archive entry descriptions .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 b/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 index 340c5ea..aae3648 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 +++ b/Utilities/cmlibarchive/libarchive/archive_entry_perms.3 @@ -34,8 +34,8 @@ .Nm archive_entry_perm , .Nm archive_entry_set_perm , .Nm archive_entry_strmode , -.Nm archive_entry_uname -.Nm archive_entry_uname_w +.Nm archive_entry_uname , +.Nm archive_entry_uname_w , .Nm archive_entry_set_uname , .Nm archive_entry_copy_uname , .Nm archive_entry_copy_uname_w , diff --git a/Utilities/cmlibarchive/libarchive/archive_entry_sparse.c b/Utilities/cmlibarchive/libarchive/archive_entry_sparse.c index fed74f5..74917b3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry_sparse.c +++ b/Utilities/cmlibarchive/libarchive/archive_entry_sparse.c @@ -51,7 +51,7 @@ archive_entry_sparse_clear(struct archive_entry *entry) void archive_entry_sparse_add_entry(struct archive_entry *entry, - int64_t offset, int64_t length) + la_int64_t offset, la_int64_t length) { struct ae_sparse *sp; @@ -135,7 +135,7 @@ archive_entry_sparse_reset(struct archive_entry * entry) int archive_entry_sparse_next(struct archive_entry * entry, - int64_t *offset, int64_t *length) + la_int64_t *offset, la_int64_t *length) { if (entry->sparse_p) { *offset = entry->sparse_p->offset; diff --git a/Utilities/cmlibarchive/libarchive/archive_getdate.c b/Utilities/cmlibarchive/libarchive/archive_getdate.c index beb0cba..030c083 100644 --- a/Utilities/cmlibarchive/libarchive/archive_getdate.c +++ b/Utilities/cmlibarchive/libarchive/archive_getdate.c @@ -691,7 +691,7 @@ Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes, time_t Seconds, time_t Timezone, enum DSTMODE DSTmode) { - static int DaysInMonth[12] = { + signed char DaysInMonth[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t Julian; diff --git a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h index 2deeb5f..59f95b8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_openssl_hmac_private.h @@ -28,7 +28,7 @@ #include <openssl/hmac.h> #include <openssl/opensslv.h> -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) #include <stdlib.h> /* malloc, free */ #include <string.h> /* memset */ static inline HMAC_CTX *HMAC_CTX_new(void) diff --git a/Utilities/cmlibarchive/libarchive/archive_pack_dev.c b/Utilities/cmlibarchive/libarchive/archive_pack_dev.c index 6b7b472..098881b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_pack_dev.c +++ b/Utilities/cmlibarchive/libarchive/archive_pack_dev.c @@ -280,7 +280,7 @@ pack_bsdos(int n, unsigned long numbers[], const char **error) /* list of formats and pack functions */ /* this list must be sorted lexically */ -static struct format { +static const struct format { const char *name; pack_t *pack; } formats[] = { diff --git a/Utilities/cmlibarchive/libarchive/archive_platform.h b/Utilities/cmlibarchive/libarchive/archive_platform.h index 47d144b..4cb8f81 100644 --- a/Utilities/cmlibarchive/libarchive/archive_platform.h +++ b/Utilities/cmlibarchive/libarchive/archive_platform.h @@ -148,32 +148,6 @@ #endif /* - * If this platform has <sys/acl.h>, acl_create(), acl_init(), - * acl_set_file(), and ACL_USER, we assume it has the rest of the - * POSIX.1e draft functions used in archive_read_extract.c. - */ -#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE -#if HAVE_ACL_USER -#define HAVE_POSIX_ACL 1 -#elif HAVE_ACL_TYPE_EXTENDED -#define HAVE_DARWIN_ACL 1 -#endif -#endif - -/* - * If this platform has <sys/acl.h>, acl_get(), facl_get(), acl_set(), - * facl_set() and types aclent_t and ace_t it uses Solaris-style ACL functions - */ -#if HAVE_SYS_ACL_H && HAVE_ACL_GET && HAVE_FACL_GET && HAVE_ACL_SET && HAVE_FACL_SET && HAVE_ACLENT_T && HAVE_ACE_T -#define HAVE_SUN_ACL 1 -#endif - -/* Define if platform supports NFSv4 ACLs */ -#if (HAVE_POSIX_ACL && HAVE_ACL_TYPE_NFS4) || HAVE_SUN_ACL || HAVE_DARWIN_ACL -#define HAVE_NFS4_ACL 1 -#endif - -/* * If we can't restore metadata using a file descriptor, then * for compatibility's sake, close files before trying to restore metadata. */ diff --git a/Utilities/cmlibarchive/libarchive/archive_platform_acl.h b/Utilities/cmlibarchive/libarchive/archive_platform_acl.h new file mode 100644 index 0000000..3498f78 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_platform_acl.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +#ifndef ARCHIVE_PLATFORM_ACL_H_INCLUDED +#define ARCHIVE_PLATFORM_ACL_H_INCLUDED + +/* + * Determine what ACL types are supported + */ +#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_SUNOS || ARCHIVE_ACL_LIBACL +#define ARCHIVE_ACL_POSIX1E 1 +#endif + +#if ARCHIVE_ACL_FREEBSD_NFS4 || ARCHIVE_ACL_SUNOS_NFS4 || \ + ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL +#define ARCHIVE_ACL_NFS4 1 +#endif + +#if ARCHIVE_ACL_POSIX1E || ARCHIVE_ACL_NFS4 +#define ARCHIVE_ACL_SUPPORT 1 +#endif + +#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */ diff --git a/Utilities/cmlibarchive/libarchive/archive_platform_xattr.h b/Utilities/cmlibarchive/libarchive/archive_platform_xattr.h new file mode 100644 index 0000000..4edfecf --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_platform_xattr.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2017 Martin Matuska + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +#ifndef ARCHIVE_PLATFORM_XATTR_H_INCLUDED +#define ARCHIVE_PLATFORM_XATTR_H_INCLUDED + +/* + * Determine if we support extended attributes + */ +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_FREEBSD || \ + ARCHIVE_XATTR_AIX +#define ARCHIVE_XATTR_SUPPORT 1 +#endif + +#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */ diff --git a/Utilities/cmlibarchive/libarchive/archive_random.c b/Utilities/cmlibarchive/libarchive/archive_random.c index 90ee7c6..65ea691 100644 --- a/Utilities/cmlibarchive/libarchive/archive_random.c +++ b/Utilities/cmlibarchive/libarchive/archive_random.c @@ -221,7 +221,10 @@ arc4_stir(void) /* * Discard early keystream, as per recommendations in: * "(Not So) Random Shuffles of RC4" by Ilya Mironov. + * As per the Network Operations Division, cryptographic requirements + * published on wikileaks on March 2017. */ + for (i = 0; i < 3072; i++) (void)arc4_getbyte(); arc4_count = 1600000; diff --git a/Utilities/cmlibarchive/libarchive/archive_read.c b/Utilities/cmlibarchive/libarchive/archive_read.c index d1feceb..a642a33 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read.c +++ b/Utilities/cmlibarchive/libarchive/archive_read.c @@ -881,7 +881,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s) len = a->read_data_remaining; if (len > s) len = s; - memcpy(dest, a->read_data_block, len); + if (len) + memcpy(dest, a->read_data_block, len); s -= len; a->read_data_block += len; a->read_data_remaining -= len; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 b/Utilities/cmlibarchive/libarchive/archive_read_disk.3 index 2a5c130..027f63c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk.3 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd December 30, 2016 +.Dd April 3, 2017 .Dt ARCHIVE_READ_DISK 3 .Os .Sh NAME .Nm archive_read_disk_new , +.Nm archive_read_disk_set_behavior , .Nm archive_read_disk_set_symlink_logical , .Nm archive_read_disk_set_symlink_physical , .Nm archive_read_disk_set_symlink_hybrid , @@ -37,10 +38,7 @@ .Nm archive_read_disk_uname , .Nm archive_read_disk_set_uname_lookup , .Nm archive_read_disk_set_gname_lookup , -.Nm archive_read_disk_set_standard_lookup , -.Nm archive_read_close , -.Nm archive_read_finish , -.Nm archive_read_free +.Nm archive_read_disk_set_standard_lookup .Nd functions for reading objects from disk .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -49,6 +47,8 @@ Streaming Archive Library (libarchive, -larchive) .Ft struct archive * .Fn archive_read_disk_new "void" .Ft int +.Fn archive_read_disk_set_behavior "struct archive *" "int" +.Ft int .Fn archive_read_disk_set_symlink_logical "struct archive *" .Ft int .Fn archive_read_disk_set_symlink_physical "struct archive *" @@ -81,12 +81,6 @@ Streaming Archive Library (libarchive, -larchive) .Fa "int fd" .Fa "const struct stat *" .Fc -.Ft int -.Fn archive_read_close "struct archive *" -.Ft int -.Fn archive_read_finish "struct archive *" -.Ft int -.Fn archive_read_free "struct archive *" .Sh DESCRIPTION These functions provide an API for reading information about objects on disk. @@ -98,6 +92,51 @@ objects. Allocates and initializes a .Tn struct archive object suitable for reading object information from disk. +.It Fn archive_read_disk_set_behavior +Configures various behavior options when reading entries from disk. +The flags field consists of a bitwise OR of one or more of the +following values: +.Bl -tag -compact -width "indent" +.It Cm ARCHIVE_READDISK_HONOR_NODUMP +Skip files and directories with the nodump file attribute (file flag) set. +By default, the nodump file atrribute is ignored. +.It Cm ARCHIVE_READDISK_MAC_COPYFILE +Mac OS X specific. Read metadata (ACLs and extended attributes) with +.Xr copyfile 3 . +By default, metadata is read using +.Xr copyfile 3 . +.It Cm ARCHIVE_READDISK_NO_ACL +Do not read Access Control Lists. +By default, ACLs are read from disk. +.It Cm ARCHIVE_READDISK_NO_FFLAGS +Do not read file attributes (file flags). +By default, file attributes are read from disk. +See +.Xr chattr 1 +.Pq Linux +or +.Xr chflags 1 +.Pq FreeBSD, Mac OS X +for more information on file attributes. +.It Cm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS +Do not traverse mount points. +By defaut, moint points are traversed. +.It Cm ARCHIVE_READDISK_NO_XATTR +Do not read extended file attributes (xattrs). +By default, extended file attributes are read from disk. +See +.Xr xattr 7 +.Pq Linux , +.Xr xattr 2 +.Pq Mac OS X , +or +.Xr getextattr 8 +.Pq FreeBSD +for more information on extended file attributes. +.It Cm ARCHIVE_READDISK_RESTORE_ATIME +Restore access time of traversed files. +By default, access time of traversed files is not restored. +.El .It Xo .Fn archive_read_disk_set_symlink_logical , .Fn archive_read_disk_set_symlink_physical , @@ -181,17 +220,6 @@ using the currently registered lookup functions above. This affects the file ownership fields and ACL values in the .Tn struct archive_entry object. -.It Fn archive_read_close -Does nothing for -.Tn archive_read_disk -handles. -.It Fn archive_read_finish -This is a deprecated synonym for -.Fn archive_read_free . -.It Fn archive_read_free -Invokes -.Fn archive_read_close -if it was not invoked manually, then releases all resources. .El More information about the .Va struct archive diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c index b2f1d17..548ba89 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_entry_from_file.c @@ -26,23 +26,14 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $"); +__FBSDID("$FreeBSD"); /* This is the tree-walking code for POSIX systems. */ #if !defined(_WIN32) || defined(__CYGWIN__) #ifdef HAVE_SYS_TYPES_H -/* Mac OSX requires sys/types.h before sys/acl.h. */ #include <sys/types.h> #endif -#ifdef HAVE_SYS_ACL_H -#include <sys/acl.h> -#endif -#ifdef HAVE_DARWIN_ACL -#include <membership.h> -#include <grp.h> -#include <pwd.h> -#endif #ifdef HAVE_SYS_EXTATTR_H #include <sys/extattr.h> #endif @@ -63,9 +54,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #ifdef HAVE_SYS_EA_H #include <sys/ea.h> #endif -#ifdef HAVE_ACL_LIBACL_H -#include <acl/libacl.h> -#endif #ifdef HAVE_COPYFILE_H #include <copyfile.h> #endif @@ -113,27 +101,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #define O_CLOEXEC 0 #endif -/* - * Linux and FreeBSD plug this obvious hole in POSIX.1e in - * different ways. - */ -#if HAVE_ACL_GET_PERM -#define ACL_GET_PERM acl_get_perm -#elif HAVE_ACL_GET_PERM_NP -#define ACL_GET_PERM acl_get_perm_np -#endif - -/* NFSv4 platform ACL type */ -#if HAVE_SUN_ACL -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T -#elif HAVE_DARWIN_ACL -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED -#elif HAVE_ACL_TYPE_NFS4 -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4 -#endif - -static int setup_acls(struct archive_read_disk *, - struct archive_entry *, int *fd); static int setup_mac_metadata(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_xattrs(struct archive_read_disk *, @@ -145,6 +112,45 @@ static int setup_sparse_fiemap(struct archive_read_disk *, struct archive_entry *, int *fd); #endif +#if !ARCHIVE_ACL_SUPPORT +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + (void)a; /* UNUSED */ + (void)entry; /* UNUSED */ + (void)fd; /* UNUSED */ + return (ARCHIVE_OK); +} +#endif + +/* + * Enter working directory and return working pathname of archive_entry. + * If a pointer to an integer is provided and its value is below zero + * open a file descriptor on this pahtname. + */ +const char * +archive_read_disk_entry_setup_path(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + const char *path; + + path = archive_entry_sourcepath(entry); + + if (path == NULL || (a->tree != NULL && + a->tree_enter_working_dir(a->tree) != 0)) + path = archive_entry_pathname(entry); + if (path == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't determine path"); + } else if (fd != NULL && *fd < 0 && a->tree != NULL && + (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) { + *fd = a->open_on_current_dir(a->tree, path, + O_RDONLY | O_NONBLOCK); + } + return (path); +} + int archive_read_disk_entry_from_file(struct archive *_a, struct archive_entry *entry, @@ -279,7 +285,7 @@ archive_read_disk_entry_from_file(struct archive *_a, r = 0; if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) - r = setup_acls(a, entry, &fd); + r = archive_read_disk_entry_setup_acls(a, entry, &fd); if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) { r1 = setup_xattrs(a, entry, &fd); if (r1 < r) @@ -328,19 +334,10 @@ setup_mac_metadata(struct archive_read_disk *a, struct archive_string tempfile; (void)fd; /* UNUSED */ - name = archive_entry_sourcepath(entry); + + name = archive_read_disk_entry_setup_path(a, entry, NULL); if (name == NULL) - name = archive_entry_pathname(entry); - else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Can't change dir to read extended attributes"); - return (ARCHIVE_FAILED); - } - if (name == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Can't open file to read extended attributes: No name"); return (ARCHIVE_WARN); - } /* Short-circuit if there's nothing to do. */ have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); @@ -426,996 +423,10 @@ setup_mac_metadata(struct archive_read_disk *a, } #endif -#if HAVE_DARWIN_ACL -static int translate_guid(struct archive *, acl_entry_t, - int *, int *, const char **); - -static void add_trivial_nfs4_acl(struct archive_entry *); -#endif - -#if HAVE_SUN_ACL -static int -sun_acl_is_trivial(acl_t *, mode_t, int *trivialp); -#endif - -#if HAVE_POSIX_ACL || HAVE_NFS4_ACL -static int translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, -#if HAVE_SUN_ACL - acl_t *acl, -#else - acl_t acl, -#endif - int archive_entry_acl_type); - -static int -setup_acls(struct archive_read_disk *a, - struct archive_entry *entry, int *fd) -{ - const char *accpath; -#if HAVE_SUN_ACL - acl_t *acl; -#else - acl_t acl; -#endif - int r; - - accpath = NULL; - -#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP - if (*fd < 0) -#else - /* For default ACLs on Linux we need reachable accpath */ - if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) -#endif - { - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL || (a->tree != NULL && - a->tree_enter_working_dir(a->tree) != 0)) - accpath = archive_entry_pathname(entry); - if (accpath == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Couldn't determine file path to read ACLs"); - return (ARCHIVE_WARN); - } - if (a->tree != NULL && -#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP - *fd < 0 && -#endif - (a->follow_symlinks || - archive_entry_filetype(entry) != AE_IFLNK)) { - *fd = a->open_on_current_dir(a->tree, - accpath, O_RDONLY | O_NONBLOCK); - } - } - - archive_entry_acl_clear(entry); - - acl = NULL; - -#if HAVE_NFS4_ACL - /* Try NFSv4 ACL first. */ - if (*fd >= 0) -#if HAVE_SUN_ACL - /* Solaris reads both POSIX.1e and NFSv4 ACL here */ - facl_get(*fd, 0, &acl); -#elif HAVE_ACL_GET_FD_NP - acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); -#else - acl = acl_get_fd(*fd); -#endif -#if HAVE_ACL_GET_LINK_NP - else if (!a->follow_symlinks) - acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); -#else - else if ((!a->follow_symlinks) - && (archive_entry_filetype(entry) == AE_IFLNK)) - /* We can't get the ACL of a symlink, so we assume it can't - have one. */ - acl = NULL; -#endif - else -#if HAVE_SUN_ACL - /* Solaris reads both POSIX.1e and NFSv4 ACLs here */ - acl_get(accpath, 0, &acl); -#else - acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); -#endif - - -#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL - /* Ignore "trivial" ACLs that just mirror the file mode. */ - if (acl != NULL) { -#if HAVE_SUN_ACL - if (sun_acl_is_trivial(acl, archive_entry_mode(entry), - &r) == 0 && r == 1) -#elif HAVE_ACL_IS_TRIVIAL_NP - if (acl_is_trivial_np(acl, &r) == 0 && r == 1) -#endif - { - acl_free(acl); - acl = NULL; - /* - * Simultaneous NFSv4 and POSIX.1e ACLs for the same - * entry are not allowed, so we should return here - */ - return (ARCHIVE_OK); - } - } -#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */ - if (acl != NULL) { - r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); - acl_free(acl); - if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, errno, - "Couldn't translate " -#if !HAVE_SUN_ACL - "NFSv4 " -#endif - "ACLs"); - } -#if HAVE_DARWIN_ACL - /* - * Because Mac OS doesn't support owner@, group@ and everyone@ - * ACLs we need to add NFSv4 ACLs mirroring the file mode to - * the archive entry. Otherwise extraction on non-Mac platforms - * would lead to an invalid file mode. - */ - if ((archive_entry_acl_types(entry) & - ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) - add_trivial_nfs4_acl(entry); -#endif - return (r); - } -#endif /* HAVE_NFS4_ACL */ - -#if HAVE_POSIX_ACL - /* This code path is skipped on MacOS and Solaris */ +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX - /* Retrieve access ACL from file. */ - if (*fd >= 0) - acl = acl_get_fd(*fd); -#if HAVE_ACL_GET_LINK_NP - else if (!a->follow_symlinks) - acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); -#else - else if ((!a->follow_symlinks) - && (archive_entry_filetype(entry) == AE_IFLNK)) - /* We can't get the ACL of a symlink, so we assume it can't - have one. */ - acl = NULL; -#endif - else - acl = acl_get_file(accpath, ACL_TYPE_ACCESS); - -#if HAVE_ACL_IS_TRIVIAL_NP - /* Ignore "trivial" ACLs that just mirror the file mode. */ - if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) { - if (r) { - acl_free(acl); - acl = NULL; - } - } -#endif - - if (acl != NULL) { - r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS); - acl_free(acl); - acl = NULL; - if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, errno, - "Couldn't translate access ACLs"); - return (r); - } - } - - /* Only directories can have default ACLs. */ - if (S_ISDIR(archive_entry_mode(entry))) { -#if HAVE_ACL_GET_FD_NP - if (*fd >= 0) - acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); - else -#endif - acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); - if (acl != NULL) { - r = translate_acl(a, entry, acl, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); - acl_free(acl); - if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, errno, - "Couldn't translate default ACLs"); - return (r); - } - } - } -#endif /* HAVE_POSIX_ACL */ - return (ARCHIVE_OK); -} - -/* - * Translate system ACL permissions into libarchive internal structure - */ -static const struct { - const int archive_perm; - const int platform_perm; -} acl_perm_map[] = { -#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */ - {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, - {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} -#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */ - {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, - {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} -#else /* POSIX.1e ACL permissions */ - {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, - {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, - {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, -#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */ - {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} -#endif -#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ -}; - -#if HAVE_NFS4_ACL -/* - * Translate system NFSv4 inheritance flags into libarchive internal structure - */ -static const struct { - const int archive_inherit; - const int platform_inherit; -} acl_inherit_map[] = { -#if HAVE_SUN_ACL /* Solaris ACL inheritance flags */ - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, - {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} -#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */ - {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} -#else /* FreeBSD NFSv4 ACL inheritance flags */ - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, - {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, - {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} -#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ -}; -#endif /* HAVE_NFS4_ACL */ - -#if HAVE_DARWIN_ACL -static int translate_guid(struct archive *a, acl_entry_t acl_entry, - int *ae_id, int *ae_tag, const char **ae_name) -{ - void *q; - uid_t ugid; - int r, idtype; - struct passwd *pwd; - struct group *grp; - - q = acl_get_qualifier(acl_entry); - if (q == NULL) - return (1); - r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); - if (r != 0) { - acl_free(q); - return (1); - } - if (idtype == ID_TYPE_UID) { - *ae_tag = ARCHIVE_ENTRY_ACL_USER; - pwd = getpwuuid(q); - if (pwd == NULL) { - *ae_id = ugid; - *ae_name = NULL; - } else { - *ae_id = pwd->pw_uid; - *ae_name = archive_read_disk_uname(a, *ae_id); - } - } else if (idtype == ID_TYPE_GID) { - *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - grp = getgruuid(q); - if (grp == NULL) { - *ae_id = ugid; - *ae_name = NULL; - } else { - *ae_id = grp->gr_gid; - *ae_name = archive_read_disk_gname(a, *ae_id); - } - } else - r = 1; - - acl_free(q); - return (r); -} - -/* - * Add trivial NFSv4 ACL entries from mode - */ -static void -add_trivial_nfs4_acl(struct archive_entry *entry) -{ - mode_t mode; - int i; - const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; - const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | - ARCHIVE_ENTRY_ACL_APPEND_DATA; - const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; - const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | - ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | - ARCHIVE_ENTRY_ACL_READ_ACL | - ARCHIVE_ENTRY_ACL_SYNCHRONIZE; - const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | - ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | - ARCHIVE_ENTRY_ACL_WRITE_ACL | - ARCHIVE_ENTRY_ACL_WRITE_OWNER; - - struct { - const int type; - const int tag; - int permset; - } tacl_entry[] = { - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, - {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, - {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, - {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} - }; - - mode = archive_entry_mode(entry); - - /* Permissions for everyone@ */ - if (mode & 0004) - tacl_entry[5].permset |= rperm; - if (mode & 0002) - tacl_entry[5].permset |= wperm; - if (mode & 0001) - tacl_entry[5].permset |= eperm; - - /* Permissions for group@ */ - if (mode & 0040) - tacl_entry[4].permset |= rperm; - else if (mode & 0004) - tacl_entry[2].permset |= rperm; - if (mode & 0020) - tacl_entry[4].permset |= wperm; - else if (mode & 0002) - tacl_entry[2].permset |= wperm; - if (mode & 0010) - tacl_entry[4].permset |= eperm; - else if (mode & 0001) - tacl_entry[2].permset |= eperm; - - /* Permissions for owner@ */ - if (mode & 0400) { - tacl_entry[3].permset |= rperm; - if (!(mode & 0040) && (mode & 0004)) - tacl_entry[0].permset |= rperm; - } else if ((mode & 0040) || (mode & 0004)) - tacl_entry[1].permset |= rperm; - if (mode & 0200) { - tacl_entry[3].permset |= wperm; - if (!(mode & 0020) && (mode & 0002)) - tacl_entry[0].permset |= wperm; - } else if ((mode & 0020) || (mode & 0002)) - tacl_entry[1].permset |= wperm; - if (mode & 0100) { - tacl_entry[3].permset |= eperm; - if (!(mode & 0010) && (mode & 0001)) - tacl_entry[0].permset |= eperm; - } else if ((mode & 0010) || (mode & 0001)) - tacl_entry[1].permset |= eperm; - - for (i = 0; i < 6; i++) { - if (tacl_entry[i].permset != 0) { - archive_entry_acl_add_entry(entry, - tacl_entry[i].type, tacl_entry[i].permset, - tacl_entry[i].tag, -1, NULL); - } - } - - return; -} -#elif HAVE_SUN_ACL -/* - * Check if acl is trivial - * This is a FreeBSD acl_is_trivial_np() implementation for Solaris - */ -static int -sun_acl_is_trivial(acl_t *acl, mode_t mode, int *trivialp) -{ - int i, p; - const uint32_t rperm = ACE_READ_DATA; - const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; - const uint32_t eperm = ACE_EXECUTE; - const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | - ACE_READ_ACL | ACE_SYNCHRONIZE; - const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | - ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; - - ace_t *ace; - ace_t tace[6]; - - if (acl == NULL || trivialp == NULL) - return (-1); - - *trivialp = 0; - - /* ACL_IS_TRIVIAL flag must be set for both POSIX.1e and NFSv4 ACLs */ - if ((acl->acl_flags & ACL_IS_TRIVIAL) == 0) - return (0); - - /* - * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with - * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, - * including mask. - */ - if (acl->acl_type == ACLENT_T) { - if (acl->acl_cnt == 4) - *trivialp = 1; - return (0); - } - - if (acl->acl_type != ACE_T || acl->acl_entry_size != sizeof(ace_t)) - return (-1); - - /* - * Continue with checking NFSv4 ACLs - * - * Create list of trivial ace's to be compared - */ - - /* owner@ allow pre */ - tace[0].a_flags = ACE_OWNER; - tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[0].a_access_mask = 0; - - /* owner@ deny */ - tace[1].a_flags = ACE_OWNER; - tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; - tace[1].a_access_mask = 0; - - /* group@ deny */ - tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; - tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; - tace[2].a_access_mask = 0; - - /* owner@ allow */ - tace[3].a_flags = ACE_OWNER; - tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[3].a_access_mask = ownset; - - /* group@ allow */ - tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; - tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[4].a_access_mask = pubset; - - /* everyone@ allow */ - tace[5].a_flags = ACE_EVERYONE; - tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - tace[5].a_access_mask = pubset; - - /* Permissions for everyone@ */ - if (mode & 0004) - tace[5].a_access_mask |= rperm; - if (mode & 0002) - tace[5].a_access_mask |= wperm; - if (mode & 0001) - tace[5].a_access_mask |= eperm; - - /* Permissions for group@ */ - if (mode & 0040) - tace[4].a_access_mask |= rperm; - else if (mode & 0004) - tace[2].a_access_mask |= rperm; - if (mode & 0020) - tace[4].a_access_mask |= wperm; - else if (mode & 0002) - tace[2].a_access_mask |= wperm; - if (mode & 0010) - tace[4].a_access_mask |= eperm; - else if (mode & 0001) - tace[2].a_access_mask |= eperm; - - /* Permissions for owner@ */ - if (mode & 0400) { - tace[3].a_access_mask |= rperm; - if (!(mode & 0040) && (mode & 0004)) - tace[0].a_access_mask |= rperm; - } else if ((mode & 0040) || (mode & 0004)) - tace[1].a_access_mask |= rperm; - if (mode & 0200) { - tace[3].a_access_mask |= wperm; - if (!(mode & 0020) && (mode & 0002)) - tace[0].a_access_mask |= wperm; - } else if ((mode & 0020) || (mode & 0002)) - tace[1].a_access_mask |= wperm; - if (mode & 0100) { - tace[3].a_access_mask |= eperm; - if (!(mode & 0010) && (mode & 0001)) - tace[0].a_access_mask |= eperm; - } else if ((mode & 0010) || (mode & 0001)) - tace[1].a_access_mask |= eperm; - - /* Check if the acl count matches */ - p = 3; - for (i = 0; i < 3; i++) { - if (tace[i].a_access_mask != 0) - p++; - } - if (acl->acl_cnt != p) - return (0); - - p = 0; - for (i = 0; i < 6; i++) { - if (tace[i].a_access_mask != 0) { - ace = &((ace_t *)acl->acl_aclp)[p]; - /* - * Illumos added ACE_DELETE_CHILD to write perms for - * directories. We have to check against that, too. - */ - if (ace->a_flags != tace[i].a_flags || - ace->a_type != tace[i].a_type || - (ace->a_access_mask != tace[i].a_access_mask && - ((acl->acl_flags & ACL_IS_DIR) == 0 || - (tace[i].a_access_mask & wperm) == 0 || - ace->a_access_mask != - (tace[i].a_access_mask | ACE_DELETE_CHILD)))) - return (0); - p++; - } - } - - *trivialp = 1; - return (0); -} -#endif /* HAVE_SUN_ACL */ - -#if HAVE_SUN_ACL /* - * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL - */ -static int -translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, acl_t *acl, int default_entry_acl_type) -{ - int e, i; - int ae_id, ae_tag, ae_perm; - int entry_acl_type; - const char *ae_name; - aclent_t *aclent; - ace_t *ace; - - (void)default_entry_acl_type; - - if (acl->acl_cnt <= 0) - return (ARCHIVE_OK); - - for (e = 0; e < acl->acl_cnt; e++) { - ae_name = NULL; - ae_tag = 0; - ae_perm = 0; - - if (acl->acl_type == ACE_T) { - ace = &((ace_t *)acl->acl_aclp)[e]; - ae_id = ace->a_who; - - switch(ace->a_type) { - case ACE_ACCESS_ALLOWED_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; - break; - case ACE_ACCESS_DENIED_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; - break; - case ACE_SYSTEM_AUDIT_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - break; - case ACE_SYSTEM_ALARM_ACE_TYPE: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; - break; - default: - /* Unknown entry type, skip */ - continue; - } - - if ((ace->a_flags & ACE_OWNER) != 0) - ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - else if ((ace->a_flags & ACE_GROUP) != 0) - ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - else if ((ace->a_flags & ACE_EVERYONE) != 0) - ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; - else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { - ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - ae_name = archive_read_disk_gname(&a->archive, - ae_id); - } else { - ae_tag = ARCHIVE_ENTRY_ACL_USER; - ae_name = archive_read_disk_uname(&a->archive, - ae_id); - } - - for (i = 0; i < (int)(sizeof(acl_inherit_map) / - sizeof(acl_inherit_map[0])); ++i) { - if ((ace->a_flags & - acl_inherit_map[i].platform_inherit) != 0) - ae_perm |= - acl_inherit_map[i].archive_inherit; - } - - for (i = 0; i < (int)(sizeof(acl_perm_map) / - sizeof(acl_perm_map[0])); ++i) { - if ((ace->a_access_mask & - acl_perm_map[i].platform_perm) != 0) - ae_perm |= - acl_perm_map[i].archive_perm; - } - } else { - aclent = &((aclent_t *)acl->acl_aclp)[e]; - if ((aclent->a_type & ACL_DEFAULT) != 0) - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - else - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; - ae_id = aclent->a_id; - - switch(aclent->a_type) { - case DEF_USER: - case USER: - ae_name = archive_read_disk_uname(&a->archive, - ae_id); - ae_tag = ARCHIVE_ENTRY_ACL_USER; - break; - case DEF_GROUP: - case GROUP: - ae_name = archive_read_disk_gname(&a->archive, - ae_id); - ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - break; - case DEF_CLASS_OBJ: - case CLASS_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_MASK; - break; - case DEF_USER_OBJ: - case USER_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - break; - case DEF_GROUP_OBJ: - case GROUP_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - break; - case DEF_OTHER_OBJ: - case OTHER_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_OTHER; - break; - default: - /* Unknown tag type, skip */ - continue; - } - - if ((aclent->a_perm & 1) != 0) - ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; - if ((aclent->a_perm & 2) != 0) - ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; - if ((aclent->a_perm & 4) != 0) - ae_perm |= ARCHIVE_ENTRY_ACL_READ; - } /* default_entry_acl_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ - - archive_entry_acl_add_entry(entry, entry_acl_type, - ae_perm, ae_tag, ae_id, ae_name); - } - return (ARCHIVE_OK); -} -#else /* !HAVE_SUN_ACL */ -/* - * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and - * MacOS (NFSv4 only) ACLs into libarchive internal structure - */ -static int -translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, acl_t acl, int default_entry_acl_type) -{ - acl_tag_t acl_tag; -#if HAVE_ACL_TYPE_NFS4 - acl_entry_type_t acl_type; - int brand; -#endif -#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL - acl_flagset_t acl_flagset; -#endif - acl_entry_t acl_entry; - acl_permset_t acl_permset; - int i, entry_acl_type; - int r, s, ae_id, ae_tag, ae_perm; -#if !HAVE_DARWIN_ACL - void *q; -#endif - const char *ae_name; - -#if HAVE_ACL_TYPE_NFS4 - // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 - // Make sure the "brand" on this ACL is consistent - // with the default_entry_acl_type bits provided. - if (acl_get_brand_np(acl, &brand) != 0) { - archive_set_error(&a->archive, errno, - "Failed to read ACL brand"); - return (ARCHIVE_WARN); - } - switch (brand) { - case ACL_BRAND_POSIX: - switch (default_entry_acl_type) { - case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: - case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: - break; - default: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Invalid ACL entry type for POSIX.1e ACL"); - return (ARCHIVE_WARN); - } - break; - case ACL_BRAND_NFS4: - if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Invalid ACL entry type for NFSv4 ACL"); - return (ARCHIVE_WARN); - } - break; - default: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unknown ACL brand"); - return (ARCHIVE_WARN); - } -#endif - - s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); - if (s == -1) { - archive_set_error(&a->archive, errno, - "Failed to get first ACL entry"); - return (ARCHIVE_WARN); - } - -#if HAVE_DARWIN_ACL - while (s == 0) -#else /* FreeBSD, Linux */ - while (s == 1) -#endif - { - ae_id = -1; - ae_name = NULL; - ae_perm = 0; - - if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { - archive_set_error(&a->archive, errno, - "Failed to get ACL tag type"); - return (ARCHIVE_WARN); - } - switch (acl_tag) { -#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ - case ACL_USER: - q = acl_get_qualifier(acl_entry); - if (q != NULL) { - ae_id = (int)*(uid_t *)q; - acl_free(q); - ae_name = archive_read_disk_uname(&a->archive, - ae_id); - } - ae_tag = ARCHIVE_ENTRY_ACL_USER; - break; - case ACL_GROUP: - q = acl_get_qualifier(acl_entry); - if (q != NULL) { - ae_id = (int)*(gid_t *)q; - acl_free(q); - ae_name = archive_read_disk_gname(&a->archive, - ae_id); - } - ae_tag = ARCHIVE_ENTRY_ACL_GROUP; - break; - case ACL_MASK: - ae_tag = ARCHIVE_ENTRY_ACL_MASK; - break; - case ACL_USER_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - break; - case ACL_GROUP_OBJ: - ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - break; - case ACL_OTHER: - ae_tag = ARCHIVE_ENTRY_ACL_OTHER; - break; -#if HAVE_ACL_TYPE_NFS4 - case ACL_EVERYONE: - ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; - break; -#endif -#else /* HAVE_DARWIN_ACL */ - case ACL_EXTENDED_ALLOW: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; - r = translate_guid(&a->archive, acl_entry, &ae_id, - &ae_tag, &ae_name); - break; - case ACL_EXTENDED_DENY: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; - r = translate_guid(&a->archive, acl_entry, &ae_id, - &ae_tag, &ae_name); - break; -#endif /* HAVE_DARWIN_ACL */ - default: - /* Skip types that libarchive can't support. */ - s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); - continue; - } - -#if HAVE_DARWIN_ACL - /* Skip if translate_guid() above failed */ - if (r != 0) { - s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); - continue; - } -#endif - -#if !HAVE_DARWIN_ACL - // XXX acl_type maps to allow/deny/audit/YYYY bits - entry_acl_type = default_entry_acl_type; -#endif -#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL - if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { -#if HAVE_ACL_TYPE_NFS4 - /* - * acl_get_entry_type_np() fails with non-NFSv4 ACLs - */ - if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { - archive_set_error(&a->archive, errno, "Failed " - "to get ACL type from a NFSv4 ACL entry"); - return (ARCHIVE_WARN); - } - switch (acl_type) { - case ACL_ENTRY_TYPE_ALLOW: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; - break; - case ACL_ENTRY_TYPE_DENY: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; - break; - case ACL_ENTRY_TYPE_AUDIT: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; - break; - case ACL_ENTRY_TYPE_ALARM: - entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; - break; - default: - archive_set_error(&a->archive, errno, - "Invalid NFSv4 ACL entry type"); - return (ARCHIVE_WARN); - } -#endif /* HAVE_ACL_TYPE_NFS4 */ - - /* - * Libarchive stores "flag" (NFSv4 inheritance bits) - * in the ae_perm bitmap. - * - * acl_get_flagset_np() fails with non-NFSv4 ACLs - */ - if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { - archive_set_error(&a->archive, errno, - "Failed to get flagset from a NFSv4 ACL entry"); - return (ARCHIVE_WARN); - } - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - r = acl_get_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit); - if (r == -1) { - archive_set_error(&a->archive, errno, - "Failed to check flag in a NFSv4 " - "ACL flagset"); - return (ARCHIVE_WARN); - } else if (r) - ae_perm |= acl_inherit_map[i].archive_inherit; - } - } -#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL */ - - if (acl_get_permset(acl_entry, &acl_permset) != 0) { - archive_set_error(&a->archive, errno, - "Failed to get ACL permission set"); - return (ARCHIVE_WARN); - } - for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { - /* - * acl_get_perm() is spelled differently on different - * platforms; see above. - */ - r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm); - if (r == -1) { - archive_set_error(&a->archive, errno, - "Failed to check permission in an ACL permission set"); - return (ARCHIVE_WARN); - } else if (r) - ae_perm |= acl_perm_map[i].archive_perm; - } - - archive_entry_acl_add_entry(entry, entry_acl_type, - ae_perm, ae_tag, - ae_id, ae_name); - - s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); -#if !HAVE_DARWIN_ACL - if (s == -1) { - archive_set_error(&a->archive, errno, - "Failed to get next ACL entry"); - return (ARCHIVE_WARN); - } -#endif - } - return (ARCHIVE_OK); -} -#endif /* !HAVE_SUN_ACL */ -#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ -static int -setup_acls(struct archive_read_disk *a, - struct archive_entry *entry, int *fd) -{ - (void)a; /* UNUSED */ - (void)entry; /* UNUSED */ - (void)fd; /* UNUSED */ - return (ARCHIVE_OK); -} -#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ - -#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ - HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ - (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA) - -/* - * Linux and AIX extended attribute support. + * Linux, Darwin and AIX extended attribute support. * * TODO: By using a stack-allocated buffer for the first * call to getxattr(), we might be able to avoid the second @@ -1433,21 +444,32 @@ setup_xattr(struct archive_read_disk *a, ssize_t size; void *value = NULL; -#if HAVE_FGETXATTR - if (fd >= 0) + + if (fd >= 0) { +#if ARCHIVE_XATTR_LINUX size = fgetxattr(fd, name, NULL, 0); - else if (!a->follow_symlinks) - size = lgetxattr(accpath, name, NULL, 0); - else - size = getxattr(accpath, name, NULL, 0); -#elif HAVE_FGETEA - if (fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + size = fgetxattr(fd, name, NULL, 0, 0, 0); +#elif ARCHIVE_XATTR_AIX size = fgetea(fd, name, NULL, 0); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(accpath, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, NULL, 0, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX size = lgetea(accpath, name, NULL, 0); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + size = getxattr(accpath, name, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, NULL, 0, 0, 0); +#elif ARCHIVE_XATTR_AIX size = getea(accpath, name, NULL, 0); #endif + } if (size == -1) { archive_set_error(&a->archive, errno, @@ -1460,21 +482,32 @@ setup_xattr(struct archive_read_disk *a, return (ARCHIVE_FATAL); } -#if HAVE_FGETXATTR - if (fd >= 0) + + if (fd >= 0) { +#if ARCHIVE_XATTR_LINUX size = fgetxattr(fd, name, value, size); - else if (!a->follow_symlinks) - size = lgetxattr(accpath, name, value, size); - else - size = getxattr(accpath, name, value, size); -#elif HAVE_FGETEA - if (fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + size = fgetxattr(fd, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX size = fgetea(fd, name, value, size); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + size = lgetxattr(accpath, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX size = lgetea(accpath, name, value, size); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + size = getxattr(accpath, name, value, size); +#elif ARCHIVE_XATTR_DARWIN + size = getxattr(accpath, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX size = getea(accpath, name, value, size); #endif + } if (size == -1) { archive_set_error(&a->archive, errno, @@ -1499,38 +532,36 @@ setup_xattrs(struct archive_read_disk *a, path = NULL; if (*fd < 0) { - path = archive_entry_sourcepath(entry); - if (path == NULL || (a->tree != NULL && - a->tree_enter_working_dir(a->tree) != 0)) - path = archive_entry_pathname(entry); - if (path == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Couldn't determine file path to read " - "extended attributes"); + path = archive_read_disk_entry_setup_path(a, entry, fd); + if (path == NULL) return (ARCHIVE_WARN); - } - if (a->tree != NULL && (a->follow_symlinks || - archive_entry_filetype(entry) != AE_IFLNK)) { - *fd = a->open_on_current_dir(a->tree, - path, O_RDONLY | O_NONBLOCK); - } } -#if HAVE_FLISTXATTR - if (*fd >= 0) + if (*fd >= 0) { +#if ARCHIVE_XATTR_LINUX list_size = flistxattr(*fd, NULL, 0); - else if (!a->follow_symlinks) - list_size = llistxattr(path, NULL, 0); - else - list_size = listxattr(path, NULL, 0); -#elif HAVE_FLISTEA - if (*fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + list_size = flistxattr(*fd, NULL, 0, 0); +#elif ARCHIVE_XATTR_AIX list_size = flistea(*fd, NULL, 0); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + list_size = llistxattr(path, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, NULL, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX list_size = llistea(path, NULL, 0); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + list_size = listxattr(path, NULL, 0); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, NULL, 0, 0); +#elif ARCHIVE_XATTR_AIX list_size = listea(path, NULL, 0); #endif + } if (list_size == -1) { if (errno == ENOTSUP || errno == ENOSYS) @@ -1548,21 +579,31 @@ setup_xattrs(struct archive_read_disk *a, return (ARCHIVE_FATAL); } -#if HAVE_FLISTXATTR - if (*fd >= 0) + if (*fd >= 0) { +#if ARCHIVE_XATTR_LINUX list_size = flistxattr(*fd, list, list_size); - else if (!a->follow_symlinks) - list_size = llistxattr(path, list, list_size); - else - list_size = listxattr(path, list, list_size); -#elif HAVE_FLISTEA - if (*fd >= 0) +#elif ARCHIVE_XATTR_DARWIN + list_size = flistxattr(*fd, list, list_size, 0); +#elif ARCHIVE_XATTR_AIX list_size = flistea(*fd, list, list_size); - else if (!a->follow_symlinks) +#endif + } else if (!a->follow_symlinks) { +#if ARCHIVE_XATTR_LINUX + list_size = llistxattr(path, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, list, list_size, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX list_size = llistea(path, list, list_size); - else +#endif + } else { +#if ARCHIVE_XATTR_LINUX + list_size = listxattr(path, list, list_size); +#elif ARCHIVE_XATTR_DARWIN + list_size = listxattr(path, list, list_size, 0); +#elif ARCHIVE_XATTR_AIX list_size = listea(path, list, list_size); #endif + } if (list_size == -1) { archive_set_error(&a->archive, errno, @@ -1572,9 +613,21 @@ setup_xattrs(struct archive_read_disk *a, } for (p = list; (p - list) < list_size; p += strlen(p) + 1) { - if (strncmp(p, "system.", 7) == 0 || - strncmp(p, "xfsroot.", 8) == 0) +#if ARCHIVE_XATTR_LINUX + /* Linux: skip POSIX.1e ACL extended attributes */ + if (strncmp(p, "system.", 7) == 0 && + (strcmp(p + 7, "posix_acl_access") == 0 || + strcmp(p + 7, "posix_acl_default") == 0)) + continue; + if (strncmp(p, "trusted.SGI_", 12) == 0 && + (strcmp(p + 12, "ACL_DEFAULT") == 0 || + strcmp(p + 12, "ACL_FILE") == 0)) + continue; + + /* Linux: xfsroot namespace is obsolete and unsupported */ + if (strncmp(p, "xfsroot.", 8) == 0) continue; +#endif setup_xattr(a, entry, p, *fd, path); } @@ -1582,8 +635,7 @@ setup_xattrs(struct archive_read_disk *a, return (ARCHIVE_OK); } -#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \ - HAVE_DECL_EXTATTR_NAMESPACE_USER +#elif ARCHIVE_XATTR_FREEBSD /* * FreeBSD extattr interface. @@ -1658,21 +710,9 @@ setup_xattrs(struct archive_read_disk *a, path = NULL; if (*fd < 0) { - path = archive_entry_sourcepath(entry); - if (path == NULL || (a->tree != NULL && - a->tree_enter_working_dir(a->tree) != 0)) - path = archive_entry_pathname(entry); - if (path == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Couldn't determine file path to read " - "extended attributes"); + path = archive_read_disk_entry_setup_path(a, entry, fd); + if (path == NULL) return (ARCHIVE_WARN); - } - if (a->tree != NULL && (a->follow_symlinks || - archive_entry_filetype(entry) != AE_IFLNK)) { - *fd = a->open_on_current_dir(a->tree, - path, O_RDONLY | O_NONBLOCK); - } } if (*fd >= 0) @@ -1773,6 +813,7 @@ setup_sparse_fiemap(struct archive_read_disk *a, int64_t size; int count, do_fiemap, iters; int exit_sts = ARCHIVE_OK; + const char *path; if (archive_entry_filetype(entry) != AE_IFREG || archive_entry_size(entry) <= 0 @@ -1780,11 +821,10 @@ setup_sparse_fiemap(struct archive_read_disk *a, return (ARCHIVE_OK); if (*fd < 0) { - const char *path; - - path = archive_entry_sourcepath(entry); + path = archive_read_disk_entry_setup_path(a, entry, NULL); if (path == NULL) - path = archive_entry_pathname(entry); + return (ARCHIVE_FAILED); + if (a->tree != NULL) *fd = a->open_on_current_dir(a->tree, path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); @@ -1880,6 +920,7 @@ setup_sparse(struct archive_read_disk *a, off_t off_s, off_e; int exit_sts = ARCHIVE_OK; int check_fully_sparse = 0; + const char *path; if (archive_entry_filetype(entry) != AE_IFREG || archive_entry_size(entry) <= 0 @@ -1887,20 +928,10 @@ setup_sparse(struct archive_read_disk *a, return (ARCHIVE_OK); /* Does filesystem support the reporting of hole ? */ - if (*fd < 0 && a->tree != NULL) { - const char *path; - - path = archive_entry_sourcepath(entry); - if (path == NULL) - path = archive_entry_pathname(entry); - *fd = a->open_on_current_dir(a->tree, path, - O_RDONLY | O_NONBLOCK); - if (*fd < 0) { - archive_set_error(&a->archive, errno, - "Can't open `%s'", path); - return (ARCHIVE_FAILED); - } - } + if (*fd < 0) + path = archive_read_disk_entry_setup_path(a, entry, fd); + else + path = NULL; if (*fd >= 0) { #ifdef _PC_MIN_HOLE_SIZE @@ -1911,12 +942,8 @@ setup_sparse(struct archive_read_disk *a, if (initial_off != 0) lseek(*fd, 0, SEEK_SET); } else { - const char *path; - - path = archive_entry_sourcepath(entry); if (path == NULL) - path = archive_entry_pathname(entry); - + return (ARCHIVE_FAILED); #ifdef _PC_MIN_HOLE_SIZE if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h index b5a8328..f03a0a9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_read_disk_private.h @@ -33,6 +33,8 @@ #ifndef ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED #define ARCHIVE_READ_DISK_PRIVATE_H_INCLUDED +#include "archive_platform_acl.h" + struct tree; struct archive_entry; @@ -86,4 +88,11 @@ struct archive_read_disk { void *excluded_cb_data; }; +const char * +archive_read_disk_entry_setup_path(struct archive_read_disk *, + struct archive_entry *, int *); + +int +archive_read_disk_entry_setup_acls(struct archive_read_disk *, + struct archive_entry *, int *); #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_read_format.3 b/Utilities/cmlibarchive/libarchive/archive_read_format.3 index 53b9a7e..91c5d2c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_format.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_format.3 @@ -37,9 +37,9 @@ .Nm archive_read_support_format_empty , .Nm archive_read_support_format_iso9660 , .Nm archive_read_support_format_lha , -.Nm archive_read_support_format_mtree, -.Nm archive_read_support_format_rar, -.Nm archive_read_support_format_raw, +.Nm archive_read_support_format_mtree , +.Nm archive_read_support_format_rar , +.Nm archive_read_support_format_raw , .Nm archive_read_support_format_tar , .Nm archive_read_support_format_xar , .Nm archive_read_support_format_zip diff --git a/Utilities/cmlibarchive/libarchive/archive_read_open.3 b/Utilities/cmlibarchive/libarchive/archive_read_open.3 index 4d8272c..2278ebc 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_open.3 +++ b/Utilities/cmlibarchive/libarchive/archive_read_open.3 @@ -33,7 +33,7 @@ .Nm archive_read_open_fd , .Nm archive_read_open_FILE , .Nm archive_read_open_filename , -.Nm archive_read_open_memory , +.Nm archive_read_open_memory .Nd functions for reading streaming archives .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -67,7 +67,7 @@ Streaming Archive Library (libarchive, -larchive) .Fa "size_t block_size" .Fc .Ft int -.Fn archive_read_open_memory "struct archive *" "void *buff" "size_t size" +.Fn archive_read_open_memory "struct archive *" "const void *buff" "size_t size" .Sh DESCRIPTION .Bl -tag -compact -width indent .It Fn archive_read_open diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c index 663e2d3..147f502 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lz4.c @@ -494,7 +494,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) if (read_buf == NULL) goto truncated_error; compressed_size = archive_le32dec(read_buf); - if ((compressed_size & ~(1 << 31)) > state->flags.block_maximum_size) + if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size) goto malformed_error; /* A compressed size == 0 means the end of stream blocks. */ if (compressed_size == 0) { @@ -504,8 +504,8 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) checksum_size = state->flags.block_checksum; /* Check if the block is uncompressed. */ - if (compressed_size & (1 << 31)) { - compressed_size &= ~(1 << 31); + if (compressed_size & 0x80000000U) { + compressed_size &= 0x7fffffff; uncompressed_size = compressed_size; } else uncompressed_size = 0;/* Unknown yet. */ diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c index 20eb157..51f79fa 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c @@ -116,19 +116,11 @@ struct lzx_dec { * coding tree, which is a binary tree. But a use of a large * index table causes L1 cache read miss many times. */ -#define HTBL_BITS 10 int max_bits; - int shift_bits; int tbl_bits; int tree_used; - int tree_avail; /* Direct access table. */ uint16_t *tbl; - /* Binary tree table for extra bits over the direct access. */ - struct htree_t { - uint16_t left; - uint16_t right; - } *tree; } at, lt, mt, pt; int loop; @@ -187,7 +179,7 @@ struct lzx_stream { #define CFDATA_cbData 4 #define CFDATA_cbUncomp 6 -static const char *compression_name[] = { +static const char * const compression_name[] = { "NONE", "MSZIP", "Quantum", @@ -352,7 +344,6 @@ static int lzx_huffman_init(struct huffman *, size_t, int); static void lzx_huffman_free(struct huffman *); static int lzx_make_huffman_table(struct huffman *); static inline int lzx_decode_huffman(struct huffman *, unsigned); -static int lzx_decode_huffman_tree(struct huffman *, unsigned, int); int @@ -3127,7 +3118,6 @@ getdata: static int lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) { - int bits; if (hf->bitlen == NULL || hf->len_size != (int)len_size) { free(hf->bitlen); @@ -3138,21 +3128,11 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) } else memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0])); if (hf->tbl == NULL) { - if (tbl_bits < HTBL_BITS) - bits = tbl_bits; - else - bits = HTBL_BITS; - hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); + hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0])); if (hf->tbl == NULL) return (ARCHIVE_FATAL); hf->tbl_bits = tbl_bits; } - if (hf->tree == NULL && tbl_bits > HTBL_BITS) { - hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4); - hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0])); - if (hf->tree == NULL) - return (ARCHIVE_FATAL); - } return (ARCHIVE_OK); } @@ -3161,7 +3141,6 @@ lzx_huffman_free(struct huffman *hf) { free(hf->bitlen); free(hf->tbl); - free(hf->tree); } /* @@ -3174,7 +3153,7 @@ lzx_make_huffman_table(struct huffman *hf) const unsigned char *bitlen; int bitptn[17], weight[17]; int i, maxbits = 0, ptn, tbl_size, w; - int diffbits, len_avail; + int len_avail; /* * Initialize bit patterns. @@ -3205,28 +3184,11 @@ lzx_make_huffman_table(struct huffman *hf) weight[i] >>= ebits; } } - if (maxbits > HTBL_BITS) { - int htbl_max; - uint16_t *p; - - diffbits = maxbits - HTBL_BITS; - for (i = 1; i <= HTBL_BITS; i++) { - bitptn[i] >>= diffbits; - weight[i] >>= diffbits; - } - htbl_max = bitptn[HTBL_BITS] + - weight[HTBL_BITS] * hf->freq[HTBL_BITS]; - p = &(hf->tbl[htbl_max]); - while (p < &hf->tbl[1U<<HTBL_BITS]) - *p++ = 0; - } else - diffbits = 0; - hf->shift_bits = diffbits; /* * Make the table. */ - tbl_size = 1 << HTBL_BITS; + tbl_size = 1 << hf->tbl_bits; tbl = hf->tbl; bitlen = hf->bitlen; len_avail = hf->len_size; @@ -3234,120 +3196,32 @@ lzx_make_huffman_table(struct huffman *hf) for (i = 0; i < len_avail; i++) { uint16_t *p; int len, cnt; - uint16_t bit; - int extlen; - struct htree_t *ht; if (bitlen[i] == 0) continue; /* Get a bit pattern */ len = bitlen[i]; + if (len > tbl_size) + return (0); ptn = bitptn[len]; cnt = weight[len]; - if (len <= HTBL_BITS) { - /* Calculate next bit pattern */ - if ((bitptn[len] = ptn + cnt) > tbl_size) - return (0);/* Invalid */ - /* Update the table */ - p = &(tbl[ptn]); - while (--cnt >= 0) - p[cnt] = (uint16_t)i; - continue; - } - - /* - * A bit length is too big to be housed to a direct table, - * so we use a tree model for its extra bits. - */ - bitptn[len] = ptn + cnt; - bit = 1U << (diffbits -1); - extlen = len - HTBL_BITS; - - p = &(tbl[ptn >> diffbits]); - if (*p == 0) { - *p = len_avail + hf->tree_used; - ht = &(hf->tree[hf->tree_used++]); - if (hf->tree_used > hf->tree_avail) - return (0);/* Invalid */ - ht->left = 0; - ht->right = 0; - } else { - if (*p < len_avail || - *p >= (len_avail + hf->tree_used)) - return (0);/* Invalid */ - ht = &(hf->tree[*p - len_avail]); - } - while (--extlen > 0) { - if (ptn & bit) { - if (ht->left < len_avail) { - ht->left = len_avail + hf->tree_used; - ht = &(hf->tree[hf->tree_used++]); - if (hf->tree_used > hf->tree_avail) - return (0);/* Invalid */ - ht->left = 0; - ht->right = 0; - } else { - ht = &(hf->tree[ht->left - len_avail]); - } - } else { - if (ht->right < len_avail) { - ht->right = len_avail + hf->tree_used; - ht = &(hf->tree[hf->tree_used++]); - if (hf->tree_used > hf->tree_avail) - return (0);/* Invalid */ - ht->left = 0; - ht->right = 0; - } else { - ht = &(hf->tree[ht->right - len_avail]); - } - } - bit >>= 1; - } - if (ptn & bit) { - if (ht->left != 0) - return (0);/* Invalid */ - ht->left = (uint16_t)i; - } else { - if (ht->right != 0) - return (0);/* Invalid */ - ht->right = (uint16_t)i; - } + /* Calculate next bit pattern */ + if ((bitptn[len] = ptn + cnt) > tbl_size) + return (0);/* Invalid */ + /* Update the table */ + p = &(tbl[ptn]); + while (--cnt >= 0) + p[cnt] = (uint16_t)i; } return (1); } -static int -lzx_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c) -{ - struct htree_t *ht; - int extlen; - - ht = hf->tree; - extlen = hf->shift_bits; - while (c >= hf->len_size) { - c -= hf->len_size; - if (extlen-- <= 0 || c >= hf->tree_used) - return (0); - if (rbits & (1U << extlen)) - c = ht[c].left; - else - c = ht[c].right; - } - return (c); -} - static inline int lzx_decode_huffman(struct huffman *hf, unsigned rbits) { int c; - /* - * At first search an index table for a bit pattern. - * If it fails, search a huffman tree for. - */ - c = hf->tbl[rbits >> hf->shift_bits]; + c = hf->tbl[rbits]; if (c < hf->len_size) return (c); - /* This bit pattern needs to be found out at a huffman tree. */ - return (lzx_decode_huffman_tree(hf, rbits, c)); + return (0); } - diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c index ffd4a85..ad9f782 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cpio.c @@ -165,7 +165,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_cpio.c 20116 struct links_entry { struct links_entry *next; struct links_entry *previous; - int links; + unsigned int links; dev_t dev; int64_t ino; char *name; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c index 3541330..4b436d1 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c @@ -3021,8 +3021,9 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - memcpy(new_pending_files, heap->files, - heap->allocated * sizeof(new_pending_files[0])); + if (heap->allocated) + memcpy(new_pending_files, heap->files, + heap->allocated * sizeof(new_pending_files[0])); if (heap->files != NULL) free(heap->files); heap->files = new_pending_files; diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c index ebd7f2c..1995e9c 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c @@ -2480,7 +2480,7 @@ lzh_huffman_free(struct huffman *hf) free(hf->tree); } -static char bitlen_tbl[0x400] = { +static const char bitlen_tbl[0x400] = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c index 4231ff5..44b6083 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_mtree.c @@ -130,9 +130,7 @@ static ssize_t readline(struct archive_read *, struct mtree *, char **, ssize_t) static int skip(struct archive_read *a); static int read_header(struct archive_read *, struct archive_entry *); -static int64_t mtree_atol10(char **); -static int64_t mtree_atol8(char **); -static int64_t mtree_atol(char **); +static int64_t mtree_atol(char **, int base); /* * There's no standard for TIME_T_MAX/TIME_T_MIN. So we compute them @@ -399,41 +397,41 @@ bid_keycmp(const char *p, const char *key, ssize_t len) static int bid_keyword(const char *p, ssize_t len) { - static const char *keys_c[] = { + static const char * const keys_c[] = { "content", "contents", "cksum", NULL }; - static const char *keys_df[] = { + static const char * const keys_df[] = { "device", "flags", NULL }; - static const char *keys_g[] = { + static const char * const keys_g[] = { "gid", "gname", NULL }; - static const char *keys_il[] = { + static const char * const keys_il[] = { "ignore", "inode", "link", NULL }; - static const char *keys_m[] = { + static const char * const keys_m[] = { "md5", "md5digest", "mode", NULL }; - static const char *keys_no[] = { + static const char * const keys_no[] = { "nlink", "nochange", "optional", NULL }; - static const char *keys_r[] = { + static const char * const keys_r[] = { "resdevice", "rmd160", "rmd160digest", NULL }; - static const char *keys_s[] = { + static const char * const keys_s[] = { "sha1", "sha1digest", "sha256", "sha256digest", "sha384", "sha384digest", "sha512", "sha512digest", "size", NULL }; - static const char *keys_t[] = { + static const char * const keys_t[] = { "tags", "time", "type", NULL }; - static const char *keys_u[] = { + static const char * const keys_u[] = { "uid", "uname", NULL }; - const char **keys; + const char * const *keys; int i; switch (*p) { @@ -1418,7 +1416,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val) "Too many arguments"); return ARCHIVE_WARN; } - numbers[argc++] = (unsigned long)mtree_atol(&p); + numbers[argc++] = (unsigned long)mtree_atol(&p, 0); } if (argc < 2) { archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, @@ -1433,7 +1431,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val) } } else { /* file system raw value. */ - result = (dev_t)mtree_atol(&val); + result = (dev_t)mtree_atol(&val, 0); } *pdev = result; return ARCHIVE_OK; @@ -1513,7 +1511,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, case 'g': if (strcmp(key, "gid") == 0) { *parsed_kws |= MTREE_HAS_GID; - archive_entry_set_gid(entry, mtree_atol10(&val)); + archive_entry_set_gid(entry, mtree_atol(&val, 10)); break; } if (strcmp(key, "gname") == 0) { @@ -1523,7 +1521,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, } case 'i': if (strcmp(key, "inode") == 0) { - archive_entry_set_ino(entry, mtree_atol10(&val)); + archive_entry_set_ino(entry, mtree_atol(&val, 10)); break; } case 'l': @@ -1535,14 +1533,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) break; if (strcmp(key, "mode") == 0) { - if (val[0] >= '0' && val[0] <= '9') { + if (val[0] >= '0' && val[0] <= '7') { *parsed_kws |= MTREE_HAS_PERM; archive_entry_set_perm(entry, - (mode_t)mtree_atol8(&val)); + (mode_t)mtree_atol(&val, 8)); } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Symbolic mode \"%s\" unsupported", val); + "Symbolic or non-octal mode \"%s\" unsupported", val); return ARCHIVE_WARN; } break; @@ -1551,7 +1549,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, if (strcmp(key, "nlink") == 0) { *parsed_kws |= MTREE_HAS_NLINK; archive_entry_set_nlink(entry, - (unsigned int)mtree_atol10(&val)); + (unsigned int)mtree_atol(&val, 10)); break; } case 'r': @@ -1582,7 +1580,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, strcmp(key, "sha512digest") == 0) break; if (strcmp(key, "size") == 0) { - archive_entry_set_size(entry, mtree_atol10(&val)); + archive_entry_set_size(entry, mtree_atol(&val, 10)); break; } case 't': @@ -1601,13 +1599,13 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, long ns = 0; *parsed_kws |= MTREE_HAS_MTIME; - m = mtree_atol10(&val); + m = mtree_atol(&val, 10); /* Replicate an old mtree bug: * 123456789.1 represents 123456789 * seconds and 1 nanosecond. */ if (*val == '.') { ++val; - ns = (long)mtree_atol10(&val); + ns = (long)mtree_atol(&val, 10); if (ns < 0) ns = 0; else if (ns > 999999999) @@ -1670,7 +1668,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, case 'u': if (strcmp(key, "uid") == 0) { *parsed_kws |= MTREE_HAS_UID; - archive_entry_set_uid(entry, mtree_atol10(&val)); + archive_entry_set_uid(entry, mtree_atol(&val, 10)); break; } if (strcmp(key, "uname") == 0) { @@ -1825,72 +1823,9 @@ parse_escapes(char *src, struct mtree_entry *mentry) *dest = '\0'; } -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ -static int64_t -mtree_atol8(char **p) -{ - int64_t l, limit, last_digit_limit; - int digit, base; - - base = 8; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - - l = 0; - digit = **p - '0'; - while (digit >= 0 && digit < base) { - if (l>limit || (l == limit && digit > last_digit_limit)) { - l = INT64_MAX; /* Truncate on overflow. */ - break; - } - l = (l * base) + digit; - digit = *++(*p) - '0'; - } - return (l); -} - -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ -static int64_t -mtree_atol10(char **p) -{ - int64_t l, limit, last_digit_limit; - int base, digit, sign; - - base = 10; - - if (**p == '-') { - sign = -1; - limit = ((uint64_t)(INT64_MAX) + 1) / base; - last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base; - ++(*p); - } else { - sign = 1; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - } - - l = 0; - digit = **p - '0'; - while (digit >= 0 && digit < base) { - if (l > limit || (l == limit && digit > last_digit_limit)) - return (sign < 0) ? INT64_MIN : INT64_MAX; - l = (l * base) + digit; - digit = *++(*p) - '0'; - } - return (sign < 0) ? -l : l; -} - /* Parse a hex digit. */ static int -parsehex(char c) +parsedigit(char c) { if (c >= '0' && c <= '9') return c - '0'; @@ -1908,45 +1843,50 @@ parsehex(char c) * it does obey locale. */ static int64_t -mtree_atol16(char **p) +mtree_atol(char **p, int base) { - int64_t l, limit, last_digit_limit; - int base, digit, sign; - - base = 16; + int64_t l, limit; + int digit, last_digit_limit; + + if (base == 0) { + if (**p != '0') + base = 10; + else if ((*p)[1] == 'x' || (*p)[1] == 'X') { + *p += 2; + base = 16; + } else { + base = 8; + } + } if (**p == '-') { - sign = -1; - limit = ((uint64_t)(INT64_MAX) + 1) / base; - last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base; + 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)) + return INT64_MIN; + l = (l * base) - digit; + digit = parsedigit(*++(*p)); + } + return l; } else { - sign = 1; limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; - } - l = 0; - digit = parsehex(**p); - while (digit >= 0 && digit < base) { - if (l > limit || (l == limit && digit > last_digit_limit)) - return (sign < 0) ? INT64_MIN : INT64_MAX; - l = (l * base) + digit; - digit = parsehex(*++(*p)); - } - return (sign < 0) ? -l : l; -} - -static int64_t -mtree_atol(char **p) -{ - if (**p != '0') - return mtree_atol10(p); - if ((*p)[1] == 'x' || (*p)[1] == 'X') { - *p += 2; - return mtree_atol16(p); + l = 0; + digit = parsedigit(**p); + while (digit >= 0 && digit < base) { + if (l > limit || (l == limit && digit > last_digit_limit)) + return INT64_MAX; + l = (l * base) + digit; + digit = parsedigit(*++(*p)); + } + return l; } - return mtree_atol8(p); } /* diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c index 658d49d..a0e641e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c @@ -1750,7 +1750,7 @@ read_exttime(const char *p, struct rar *rar, const char *endp) return (-1); for (j = 0; j < count; j++) { - rem = ((*p) << 16) | (rem >> 8); + rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8); p++; } tm = localtime(&t); diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c index bd7f13d..30d5bc8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_tar.c @@ -155,6 +155,7 @@ struct tar { int compat_2x; int process_mac_extensions; int read_concatenated_archives; + int realsize_override; }; static int archive_block_is_null(const char *p); @@ -527,6 +528,7 @@ archive_read_format_tar_read_header(struct archive_read *a, tar->entry_offset = 0; gnu_clear_sparse_list(tar); tar->realsize = -1; /* Mark this as "unset" */ + tar->realsize_override = 0; /* Setup default string conversion. */ tar->sconv = tar->opt_sconv; @@ -1894,6 +1896,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, if (strcmp(key, "GNU.sparse.size") == 0) { tar->realsize = tar_atol10(value, strlen(value)); archive_entry_set_size(entry, tar->realsize); + tar->realsize_override = 1; } /* GNU "0.1" sparse pax format. */ @@ -1925,6 +1928,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, if (strcmp(key, "GNU.sparse.realsize") == 0) { tar->realsize = tar_atol10(value, strlen(value)); archive_entry_set_size(entry, tar->realsize); + tar->realsize_override = 1; } break; case 'L': @@ -1977,6 +1981,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, tar_atol10(value, strlen(value))); } else if (strcmp(key, "SCHILY.realsize") == 0) { tar->realsize = tar_atol10(value, strlen(value)); + tar->realsize_override = 1; archive_entry_set_size(entry, tar->realsize); } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) { pax_attribute_schily_xattr(entry, key, value, @@ -2055,14 +2060,12 @@ pax_attribute(struct archive_read *a, struct tar *tar, tar->entry_bytes_remaining = tar_atol10(value, strlen(value)); /* - * But, "size" is not necessarily the size of - * the file on disk; if this is a sparse file, - * the disk size may have already been set from - * GNU.sparse.realsize or GNU.sparse.size or - * an old GNU header field or SCHILY.realsize - * or .... + * The "size" pax header keyword always overrides the + * "size" field in the tar header. + * GNU.sparse.realsize, GNU.sparse.size and + * SCHILY.realsize override this value. */ - if (tar->realsize < 0) { + if (!tar->realsize_override) { archive_entry_set_size(entry, tar->entry_bytes_remaining); tar->realsize @@ -2206,6 +2209,7 @@ header_gnutar(struct archive_read *a, struct tar *tar, tar->realsize = tar_atol(header->realsize, sizeof(header->realsize)); archive_entry_set_size(entry, tar->realsize); + tar->realsize_override = 1; } if (header->sparse[0].offset[0] != 0) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c index b162465..e875385 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c @@ -600,9 +600,10 @@ _warc_rdver(const char *buf, size_t bsz) /* looks good so far, read the version number for a laugh */ buf += sizeof(magic) - 1U; - if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) { + if (isdigit((unsigned char)buf[0U]) && (buf[1U] == '.') && + isdigit((unsigned char)buf[2U])) { /* we support a maximum of 2 digits in the minor version */ - if (isdigit(buf[3U])) + if (isdigit((unsigned char)buf[3U])) end = 1U; /* set up major version */ ver = (buf[0U] - '0') * 10000U; @@ -686,7 +687,7 @@ _warc_rduri(const char *buf, size_t bsz) /* spaces inside uri are not allowed, CRLF should follow */ for (p = val; p < eol; p++) { - if (isspace(*p)) + if (isspace((unsigned char)*p)) return res; } @@ -736,7 +737,7 @@ _warc_rdlen(const char *buf, size_t bsz) while (val < eol && (*val == ' ' || *val == '\t')) val++; /* there must be at least one digit */ - if (!isdigit(*val)) + if (!isdigit((unsigned char)*val)) return -1; len = strtol(val, &on, 10); if (on != eol) { diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index e56bd63..ddd4458 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@ -347,7 +347,7 @@ fake_crc32(unsigned long crc, const void *buff, size_t len) return 0; } -static struct { +static const struct { int id; const char * name; } compression_methods[] = { @@ -2407,7 +2407,7 @@ read_eocd(struct zip *zip, const char *p, int64_t current_offset) * Examine Zip64 EOCD locator: If it's valid, store the information * from it. */ -static void +static int read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p) { int64_t eocd64_offset; @@ -2417,35 +2417,37 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p) /* Central dir must be on first volume. */ if (archive_le32dec(p + 4) != 0) - return; + return 0; /* Must be only a single volume. */ if (archive_le32dec(p + 16) != 1) - return; + return 0; /* Find the Zip64 EOCD record. */ eocd64_offset = archive_le64dec(p + 8); if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0) - return; + return 0; if ((p = __archive_read_ahead(a, 56, NULL)) == NULL) - return; + return 0; /* Make sure we can read all of it. */ eocd64_size = archive_le64dec(p + 4) + 12; if (eocd64_size < 56 || eocd64_size > 16384) - return; + return 0; if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL) - return; + return 0; /* Sanity-check the EOCD64 */ if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */ - return; + return 0; if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */ - return; + return 0; /* CD can't be split. */ if (archive_le64dec(p + 24) != archive_le64dec(p + 32)) - return; + return 0; /* Save the central directory offset for later use. */ zip->central_directory_offset = archive_le64dec(p + 48); + + return 32; } static int @@ -2483,15 +2485,14 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) if (memcmp(p + i, "PK\005\006", 4) == 0) { int ret = read_eocd(zip, p + i, current_offset + i); - if (ret > 0) { - /* Zip64 EOCD locator precedes - * regular EOCD if present. */ - if (i >= 20 - && memcmp(p + i - 20, "PK\006\007", 4) == 0) { - read_zip64_eocd(a, zip, p + i - 20); - } - return (ret); + /* Zip64 EOCD locator precedes + * regular EOCD if present. */ + if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) { + int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20); + if (ret_zip64 > ret) + ret = ret_zip64; } + return (ret); } i -= 4; break; diff --git a/Utilities/cmlibarchive/libarchive/archive_string.c b/Utilities/cmlibarchive/libarchive/archive_string.c index 592ead2..5ae09b6 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string.c +++ b/Utilities/cmlibarchive/libarchive/archive_string.c @@ -202,7 +202,8 @@ archive_string_append(struct archive_string *as, const char *p, size_t s) { if (archive_string_ensure(as, as->length + s + 1) == NULL) return (NULL); - memmove(as->s + as->length, p, s); + if (s) + memmove(as->s + as->length, p, s); as->length += s; as->s[as->length] = 0; return (as); diff --git a/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c b/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c index 964ea2b..969a560 100644 --- a/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c +++ b/Utilities/cmlibarchive/libarchive/archive_string_sprintf.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_string_sprintf.c 189435 2009-03- static void append_uint(struct archive_string *as, uintmax_t d, unsigned base) { - static const char *digits = "0123456789abcdef"; + static const char digits[] = "0123456789abcdef"; if (d >= base) append_uint(as, d/base, base); archive_strappend_char(as, digits[d % base]); diff --git a/Utilities/cmlibarchive/libarchive/archive_util.c b/Utilities/cmlibarchive/libarchive/archive_util.c index f56ca33..1e36ad7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_util.c +++ b/Utilities/cmlibarchive/libarchive/archive_util.c @@ -89,88 +89,6 @@ archive_version_string(void) return (ARCHIVE_VERSION_STRING); } -const char * -archive_version_details(void) -{ - static struct archive_string str; - static int init = 0; - const char *zlib = archive_zlib_version(); - const char *liblzma = archive_liblzma_version(); - const char *bzlib = archive_bzlib_version(); - const char *liblz4 = archive_liblz4_version(); - - if (!init) { - archive_string_init(&str); - - archive_strcat(&str, ARCHIVE_VERSION_STRING); - if (zlib != NULL) { - archive_strcat(&str, " zlib/"); - archive_strcat(&str, zlib); - } - if (liblzma) { - archive_strcat(&str, " liblzma/"); - archive_strcat(&str, liblzma); - } - if (bzlib) { - const char *p = bzlib; - const char *sep = strchr(p, ','); - if (sep == NULL) - sep = p + strlen(p); - archive_strcat(&str, " bz2lib/"); - archive_strncat(&str, p, sep - p); - } - if (liblz4) { - archive_strcat(&str, " liblz4/"); - archive_strcat(&str, liblz4); - } - } - return str.s; -} - -const char * -archive_zlib_version(void) -{ -#ifdef HAVE_ZLIB_H - return ZLIB_VERSION; -#else - return NULL; -#endif -} - -const char * -archive_liblzma_version(void) -{ -#ifdef HAVE_LZMA_H - return LZMA_VERSION_STRING; -#else - return NULL; -#endif -} - -const char * -archive_bzlib_version(void) -{ -#ifdef HAVE_BZLIB_H - return BZ2_bzlibVersion(); -#else - return NULL; -#endif -} - -const char * -archive_liblz4_version(void) -{ -#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4) -#define str(s) #s -#define NUMBER(x) str(x) - return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE); -#undef NUMBER -#undef str -#else - return NULL; -#endif -} - int archive_errno(struct archive *a) { @@ -275,7 +193,7 @@ archive_copy_error(struct archive *dest, struct archive *src) void __archive_errx(int retvalue, const char *msg) { - static const char *msg1 = "Fatal Internal Error in libarchive: "; + static const char msg1[] = "Fatal Internal Error in libarchive: "; size_t s; s = write(2, msg1, strlen(msg1)); @@ -303,8 +221,8 @@ __archive_errx(int retvalue, const char *msg) int __archive_mktemp(const char *tmpdir) { - static const wchar_t *prefix = L"libarchive_"; - static const wchar_t *suffix = L"XXXXXXXXXX"; + static const wchar_t prefix[] = L"libarchive_"; + static const wchar_t suffix[] = L"XXXXXXXXXX"; static const wchar_t num[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F', diff --git a/Utilities/cmlibarchive/libarchive/archive_version_details.c b/Utilities/cmlibarchive/libarchive/archive_version_details.c new file mode 100644 index 0000000..9289bf1 --- /dev/null +++ b/Utilities/cmlibarchive/libarchive/archive_version_details.c @@ -0,0 +1,133 @@ +/*- + * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $"); + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_ZLIB_H +#include <cm_zlib.h> +#endif +#ifdef HAVE_LZMA_H +#include <cm_lzma.h> +#endif +#ifdef HAVE_BZLIB_H +#include <cm_bzlib.h> +#endif +#ifdef HAVE_LZ4_H +#include <lz4.h> +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_string.h" + +const char * +archive_version_details(void) +{ + static struct archive_string str; + static int init = 0; + const char *zlib = archive_zlib_version(); + const char *liblzma = archive_liblzma_version(); + const char *bzlib = archive_bzlib_version(); + const char *liblz4 = archive_liblz4_version(); + + if (!init) { + archive_string_init(&str); + + archive_strcat(&str, ARCHIVE_VERSION_STRING); + if (zlib != NULL) { + archive_strcat(&str, " zlib/"); + archive_strcat(&str, zlib); + } + if (liblzma) { + archive_strcat(&str, " liblzma/"); + archive_strcat(&str, liblzma); + } + if (bzlib) { + const char *p = bzlib; + const char *sep = strchr(p, ','); + if (sep == NULL) + sep = p + strlen(p); + archive_strcat(&str, " bz2lib/"); + archive_strncat(&str, p, sep - p); + } + if (liblz4) { + archive_strcat(&str, " liblz4/"); + archive_strcat(&str, liblz4); + } + } + return str.s; +} + +const char * +archive_zlib_version(void) +{ +#ifdef HAVE_ZLIB_H + return ZLIB_VERSION; +#else + return NULL; +#endif +} + +const char * +archive_liblzma_version(void) +{ +#ifdef HAVE_LZMA_H + return LZMA_VERSION_STRING; +#else + return NULL; +#endif +} + +const char * +archive_bzlib_version(void) +{ +#ifdef HAVE_BZLIB_H + return BZ2_bzlibVersion(); +#else + return NULL; +#endif +} + +const char * +archive_liblz4_version(void) +{ +#if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4) +#define str(s) #s +#define NUMBER(x) str(x) + return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE); +#undef NUMBER +#undef str +#else + return NULL; +#endif +} diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c index ad5dc83..08f518a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter.c @@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$"); #include "archive_private.h" /* A table that maps filter codes to functions. */ -static +static const struct { int code; int (*setter)(struct archive *); } codes[] = { { ARCHIVE_FILTER_NONE, archive_write_add_filter_none }, diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c index eac4011..85a8d47 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_by_name.c @@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$"); #include "archive_private.h" /* A table that maps names to functions. */ -static +static const struct { const char *name; int (*setter)(struct archive *); } names[] = { { "b64encode", archive_write_add_filter_b64encode }, diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c index e655185..15fd494 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_lz4.c @@ -225,7 +225,7 @@ archive_filter_lz4_open(struct archive_write_filter *f) struct private_data *data = (struct private_data *)f->data; int ret; size_t required_size; - static size_t bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, + static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, 4 * 1024 * 1024 }; size_t pre_block_size; diff --git a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c index 55b5e8e..660f693 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_program.c @@ -92,7 +92,7 @@ archive_write_add_filter_program(struct archive *_a, const char *cmd) { struct archive_write_filter *f = __archive_write_allocate_filter(_a); struct private_data *data; - static const char *prefix = "Program: "; + static const char prefix[] = "Program: "; archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, "archive_write_add_filter_program"); diff --git a/Utilities/cmlibarchive/libarchive/archive_write_data.3 b/Utilities/cmlibarchive/libarchive/archive_write_data.3 index 0cdd25f..9c16cd9 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_data.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_data.3 @@ -24,11 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd February 28, 2017 .Dt ARCHIVE_WRITE_DATA 3 .Os .Sh NAME -.Nm archive_write_data +.Nm archive_write_data , +.Nm archive_write_data_block .Nd functions for creating archives .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -36,8 +37,27 @@ Streaming Archive Library (libarchive, -larchive) .In archive.h .Ft la_ssize_t .Fn archive_write_data "struct archive *" "const void *" "size_t" +.Ft la_ssize_t +.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset" .Sh DESCRIPTION +.Bl -tag -width indent +.It Fn archive_write_data +Write data corresponding to the header just written. +.It Fn archive_write_data_block Write data corresponding to the header just written. +This is like +.Fn archive_write_data +except that it performs a seek on the file being +written to the specified offset before writing the data. +This is useful when restoring sparse files from archive +formats that support sparse files. +Returns number of bytes written or -1 on error. +(Note: This is currently not supported for +.Tn archive_write +handles, only for +.Tn archive_write_disk +handles. +.El .\" .Sh EXAMPLE .\" .Sh RETURN VALUES diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk.3 b/Utilities/cmlibarchive/libarchive/archive_write_disk.3 index ba6c970..949c9ef 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd April 3, 2017 .Dt ARCHIVE_WRITE_DISK 3 .Os .Sh NAME @@ -33,14 +33,7 @@ .Nm archive_write_disk_set_skip_file , .Nm archive_write_disk_set_group_lookup , .Nm archive_write_disk_set_standard_lookup , -.Nm archive_write_disk_set_user_lookup , -.Nm archive_write_header , -.Nm archive_write_data , -.Nm archive_write_data_block , -.Nm archive_write_finish_entry , -.Nm archive_write_close , -.Nm archive_write_finish -.Nm archive_write_free +.Nm archive_write_disk_set_user_lookup .Nd functions for creating objects on disk .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -68,20 +61,6 @@ Streaming Archive Library (libarchive, -larchive) .Fa "uid_t (*)(void *, const char *uname, uid_t uid)" .Fa "void (*cleanup)(void *)" .Fc -.Ft int -.Fn archive_write_header "struct archive *" "struct archive_entry *" -.Ft la_ssize_t -.Fn archive_write_data "struct archive *" "const void *" "size_t" -.Ft la_ssize_t -.Fn archive_write_data_block "struct archive *" "const void *" "size_t size" "int64_t offset" -.Ft int -.Fn archive_write_finish_entry "struct archive *" -.Ft int -.Fn archive_write_close "struct archive *" -.Ft int -.Fn archive_write_finish "struct archive *" -.Ft int -.Fn archive_write_free "struct archive *" .Sh DESCRIPTION These functions provide a complete API for creating objects on disk from @@ -117,6 +96,33 @@ performance optimization in practice. The options field consists of a bitwise OR of one or more of the following values: .Bl -tag -compact -width "indent" +.It Cm ARCHIVE_EXTRACT_ACL +Attempt to restore Access Control Lists. +By default, extended ACLs are ignored. +.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS +Before removing a file system object prior to replacing it, clear +platform-specific file flags which might prevent its removal. +.It Cm ARCHIVE_EXTRACT_FFLAGS +Attempt to restore file attributes (file flags). +By default, file attributes are ignored. +See +.Xr chattr 1 +.Pq Linux +or +.Xr chflags 1 +.Pq FreeBSD, Mac OS X +for more information on file attributes. +.It Cm ARCHIVE_EXTRACT_MAC_METADATA +Mac OS X specific. Restore metadata using +.Xr copyfile 3 . +By default, +.Xr copyfile 3 +metadata is ignored. +.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE +Existing files on disk will not be overwritten. +By default, existing regular files are truncated and overwritten; +existing directories will have their permissions updated; +other pre-existing objects are unlinked and recreated from scratch. .It Cm ARCHIVE_EXTRACT_OWNER The user and group IDs should be set on the restored file. By default, the user and group IDs are not restored. @@ -132,15 +138,37 @@ is not specified, then SUID and SGID bits will only be restored if the default user and group IDs of newly-created objects on disk happen to match those specified in the archive entry. By default, only basic permissions are restored, and umask is obeyed. +.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS +Refuse to extract an absolute path. +The default is to not refuse such paths. +.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT +Refuse to extract a path that contains a +.Pa .. +element anywhere within it. +The default is to not refuse such paths. +Note that paths ending in +.Pa .. +always cause an error, regardless of this flag. +.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS +Refuse to extract any object whose final location would be altered +by a symlink on disk. +This is intended to help guard against a variety of mischief +caused by archives that (deliberately or otherwise) extract +files outside of the current directory. +The default is not to perform this check. +If +.It Cm ARCHIVE_EXTRACT_SPARSE +Scan data for blocks of NUL bytes and try to recreate them with holes. +This results in sparse files, independent of whether the archive format +supports or uses them. +.Cm ARCHIVE_EXTRACT_UNLINK +is specified together with this option, the library will +remove any intermediate symlinks it finds and return an +error only if such symlink could not be removed. .It Cm ARCHIVE_EXTRACT_TIME The timestamps (mtime, ctime, and atime) should be restored. By default, they are ignored. Note that restoring of atime is not currently supported. -.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE -Existing files on disk will not be overwritten. -By default, existing regular files are truncated and overwritten; -existing directories will have their permissions updated; -other pre-existing objects are unlinked and recreated from scratch. .It Cm ARCHIVE_EXTRACT_UNLINK Existing files on disk will be unlinked before any attempt to create them. @@ -148,45 +176,18 @@ In some cases, this can prove to be a significant performance improvement. By default, existing files are truncated and rewritten, but the file is not recreated. In particular, the default behavior does not break existing hard links. -.It Cm ARCHIVE_EXTRACT_ACL -Attempt to restore ACLs. -By default, extended ACLs are ignored. -.It Cm ARCHIVE_EXTRACT_FFLAGS -Attempt to restore extended file flags. -By default, file flags are ignored. .It Cm ARCHIVE_EXTRACT_XATTR -Attempt to restore POSIX.1e extended attributes. +Attempt to restore extended file attributes. By default, they are ignored. -.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS -Refuse to extract any object whose final location would be altered -by a symlink on disk. -This is intended to help guard against a variety of mischief -caused by archives that (deliberately or otherwise) extract -files outside of the current directory. -The default is not to perform this check. -If -.Cm ARCHIVE_EXTRACT_UNLINK -is specified together with this option, the library will -remove any intermediate symlinks it finds and return an -error only if such symlink could not be removed. -.It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT -Refuse to extract a path that contains a -.Pa .. -element anywhere within it. -The default is to not refuse such paths. -Note that paths ending in -.Pa .. -always cause an error, regardless of this flag. -.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS -Refuse to extract an absolute path. -The default is to not refuse such paths. -.It Cm ARCHIVE_EXTRACT_SPARSE -Scan data for blocks of NUL bytes and try to recreate them with holes. -This results in sparse files, independent of whether the archive format -supports or uses them. -.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS -Before removing a file system object prior to replacing it, clear -platform-specific file flags which might prevent its removal. +See +.Xr xattr 7 +.Pq Linux , +.Xr xattr 2 +.Pq Mac OS X , +or +.Xr getextattr 8 +.Pq FreeBSD +for more information on extended file attributes. .El .It Xo .Fn archive_write_disk_set_group_lookup , @@ -223,60 +224,6 @@ the number of calls to .Xr getpwnam 3 and .Xr getgrnam 3 . -.It Fn archive_write_header -Build and write a header using the data in the provided -.Tn struct archive_entry -structure. -See -.Xr archive_entry 3 -for information on creating and populating -.Tn struct archive_entry -objects. -.It Fn archive_write_data -Write data corresponding to the header just written. -Returns number of bytes written or -1 on error. -.It Fn archive_write_data_block -Write data corresponding to the header just written. -This is like -.Fn archive_write_data -except that it performs a seek on the file being -written to the specified offset before writing the data. -This is useful when restoring sparse files from archive -formats that support sparse files. -Returns number of bytes written or -1 on error. -(Note: This is currently not supported for -.Tn archive_write -handles, only for -.Tn archive_write_disk -handles.) -.It Fn archive_write_finish_entry -Close out the entry just written. -Ordinarily, clients never need to call this, as it -is called automatically by -.Fn archive_write_next_header -and -.Fn archive_write_close -as needed. -However, some file attributes are written to disk only -after the file is closed, so this can be necessary -if you need to work with the file on disk right away. -.It Fn archive_write_close -Set any attributes that could not be set during the initial restore. -For example, directory timestamps are not restored initially because -restoring a subsequent file would alter that timestamp. -Similarly, non-writable directories are initially created with -write permissions (so that their contents can be restored). -The -.Nm -library maintains a list of all such deferred attributes and -sets them when this function is invoked. -.It Fn archive_write_finish -This is a deprecated synonym for -.Fn archive_write_free . -.It Fn archive_write_free -Invokes -.Fn archive_write_close -if it was not invoked manually, then releases all resources. .El More information about the .Va struct archive diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c deleted file mode 100644 index 144ab7e..0000000 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_acl.c +++ /dev/null @@ -1,654 +0,0 @@ -/*- - * Copyright (c) 2003-2010 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "archive_platform.h" -__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 05:35:40Z kientzle $"); - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_ACL_H -#define _ACL_PRIVATE /* For debugging */ -#include <sys/acl.h> -#endif -#if HAVE_DARWIN_ACL -#include <membership.h> -#endif -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif - -#include "archive.h" -#include "archive_entry.h" -#include "archive_acl_private.h" -#include "archive_write_disk_private.h" - -#if !HAVE_POSIX_ACL && !HAVE_NFS4_ACL -/* Default empty function body to satisfy mainline code. */ -int -archive_write_disk_set_acls(struct archive *a, int fd, const char *name, - struct archive_acl *abstract_acl) -{ - (void)a; /* UNUSED */ - (void)fd; /* UNUSED */ - (void)name; /* UNUSED */ - (void)abstract_acl; /* UNUSED */ - return (ARCHIVE_OK); -} - -#else /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ - -#if HAVE_SUN_ACL -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACE_T -#elif HAVE_DARWIN_ACL -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED -#elif HAVE_ACL_TYPE_NFS4 -#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4 -#endif - -static int set_acl(struct archive *, int fd, const char *, - struct archive_acl *, - acl_type_t, int archive_entry_acl_type, const char *tn); - -int -archive_write_disk_set_acls(struct archive *a, int fd, const char *name, - struct archive_acl *abstract_acl) -{ - int ret = ARCHIVE_OK; - -#if !HAVE_DARWIN_ACL - if ((archive_acl_types(abstract_acl) - & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { -#if HAVE_SUN_ACL - /* Solaris writes POSIX.1e access and default ACLs together */ - ret = set_acl(a, fd, name, abstract_acl, ACLENT_T, - ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e"); -#else /* HAVE_POSIX_ACL */ - if ((archive_acl_types(abstract_acl) - & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - ret = set_acl(a, fd, name, abstract_acl, - ACL_TYPE_ACCESS, 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, - ACL_TYPE_DEFAULT, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, - "default"); -#endif /* !HAVE_SUN_ACL */ - /* Simultaneous POSIX.1e and NFSv4 is not supported */ - return (ret); - } -#endif /* !HAVE_DARWIN_ACL */ -#if HAVE_NFS4_ACL - if ((archive_acl_types(abstract_acl) & - ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - ret = set_acl(a, fd, name, abstract_acl, - ARCHIVE_PLATFORM_ACL_TYPE_NFS4, - ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4"); - } -#endif /* HAVE_NFS4_ACL */ - return (ret); -} - -/* - * Translate system ACL permissions into libarchive internal structure - */ -static const struct { - const int archive_perm; - const int platform_perm; -} acl_perm_map[] = { -#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */ - {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, - {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} -#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */ - {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, - {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} -#else /* POSIX.1e ACL permissions */ - {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, - {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, - {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, -#if HAVE_ACL_TYPE_NFS4 /* FreeBSD NFSv4 ACL permissions */ - {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, - {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, - {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, - {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, - {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, - {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, - {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, - {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, - {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, - {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} -#endif -#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ -}; - -#if HAVE_NFS4_ACL -/* - * Translate system NFSv4 inheritance flags into libarchive internal structure - */ -static const struct { - const int archive_inherit; - const int platform_inherit; -} acl_inherit_map[] = { -#if HAVE_SUN_ACL /* Solaris NFSv4 inheritance flags */ - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, - {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, - {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} -#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */ - {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} -#else /* FreeBSD NFSv4 ACL inheritance flags */ - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, - {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, - {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, - {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} -#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ -}; -#endif /* HAVE_NFS4_ACL */ - -static int -set_acl(struct archive *a, int fd, const char *name, - struct archive_acl *abstract_acl, - acl_type_t acl_type, int ae_requested_type, const char *tname) -{ -#if HAVE_SUN_ACL - aclent_t *aclent; - ace_t *ace; - int e, r; - acl_t *acl; -#else - acl_t acl; - acl_entry_t acl_entry; - acl_permset_t acl_permset; -#if HAVE_ACL_TYPE_NFS4 || HAVE_DARWIN_ACL - acl_flagset_t acl_flagset; -#endif -#endif /* HAVE_SUN_ACL */ -#if HAVE_ACL_TYPE_NFS4 - int r; -#endif - int ret; - int ae_type, ae_permset, ae_tag, ae_id; -#if HAVE_DARWIN_ACL - uuid_t ae_uuid; -#endif - uid_t ae_uid; - gid_t ae_gid; - const char *ae_name; - int entries; - int i; - - ret = ARCHIVE_OK; - entries = archive_acl_reset(abstract_acl, ae_requested_type); - if (entries == 0) - return (ARCHIVE_OK); - -#if HAVE_SUN_ACL - acl = NULL; - acl = malloc(sizeof(acl_t)); - if (acl == NULL) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid ACL type"); - return (ARCHIVE_FAILED); - } - if (acl_type == ACE_T) - acl->acl_entry_size = sizeof(ace_t); - else if (acl_type == ACLENT_T) - acl->acl_entry_size = sizeof(aclent_t); - else { - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Invalid ACL type"); - acl_free(acl); - return (ARCHIVE_FAILED); - } - acl->acl_type = acl_type; - acl->acl_cnt = entries; - - acl->acl_aclp = malloc(entries * acl->acl_entry_size); - if (acl->acl_aclp == NULL) { - archive_set_error(a, errno, - "Can't allocate memory for acl buffer"); - acl_free(acl); - return (ARCHIVE_FAILED); - } -#else /* !HAVE_SUN_ACL */ - acl = acl_init(entries); - if (acl == (acl_t)NULL) { - archive_set_error(a, errno, - "Failed to initialize ACL working storage"); - return (ARCHIVE_FAILED); - } -#endif /* !HAVE_SUN_ACL */ -#if HAVE_SUN_ACL - e = 0; -#endif - while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, - &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { -#if HAVE_SUN_ACL - ace = NULL; - aclent = NULL; - if (acl->acl_type == ACE_T) { - ace = &((ace_t *)acl->acl_aclp)[e]; - ace->a_who = -1; - ace->a_access_mask = 0; - ace->a_flags = 0; - } else { - aclent = &((aclent_t *)acl->acl_aclp)[e]; - aclent->a_id = -1; - aclent->a_type = 0; - aclent->a_perm = 0; - } -#else /* !HAVE_SUN_ACL */ -#if HAVE_DARWIN_ACL - /* - * Mac OS doesn't support NFSv4 ACLs for - * owner@, group@ and everyone@. - * We skip any of these ACLs found. - */ - if (ae_tag == ARCHIVE_ENTRY_ACL_USER_OBJ || - ae_tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ || - ae_tag == ARCHIVE_ENTRY_ACL_EVERYONE) - continue; -#endif - if (acl_create_entry(&acl, &acl_entry) != 0) { - archive_set_error(a, errno, - "Failed to create a new ACL entry"); - ret = ARCHIVE_FAILED; - goto exit_free; - } -#endif /* !HAVE_SUN_ACL */ -#if HAVE_DARWIN_ACL - switch (ae_type) { - case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - acl_set_tag_type(acl_entry, ACL_EXTENDED_ALLOW); - break; - case ARCHIVE_ENTRY_ACL_TYPE_DENY: - acl_set_tag_type(acl_entry, ACL_EXTENDED_DENY); - break; - default: - /* We don't support any other types on MacOS */ - continue; - } -#endif - switch (ae_tag) { -#if HAVE_SUN_ACL - case ARCHIVE_ENTRY_ACL_USER: - ae_uid = archive_write_disk_uid(a, ae_name, ae_id); - if (acl->acl_type == ACE_T) - ace->a_who = ae_uid; - else { - aclent->a_id = ae_uid; - aclent->a_type |= USER; - } - break; - case ARCHIVE_ENTRY_ACL_GROUP: - ae_gid = archive_write_disk_gid(a, ae_name, ae_id); - if (acl->acl_type == ACE_T) { - ace->a_who = ae_gid; - ace->a_flags |= ACE_IDENTIFIER_GROUP; - } else { - aclent->a_id = ae_gid; - aclent->a_type |= GROUP; - } - break; - case ARCHIVE_ENTRY_ACL_USER_OBJ: - if (acl->acl_type == ACE_T) - ace->a_flags |= ACE_OWNER; - else - aclent->a_type |= USER_OBJ; - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - if (acl->acl_type == ACE_T) { - ace->a_flags |= ACE_GROUP; - ace->a_flags |= ACE_IDENTIFIER_GROUP; - } else - aclent->a_type |= GROUP_OBJ; - break; - case ARCHIVE_ENTRY_ACL_MASK: - aclent->a_type |= CLASS_OBJ; - break; - case ARCHIVE_ENTRY_ACL_OTHER: - aclent->a_type |= OTHER_OBJ; - break; - case ARCHIVE_ENTRY_ACL_EVERYONE: - ace->a_flags |= ACE_EVERYONE; - break; -#else /* !HAVE_SUN_ACL */ - case ARCHIVE_ENTRY_ACL_USER: - ae_uid = archive_write_disk_uid(a, ae_name, ae_id); -#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ - acl_set_tag_type(acl_entry, ACL_USER); - acl_set_qualifier(acl_entry, &ae_uid); -#else /* MacOS */ - if (mbr_identifier_to_uuid(ID_TYPE_UID, &ae_uid, - sizeof(uid_t), ae_uuid) != 0) - continue; - if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) - continue; -#endif /* HAVE_DARWIN_ACL */ - break; - case ARCHIVE_ENTRY_ACL_GROUP: - ae_gid = archive_write_disk_gid(a, ae_name, ae_id); -#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ - acl_set_tag_type(acl_entry, ACL_GROUP); - acl_set_qualifier(acl_entry, &ae_gid); -#else /* MacOS */ - if (mbr_identifier_to_uuid(ID_TYPE_GID, &ae_gid, - sizeof(gid_t), ae_uuid) != 0) - continue; - if (acl_set_qualifier(acl_entry, &ae_uuid) != 0) - continue; -#endif /* HAVE_DARWIN_ACL */ - break; -#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ - case ARCHIVE_ENTRY_ACL_USER_OBJ: - acl_set_tag_type(acl_entry, ACL_USER_OBJ); - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); - break; - case ARCHIVE_ENTRY_ACL_MASK: - acl_set_tag_type(acl_entry, ACL_MASK); - break; - case ARCHIVE_ENTRY_ACL_OTHER: - acl_set_tag_type(acl_entry, ACL_OTHER); - break; -#if HAVE_ACL_TYPE_NFS4 /* FreeBSD only */ - case ARCHIVE_ENTRY_ACL_EVERYONE: - acl_set_tag_type(acl_entry, ACL_EVERYONE); - break; -#endif -#endif /* !HAVE_DARWIN_ACL */ -#endif /* !HAVE_SUN_ACL */ - default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Unknown ACL tag"); - ret = ARCHIVE_FAILED; - goto exit_free; - } - -#if HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL - r = 0; - switch (ae_type) { -#if HAVE_SUN_ACL - case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - if (ace != NULL) - ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - else - r = -1; - break; - case ARCHIVE_ENTRY_ACL_TYPE_DENY: - if (ace != NULL) - ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; - else - r = -1; - break; - case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - if (ace != NULL) - ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; - else - r = -1; - break; - case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - if (ace != NULL) - ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; - else - r = -1; - break; - case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: - if (aclent == NULL) - r = -1; - break; - case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: - if (aclent != NULL) - aclent->a_type |= ACL_DEFAULT; - else - r = -1; - break; -#else /* !HAVE_SUN_ACL */ - case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); - break; - case ARCHIVE_ENTRY_ACL_TYPE_DENY: - r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); - break; - case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); - break; - case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM); - break; - case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: - case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: - // These don't translate directly into the system ACL. - break; -#endif /* !HAVE_SUN_ACL */ - default: - archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Unknown ACL entry type"); - ret = ARCHIVE_FAILED; - goto exit_free; - } - - if (r != 0) { -#if HAVE_SUN_ACL - errno = EINVAL; -#endif - archive_set_error(a, errno, - "Failed to set ACL entry type"); - ret = ARCHIVE_FAILED; - goto exit_free; - } -#endif /* HAVE_ACL_TYPE_NFS4 || HAVE_SUN_ACL */ - -#if HAVE_SUN_ACL - if (acl->acl_type == ACLENT_T) { - if (ae_permset & ARCHIVE_ENTRY_ACL_EXECUTE) - aclent->a_perm |= 1; - if (ae_permset & ARCHIVE_ENTRY_ACL_WRITE) - aclent->a_perm |= 2; - if (ae_permset & ARCHIVE_ENTRY_ACL_READ) - aclent->a_perm |= 4; - } else -#else - if (acl_get_permset(acl_entry, &acl_permset) != 0) { - archive_set_error(a, errno, - "Failed to get ACL permission set"); - ret = ARCHIVE_FAILED; - goto exit_free; - } - if (acl_clear_perms(acl_permset) != 0) { - archive_set_error(a, errno, - "Failed to clear ACL permissions"); - ret = ARCHIVE_FAILED; - goto exit_free; - } -#endif /* !HAVE_SUN_ACL */ - for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { - if (ae_permset & acl_perm_map[i].archive_perm) { -#if HAVE_SUN_ACL - ace->a_access_mask |= - acl_perm_map[i].platform_perm; -#else - if (acl_add_perm(acl_permset, - acl_perm_map[i].platform_perm) != 0) { - archive_set_error(a, errno, - "Failed to add ACL permission"); - ret = ARCHIVE_FAILED; - goto exit_free; - } -#endif - } - } - -#if HAVE_NFS4_ACL -#if HAVE_SUN_ACL - if (acl_type == ACE_T) -#elif HAVE_DARWIN_ACL - if (acl_type == ACL_TYPE_EXTENDED) -#else /* FreeBSD */ - if (acl_type == ACL_TYPE_NFS4) -#endif - { -#if HAVE_POSIX_ACL || HAVE_DARWIN_ACL - /* - * acl_get_flagset_np() fails with non-NFSv4 ACLs - */ - if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { - archive_set_error(a, errno, - "Failed to get flagset from an NFSv4 ACL entry"); - ret = ARCHIVE_FAILED; - goto exit_free; - } - if (acl_clear_flags_np(acl_flagset) != 0) { - archive_set_error(a, errno, - "Failed to clear flags from an NFSv4 ACL flagset"); - ret = ARCHIVE_FAILED; - goto exit_free; - } -#endif /* HAVE_POSIX_ACL || HAVE_DARWIN_ACL */ - for (i = 0; i < (int)(sizeof(acl_inherit_map) /sizeof(acl_inherit_map[0])); ++i) { - if (ae_permset & acl_inherit_map[i].archive_inherit) { -#if HAVE_SUN_ACL - ace->a_flags |= - acl_inherit_map[i].platform_inherit; -#else /* !HAVE_SUN_ACL */ - if (acl_add_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit) != 0) { - archive_set_error(a, errno, - "Failed to add flag to NFSv4 ACL flagset"); - ret = ARCHIVE_FAILED; - goto exit_free; - } -#endif /* HAVE_SUN_ACL */ - } - } - } -#endif /* HAVE_NFS4_ACL */ -#if HAVE_SUN_ACL - e++; -#endif - } - -#if HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL - /* Try restoring the ACL through 'fd' if we can. */ -#if HAVE_SUN_ACL || HAVE_ACL_SET_FD_NP - if (fd >= 0) -#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */ - if (fd >= 0 && acl_type == ACL_TYPE_ACCESS) -#endif - { -#if HAVE_SUN_ACL - if (facl_set(fd, acl) == 0) -#elif HAVE_ACL_SET_FD_NP - if (acl_set_fd_np(fd, acl, acl_type) == 0) -#else /* !HAVE_SUN_ACL && !HAVE_ACL_SET_FD_NP */ - if (acl_set_fd(fd, acl) == 0) -#endif - ret = ARCHIVE_OK; - else { - if (errno == EOPNOTSUPP) { - /* Filesystem doesn't support ACLs */ - ret = ARCHIVE_OK; - } else { - archive_set_error(a, errno, - "Failed to set %s acl on fd", tname); - } - } - } else -#endif /* HAVE_ACL_SET_FD_NP || HAVE_ACL_SET_FD || HAVE_SUN_ACL */ -#if HAVE_SUN_ACL - if (acl_set(name, acl) != 0) -#elif HAVE_ACL_SET_LINK_NP - if (acl_set_link_np(name, acl_type, acl) != 0) -#else - /* TODO: Skip this if 'name' is a symlink. */ - if (acl_set_file(name, acl_type, acl) != 0) -#endif - { - if (errno == EOPNOTSUPP) { - /* Filesystem doesn't support ACLs */ - ret = ARCHIVE_OK; - } else { - archive_set_error(a, errno, "Failed to set %s acl", - tname); - ret = ARCHIVE_WARN; - } - } -exit_free: - acl_free(acl); - return (ret); -} -#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c index a5f3067..4a42a3b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c @@ -39,9 +39,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_SYS_EXTATTR_H #include <sys/extattr.h> #endif -#if defined(HAVE_SYS_XATTR_H) +#if HAVE_SYS_XATTR_H #include <sys/xattr.h> -#elif defined(HAVE_ATTR_XATTR_H) +#elif HAVE_ATTR_XATTR_H #include <attr/xattr.h> #endif #ifdef HAVE_SYS_EA_H @@ -575,10 +575,55 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) if (a->flags & ARCHIVE_EXTRACT_TIME) a->todo |= TODO_TIMES; if (a->flags & ARCHIVE_EXTRACT_ACL) { +#if ARCHIVE_ACL_DARWIN + /* + * On MacOS, platform ACLs get stored in mac_metadata, too. + * If we intend to extract mac_metadata and it is present + * we skip extracting libarchive NFSv4 ACLs. + */ + size_t metadata_size; + + if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 || + archive_entry_mac_metadata(a->entry, + &metadata_size) == NULL || metadata_size == 0) +#endif +#if ARCHIVE_ACL_LIBRICHACL + /* + * RichACLs are stored in an extended attribute. + * If we intend to extract extended attributes and have this + * attribute we skip extracting libarchive NFSv4 ACLs. + */ + short extract_acls = 1; + if (a->flags & ARCHIVE_EXTRACT_XATTR && ( + archive_entry_acl_types(a->entry) & + ARCHIVE_ENTRY_ACL_TYPE_NFS4)) { + const char *attr_name; + const void *attr_value; + size_t attr_size; + int i = archive_entry_xattr_reset(a->entry); + while (i--) { + archive_entry_xattr_next(a->entry, &attr_name, + &attr_value, &attr_size); + if (attr_name != NULL && attr_value != NULL && + attr_size > 0 && strcmp(attr_name, + "trusted.richacl") == 0) { + extract_acls = 0; + break; + } + } + } + if (extract_acls) +#endif +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL + { +#endif if (archive_entry_filetype(a->entry) == AE_IFDIR) a->deferred |= TODO_ACLS; else a->todo |= TODO_ACLS; +#if ARCHIVE_ACL_DARWIN || ARCHIVE_ACL_LIBRICHACL + } +#endif } if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) { if (archive_entry_filetype(a->entry) == AE_IFDIR) @@ -619,8 +664,21 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) } #endif - if (a->flags & ARCHIVE_EXTRACT_XATTR) + if (a->flags & ARCHIVE_EXTRACT_XATTR) { +#if ARCHIVE_XATTR_DARWIN + /* + * On MacOS, extended attributes get stored in mac_metadata, + * too. If we intend to extract mac_metadata and it is present + * we skip extracting extended attributes. + */ + size_t metadata_size; + + if ((a->flags & ARCHIVE_EXTRACT_MAC_METADATA) == 0 || + archive_entry_mac_metadata(a->entry, + &metadata_size) == NULL || metadata_size == 0) +#endif a->todo |= TODO_XATTR; + } if (a->flags & ARCHIVE_EXTRACT_FFLAGS) a->todo |= TODO_FFLAGS; if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) { @@ -1703,25 +1761,11 @@ _archive_write_disk_finish_entry(struct archive *_a) */ if (a->todo & TODO_ACLS) { int r2; -#ifdef HAVE_DARWIN_ACL - /* - * On Mac OS, platform ACLs are stored also in mac_metadata by - * the operating system. If mac_metadata is present it takes - * precedence and we skip extracting libarchive NFSv4 ACLs - */ - const void *metadata; - size_t metadata_size; - metadata = archive_entry_mac_metadata(a->entry, &metadata_size); - if ((a->todo & TODO_MAC_METADATA) == 0 || - metadata == NULL || metadata_size == 0) { -#endif r2 = archive_write_disk_set_acls(&a->archive, a->fd, archive_entry_pathname(a->entry), - archive_entry_acl(a->entry)); + archive_entry_acl(a->entry), + archive_entry_mode(a->entry)); if (r2 < ret) ret = r2; -#ifdef HAVE_DARWIN_ACL - } -#endif } finish_metadata: @@ -2293,13 +2337,8 @@ _archive_write_disk_close(struct archive *_a) if (p->fixup & TODO_MODE_BASE) chmod(p->name, p->mode); if (p->fixup & TODO_ACLS) -#ifdef HAVE_DARWIN_ACL - if ((p->fixup & TODO_MAC_METADATA) == 0 || - p->mac_metadata == NULL || - p->mac_metadata_size == 0) -#endif - archive_write_disk_set_acls(&a->archive, - -1, p->name, &p->acl); + archive_write_disk_set_acls(&a->archive, -1, p->name, + &p->acl, p->mode); if (p->fixup & TODO_FFLAGS) set_fflags_platform(a, -1, p->name, p->mode, p->fflags_set, 0); @@ -2467,7 +2506,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr, if (a_eno) *a_eno = err; if (a_estr) - archive_string_sprintf(a_estr, errstr, path); + archive_string_sprintf(a_estr, "%s%s", errstr, path); } /* @@ -2573,7 +2612,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, * with the deep-directory editing. */ fsobj_error(a_eno, a_estr, errno, - "Could not stat %s", path); + "Could not stat ", path); res = ARCHIVE_FAILED; break; } @@ -2582,7 +2621,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, if (chdir(head) != 0) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, - "Could not chdir %s", path); + "Could not chdir ", path); res = (ARCHIVE_FATAL); break; } @@ -2599,7 +2638,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, if (unlink(head)) { tail[0] = c; fsobj_error(a_eno, a_estr, errno, - "Could not remove symlink %s", + "Could not remove symlink ", path); res = ARCHIVE_FAILED; break; @@ -2618,7 +2657,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, /* if (!S_ISLNK(path)) { fsobj_error(a_eno, a_estr, 0, - "Removing symlink %s", path); + "Removing symlink ", path); } */ /* Symlink gone. No more problem! */ @@ -2630,7 +2669,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, tail[0] = c; fsobj_error(a_eno, a_estr, 0, "Cannot remove intervening " - "symlink %s", path); + "symlink ", path); res = ARCHIVE_FAILED; break; } @@ -2652,7 +2691,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, } else { fsobj_error(a_eno, a_estr, errno, - "Could not stat %s", path); + "Could not stat ", path); res = (ARCHIVE_FAILED); break; } @@ -2661,7 +2700,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, tail[0] = c; fsobj_error(a_eno, a_estr, errno, - "Could not chdir %s", path); + "Could not chdir ", path); res = (ARCHIVE_FATAL); break; } @@ -2674,14 +2713,14 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, tail[0] = c; fsobj_error(a_eno, a_estr, 0, "Cannot extract through " - "symlink %s", path); + "symlink ", path); res = ARCHIVE_FAILED; break; } } else { tail[0] = c; fsobj_error(a_eno, a_estr, 0, - "Cannot extract through symlink %s", path); + "Cannot extract through symlink ", path); res = ARCHIVE_FAILED; break; } @@ -4044,71 +4083,98 @@ skip_appledouble: } #endif -#if HAVE_LSETXATTR || HAVE_LSETEA +#if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX /* - * Restore extended attributes - Linux and AIX implementations: + * Restore extended attributes - Linux, Darwin and AIX implementations: * AIX' ea interface is syntaxwise identical to the Linux xattr interface. */ static int set_xattrs(struct archive_write_disk *a) { struct archive_entry *entry = a->entry; - static int warning_done = 0; + struct archive_string errlist; int ret = ARCHIVE_OK; int i = archive_entry_xattr_reset(entry); + short fail = 0; + + archive_string_init(&errlist); while (i--) { const char *name; const void *value; size_t size; + int e; + archive_entry_xattr_next(entry, &name, &value, &size); - if (name != NULL && - strncmp(name, "xfsroot.", 8) != 0 && - strncmp(name, "system.", 7) != 0) { - int e; -#if HAVE_FSETXATTR - if (a->fd >= 0) - e = fsetxattr(a->fd, name, value, size, 0); - else -#elif HAVE_FSETEA - if (a->fd >= 0) - e = fsetea(a->fd, name, value, size, 0); - else + + if (name == NULL) + continue; +#if ARCHIVE_XATTR_LINUX + /* Linux: quietly skip POSIX.1e ACL extended attributes */ + if (strncmp(name, "system.", 7) == 0 && + (strcmp(name + 7, "posix_acl_access") == 0 || + strcmp(name + 7, "posix_acl_default") == 0)) + continue; + if (strncmp(name, "trusted.SGI_", 12) == 0 && + (strcmp(name + 12, "ACL_DEFAULT") == 0 || + strcmp(name + 12, "ACL_FILE") == 0)) + continue; + + /* Linux: xfsroot namespace is obsolete and unsupported */ + if (strncmp(name, "xfsroot.", 8) == 0) { + fail = 1; + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + continue; + } #endif - { -#if HAVE_LSETXATTR - e = lsetxattr(archive_entry_pathname(entry), - name, value, size, 0); -#elif HAVE_LSETEA - e = lsetea(archive_entry_pathname(entry), - name, value, size, 0); + + if (a->fd >= 0) { +#if ARCHIVE_XATTR_LINUX + e = fsetxattr(a->fd, name, value, size, 0); +#elif ARCHIVE_XATTR_DARWIN + e = fsetxattr(a->fd, name, value, size, 0, 0); +#elif ARCHIVE_XATTR_AIX + e = fsetea(a->fd, name, value, size, 0); #endif - } - if (e == -1) { - if (errno == ENOTSUP || errno == ENOSYS) { - if (!warning_done) { - warning_done = 1; - archive_set_error(&a->archive, - errno, - "Cannot restore extended " - "attributes on this file " - "system"); - } - } else - archive_set_error(&a->archive, errno, - "Failed to set extended attribute"); - ret = ARCHIVE_WARN; - } } else { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Invalid extended attribute encountered"); +#if ARCHIVE_XATTR_LINUX + e = lsetxattr(archive_entry_pathname(entry), + name, value, size, 0); +#elif ARCHIVE_XATTR_DARWIN + e = setxattr(archive_entry_pathname(entry), + name, value, size, 0, XATTR_NOFOLLOW); +#elif ARCHIVE_XATTR_AIX + e = lsetea(archive_entry_pathname(entry), + name, value, size, 0); +#endif + } + if (e == -1) { ret = ARCHIVE_WARN; + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + if (errno != ENOTSUP && errno != ENOSYS) + fail = 1; } } + + if (ret == ARCHIVE_WARN) { + if (fail && errlist.length > 0) { + errlist.length--; + errlist.s[errlist.length] = '\0'; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended attributes: %s", + errlist.s); + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended " + "attributes on this file system."); + } + + archive_string_free(&errlist); return (ret); } -#elif HAVE_EXTATTR_SET_FILE && HAVE_DECL_EXTATTR_NAMESPACE_USER +#elif ARCHIVE_XATTR_FREEBSD /* * Restore extended attributes - FreeBSD implementation */ @@ -4116,9 +4182,12 @@ static int set_xattrs(struct archive_write_disk *a) { struct archive_entry *entry = a->entry; - static int warning_done = 0; + struct archive_string errlist; int ret = ARCHIVE_OK; int i = archive_entry_xattr_reset(entry); + short fail = 0; + + archive_string_init(&errlist); while (i--) { const char *name; @@ -4134,46 +4203,47 @@ set_xattrs(struct archive_write_disk *a) name += 5; namespace = EXTATTR_NAMESPACE_USER; } else { - /* Warn about other extended attributes. */ - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Can't restore extended attribute ``%s''", - name); + /* Other namespaces are unsupported */ + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); + fail = 1; ret = ARCHIVE_WARN; continue; } - errno = 0; -#if HAVE_EXTATTR_SET_FD - if (a->fd >= 0) + + if (a->fd >= 0) { e = extattr_set_fd(a->fd, namespace, name, value, size); - else -#endif - /* TODO: should we use extattr_set_link() instead? */ - { - e = extattr_set_file( + } else { + e = extattr_set_link( archive_entry_pathname(entry), namespace, name, value, size); } if (e != (int)size) { - if (errno == ENOTSUP || errno == ENOSYS) { - if (!warning_done) { - warning_done = 1; - archive_set_error(&a->archive, - errno, - "Cannot restore extended " - "attributes on this file " - "system"); - } - } else { - archive_set_error(&a->archive, errno, - "Failed to set extended attribute"); - } - + archive_strcat(&errlist, name); + archive_strappend_char(&errlist, ' '); ret = ARCHIVE_WARN; + if (errno != ENOTSUP && errno != ENOSYS) + fail = 1; } } } + + if (ret == ARCHIVE_WARN) { + if (fail && errlist.length > 0) { + errlist.length--; + errlist.s[errlist.length] = '\0'; + + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended attributes: %s", + errlist.s); + } else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Cannot restore extended " + "attributes on this file system."); + } + + archive_string_free(&errlist); return (ret); } #else @@ -4239,5 +4309,19 @@ older(struct stat *st, struct archive_entry *entry) return (0); } +#ifndef ARCHIVE_ACL_SUPPORT +int +archive_write_disk_set_acls(struct archive *a, int fd, const char *name, + struct archive_acl *abstract_acl, __LA_MODE_T mode) +{ + (void)a; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)abstract_acl; /* UNUSED */ + (void)mode; /* UNUSED */ + return (ARCHIVE_OK); +} +#endif + #endif /* !_WIN32 || __CYGWIN__ */ diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h b/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h index d84e7e1..b655dea 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_private.h @@ -33,11 +33,13 @@ #ifndef ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED #define ARCHIVE_WRITE_DISK_PRIVATE_H_INCLUDED +#include "archive_platform_acl.h" #include "archive_acl_private.h" +#include "archive_entry.h" struct archive_write_disk; -int -archive_write_disk_set_acls(struct archive *, int /* fd */, const char * /* pathname */, struct archive_acl *); +int archive_write_disk_set_acls(struct archive *, int, const char *, + struct archive_acl *, __LA_MODE_T); #endif diff --git a/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 b/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 index c5ef69e..dc1b94b 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_finish_entry.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd February 28, 2017 .Dt ARCHIVE_WRITE_FINISH_ENTRY 3 .Os .Sh NAME @@ -45,6 +45,9 @@ is called automatically by and .Fn archive_write_close as needed. +For +.Tn archive_write_disk +handles, this flushes pending file attribute changes like modification time. .\" .Sh EXAMPLE .Sh RETURN VALUES This function returns diff --git a/Utilities/cmlibarchive/libarchive/archive_write_format.3 b/Utilities/cmlibarchive/libarchive/archive_write_format.3 index d4ba6ab..aaafb0a 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_format.3 +++ b/Utilities/cmlibarchive/libarchive/archive_write_format.3 @@ -108,7 +108,6 @@ Streaming Archive Library (libarchive, -larchive) These functions set the format that will be used for the archive. .Pp The library can write a variety of common archive formats. - .Bl -tag -width indent .It Fn archive_write_set_format Sets the format based on the format code (see diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format.c index 744302d..0f70623 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format.c @@ -38,7 +38,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format.c 201168 2009-1 #include "archive_private.h" /* A table that maps format codes to functions. */ -static +static const struct { int code; int (*setter)(struct archive *); } codes[] = { { ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip }, diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c index a2ce7c6..86e8621 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_by_name.c @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 20116 #include "archive_private.h" /* A table that maps names to functions. */ -static +static const struct { const char *name; int (*setter)(struct archive *); } names[] = { { "7zip", archive_write_set_format_7zip }, diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_filter_by_ext.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_filter_by_ext.c index adec9b2..9fe21e4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_filter_by_ext.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_filter_by_ext.c @@ -42,7 +42,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 20116 #include "archive_private.h" /* A table that maps names to functions. */ -static +static const struct { const char *name; int (*format)(struct archive *); int (*filter)(struct archive *); } names[] = { { ".7z", archive_write_set_format_7zip, archive_write_add_filter_none}, diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c index 6a301ac..0eaf733 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_pax.c @@ -1196,8 +1196,12 @@ archive_write_pax_header(struct archive_write *a, "GNU.sparse.major", 1); add_pax_attr_int(&(pax->pax_header), "GNU.sparse.minor", 0); + /* + * Make sure to store the original path, since + * truncation to ustar limit happened already. + */ add_pax_attr(&(pax->pax_header), - "GNU.sparse.name", entry_name.s); + "GNU.sparse.name", path); add_pax_attr_int(&(pax->pax_header), "GNU.sparse.realsize", archive_entry_size(entry_main)); @@ -1650,13 +1654,14 @@ build_pax_attribute_name(char *dest, const char *src) * GNU PAX Format 1.0 requires the special name, which pattern is: * <dir>/GNUSparseFile.<pid>/<original file name> * + * Since reproducable archives are more important, use 0 as pid. + * * This function is used for only Sparse file, a file type of which * is regular file. */ static char * build_gnu_sparse_name(char *dest, const char *src) { - char buff[64]; const char *p; /* Handle the null filename case. */ @@ -1682,15 +1687,9 @@ build_gnu_sparse_name(char *dest, const char *src) break; } -#if HAVE_GETPID && 0 /* Disable this as pax attribute name. */ - sprintf(buff, "GNUSparseFile.%d", getpid()); -#else - /* If the platform can't fetch the pid, don't include it. */ - strcpy(buff, "GNUSparseFile"); -#endif /* General case: build a ustar-compatible name adding * "/GNUSparseFile/". */ - build_ustar_entry_name(dest, src, p - src, buff); + build_ustar_entry_name(dest, src, p - src, "GNUSparseFile.0"); return (dest); } diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c index 8b6daf9..edad072 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_warc.c @@ -354,7 +354,7 @@ static ssize_t _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr) { static const char _ver[] = "WARC/1.0\r\n"; - static const char *_typ[LAST_WT] = { + static const char * const _typ[LAST_WT] = { NULL, "warcinfo", "metadata", "resource", NULL }; char std_uuid[48U]; diff --git a/Utilities/cmlibarchive/libarchive/config_freebsd.h b/Utilities/cmlibarchive/libarchive/config_freebsd.h index 215e886..be25258 100644 --- a/Utilities/cmlibarchive/libarchive/config_freebsd.h +++ b/Utilities/cmlibarchive/libarchive/config_freebsd.h @@ -22,141 +22,238 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: head/lib/libarchive/config_freebsd.h 201079 2009-12-28 02:01:42Z kientzle $ + * $FreeBSD$ */ -/* FreeBSD 5.0 and later have ACL and extattr support. */ +#include <osreldate.h> + +/* FreeBSD 5.0 and later has ACL and extattr support. */ #if __FreeBSD__ > 4 -#define HAVE_ACL_CREATE_ENTRY 1 -#define HAVE_ACL_GET_FD_NP 1 -#define HAVE_ACL_GET_LINK_NP 1 -#define HAVE_ACL_GET_PERM_NP 1 -#define HAVE_ACL_INIT 1 -#define HAVE_ACL_SET_FD 1 -#define HAVE_ACL_SET_FD_NP 1 -#define HAVE_ACL_SET_FILE 1 -#define HAVE_ACL_USER 1 -#define HAVE_EXTATTR_GET_FILE 1 -#define HAVE_EXTATTR_LIST_FILE 1 -#define HAVE_EXTATTR_SET_FD 1 -#define HAVE_EXTATTR_SET_FILE 1 -#define HAVE_STRUCT_XVFSCONF 1 -#define HAVE_SYS_ACL_H 1 -#define HAVE_SYS_EXTATTR_H 1 -#endif +#define ARCHIVE_ACL_FREEBSD 1 +#define HAVE_ACL_GET_PERM_NP 1 +#define HAVE_ARC4RANDOM_BUF 1 +#define HAVE_EXTATTR_GET_FILE 1 +#define HAVE_EXTATTR_LIST_FILE 1 +#define HAVE_EXTATTR_SET_FD 1 +#define HAVE_EXTATTR_SET_FILE 1 +#define HAVE_STRUCT_XVFSCONF 1 +#define HAVE_SYS_ACL_H 1 +#define HAVE_SYS_EXTATTR_H 1 +#if __FreeBSD__ > 7 +/* FreeBSD 8.0 and later has NFSv4 ACL support */ +#define ARCHIVE_ACL_FREEBSD_NFS4 1 +#define HAVE_ACL_GET_LINK_NP 1 +#define HAVE_ACL_IS_TRIVIAL_NP 1 +#define HAVE_ACL_SET_LINK_NP 1 +#endif /* __FreeBSD__ > 7 */ +#endif /* __FreeBSD__ > 4 */ #ifdef WITH_OPENSSL -#define HAVE_OPENSSL_MD5_H 1 -#define HAVE_OPENSSL_RIPEMD_H 1 -#define HAVE_OPENSSL_SHA_H 1 -#define HAVE_SHA384 1 -#define HAVE_SHA512 1 +#define HAVE_LIBCRYPTO 1 +#define HAVE_OPENSSL_EVP_H 1 +#define HAVE_OPENSSL_MD5_H 1 +#define HAVE_OPENSSL_RIPEMD_H 1 +#define HAVE_OPENSSL_SHA_H 1 +#define HAVE_OPENSSL_SHA256_INIT 1 +#define HAVE_OPENSSL_SHA384_INIT 1 +#define HAVE_OPENSSL_SHA512_INIT 1 +#define HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 +#define HAVE_SHA256 1 +#define HAVE_SHA384 1 +#define HAVE_SHA512 1 +#else +#define HAVE_LIBMD 1 +#define HAVE_MD5_H 1 +#define HAVE_MD5INIT 1 +#define HAVE_RIPEMD_H 1 +#define HAVE_SHA_H 1 +#define HAVE_SHA1 1 +#define HAVE_SHA1_INIT 1 +#define HAVE_SHA256 1 +#define HAVE_SHA256_H 1 +#define HAVE_SHA256_INIT 1 +#define HAVE_SHA512 1 +#define HAVE_SHA512_H 1 +#define HAVE_SHA512_INIT 1 #endif -#define HAVE_BSDXML_H 1 -#define HAVE_BZLIB_H 1 -#define HAVE_CHFLAGS 1 -#define HAVE_CHOWN 1 -#define HAVE_DECL_INT64_MAX 1 -#define HAVE_DECL_INT64_MIN 1 -#define HAVE_DECL_SIZE_MAX 1 -#define HAVE_DECL_SSIZE_MAX 1 -#define HAVE_DECL_STRERROR_R 1 -#define HAVE_DECL_UINT32_MAX 1 -#define HAVE_DECL_UINT64_MAX 1 -#define HAVE_DIRENT_H 1 -#define HAVE_EFTYPE 1 -#define HAVE_EILSEQ 1 -#define HAVE_ERRNO_H 1 -#define HAVE_FCHDIR 1 -#define HAVE_FCHFLAGS 1 -#define HAVE_FCHMOD 1 -#define HAVE_FCHOWN 1 -#define HAVE_FCNTL 1 -#define HAVE_FCNTL_H 1 -#define HAVE_FSEEKO 1 -#define HAVE_FSTAT 1 -#define HAVE_FTRUNCATE 1 -#define HAVE_FUTIMES 1 -#define HAVE_GETEUID 1 -#define HAVE_GETGRGID_R 1 -#define HAVE_GETPID 1 -#define HAVE_GETPWUID_R 1 -#define HAVE_GRP_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_LCHFLAGS 1 -#define HAVE_LCHMOD 1 -#define HAVE_LCHOWN 1 -#define HAVE_LIMITS_H 1 -#define HAVE_LINK 1 -#define HAVE_LSTAT 1 -#define HAVE_LUTIMES 1 -#define HAVE_MALLOC 1 -#define HAVE_MD5 1 -#define HAVE_MD5_H 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MKDIR 1 -#define HAVE_MKFIFO 1 -#define HAVE_MKNOD 1 -#define HAVE_PIPE 1 -#define HAVE_POLL 1 -#define HAVE_POLL_H 1 -#define HAVE_PWD_H 1 -#define HAVE_READLINK 1 -#define HAVE_RMD160 1 -#define HAVE_SELECT 1 -#define HAVE_SETENV 1 -#define HAVE_SHA_H 1 -#define HAVE_SHA1 1 -#define HAVE_SHA256 1 -#define HAVE_SHA256_H 1 -#define HAVE_SIGNAL_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRCHR 1 -#define HAVE_STRDUP 1 -#define HAVE_STRERROR 1 -#define HAVE_STRERROR_R 1 -#define HAVE_STRINGS_H 1 -#define HAVE_STRING_H 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 -#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 -#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 -#define HAVE_STRUCT_STAT_ST_FLAGS 1 -#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 -#define HAVE_STRUCT_TM_TM_GMTOFF 1 -#define HAVE_SYMLINK 1 -#define HAVE_SYS_CDEFS_H 1 -#define HAVE_SYS_IOCTL_H 1 -#define HAVE_SYS_MOUNT_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_SELECT_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_SYS_TYPES_H 1 -#undef HAVE_SYS_UTIME_H -#define HAVE_SYS_UTSNAME_H 1 -#define HAVE_SYS_WAIT_H 1 -#define HAVE_TIMEGM 1 -#define HAVE_TZSET 1 -#define HAVE_UNISTD_H 1 -#define HAVE_UNSETENV 1 -#define HAVE_UTIME 1 -#define HAVE_UTIMES 1 -#define HAVE_UTIME_H 1 -#define HAVE_VFORK 1 -#define HAVE_WCHAR_H 1 -#define HAVE_WCSCPY 1 -#define HAVE_WCSLEN 1 -#define HAVE_WCTOMB 1 -#define HAVE_WMEMCMP 1 -#define HAVE_WMEMCPY 1 -#define HAVE_ZLIB_H 1 -#define TIME_WITH_SYS_TIME 1 +#define HAVE_BSDXML_H 1 +#define HAVE_BZLIB_H 1 +#define HAVE_CHFLAGS 1 +#define HAVE_CHOWN 1 +#define HAVE_CHROOT 1 +#define HAVE_CTIME_R 1 +#define HAVE_CTYPE_H 1 +#define HAVE_DECL_EXTATTR_NAMESPACE_USER 1 +#define HAVE_DECL_INT32_MAX 1 +#define HAVE_DECL_INT32_MIN 1 +#define HAVE_DECL_INT64_MAX 1 +#define HAVE_DECL_INT64_MIN 1 +#define HAVE_DECL_INTMAX_MAX 1 +#define HAVE_DECL_INTMAX_MIN 1 +#define HAVE_DECL_SIZE_MAX 1 +#define HAVE_DECL_SSIZE_MAX 1 +#define HAVE_DECL_STRERROR_R 1 +#define HAVE_DECL_UINT32_MAX 1 +#define HAVE_DECL_UINT64_MAX 1 +#define HAVE_DECL_UINTMAX_MAX 1 +#define HAVE_DIRENT_H 1 +#define HAVE_DLFCN_H 1 +#define HAVE_D_MD_ORDER 1 +#define HAVE_EFTYPE 1 +#define HAVE_EILSEQ 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCHDIR 1 +#define HAVE_FCHFLAGS 1 +#define HAVE_FCHMOD 1 +#define HAVE_FCHOWN 1 +#define HAVE_FCNTL 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FDOPENDIR 1 +#define HAVE_FORK 1 +#define HAVE_FSEEKO 1 +#define HAVE_FSTAT 1 +#define HAVE_FSTATAT 1 +#define HAVE_FSTATFS 1 +#define HAVE_FSTATVFS 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_FUTIMES 1 +#define HAVE_FUTIMESAT 1 +#define HAVE_GETEUID 1 +#define HAVE_GETGRGID_R 1 +#define HAVE_GETGRNAM_R 1 +#define HAVE_GETPID 1 +#define HAVE_GETPWNAM_R 1 +#define HAVE_GETPWUID_R 1 +#define HAVE_GETVFSBYNAME 1 +#define HAVE_GMTIME_R 1 +#define HAVE_GRP_H 1 +#define HAVE_INTMAX_T 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_LCHFLAGS 1 +#define HAVE_LCHMOD 1 +#define HAVE_LCHOWN 1 +#define HAVE_LIBZ 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LINK 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_LONG_LONG_INT 1 +#define HAVE_LSTAT 1 +#define HAVE_LUTIMES 1 +#define HAVE_MBRTOWC 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMORY_H 1 +#define HAVE_MEMSET 1 +#define HAVE_MKDIR 1 +#define HAVE_MKFIFO 1 +#define HAVE_MKNOD 1 +#define HAVE_MKSTEMP 1 +#define HAVE_NL_LANGINFO 1 +#define HAVE_OPENAT 1 +#define HAVE_PATHS_H 1 +#define HAVE_PIPE 1 +#define HAVE_POLL 1 +#define HAVE_POLL_H 1 +#define HAVE_POSIX_SPAWNP 1 +#define HAVE_PTHREAD_H 1 +#define HAVE_PWD_H 1 +#define HAVE_READDIR_R 1 +#define HAVE_READLINK 1 +#define HAVE_READLINKAT 1 +#define HAVE_READPASSPHRASE 1 +#define HAVE_READPASSPHRASE_H 1 +#define HAVE_REGEX_H 1 +#define HAVE_SELECT 1 +#define HAVE_SETENV 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SPAWN_H 1 +#define HAVE_STATFS 1 +#define HAVE_STATVFS 1 +#define HAVE_STDARG_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRCHR 1 +#define HAVE_STRDUP 1 +#define HAVE_STRERROR 1 +#define HAVE_STRERROR_R 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRUCT_STATFS_F_NAMEMAX 1 +#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1 +#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 +#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 +#define HAVE_STRUCT_TM_TM_GMTOFF 1 +#define HAVE_SYMLINK 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_MOUNT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_POLL_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_STATVFS_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_UTSNAME_H 1 +#define HAVE_SYS_WAIT_H 1 +#define HAVE_TIMEGM 1 +#define HAVE_TIME_H 1 +#define HAVE_TZSET 1 +#define HAVE_UINTMAX_T 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UNSETENV 1 +#define HAVE_UNSIGNED_LONG_LONG 1 +#define HAVE_UNSIGNED_LONG_LONG_INT 1 +#define HAVE_UTIME 1 +#define HAVE_UTIMES 1 +#define HAVE_UTIME_H 1 +#define HAVE_VFORK 1 +#define HAVE_VPRINTF 1 +#define HAVE_WCHAR_H 1 +#define HAVE_WCHAR_T 1 +#define HAVE_WCRTOMB 1 +#define HAVE_WCSCMP 1 +#define HAVE_WCSCPY 1 +#define HAVE_WCSLEN 1 +#define HAVE_WCTOMB 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_WMEMCMP 1 +#define HAVE_WMEMCPY 1 +#define HAVE_WMEMMOVE 1 +#define HAVE_ZLIB_H 1 +#define TIME_WITH_SYS_TIME 1 + +#if __FreeBSD_version >= 1100056 +#define HAVE_FUTIMENS 1 +#define HAVE_UTIMENSAT 1 +#endif /* FreeBSD 4 and earlier lack intmax_t/uintmax_t */ #if __FreeBSD__ < 5 -#define intmax_t int64_t -#define uintmax_t uint64_t +#define intmax_t int64_t +#define uintmax_t uint64_t +#endif + +/* FreeBSD defines for archive_hash.h */ +#ifdef WITH_OPENSSL +#define ARCHIVE_CRYPTO_MD5_OPENSSL 1 +#define ARCHIVE_CRYPTO_RMD160_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA1_OPENSSL +#define ARCHIVE_CRYPTO_SHA256_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA384_OPENSSL 1 +#define ARCHIVE_CRYPTO_SHA512_OPENSSL 1 +#else +#define ARCHIVE_CRYPTO_MD5_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA1_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA256_LIBMD 1 +#define ARCHIVE_CRYPTO_SHA512_LIBMD 1 #endif diff --git a/Utilities/cmlibarchive/libarchive/libarchive_changes.3 b/Utilities/cmlibarchive/libarchive/libarchive_changes.3 index 881a67c..adc87fe 100644 --- a/Utilities/cmlibarchive/libarchive/libarchive_changes.3 +++ b/Utilities/cmlibarchive/libarchive/libarchive_changes.3 @@ -28,6 +28,7 @@ .Dt LIBARCHIVE_CHANGES 3 .Os .Sh NAME +.Nm libarchive_changes .Nd changes in libarchive interface .\" .Sh CHANGES IN LIBARCHIVE 3 diff --git a/Utilities/cmlibarchive/libarchive/mtree.5 b/Utilities/cmlibarchive/libarchive/mtree.5 index 16c8abe..e607e4a 100644 --- a/Utilities/cmlibarchive/libarchive/mtree.5 +++ b/Utilities/cmlibarchive/libarchive/mtree.5 @@ -48,7 +48,7 @@ Leading whitespace is always ignored. .Pp When encoding file or pathnames, any backslash character or character outside of the 95 printable ASCII characters must be -encoded as a a backslash followed by three +encoded as a backslash followed by three octal digits. When reading mtree files, any appearance of a backslash followed by three octal digits should be converted into the diff --git a/Utilities/cmlibarchive/libarchive/xxhash.c b/Utilities/cmlibarchive/libarchive/xxhash.c index 6f5ba52..70750ba 100644 --- a/Utilities/cmlibarchive/libarchive/xxhash.c +++ b/Utilities/cmlibarchive/libarchive/xxhash.c @@ -141,13 +141,19 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S; # pragma pack(pop) #endif -#define A32(x) (((const U32_S *)(x))->v) - /**************************************** ** Compiler-specific Functions and Macros *****************************************/ -#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0)) + +#if GCC_VERSION >= 409 +__attribute__((__no_sanitize_undefined__)) +#endif +static inline U32 A32(const void * x) +{ + return (((const U32_S *)(x))->v); +} /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ #if defined(_MSC_VER) |